From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Newsgroups: gmane.emacs.bugs Subject: bug#55738: character escape bugs in the reader Date: Wed, 1 Jun 2022 12:00:21 +0200 Message-ID: <84CE3A6F-E487-4823-96CB-208C79EB235C@acm.org> References: <20BC6F3C-1C72-4469-946D-8B9583C73024@acm.org> Mime-Version: 1.0 (Mac OS X Mail 14.0 \(3654.120.0.1.13\)) Content-Type: multipart/mixed; boundary="Apple-Mail=_B2E9BE98-FFA7-4486-AB62-58F74E38D9E2" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="18741"; mail-complaints-to="usenet@ciao.gmane.io" To: 55738@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Wed Jun 01 12:01:32 2022 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1nwLAR-0004cc-EI for geb-bug-gnu-emacs@m.gmane-mx.org; Wed, 01 Jun 2022 12:01:31 +0200 Original-Received: from localhost ([::1]:45522 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nwLAQ-0008KC-3M for geb-bug-gnu-emacs@m.gmane-mx.org; Wed, 01 Jun 2022 06:01:30 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:42708) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nwL9y-0008H4-8j for bug-gnu-emacs@gnu.org; Wed, 01 Jun 2022 06:01:03 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:55868) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1nwL9x-0004Tq-Vy for bug-gnu-emacs@gnu.org; Wed, 01 Jun 2022 06:01:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1nwL9x-0006xQ-NW for bug-gnu-emacs@gnu.org; Wed, 01 Jun 2022 06:01:01 -0400 X-Loop: help-debbugs@gnu.org In-Reply-To: <20BC6F3C-1C72-4469-946D-8B9583C73024@acm.org> Resent-From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Wed, 01 Jun 2022 10:01:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 55738 X-GNU-PR-Package: emacs Original-Received: via spool by 55738-submit@debbugs.gnu.org id=B55738.165407763026687 (code B ref 55738); Wed, 01 Jun 2022 10:01:01 +0000 Original-Received: (at 55738) by debbugs.gnu.org; 1 Jun 2022 10:00:30 +0000 Original-Received: from localhost ([127.0.0.1]:49765 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nwL9S-0006wM-5P for submit@debbugs.gnu.org; Wed, 01 Jun 2022 06:00:30 -0400 Original-Received: from mail176c50.megamailservers.eu ([91.136.10.186]:44318 helo=mail37c50.megamailservers.eu) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nwL9O-0006wA-Iw for 55738@debbugs.gnu.org; Wed, 01 Jun 2022 06:00:28 -0400 X-Authenticated-User: mattiase@bredband.net DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=megamailservers.eu; s=maildub; t=1654077624; bh=m0Vcst+2T/jZyV4YTADKiX1UKZQeUN0Xb/wuUDRrzuY=; h=From:Subject:Date:To:From; b=innBPb63p6TTXbXMj9wQkYlyRoDL47l9TxwxDhdoeKuaAJtkrXcbDCaQUE8ID5ynG Bxgxe88wIlUwAuc8HMdIwA7kxDzcTBKe5yb4kO5E4RUET6XBuChnBnKhxIN+BBNeZ+ 316ig9ZhHDHrnGmyqeANxlyEMWcTaC1ukyztRSwo= Feedback-ID: mattiase@acm.or Original-Received: from smtpclient.apple (c188-150-171-71.bredband.tele2.se [188.150.171.71]) (authenticated bits=0) by mail37c50.megamailservers.eu (8.14.9/8.13.1) with ESMTP id 251A0MQU027869 for <55738@debbugs.gnu.org>; Wed, 1 Jun 2022 10:00:23 +0000 X-Mailer: Apple Mail (2.3654.120.0.1.13) X-CTCH-RefID: str=0001.0A742F1F.629738B8.0027, ss=1, re=0.000, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0 X-CTCH-VOD: Unknown X-CTCH-Spam: Unknown X-CTCH-Score: 0.000 X-CTCH-Flags: 0 X-CTCH-ScoreCust: 0.000 X-Origin-Country: SE X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list 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-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:233481 Archived-At: --Apple-Mail=_B2E9BE98-FFA7-4486-AB62-58F74E38D9E2 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=us-ascii Suggested patch. It does not address the third bug above (\C-SPC). --Apple-Mail=_B2E9BE98-FFA7-4486-AB62-58F74E38D9E2 Content-Disposition: attachment; filename=0001-Fix-reader-char-escape-bugs-bug-55738.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="0001-Fix-reader-char-escape-bugs-bug-55738.patch" Content-Transfer-Encoding: quoted-printable =46rom=20801c6789d753eb1d94adec95af76e6c28dc27e21=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20=3D?UTF-8?q?Mattias=3D20Engdeg=3DC3=3DA5rd?=3D=20= =0ADate:=20Wed,=201=20Jun=202022=2011:39:44=20+0200=0A= Subject:=20[PATCH]=20Fix=20reader=20char=20escape=20bugs=20(bug#55738)=0A= =0AMake=20the=20character=20literal=20?\LF=20(linefeed)=20generate=2010,=20= not=20-1.=0A=0AEnsure=20that=20Control=20escape=20sequences=20in=20= character=20literals=20are=0Aidempotent:=20?\C-\C-a=20and=20?\^\^a=20= mean=20the=20same=20thing=20as=20?\C-a=20and=20?\^a,=0Agenerating=20the=20= control=20character=20with=20value=201.=20=20"\C-\C-a"=20no=20longer=0A= signals=20an=20error.=0A=0A*=20src/lread.c=20(read_escape):=20Make=20= nonrecursive=20and=20only=20combine=0Athe=20base=20char=20with=20= modifiers=20at=20the=20end,=20creating=20control=20chars=0Aif=20= applicable.=20=20Remove=20the=20`stringp`=20argument;=20assume=20= character=0Aliteral=20syntax.=20=20Never=20return=20-1.=0A= (read_string_literal):=20Handle=20string-specific=20escape=20semantics=20= here=0Aand=20simplify.=0A*=20test/src/lread-tests.el=20(lread-misc-2):=20= New=20test.=0A---=0A=20src/lread.c=20=20=20=20=20=20=20=20=20=20=20=20=20= |=20201=20++++++++++++++++++++--------------------=0A=20= test/src/lread-tests.el=20|=20=2010=20++=0A=202=20files=20changed,=20112=20= insertions(+),=2099=20deletions(-)=0A=0Adiff=20--git=20a/src/lread.c=20= b/src/lread.c=0Aindex=20a1045184d9..670413efc0=20100644=0A---=20= a/src/lread.c=0A+++=20b/src/lread.c=0A@@=20-2631,93=20+2631,88=20@@=20= character_name_to_code=20(char=20const=20*name,=20ptrdiff_t=20name_len,=0A= =20enum=20{=20UNICODE_CHARACTER_NAME_LENGTH_BOUND=20=3D=20200=20};=0A=20=0A= =20/*=20Read=20a=20\-escape=20sequence,=20assuming=20we=20already=20read=20= the=20`\'.=0A+=20=20=20When=20there=20is=20a=20difference=20between=20= string=20and=20character=20literal=20\-sequences,=0A+=20=20=20the=20= latter=20is=20assumed.=0A=20=20=20=20If=20the=20escape=20sequence=20= forces=20unibyte,=20return=20eight-bit=20char.=20=20*/=0A=20=0A=20static=20= int=0A-read_escape=20(Lisp_Object=20readcharfun,=20bool=20stringp)=0A= +read_escape=20(Lisp_Object=20readcharfun)=0A=20{=0A+=20=20int=20= modifiers=20=3D=200;=0A+=20again:=20;=0A=20=20=20int=20c=20=3D=20= READCHAR;=0A-=20=20/*=20\u=20allows=20up=20to=20four=20hex=20digits,=20= \U=20up=20to=20eight.=20=20Default=20to=20the=0A-=20=20=20=20=20behavior=20= for=20\u,=20and=20change=20this=20value=20in=20the=20case=20that=20\U=20= is=20seen.=20=20*/=0A-=20=20int=20unicode_hex_count=20=3D=204;=0A+=20=20= int=20unicode_hex_count;=0A=20=0A=20=20=20switch=20(c)=0A=20=20=20=20=20= {=0A=20=20=20=20=20case=20-1:=0A=20=20=20=20=20=20=20end_of_file_error=20= ();=0A=20=0A-=20=20=20=20case=20'a':=0A-=20=20=20=20=20=20return=20= '\007';=0A-=20=20=20=20case=20'b':=0A-=20=20=20=20=20=20return=20'\b';=0A= -=20=20=20=20case=20'd':=0A-=20=20=20=20=20=20return=200177;=0A-=20=20=20= =20case=20'e':=0A-=20=20=20=20=20=20return=20033;=0A-=20=20=20=20case=20= 'f':=0A-=20=20=20=20=20=20return=20'\f';=0A-=20=20=20=20case=20'n':=0A-=20= =20=20=20=20=20return=20'\n';=0A-=20=20=20=20case=20'r':=0A-=20=20=20=20=20= =20return=20'\r';=0A-=20=20=20=20case=20't':=0A-=20=20=20=20=20=20return=20= '\t';=0A-=20=20=20=20case=20'v':=0A-=20=20=20=20=20=20return=20'\v';=0A-=20= =20=20=20case=20'\n':=0A-=20=20=20=20=20=20return=20-1;=0A-=20=20=20=20= case=20'=20':=0A-=20=20=20=20=20=20if=20(stringp)=0A-=09return=20-1;=0A-=20= =20=20=20=20=20return=20'=20';=0A+=20=20=20=20case=20'a':=20c=20=3D=20= '\a';=20break;=0A+=20=20=20=20case=20'b':=20c=20=3D=20'\b';=20break;=0A+=20= =20=20=20case=20'd':=20c=20=3D=20127;=20break;=0A+=20=20=20=20case=20= 'e':=20c=20=3D=2027;=20break;=0A+=20=20=20=20case=20'f':=20c=20=3D=20= '\f';=20break;=0A+=20=20=20=20case=20'n':=20c=20=3D=20'\n';=20break;=0A+=20= =20=20=20case=20'r':=20c=20=3D=20'\r';=20break;=0A+=20=20=20=20case=20= 't':=20c=20=3D=20'\t';=20break;=0A+=20=20=20=20case=20'v':=20c=20=3D=20= '\v';=20break;=0A=20=0A=20=20=20=20=20case=20'M':=0A=20=20=20=20=20=20=20= c=20=3D=20READCHAR;=0A=20=20=20=20=20=20=20if=20(c=20!=3D=20'-')=0A=20=09= error=20("Invalid=20escape=20character=20syntax");=0A+=20=20=20=20=20=20= modifiers=20|=3D=20meta_modifier;=0A=20=20=20=20=20=20=20c=20=3D=20= READCHAR;=0A=20=20=20=20=20=20=20if=20(c=20=3D=3D=20'\\')=0A-=09c=20=3D=20= read_escape=20(readcharfun,=200);=0A-=20=20=20=20=20=20return=20c=20|=20= meta_modifier;=0A+=09goto=20again;=0A+=20=20=20=20=20=20break;=0A=20=0A=20= =20=20=20=20case=20'S':=0A=20=20=20=20=20=20=20c=20=3D=20READCHAR;=0A=20=20= =20=20=20=20=20if=20(c=20!=3D=20'-')=0A=20=09error=20("Invalid=20escape=20= character=20syntax");=0A+=20=20=20=20=20=20modifiers=20|=3D=20= shift_modifier;=0A=20=20=20=20=20=20=20c=20=3D=20READCHAR;=0A=20=20=20=20= =20=20=20if=20(c=20=3D=3D=20'\\')=0A-=09c=20=3D=20read_escape=20= (readcharfun,=200);=0A-=20=20=20=20=20=20return=20c=20|=20= shift_modifier;=0A+=09goto=20again;=0A+=20=20=20=20=20=20break;=0A=20=0A=20= =20=20=20=20case=20'H':=0A=20=20=20=20=20=20=20c=20=3D=20READCHAR;=0A=20=20= =20=20=20=20=20if=20(c=20!=3D=20'-')=0A=20=09error=20("Invalid=20escape=20= character=20syntax");=0A+=20=20=20=20=20=20modifiers=20|=3D=20= hyper_modifier;=0A=20=20=20=20=20=20=20c=20=3D=20READCHAR;=0A=20=20=20=20= =20=20=20if=20(c=20=3D=3D=20'\\')=0A-=09c=20=3D=20read_escape=20= (readcharfun,=200);=0A-=20=20=20=20=20=20return=20c=20|=20= hyper_modifier;=0A+=09goto=20again;=0A+=20=20=20=20=20=20break;=0A=20=0A=20= =20=20=20=20case=20'A':=0A=20=20=20=20=20=20=20c=20=3D=20READCHAR;=0A=20=20= =20=20=20=20=20if=20(c=20!=3D=20'-')=0A=20=09error=20("Invalid=20escape=20= character=20syntax");=0A+=20=20=20=20=20=20modifiers=20|=3D=20= alt_modifier;=0A=20=20=20=20=20=20=20c=20=3D=20READCHAR;=0A=20=20=20=20=20= =20=20if=20(c=20=3D=3D=20'\\')=0A-=09c=20=3D=20read_escape=20= (readcharfun,=200);=0A-=20=20=20=20=20=20return=20c=20|=20alt_modifier;=0A= +=09goto=20again;=0A+=20=20=20=20=20=20break;=0A=20=0A=20=20=20=20=20= case=20's':=0A=20=20=20=20=20=20=20c=20=3D=20READCHAR;=0A-=20=20=20=20=20= =20if=20(stringp=20||=20c=20!=3D=20'-')=0A+=20=20=20=20=20=20if=20(c=20= =3D=3D=20'-')=0A+=09{=0A+=09=20=20modifiers=20|=3D=20super_modifier;=0A+=09= =20=20c=20=3D=20READCHAR;=0A+=09=20=20if=20(c=20=3D=3D=20'\\')=0A+=09=20=20= =20=20goto=20again;=0A+=09}=0A+=20=20=20=20=20=20else=0A=20=09{=0A=20=09=20= =20UNREAD=20(c);=0A-=09=20=20return=20'=20';=0A+=09=20=20c=20=3D=20'=20= ';=0A=20=09}=0A-=20=20=20=20=20=20c=20=3D=20READCHAR;=0A-=20=20=20=20=20=20= if=20(c=20=3D=3D=20'\\')=0A-=09c=20=3D=20read_escape=20(readcharfun,=20= 0);=0A-=20=20=20=20=20=20return=20c=20|=20super_modifier;=0A+=20=20=20=20= =20=20break;=0A=20=0A=20=20=20=20=20case=20'C':=0A=20=20=20=20=20=20=20c=20= =3D=20READCHAR;=0A@@=20-2725,21=20+2720,11=20@@=20read_escape=20= (Lisp_Object=20readcharfun,=20bool=20stringp)=0A=20=09error=20("Invalid=20= escape=20character=20syntax");=0A=20=20=20=20=20=20=20FALLTHROUGH;=0A=20=20= =20=20=20case=20'^':=0A+=20=20=20=20=20=20modifiers=20|=3D=20= ctrl_modifier;=0A=20=20=20=20=20=20=20c=20=3D=20READCHAR;=0A=20=20=20=20=20= =20=20if=20(c=20=3D=3D=20'\\')=0A-=09c=20=3D=20read_escape=20= (readcharfun,=200);=0A-=20=20=20=20=20=20if=20((c=20&=20= ~CHAR_MODIFIER_MASK)=20=3D=3D=20'?')=0A-=09return=200177=20|=20(c=20&=20= CHAR_MODIFIER_MASK);=0A-=20=20=20=20=20=20else=20if=20(!=20ASCII_CHAR_P=20= ((c=20&=20~CHAR_MODIFIER_MASK)))=0A-=09return=20c=20|=20ctrl_modifier;=0A= -=20=20=20=20=20=20/*=20ASCII=20control=20chars=20are=20made=20from=20= letters=20(both=20cases),=0A-=09=20as=20well=20as=20the=20non-letters=20= within=200100...0137.=20=20*/=0A-=20=20=20=20=20=20else=20if=20((c=20&=20= 0137)=20>=3D=200101=20&&=20(c=20&=200137)=20<=3D=200132)=0A-=09return=20= (c=20&=20(037=20|=20~0177));=0A-=20=20=20=20=20=20else=20if=20((c=20&=20= 0177)=20>=3D=200100=20&&=20(c=20&=200177)=20<=3D=200137)=0A-=09return=20= (c=20&=20(037=20|=20~0177));=0A-=20=20=20=20=20=20else=0A-=09return=20c=20= |=20ctrl_modifier;=0A+=09goto=20again;=0A+=20=20=20=20=20=20break;=0A=20=0A= =20=20=20=20=20case=20'0':=0A=20=20=20=20=20case=20'1':=0A@@=20-2749,31=20= +2734,30=20@@=20read_escape=20(Lisp_Object=20readcharfun,=20bool=20= stringp)=0A=20=20=20=20=20case=20'5':=0A=20=20=20=20=20case=20'6':=0A=20=20= =20=20=20case=20'7':=0A-=20=20=20=20=20=20/*=20An=20octal=20escape,=20as=20= in=20ANSI=20C.=20=20*/=0A+=20=20=20=20=20=20/*=201-3=20octal=20digits.=20= =20*/=0A=20=20=20=20=20=20=20{=0A-=09register=20int=20i=20=3D=20c=20-=20= '0';=0A-=09register=20int=20count=20=3D=200;=0A+=09int=20i=20=3D=20c=20-=20= '0';=0A+=09int=20count=20=3D=200;=0A=20=09while=20(++count=20<=203)=0A=20= =09=20=20{=0A-=09=20=20=20=20if=20((c=20=3D=20READCHAR)=20>=3D=20'0'=20= &&=20c=20<=3D=20'7')=0A-=09=20=20=20=20=20=20{=0A-=09=09i=20*=3D=208;=0A= -=09=09i=20+=3D=20c=20-=20'0';=0A-=09=20=20=20=20=20=20}=0A-=09=20=20=20=20= else=0A+=09=20=20=20=20c=20=3D=20READCHAR;=0A+=09=20=20=20=20if=20(c=20<=20= '0'=20||=20c=20>=20'7')=0A=20=09=20=20=20=20=20=20{=0A=20=09=09UNREAD=20= (c);=0A=20=09=09break;=0A=20=09=20=20=20=20=20=20}=0A+=09=20=20=20=20i=20= *=3D=208;=0A+=09=20=20=20=20i=20+=3D=20c=20-=20'0';=0A=20=09=20=20}=0A=20= =0A=20=09if=20(i=20>=3D=200x80=20&&=20i=20<=200x100)=0A=20=09=20=20i=20=3D= =20BYTE8_TO_CHAR=20(i);=0A-=09return=20i;=0A+=09c=20=3D=20i;=0A+=09= break;=0A=20=20=20=20=20=20=20}=0A=20=0A=20=20=20=20=20case=20'x':=0A-=20= =20=20=20=20=20/*=20A=20hex=20escape,=20as=20in=20ANSI=20C.=20=20*/=0A+=20= =20=20=20=20=20/*=20One=20or=20more=20hex=20digits.=20=20*/=0A=20=20=20=20= =20=20=20{=0A=20=09unsigned=20int=20i=20=3D=200;=0A=20=09int=20count=20=3D= =200;=0A@@=20-2795,16=20+2779,18=20@@=20read_escape=20(Lisp_Object=20= readcharfun,=20bool=20stringp)=0A=20=09=20=20}=0A=20=0A=20=09if=20(count=20= <=203=20&&=20i=20>=3D=200x80)=0A-=09=20=20return=20BYTE8_TO_CHAR=20(i);=0A= -=09return=20i;=0A+=09=20=20i=20=3D=20BYTE8_TO_CHAR=20(i);=0A+=09c=20=3D=20= i;=0A+=09break;=0A=20=20=20=20=20=20=20}=0A=20=0A-=20=20=20=20case=20= 'U':=0A-=20=20=20=20=20=20/*=20Post-Unicode-2.0:=20Up=20to=20eight=20hex=20= chars.=20=20*/=0A+=20=20=20=20case=20'U':=09=09=09/*=20Eight=20hex=20= digits.=20=20*/=0A=20=20=20=20=20=20=20unicode_hex_count=20=3D=208;=0A-=20= =20=20=20=20=20FALLTHROUGH;=0A-=20=20=20=20case=20'u':=0A+=20=20=20=20=20= =20goto=20unicode;=0A=20=0A+=20=20=20=20case=20'u':=09=09=09/*=20Four=20= hex=20digits.=20=20*/=0A+=20=20=20=20=20=20unicode_hex_count=20=3D=204;=0A= +=20=20=20=20unicode:=0A=20=20=20=20=20=20=20/*=20A=20Unicode=20escape.=20= =20We=20only=20permit=20them=20in=20strings=20and=20characters,=0A=20=09=20= not=20arbitrarily=20in=20the=20source=20code,=20as=20in=20some=20other=20= languages.=20=20*/=0A=20=20=20=20=20=20=20{=0A@@=20-2815,12=20+2801,8=20= @@=20read_escape=20(Lisp_Object=20readcharfun,=20bool=20stringp)=0A=20=09= =20=20{=0A=20=09=20=20=20=20c=20=3D=20READCHAR;=0A=20=09=20=20=20=20if=20= (c=20<=200)=0A-=09=20=20=20=20=20=20{=0A-=09=09if=20(unicode_hex_count=20= >=204)=0A-=09=09=20=20error=20("Malformed=20Unicode=20escape:=20\\U%x",=20= i);=0A-=09=09else=0A-=09=09=20=20error=20("Malformed=20Unicode=20escape:=20= \\u%x",=20i);=0A-=09=20=20=20=20=20=20}=0A+=09=20=20=20=20=20=20error=20= ("Malformed=20Unicode=20escape:=20\\%c%x",=0A+=09=09=20=20=20=20=20= unicode_hex_count=20=3D=3D=204=20?=20'u'=20:=20'U',=20i);=0A=20=09=20=20=20= =20/*=20`isdigit'=20and=20`isalpha'=20may=20be=20locale-specific,=20= which=20we=20don't=0A=20=09=20=20=20=20=20=20=20want.=20=20*/=0A=20=09=20= =20=20=20int=20digit=20=3D=20char_hexdigit=20(c);=0A@@=20-2831,7=20= +2813,8=20@@=20read_escape=20(Lisp_Object=20readcharfun,=20bool=20= stringp)=0A=20=09=20=20}=0A=20=09if=20(i=20>=200x10FFFF)=0A=20=09=20=20= error=20("Non-Unicode=20character:=200x%x",=20i);=0A-=09return=20i;=0A+=09= c=20=3D=20i;=0A+=09break;=0A=20=20=20=20=20=20=20}=0A=20=0A=20=20=20=20=20= case=20'N':=0A@@=20-2880,12=20+2863,31=20@@=20read_escape=20(Lisp_Object=20= readcharfun,=20bool=20stringp)=0A=20=0A=20=09/*=20character_name_to_code=20= can=20invoke=20read0,=20recursively.=0A=20=09=20=20=20This=20is=20why=20= read0's=20buffer=20is=20not=20static.=20=20*/=0A-=09return=20= character_name_to_code=20(name,=20length,=20readcharfun);=0A+=09c=20=3D=20= character_name_to_code=20(name,=20length,=20readcharfun);=0A+=09break;=0A= =20=20=20=20=20=20=20}=0A+=20=20=20=20}=0A=20=0A-=20=20=20=20default:=0A= -=20=20=20=20=20=20return=20c;=0A+=20=20c=20|=3D=20modifiers;=0A+=20=20= if=20(c=20&=20ctrl_modifier)=0A+=20=20=20=20{=0A+=20=20=20=20=20=20int=20= b=20=3D=20c=20&=20~CHAR_MODIFIER_MASK;=0A+=20=20=20=20=20=20/*=20If=20= the=20base=20char=20is=20in=20the=200x3f..0x5f=20range=20or=20a=20lower=20= case=0A+=09=20letter,=20drop=20the=20ctrl_modifier=20bit=20and=20= generate=20a=20C0=20control=0A+=09=20character=20instead.=20=20*/=0A+=20=20= =20=20=20=20if=20((b=20>=3D=200x3f=20&&=20b=20<=3D=200x5f)=20||=20(b=20= >=3D=20'a'=20&&=20b=20<=3D=20'z'))=0A+=09{=0A+=09=20=20c=20&=3D=20= ~ctrl_modifier;=0A+=09=20=20if=20(b=20=3D=3D=20'?')=0A+=09=20=20=20=20/*=20= Special=20case:=20^?=20is=20DEL.=20=20*/=0A+=09=20=20=20=20b=20=3D=20= 127;=0A+=09=20=20else=0A+=09=20=20=20=20/*=20Make=20a=20C0=20control=20= in=200..31=20by=20clearing=20bits=205=20and=206.=20=20*/=0A+=09=20=20=20=20= b=20&=3D=200x1f;=0A+=09}=0A+=20=20=20=20=20=20c=20=3D=20b=20|=20(c=20&=20= CHAR_MODIFIER_MASK);=0A=20=20=20=20=20}=0A+=20=20return=20c;=0A=20}=0A=20= =0A=20/*=20Return=20the=20digit=20that=20CHARACTER=20stands=20for=20in=20= the=20given=20BASE.=0A@@=20-3012,7=20+3014,7=20@@=20read_char_literal=20= (Lisp_Object=20readcharfun)=0A=20=20=20=20=20}=0A=20=0A=20=20=20if=20(ch=20= =3D=3D=20'\\')=0A-=20=20=20=20ch=20=3D=20read_escape=20(readcharfun,=20= 0);=0A+=20=20=20=20ch=20=3D=20read_escape=20(readcharfun);=0A=20=0A=20=20= =20int=20modifiers=20=3D=20ch=20&=20CHAR_MODIFIER_MASK;=0A=20=20=20ch=20= &=3D=20~CHAR_MODIFIER_MASK;=0A@@=20-3066,14=20+3068,21=20@@=20= read_string_literal=20(char=20stackbuf[VLA_ELEMS=20(stackbufsize)],=0A=20= =0A=20=20=20=20=20=20=20if=20(ch=20=3D=3D=20'\\')=0A=20=09{=0A-=09=20=20= ch=20=3D=20read_escape=20(readcharfun,=201);=0A-=0A-=09=20=20/*=20CH=20= is=20-1=20if=20\=20newline=20or=20\=20space=20has=20just=20been=20seen.=20= =20*/=0A-=09=20=20if=20(ch=20=3D=3D=20-1)=0A+=09=20=20ch=20=3D=20= READCHAR;=0A+=09=20=20switch=20(ch)=0A=20=09=20=20=20=20{=0A+=09=20=20=20= =20case=20's':=0A+=09=20=20=20=20=20=20ch=20=3D=20'=20';=0A+=09=20=20=20=20= =20=20break;=0A+=09=20=20=20=20case=20'=20':=0A+=09=20=20=20=20case=20= '\n':=0A=20=09=20=20=20=20=20=20if=20(p=20=3D=3D=20read_buffer)=0A=20=09=09= cancel=20=3D=20true;=0A=20=09=20=20=20=20=20=20continue;=0A+=09=20=20=20=20= default:=0A+=09=20=20=20=20=20=20UNREAD=20(ch);=0A+=09=20=20=20=20=20=20= ch=20=3D=20read_escape=20(readcharfun);=0A+=09=20=20=20=20=20=20break;=0A= =20=09=20=20=20=20}=0A=20=0A=20=09=20=20int=20modifiers=20=3D=20ch=20&=20= CHAR_MODIFIER_MASK;=0A@@=20-3085,19=20+3094,13=20@@=20= read_string_literal=20(char=20stackbuf[VLA_ELEMS=20(stackbufsize)],=0A=20= =09=20=20=20=20force_multibyte=20=3D=20true;=0A=20=09=20=20else=09=09/*=20= I.e.=20ASCII_CHAR_P=20(ch).=20=20*/=0A=20=09=20=20=20=20{=0A-=09=20=20=20= =20=20=20/*=20Allow=20`\C-=20'=20and=20`\C-?'.=20=20*/=0A-=09=20=20=20=20= =20=20if=20(modifiers=20=3D=3D=20CHAR_CTL)=0A+=09=20=20=20=20=20=20/*=20= Allow=20`\C-SPC'=20and=20`\^SPC'.=20=20This=20is=20done=20here=20because=0A= +=09=09=20the=20literals=20?\C-SPC=20and=20?\^SPC=20(rather=20= inconsistently)=0A+=09=09=20yield=20('=20'=20|=20CHAR_CTL);=20see=20= bug#55738.=20=20*/=0A+=09=20=20=20=20=20=20if=20(modifiers=20=3D=3D=20= CHAR_CTL=20&&=20ch=20=3D=3D=20'=20')=0A=20=09=09{=0A-=09=09=20=20if=20= (ch=20=3D=3D=20'=20')=0A-=09=09=20=20=20=20{=0A-=09=09=20=20=20=20=20=20= ch=20=3D=200;=0A-=09=09=20=20=20=20=20=20modifiers=20=3D=200;=0A-=09=09=20= =20=20=20}=0A-=09=09=20=20else=20if=20(ch=20=3D=3D=20'?')=0A-=09=09=20=20= =20=20{=0A-=09=09=20=20=20=20=20=20ch=20=3D=20127;=0A-=09=09=20=20=20=20=20= =20modifiers=20=3D=200;=0A-=09=09=20=20=20=20}=0A+=09=09=20=20ch=20=3D=20= 0;=0A+=09=09=20=20modifiers=20=3D=200;=0A=20=09=09}=0A=20=09=20=20=20=20=20= =20if=20(modifiers=20&=20CHAR_SHIFT)=0A=20=09=09{=0Adiff=20--git=20= a/test/src/lread-tests.el=20b/test/src/lread-tests.el=0Aindex=20= 47351c1d11..59d5ca076f=20100644=0A---=20a/test/src/lread-tests.el=0A+++=20= b/test/src/lread-tests.el=0A@@=20-317,4=20+317,14=20@@=20lread-misc=0A=20= =20=20(should=20(equal=20(read-from-string=20"#_")=0A=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20'(##=20.=202))))=0A=20=0A+(ert-deftest=20= lread-misc-2=20()=0A+=20=20;;=20?\LF=20should=20produce=20LF=20(only=20= inside=20string=20literals=20do=20we=20ignore=20\LF).=0A+=20=20(should=20= (equal=20(read-from-string=20"?\\\n")=20'(?\n=20.=203)))=0A+=20=20= (should=20(equal=20(read-from-string=20"\"a\\\nb\"")=20'("ab"=20.=206)))=0A= +=20=20;;=20The=20Control=20modifier=20constructs=20should=20be=20= idempotent.=0A+=20=20(should=20(equal=20?\C-\C-x=20?\C-x))=0A+=20=20= (should=20(equal=20?\^\^x=20?\C-x))=0A+=20=20(should=20(equal=20?\C-\^x=20= ?\C-x))=0A+=20=20(should=20(equal=20?\^\C-x=20?\C-x)))=0A+=0A=20;;;=20= lread-tests.el=20ends=20here=0A--=20=0A2.32.0=20(Apple=20Git-132)=0A=0A= --Apple-Mail=_B2E9BE98-FFA7-4486-AB62-58F74E38D9E2--