From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Noam Postavsky Newsgroups: gmane.emacs.bugs Subject: bug#32939: 27.0.50; Don't reject confusable quotes, just fontify & mention them in error messages Date: Wed, 24 Oct 2018 18:25:53 -0400 Message-ID: <877ei7m172.fsf@gmail.com> References: <87lg7dmfhp.fsf@gmail.com> <83woqw235n.fsf@gnu.org> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: blaine.gmane.org 1540419916 4904 195.159.176.226 (24 Oct 2018 22:25:16 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Wed, 24 Oct 2018 22:25:16 +0000 (UTC) User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.1 (gnu/linux) Cc: 32939@debbugs.gnu.org To: Eli Zaretskii Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Thu Oct 25 00:25:12 2018 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1gFRaR-00018s-R9 for geb-bug-gnu-emacs@m.gmane.org; Thu, 25 Oct 2018 00:25:12 +0200 Original-Received: from localhost ([::1]:50714 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gFRcY-000168-Ar for geb-bug-gnu-emacs@m.gmane.org; Wed, 24 Oct 2018 18:27:22 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:56081) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gFRcO-000143-9W for bug-gnu-emacs@gnu.org; Wed, 24 Oct 2018 18:27:14 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gFRcE-0000uP-TG for bug-gnu-emacs@gnu.org; Wed, 24 Oct 2018 18:27:10 -0400 Original-Received: from debbugs.gnu.org ([208.118.235.43]:36707) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gFRcE-0000st-AN for bug-gnu-emacs@gnu.org; Wed, 24 Oct 2018 18:27:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1gFRcE-00089a-4E for bug-gnu-emacs@gnu.org; Wed, 24 Oct 2018 18:27:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Noam Postavsky Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Wed, 24 Oct 2018 22:27:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 32939 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: Original-Received: via spool by 32939-submit@debbugs.gnu.org id=B32939.154041996431276 (code B ref 32939); Wed, 24 Oct 2018 22:27:02 +0000 Original-Received: (at 32939) by debbugs.gnu.org; 24 Oct 2018 22:26:04 +0000 Original-Received: from localhost ([127.0.0.1]:40965 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1gFRbH-00088O-K3 for submit@debbugs.gnu.org; Wed, 24 Oct 2018 18:26:04 -0400 Original-Received: from mail-it1-f173.google.com ([209.85.166.173]:34855) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1gFRbF-00087t-LY for 32939@debbugs.gnu.org; Wed, 24 Oct 2018 18:26:02 -0400 Original-Received: by mail-it1-f173.google.com with SMTP id p64-v6so8684890itp.0 for <32939@debbugs.gnu.org>; Wed, 24 Oct 2018 15:26:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:references:date:in-reply-to:message-id :user-agent:mime-version; bh=GrIonLn0QztRWZk93/kRwuYzmNCL/NOeU8LXvARTYqs=; b=PgSf3LMG/3XZID4UV37ksRlNhl7L/m4DkDIwBgutDY23ddwuK1s+ZITKaGmq4z8dOw 9I1uWQzKqJWz9LprBGq5VPb5ognsj8SorWB1Va7ny66Cc6xa7HxKrllX0xQXE2H5l1LP WW60JVO7D5g95rR4gougzD/OjReaaiQ9dFdkrvJ803h9eHWOBo9kPuHxdQK3h4b3F92o sDmpjVtakWklZzGxPbpLfBhS/htdlde5I/m/DfLsHTj04te4o1Z64BFshV75qbMQdmxi vKTMdsQkI1q/1exco6JU9HXkiqU8lyuQ+8wnY8LDCcr66Hep6s0HcVeHa9lYO/gODhZb HQ0Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:references:date:in-reply-to :message-id:user-agent:mime-version; bh=GrIonLn0QztRWZk93/kRwuYzmNCL/NOeU8LXvARTYqs=; b=DCrgC1de7cvHQPS0Rhlr8BUygsbnECyIwotmyJvkfuRFweVOF6aPkTV8nJgQDsd3pp tw/WQwwSrfAkTFVidPjLHmEAT1IM0p+gFhqrhXAbZql0I7gv2UKpXIEyE+D228m6IRkd k6K2mqejzc6wRw/60rB89pTrrVM1wvRpeemPyfO7cMzPfcIiJ45y/7STqQ7Rz/RKIZ9S F6IDRoi9ffLRdXEnNrIoUfHKy/NN/xQVh820vj9FpqtjHQM1R0tx1/fhIYex3JX1LVyA 5FUNUFXqDvwHMeVk0fcr60Gzx+7pk/OzfZenh4ZKJXI430y4WFP0po1LSdm3VXUsWfuB 6IMA== X-Gm-Message-State: AGRZ1gJaEMkVyXHwKo6MvplJhhAikX8OxAwviSUnvAyZZNoNJIkvD1CE 6y/67NxnPaE3POKn9DETXpSzPu7q X-Google-Smtp-Source: AJdET5cEjG14uv6xB5JZCK1vgLFWpFzS0905Awq5BiDoq+cuOXQkl6VQz0Z980l37GHlzDZeUUKHsA== X-Received: by 2002:a02:15d3:: with SMTP id 80-v6mr3371434jaq.116.1540419955859; Wed, 24 Oct 2018 15:25:55 -0700 (PDT) Original-Received: from zebian (cbl-45-2-119-34.yyz.frontiernetworks.ca. [45.2.119.34]) by smtp.googlemail.com with ESMTPSA id i9-v6sm2111843ioj.9.2018.10.24.15.25.54 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 24 Oct 2018 15:25:54 -0700 (PDT) In-Reply-To: <83woqw235n.fsf@gnu.org> (Eli Zaretskii's message of "Fri, 05 Oct 2018 11:44:52 +0300") X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 208.118.235.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:151573 Archived-At: --=-=-= Content-Type: text/plain Eli Zaretskii writes: >> From: Noam Postavsky >> Date: Thu, 04 Oct 2018 19:58:10 -0400 >> >> As a followup from [1], here is a patchset which replaces the master's >> current rejection of confusable quotes on `read', and instead adds a >> hint to the error message when evaluating an expression with a >> confusable quote leads to an error. >> >> And also highlight such quotes with warning-face. > > Thanks. If this is accepted, it will need documentation changes, > including NEWS. I adjusted the first patch so it applies cleanly to more recent master, and added a NEWS entry for the fontification. I'm not sure about what other documentation we need though. --=-=-= Content-Type: text/plain; charset=utf-8 Content-Disposition: attachment; filename=v2-0001-Stop-signaling-an-error-when-reading-smart-quotes.patch Content-Transfer-Encoding: quoted-printable Content-Description: patch >From 6d3b86eb41660d8908646d8461a7afff03fd17b7 Mon Sep 17 00:00:00 2001 From: Noam Postavsky Date: Sat, 10 Mar 2018 18:20:45 -0500 Subject: [PATCH v2 1/2] Stop signaling an error when reading "smart quotes"= in symbols Revert commits from 2018-01-28 "Fix round tripping of read->print for symbols with strange quotes", and 2017-07-22 "Signal error for symbol names with strange quotes (Bug#2967)". * etc/NEWS: Remove corresponding entries. * src/character.c (confusable_symbol_character_p): * test/src/lread-tests.el (lread-tests--old-style-backquotes): Remove. * src/lread.c (read1): Don't signal error on confusable character. * src/print.c (print_object): Don't escape confusable characters. --- etc/NEWS | 9 --------- src/character.c | 26 -------------------------- src/character.h | 2 -- src/lread.c | 7 ------- src/print.c | 3 +-- test/src/lread-tests.el | 17 ----------------- 6 files changed, 1 insertion(+), 63 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 946a823173..8bed92430b 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1089,15 +1089,6 @@ and if the new behavior breaks your code please email 32252@debbugs.gnu.org. Because %o and %x can now format signed integers, they now support the + and space flags. =20 -** To avoid confusion caused by "smart quotes", the reader signals an -error when reading Lisp symbols which begin with one of the following -quotation characters: =E2=80=98=E2=80=99=E2=80=9B=E2=80=9C=E2=80=9D=E2=80= =9F=E3=80=9E=EF=BC=82=EF=BC=87. A symbol beginning with such a -character can be written by escaping the quotation character with a -backslash. For example: - - (read "=E2=80=98smart") =3D> (invalid-read-syntax "strange quote" "=E2= =80=98") - (read "\\=E2=80=98smart") =3D=3D (intern "=E2=80=98smart") - +++ ** Omitting variables after '&optional' and '&rest' is now allowed. For example (defun foo (&optional)) is no longer an error. This is diff --git a/src/character.c b/src/character.c index 0b14e476c1..edaeca0a35 100644 --- a/src/character.c +++ b/src/character.c @@ -1056,32 +1056,6 @@ blankp (int c) return XFIXNUM (category) =3D=3D UNICODE_CATEGORY_Zs; /* separator, spac= e */ } =20 - -/* Return true for characters that would read as symbol characters, - but graphically may be confused with some kind of punctuation. We - require an escaping backslash, when such characters begin a - symbol. */ -bool -confusable_symbol_character_p (int ch) -{ - switch (ch) - { - case 0x2018: /* LEFT SINGLE QUOTATION MARK */ - case 0x2019: /* RIGHT SINGLE QUOTATION MARK */ - case 0x201B: /* SINGLE HIGH-REVERSED-9 QUOTATION MARK */ - case 0x201C: /* LEFT DOUBLE QUOTATION MARK */ - case 0x201D: /* RIGHT DOUBLE QUOTATION MARK */ - case 0x201F: /* DOUBLE HIGH-REVERSED-9 QUOTATION MARK */ - case 0x301E: /* DOUBLE PRIME QUOTATION MARK */ - case 0xFF02: /* FULLWIDTH QUOTATION MARK */ - case 0xFF07: /* FULLWIDTH APOSTROPHE */ - return true; - - default: - return false; - } -} - signed char HEXDIGIT_CONST hexdigit[UCHAR_MAX + 1] =3D { #if HEXDIGIT_IS_CONST diff --git a/src/character.h b/src/character.h index 5dff85aed4..6d5349e07d 100644 --- a/src/character.h +++ b/src/character.h @@ -683,8 +683,6 @@ char_surrogate_p (int c) extern bool printablep (int); extern bool blankp (int); =20 -extern bool confusable_symbol_character_p (int ch); - /* Return a translation table of id number ID. */ #define GET_TRANSLATION_TABLE(id) \ (XCDR (XVECTOR (Vtranslation_table_vector)->contents[(id)])) diff --git a/src/lread.c b/src/lread.c index 62616cb681..bf06b41caa 100644 --- a/src/lread.c +++ b/src/lread.c @@ -3543,13 +3543,6 @@ read1 (Lisp_Object readcharfun, int *pch, bool first= _in_list) if (! NILP (result) && len =3D=3D nbytes) return unbind_to (count, result); } - if (!quoted && multibyte) - { - int ch =3D STRING_CHAR ((unsigned char *) read_buffer); - if (confusable_symbol_character_p (ch)) - xsignal2 (Qinvalid_read_syntax, build_string ("strange quote= "), - CALLN (Fstring, make_fixnum (ch))); - } { Lisp_Object result; ptrdiff_t nchars diff --git a/src/print.c b/src/print.c index d15ff97b00..3a19bd5e31 100644 --- a/src/print.c +++ b/src/print.c @@ -2030,8 +2030,7 @@ print_object (Lisp_Object obj, Lisp_Object printcharf= un, bool escapeflag) || c =3D=3D ',' || c =3D=3D '.' || c =3D=3D '`' || c =3D=3D '[' || c =3D=3D ']' || c =3D=3D '?' || c <=3D 040 || c =3D=3D NO_BREAK_SPACE - || confusing - || (i =3D=3D 1 && confusable_symbol_character_p (c))) + || confusing) { printchar ('\\', printcharfun); confusing =3D false; diff --git a/test/src/lread-tests.el b/test/src/lread-tests.el index f19d98320a..0d7cd962bd 100644 --- a/test/src/lread-tests.el +++ b/test/src/lread-tests.el @@ -142,23 +142,6 @@ lread-tests--last-message "unescaped character literals " "`?\"', `?(', `?)', `?;', `?[', `?]' detected!"= ))))) =20 -(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)))))) - (ert-deftest lread-test-bug26837 () "Test for https://debbugs.gnu.org/26837 ." (let ((load-path (cons --=20 2.11.0 --=-=-= Content-Type: text/plain; charset=utf-8 Content-Disposition: attachment; filename=v2-0002-Improve-errors-warnings-due-to-fancy-quoted-vars-.patch Content-Transfer-Encoding: quoted-printable Content-Description: patch >From acb2e416688dd3612225aa593c264f37edb5ba9f Mon Sep 17 00:00:00 2001 From: Noam Postavsky Date: Sat, 10 Mar 2018 18:12:55 -0500 Subject: [PATCH v2 2/2] Improve errors & warnings due to fancy quoted vars (Bug#32939) Add some hints to the message for byte compiler free & unused variable warnings, and 'void-variable' errors where the variable has confusable quote characters in it. * lisp/help.el (uni-confusables), uni-confusables-regexp): New constants. (help-command-error-confusable-suggestions): New function, added to `command-error-function'. (help-uni-confusable-suggestions): New function. * lisp/emacs-lisp/bytecomp.el (byte-compile-variable-ref): * lisp/emacs-lisp/cconv.el (cconv--analyze-use): Use it. * lisp/emacs-lisp/lisp-mode.el (lisp--match-confusable-symbol-character): New function. (lisp-fdefs): Use it to fontify confusable characters with font-lock-warning-face when they occur in symbol names. * etc/NEWS: Announce the new fontification behavior. --- etc/NEWS | 4 ++++ lisp/emacs-lisp/bytecomp.el | 10 +++++++-- lisp/emacs-lisp/cconv.el | 6 ++++-- lisp/emacs-lisp/lisp-mode.el | 16 ++++++++++++++- lisp/help.el | 49 ++++++++++++++++++++++++++++++++++++++++= ++++ 5 files changed, 80 insertions(+), 5 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 8bed92430b..3f86195695 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1089,6 +1089,10 @@ and if the new behavior breaks your code please email 32252@debbugs.gnu.org. Because %o and %x can now format signed integers, they now support the + and space flags. =20 +** In Emacs Lisp mode, symbols with confusable quotes are highlighted. +For example, the first character in '=E2=80=98foo' would be highlighted in +'font-lock-warning-face'. + +++ ** Omitting variables after '&optional' and '&rest' is now allowed. For example (defun foo (&optional)) is no longer an error. This is diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 8b67e1007d..31d589ab02 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -3407,7 +3407,10 @@ byte-compile-variable-ref (boundp var) (memq var byte-compile-bound-variables) (memq var byte-compile-free-references)) - (byte-compile-warn "reference to free variable `%S'" var) + (let* ((varname (prin1-to-string var)) + (suggestions (help-uni-confusable-suggestions varname))) + (byte-compile-warn "reference to free variable `%s'%s" varname + (if suggestions (concat "\n " suggestions) "= "))) (push var byte-compile-free-references)) (byte-compile-dynamic-variable-op 'byte-varref var)))) =20 @@ -3423,7 +3426,10 @@ byte-compile-variable-set (boundp var) (memq var byte-compile-bound-variables) (memq var byte-compile-free-assignments)) - (byte-compile-warn "assignment to free variable `%s'" var) + (let* ((varname (prin1-to-string var)) + (suggestions (help-uni-confusable-suggestions varname))) + (byte-compile-warn "assignment to free variable `%s'%s" varname + (if suggestions (concat "\n " suggestions) "= "))) (push var byte-compile-free-assignments)) (byte-compile-dynamic-variable-op 'byte-varset var)))) =20 diff --git a/lisp/emacs-lisp/cconv.el b/lisp/emacs-lisp/cconv.el index 010026b416..b62c69868b 100644 --- a/lisp/emacs-lisp/cconv.el +++ b/lisp/emacs-lisp/cconv.el @@ -591,8 +591,10 @@ cconv--analyze-use (eq ?_ (aref (symbol-name var) 0)) ;; As a special exception, ignore "ignore". (eq var 'ignored)) - (byte-compile-warn "Unused lexical %s `%S'" - varkind var))) + (let ((suggestions (help-uni-confusable-suggestions (symbol-name va= r)))) + (byte-compile-warn "Unused lexical %s `%S'%s" + varkind var + (if suggestions (concat "\n " suggestions) ""= ))))) ;; If it's unused, there's no point converting it into a cons-cell, ev= en if ;; it's captured and mutated. (`(,binder ,_ t t ,_) diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index f31b4d4dd2..87bdafa976 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el @@ -280,6 +280,17 @@ elisp--font-lock-backslash `(face ,font-lock-warning-face help-echo "This \\ has no effect")))) =20 +(defun lisp--match-confusable-symbol-character (limit) + ;; Match a confusable character within a Lisp symbol. + (catch 'matched + (while t + (if (not (re-search-forward uni-confusables-regexp limit t)) + (throw 'matched nil) + ;; Skip confusables inside strings or comments. + (save-match-data + (if (not (nth 8 (syntax-ppss))) + (throw 'matched t))))))) + (let-when-compile ((lisp-fdefs '("defmacro" "defun")) (lisp-vdefs '("defvar")) @@ -463,7 +474,10 @@ elisp--font-lock-backslash (3 'font-lock-regexp-grouping-construct prepend)) (lisp--match-hidden-arg (0 '(face font-lock-warning-face - help-echo "Hidden behind deeper element; move to another li= ne?"))) + help-echo "Hidden behind deeper element; move to anoth= er line?"))) + (lisp--match-confusable-symbol-character + 0 '(face font-lock-warning-face + help-echo "Confusable character")) )) "Gaudy level highlighting for Emacs Lisp mode.") =20 diff --git a/lisp/help.el b/lisp/help.el index 6e06fc9e1c..2cc28fca24 100644 --- a/lisp/help.el +++ b/lisp/help.el @@ -1489,6 +1489,55 @@ help--make-usage-docstring (help--docstring-quote (format "%S" (help--make-usage fn arglist))))) =20 + +;; Just some quote-like characters for now. TODO: generate this stuff +;; from official Unicode data. +(defconst uni-confusables + '((#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 + )) + +(defconst uni-confusables-regexp + (concat "[" (mapcar #'car uni-confusables) "]")) + +(defun help-uni-confusable-suggestions (string) + "Return a message describing confusables in STRING." + (let ((i 0) + (confusables nil)) + (while (setq i (string-match uni-confusables-regexp string i)) + (let ((replacement (alist-get (aref string i) uni-confusables))) + (push (aref string i) confusables) + (setq string (replace-match replacement t t string)) + (setq i (+ i (length replacement))))) + (when confusables + (format-message + (if (> (length confusables) 1) + "Found confusable characters: %s; perhaps you meant: `%s'?" + "Found confusable character: %s, perhaps you meant: `%s'?") + (mapconcat (lambda (c) (format-message "`%c'" c)) + confusables ", ") + string)))) + +(defun help-command-error-confusable-suggestions (data _context _signal) + (pcase data + (`(void-variable ,var) + (let ((suggestions (help-uni-confusable-suggestions + (symbol-name var)))) + (when suggestions + (princ (concat "\n " suggestions) t)))) + (_ nil))) + +(add-function :after command-error-function + #'help-command-error-confusable-suggestions) + + (provide 'help) =20 ;;; help.el ends here --=20 2.11.0 --=-=-=--