From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.ciao.gmane.io!not-for-mail From: =?utf-8?Q?Mattias_Engdeg=C3=A5rd?= Newsgroups: gmane.emacs.devel Subject: Re: Regexp bytecode disassembler Date: Sat, 21 Mar 2020 17:52:51 +0100 Message-ID: <68FB4EC3-3C67-4D07-8473-5FC671024515@acm.org> References: <4201DF24-BCC4-4C08-9857-38207B7C10B4@acm.org> <83mu8bdriv.fsf@gnu.org> Mime-Version: 1.0 (Mac OS X Mail 12.4 \(3445.104.11\)) Content-Type: multipart/mixed; boundary="Apple-Mail=_B666AE44-4B1F-4801-9DEB-12C5E92A1CD4" Injection-Info: ciao.gmane.io; posting-host="ciao.gmane.io:159.69.161.202"; logging-data="108191"; mail-complaints-to="usenet@ciao.gmane.io" Cc: emacs-devel@gnu.org To: Eli Zaretskii Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Sat Mar 21 18:11:05 2020 Return-path: Envelope-to: ged-emacs-devel@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 1jFheK-000S0A-AC for ged-emacs-devel@m.gmane-mx.org; Sat, 21 Mar 2020 18:11:04 +0100 Original-Received: from localhost ([::1]:39190 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jFheJ-0000vV-Ba for ged-emacs-devel@m.gmane-mx.org; Sat, 21 Mar 2020 13:11:03 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:53721) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jFhde-0000D8-HK for emacs-devel@gnu.org; Sat, 21 Mar 2020 13:10:24 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1jFhdc-0002t9-Fx for emacs-devel@gnu.org; Sat, 21 Mar 2020 13:10:22 -0400 Original-Received: from mail1457c50.megamailservers.eu ([91.136.14.57]:39602 helo=mail267c50.megamailservers.eu) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1jFhdb-0002pW-P0 for emacs-devel@gnu.org; Sat, 21 Mar 2020 13:10:20 -0400 X-Authenticated-User: mattiase@bredband.net DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=megamailservers.eu; s=maildub; t=1584809574; bh=/2iw8MLL1TN4FfGSqIt+EJ+TQqjVX3SJFpj3EF9h80c=; h=From:Subject:Date:In-Reply-To:Cc:To:References:From; b=CeWflUqQiNLcidoGs6v3gzouQQX+qLSXi5vL+Huh6yhaht4Mo085WYpAXWDcxhqbd 7pXC1QuVtKSjGwuhtP2SSuIt4p9YS/E73HWcDSVdTeItwNe8BuO14MZjAf/Py1Y+7e acjptUsYPEbdmi6iau/kQtSQPAzYt8ZQhDcM1MJ4= Feedback-ID: mattiase@acm.or Original-Received: from stanniol.lan (c-6f4fe655.032-75-73746f71.bbcust.telenor.se [85.230.79.111]) (authenticated bits=0) by mail267c50.megamailservers.eu (8.14.9/8.13.1) with ESMTP id 02LGqpdp028273; Sat, 21 Mar 2020 16:52:53 +0000 In-Reply-To: <83mu8bdriv.fsf@gnu.org> X-Mailer: Apple Mail (2.3445.104.11) X-CTCH-RefID: str=0001.0A782F22.5E76464F.0032, 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-CSC: 0 X-CHA: v=2.3 cv=Cf92G4jl c=1 sm=1 tr=0 a=fHaj9vQUQVKQ4sUldAaXuQ==:117 a=fHaj9vQUQVKQ4sUldAaXuQ==:17 a=jpOVt7BSZ2e4Z31A5e1TngXxSK0=:19 a=M51BFTxLslgA:10 a=tBb2bbeoAAAA:8 a=mDV3o1hIAAAA:8 a=j7RV0LZqmf69_3iC1KAA:9 a=N1znxZMwIpnK9hRI:21 a=pDhRPmUqCGweSqK9:21 a=CjuIK1q_8ugA:10 a=TWhqyxVC8Q0bYoZRmfUA:9 a=B2y7HmGcmWMA:10 a=Oj-tNtZlA1e06AYgeCfH:22 a=_FVE-zBwftR9WsbkzFJk:22 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x (no timestamps) [generic] X-Received-From: 91.136.14.57 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.io gmane.emacs.devel:245634 Archived-At: --Apple-Mail=_B666AE44-4B1F-4801-9DEB-12C5E92A1CD4 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii 20 mars 2020 kl. 13.58 skrev Andreas Schwab : > This loop would create less garbage if you used '(no-op . 1) instead = of > (cons 'no-op 1). Thank you, we can't have that now can we. Fixed. 20 mars 2020 kl. 15.34 skrev Eli Zaretskii : > First, please document this in NEWS and in the ELisp manual. IMNSHO, > this feature will be much less useful without documentation. Sorry, I should have been clear on the point that this is primarily a = debug and maintenance aid for the regexp-engine developer and not = intended as a user-facing feature. Nobody is barred from using it, but = they are expected to read the circuit schematics that comes with Emacs = (ie, the source code). In particular, there is no user interface to the regexp bytecode at all; = users can't write program in it and have Emacs run them. It is also not = stable in the slightest. Documenting the inner workings of the regexp = engine would only put a burden on its maintainers. >> * src/search.c (Fregexp_bytecode): New function. >> (syms_of_search): Define the symbol. >=20 > Which symbol is that? I meant regexp-bytecode, sorry. Reworded. >> * lisp/emacs-lisp/regexp-disasm.el (regexp-disasm--classes) >> (regexp-disasm--syntax-codes, regexp-disasm, regexp-disassemble): = New. >=20 > This is a new file, so it is customary just to say "New file" without > listing the functions, which are all new. Understood and corrected. >> +;; Decode compiled Emacs regexp bytecode and pretty-print. >=20 > "Decode compiled Emacs regexp bytecode, and pretty-print them." Reworded. >> +(defconst regexp-disasm--classes >> + [word lower punct space upper multibyte alpha alnum graph print = blank] >> + "Vector of character classes, corresponding to BIT_* in = regex-emacs.c.") >=20 > This is one place where a more detailed description in the doc string > could be most beneficial. Expanded and made more precise. >> +(defconst regexp-disasm--syntax-codes >> + [whitespace punctuation word symbol >> + open-parenthesis close-parenthesis expression-prefix string-quote >> + paired-delimiter escape character-quote comment-start comment-end >> + inherit comment-delimiter string-delimiter] >> + "Vector of syntax codes, corresponding to enum syntaxcode in = syntax.h >> +but using names from `rx'.") >=20 > And this is another. (Btw, the first line should be a complete > sentence.) Fixed. > Any way to make sure these two get updated, or at least the build > displays an alert when the C sources are modified without also > updating the above defconst's? At the very least, we should have > comments in the C sources to the effect that any change there needs an > update here. I added comments to the C sources, since I was unsure about whether it = was worth the trouble to add Lisp accessors to the respective constants. = After all, if the definitions get out of sync, then regexp-disasm stops = working which isn't a disaster. >> +;;;###autoload >> +(defun regexp-disasm (regexp) >=20 > Why do we need to auto-load this? Actually, a function that returns the bytecode in symbolic form turned = out to be useful in its own right, and I found it handy for some = programmatic uses like comparing the bytecodes of two regexps. >> +Instructions are on the form (ADDRESS . INSTR) where ADDRESS is the > ^^^^^^^^^^^ > "of the form" Reworded. >> + (read-u16 (lambda (ofs) (+ (aref bc ofs) >> + (ash (aref bc (1+ ofs)) 8)))) >=20 > Why lambda-forms and not functions (or desfsubst)? Because they need to close over variables in scope. With lexical = binding, elisp almost feels like a real programming language! >> + (mb (multibyte-string-p regexp)) >=20 > Please use more self-describing names of variables. E.g., how about > multibyte-p in this case? Likewise regarding "bc". Agreed about mb, thanks. I'm keeping 'bc' because it's used everywhere, = and the shorthand definitely increases readability. >> + (str (if mb >> + (decode-coding-string raw = 'utf-8-emacs) >> + raw))) >=20 > This call to decode-coding-string needs a comment that explains why > it's needed. You are quite right, and decoding turned out to be more complicated as = well. Fixed. >> + (pcase opcode >> + (0 (cons 'no-op 1)) >> + (1 (cons 'succeed 1)) >=20 > Is pcase really needed here? It looks like a simple cond will do. Well, pcase is a lot more readable here, don't you think? >> + (_ (error "bad opcode at ofs %d: 0x%02x" i = opcode)))) > ^^^ > "offset", please, not "ofs". Right, thanks. >> +(defun regexp-disassemble (regexp) >> + "Compile REGEXP and print the disassembled bytecode." >=20 > I think the fact that it compiles PATTERN is an implementation > detail. The real purpose of this command is different. Can you > propose a better description of that purpose? Agreed, and rewritten. >> + (interactive "XRegexp (evaluated): ") >=20 > This prompt should do a better job describing what kind of input is > expected here. I'm not sure what else to say in the prompt. I found it more useful to = input the regexp as a lisp expression than a string (for cut-and-paste = from source code, or for rx) but maybe that's just me. >> +DEFUN ("regexp-bytecode", Fregexp_bytecode, Sregexp_bytecode, 1, 1, = 0, >> + doc: /* Compile REGEXP and return the compiled bytecode. >> +The compiled bytecode is returned as a string; its format is >> +implementation-dependent. Cached bytecode may be returned if = available. */) >=20 > Is this function useful on its own, or is it an internal API? If the > latter, let's use an internal notation for its name, and let's > document that it's an internal function. It's probably not useful for anything else. I made it internal. >> + struct regexp_cache *cache_entry =3D compile_pattern ( >> + regexp, >> + NULL, >> + (!NILP (BVAR (current_buffer, case_fold_search)) >> + ? BVAR (current_buffer, case_canon_table) : Qnil), >> + false, >> + true); >=20 > That's not our style of formatting such function calls. It is hard to > read. >=20 > And why are you using variables related to the current buffer here? You are right, the case folding is better made explicit. Fixed. Revised patch attached. --Apple-Mail=_B666AE44-4B1F-4801-9DEB-12C5E92A1CD4 Content-Disposition: attachment; filename=0001-Add-regexp-bytecode-disassembler.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="0001-Add-regexp-bytecode-disassembler.patch" Content-Transfer-Encoding: quoted-printable =46rom=2050daa712e6740a60bf73840f43b7c4a7d782523f=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20=3D?UTF-8?q?Mattias=3D20Engdeg=3DC3=3DA5rd?=3D=20= =0ADate:=20Tue,=2017=20Mar=202020=2015:09:10=20+0100=0A= Subject:=20[PATCH]=20Add=20regexp=20bytecode=20disassembler=0A=0AThis=20= is=20mainly=20intended=20as=20a=20regexp=20engine=20maintenance=20and=20= debugging=0Aaid.=20=20See=20discussion=20at=0A= https://lists.gnu.org/archive/html/emacs-devel/2020-03/msg00461.html=20.=0A= =0A*=20lisp/emacs-lisp/regexp-disasm.el:=20New=20file.=0A*=20= src/search.c=20(Finternal__regexp_bytecode):=20New=20function.=0A= (syms_of_search):=20Define=20it=20as=20Lisp=20function.=0A*=20= src/regex-emacs.c:=0A*=20src/syntax.h:=20Add=20comments=20to=20keep=20= definitions=20in=20sync=20with=0Aregexp-disasm.el.=0A---=0A=20= lisp/emacs-lisp/regexp-disasm.el=20|=20317=20= +++++++++++++++++++++++++++++++=0A=20src/regex-emacs.c=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20|=20=20=207=20+-=0A=20src/search.c=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20=2017=20++=0A=20= src/syntax.h=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= |=20=20=202=20+=0A=204=20files=20changed,=20341=20insertions(+),=202=20= deletions(-)=0A=20create=20mode=20100644=20= lisp/emacs-lisp/regexp-disasm.el=0A=0Adiff=20--git=20= a/lisp/emacs-lisp/regexp-disasm.el=20b/lisp/emacs-lisp/regexp-disasm.el=0A= new=20file=20mode=20100644=0Aindex=200000000000..4c467141e8=0A---=20= /dev/null=0A+++=20b/lisp/emacs-lisp/regexp-disasm.el=0A@@=20-0,0=20= +1,317=20@@=0A+;;;=20regexp-disasm=20--=20disassemble=20regexp=20= bytecode=20=20-*-=20lexical-binding:=20t=20-*-=0A+=0A+;;=20Copyright=20= (C)=202020=20Free=20Software=20Foundation,=20Inc.=0A+=0A+;;=20This=20= file=20is=20part=20of=20GNU=20Emacs.=0A+=0A+;;=20GNU=20Emacs=20is=20free=20= software:=20you=20can=20redistribute=20it=20and/or=20modify=0A+;;=20it=20= under=20the=20terms=20of=20the=20GNU=20General=20Public=20License=20as=20= published=20by=0A+;;=20the=20Free=20Software=20Foundation,=20either=20= version=203=20of=20the=20License,=20or=0A+;;=20(at=20your=20option)=20= any=20later=20version.=0A+=0A+;;=20GNU=20Emacs=20is=20distributed=20in=20= the=20hope=20that=20it=20will=20be=20useful,=0A+;;=20but=20WITHOUT=20ANY=20= WARRANTY;=20without=20even=20the=20implied=20warranty=20of=0A+;;=20= MERCHANTABILITY=20or=20FITNESS=20FOR=20A=20PARTICULAR=20PURPOSE.=20=20= See=20the=0A+;;=20GNU=20General=20Public=20License=20for=20more=20= details.=0A+=0A+;;=20You=20should=20have=20received=20a=20copy=20of=20= the=20GNU=20General=20Public=20License=0A+;;=20along=20with=20GNU=20= Emacs.=20=20If=20not,=20see=20.=0A+=0A= +;;;=20Commentary:=0A+=0A+;;=20Decode=20compiled=20Emacs=20regexp=20= bytecode,=20and=20pretty-print=20it.=0A+;;=20Effective=20use=20of=20this=20= code=20requires=20some=20knowledge=20of=20the=20internals=0A+;;=20of=20= the=20regexp=20engine.=20=20See=20re_opcode_t=20in=20regex-emacs.c.=0A+=0A= +(defconst=20regexp-disasm--classes=0A+=20=20[word=20lower=20punct=20= space=20upper=20multibyte=20alpha=20alnum=20graph=20print=20blank]=0A+=20= =20"Vector=20of=20character=20classes,=20corresponding=20to=20BIT_*=20in=20= regex-emacs.c.=0A+The=20vector=20index=20corresponds=20to=20the=20bit=20= number.")=0A+=0A+(defconst=20regexp-disasm--syntax-codes=0A+=20=20= [whitespace=20punctuation=20word=20symbol=0A+=20=20=20open-parenthesis=20= close-parenthesis=20expression-prefix=20string-quote=0A+=20=20=20= paired-delimiter=20escape=20character-quote=20comment-start=20= comment-end=0A+=20=20=20inherit=20comment-delimiter=20string-delimiter]=0A= +=20=20"Vector=20of=20syntax=20codes,=20corresponding=20to=20enum=20= syntaxcode=20in=20syntax.h.=0A+The=20vector=20index=20is=20the=20enum=20= value;=20the=20symbol=20names=20are=20from=20`rx'.")=0A+=0A+(defun=20= regexp-disasm--decode-multibyte=20(bytes)=0A+=20=20"Decode=20BYTES=20= from=20the=20internal=20string=20format=20to=20the=20string=20it=20= represents."=0A+=20=20;;=20Each=20raw=20byte=20in=20the=2080..ff=20range=20= is=20internally=20represented=20as=20the=0A+=20=20;;=20two=20bytes=20= 1100000x=2010xxxxxx,=20which=20are=20decoded=20as=20separate=20raw=20= bytes=0A+=20=20;;=20by=20utf-8-emacs,=20so=20we=20have=20to=20= post-process=20the=20results.=0A+=20=20(let*=20((s=20= (decode-coding-string=20bytes=20'utf-8-emacs))=0A+=20=20=20=20=20=20=20=20= =20(len=20(length=20s))=0A+=20=20=20=20=20=20=20=20=20(i=200)=0A+=20=20=20= =20=20=20=20=20=20(start=200)=0A+=20=20=20=20=20=20=20=20=20(parts=20= nil))=0A+=20=20=20=20(while=20(<=20i=20(1-=20len))=0A+=20=20=20=20=20=20= (if=20(and=20(<=3D=20#x3fffc0=20(aref=20s=20i)=20#x3fffc1)=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20(<=3D=20#x3fff80=20(aref=20s=20(1+=20= i))=20#x3fffbf))=0A+=20=20=20=20=20=20=20=20=20=20;;=20A=20pair=20of=20= chars=20representing=20a=20raw=20byte.=0A+=20=20=20=20=20=20=20=20=20=20= (progn=0A+=20=20=20=20=20=20=20=20=20=20=20=20(when=20(>=20i=20start)=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20(push=20(substring=20s=20= start=20i)=20parts))=0A+=20=20=20=20=20=20=20=20=20=20=20=20(push=20= (string=20(+=20#x3fff80=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(ash=20(logand=20(aref=20s=20i)=20= 1)=206)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(logand=20(aref=20s=20(1+=20i))=20#x3f)))=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20parts)=0A+=20=20=20=20=20= =20=20=20=20=20=20=20(setq=20start=20(+=20i=202))=0A+=20=20=20=20=20=20=20= =20=20=20=20=20(setq=20i=20start))=0A+=20=20=20=20=20=20=20=20(setq=20i=20= (1+=20i))))=0A+=20=20=20=20(when=20(>=20len=20start)=0A+=20=20=20=20=20=20= (push=20(substring=20s=20start)=20parts))=0A+=20=20=20=20(apply=20= #'concat=20(nreverse=20parts))))=0A+=0A+;;;###autoload=0A+(defun=20= regexp-disasm=20(regexp=20&optional=20case-table)=0A+=20=20"Disassemble=20= the=20bytecode=20for=20REGEXP;=20return=20list=20of=20instructions.=0A= +CASE-TABLE,=20if=20non-nil,=20is=20a=20translation=20table=20for=20= case-folding.=0A+Instructions=20take=20the=20form=20(ADDRESS=20.=20= INSTR)=20where=20ADDRESS=20is=20the=0A+byte=20offset=20and=20INSTR=20an=20= S-expression=20representing=20the=20instruction."=0A+=20=20(let*=20((bc=20= (internal--regexp-bytecode=20regexp=20case-table))=0A+=20=20=20=20=20=20=20= =20=20(read-u16=20(lambda=20(ofs)=20(+=20(aref=20bc=20ofs)=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20(ash=20(aref=20bc=20(1+=20ofs))=208))))=0A+=20=20=20= =20=20=20=20=20=20(read-u24=20(lambda=20(ofs)=20(+=20(aref=20bc=20ofs)=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(ash=20(aref=20bc=20(+=20ofs=201))=20= 8)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(ash=20(aref=20bc=20(+=20ofs=20= 2))=2016))))=0A+=20=20=20=20=20=20=20=20=20(read-s16=20(lambda=20(ofs)=20= (let=20((x=20(funcall=20read-u16=20ofs)))=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (-=20x=20(ash=20(logand=20x=20#x8000)=201)))))=0A+=20=20=20=20=20=20=20=20= =20(len=20(length=20bc))=0A+=20=20=20=20=20=20=20=20=20(i=200)=0A+=20=20=20= =20=20=20=20=20=20(entries=20nil))=0A+=20=20=20=20(while=20(<=20i=20len)=0A= +=20=20=20=20=20=20;;=20This=20code=20depends=20on=20the=20exact=20= details=20of=20the=20regexp=20bytecode=0A+=20=20=20=20=20=20;;=20= representation;=20see=20re_opcode_t=20in=20regex-emacs.c.=0A+=20=20=20=20= =20=20(let*=20((opcode=20(aref=20bc=20i))=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20(entry-and-size=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (pcase=20opcode=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(0=20= '(no-op=20.=201))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (1=20'(succeed=20.=201))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20(2=20(let*=20((nbytes=20(aref=20bc=20(1+=20i)))=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(raw=20= (substring=20bc=20(+=20i=202)=20(+=20i=202=20nbytes)))=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20= Exact=20strings=20are=20multibyte-coded=20iff=20the=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20= original=20regexp=20is.=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20(str=20(if=20(multibyte-string-p=20= regexp)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (regexp-disasm--decode-multibyte=20raw)=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= raw)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20(cons=20(list=20'exact=20str)=20(+=202=20nbytes))))=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(3=20'(not-newline=20.=201))=20=20=20= =20=20=20=20=20;=20`anychar'=20is=20a=20misnomer=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20((or=204=205)=20=20=20=20=20=20=20=20=20=20= =20=20=20=20;=20`charset',=20`charset-not'=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(let*=20((negated=20(=3D=20opcode=205))=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (bitmap-len-raw=20(aref=20bc=20(1+=20i)))=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(bitmap-len=20(logand=20= bitmap-len-raw=20#x7f))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(have-range-table=20(/=3D=20(logand=20= bitmap-len-raw=20#x80)=200))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20(npairs=20(if=20have-range-table=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(funcall=20read-u16=20(+=20i=202=20= bitmap-len=202))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=200))=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (bitmap-pairs=20nil)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(classes=20nil)=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(pairs=20nil))=0A+=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20Convert=20the=20= bitmap=20to=20ranges.=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(let=20((first=20nil))=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(dotimes=20(j=20(*=20bitmap-len=208))=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(if=20= (/=3D=20(logand=20(aref=20bc=20(+=20i=202=20(ash=20j=20-3)))=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(ash=201=20(logand=20j=207)))=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=200)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(unless=20first=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(setq=20= first=20j))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20(when=20first=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(push=20(cons=20first=20(1-=20= j))=20bitmap-pairs)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20(setq=20first=20nil))))=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(when=20first=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(push=20= (cons=20first=20(1-=20(*=20bitmap-len=208)))=20bitmap-pairs)))=0A+=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(when=20= have-range-table=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20;;=20Convert=20class=20bits=20to=20list=20of=20classes.=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let=20= ((class-bits=20(funcall=20read-u16=20(+=20i=202=20bitmap-len))))=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (dotimes=20(j=20(length=20regexp-disasm--classes))=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(when=20(/=3D=20= (logand=20class-bits=20(ash=201=20j))=200)=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(push=20(aref=20= regexp-disasm--classes=20j)=20classes))))=0A+=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20Read=20range=20table.=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(dotimes=20= (j=20npairs)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(let*=20((ofs=20(+=20i=202=20bitmap-len=204=20(*=20j=20= 6)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(from=20(funcall=20read-u24=20ofs))=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(to=20=20=20(funcall=20read-u24=20(+=20ofs=203))))=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(push=20= (cons=20from=20to)=20pairs))))=0A+=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(cons=20(list=20(if=20negated=20'charset-not=20= 'charset)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(nreverse=20bitmap-pairs)=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(nreverse=20classes)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(nreverse=20= pairs))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(+=202=20bitmap-len=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(if=20= have-range-table=204=200)=20(*=20npairs=206)))))=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(6=20(cons=20(list=20'start-memory=20(aref=20= bc=20(1+=20i)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=202))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(7=20(cons=20(list=20'stop-memory=20(aref=20bc=20(1+=20i)))=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= 2))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(8=20(cons=20= (list=20'duplicate=20(aref=20bc=20(1+=20i)))=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=202))=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(9=20'(begline=20.=201))=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(10=20'(endline=20.=201))=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(11=20'(begbuf=20.=201))=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(12=20'(endbuf=20.=20= 1))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(13=20(cons=20= (list=20'jump=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(+=20(funcall=20read-s16=20(1+=20= i))=20i=203))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=203))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(14=20(cons=20(list=20'on-failure-jump=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (+=20(funcall=20read-s16=20(1+=20i))=20i=203))=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=203))=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(15=20(cons=20(list=20= 'on-failure-keep-string-jump=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(+=20(funcall=20= read-s16=20(1+=20i))=20i=203))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=203))=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(16=20(cons=20(list=20'on-failure-jump-loop=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(+=20(funcall=20read-s16=20(1+=20i))=20i=20= 3))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=203))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (17=20(cons=20(list=20'on-failure-jump-nastyloop=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20(+=20(funcall=20read-s16=20(1+=20i))=20i=203))=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=203))=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(18=20(cons=20(list=20= 'on-failure-jump-smart=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(+=20(funcall=20= read-s16=20(1+=20i))=20i=203))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=203))=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(19=20(cons=20(list=20'succeed-n=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(+=20(funcall=20read-s16=20(1+=20i))=20i=203)=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(funcall=20read-u16=20(+=20i=203)))=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=205))=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(20=20(cons=20(list=20'jump-n=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(+=20(funcall=20read-s16=20(1+=20i))=20i=203)=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(funcall=20read-u16=20(+=20i=203)))=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= 5))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(21=20(cons=20= (list=20'set-number-at=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(+=20(funcall=20= read-s16=20(1+=20i))=20i=203)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(funcall=20= read-u16=20(+=20i=203)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=205))=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20(22=20'(wordbeg=20.=201))=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(23=20'(wordend=20.=201))=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20(24=20'(wordbound=20.=201))=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(25=20'(notwordbound=20.=201))=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(26=20'(symbeg=20.=20= 1))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(27=20'(symend=20= .=201))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20Use=20= symbolic=20names=20for=20syntax=20classes.=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(28=20(cons=20(list=20'syntaxspec=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(aref=20regexp-disasm--syntax-codes=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20(aref=20bc=20(1+=20i))))=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=202))=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(29=20(cons=20(list=20= 'notsyntaxspec=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(aref=20= regexp-disasm--syntax-codes=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (aref=20bc=20(1+=20i))))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=202))=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20(30=20'(at-dot=20.=201))=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20;;=20Use=20the=20category=20code=20char=20for=20= categories.=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(31=20= (cons=20(list=20'categoryspec=20(aref=20bc=20(1+=20i)))=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=202))=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(32=20(cons=20(list=20= 'notcategoryspec=20(aref=20bc=20(1+=20i)))=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=202))=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(_=20(error=20"bad=20opcode=20at=20= offset=20%d:=200x%02x"=20i=20opcode))))=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20(entry=20(car=20entry-and-size))=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20(size=20(cdr=20entry-and-size)))=0A+=20=20=20=20=20=20=20=20= (push=20(cons=20i=20entry)=20entries)=0A+=20=20=20=20=20=20=20=20(setq=20= i=20(+=20i=20size))))=0A+=20=20=20=20(nreverse=20entries)))=0A+=0A= +;;;###autoload=0A+(defun=20regexp-disassemble=20(regexp=20&optional=20= case-table)=0A+=20=20"Print=20the=20disassembled=20bytecode=20for=20= REGEXP.=0A+If=20CASE-TABLE=20is=20non-nil,=20use=20it=20as=20translation=20= table=20for=20case-folding.=0A+=0A+Cached=20bytecode=20is=20returned=20= if=20available.=20=20Since=20a=20compiled=20regexp=20can=0A+be=20= modified=20when=20it=20is=20used=20in=20matching,=20the=20exact=20output=20= of=20this=20function=0A+may=20vary,=20but=20it=20should=20be=20= operationally=20equivalent."=0A+=20=20(interactive=20"XRegexp=20= (evaluated):=20")=0A+=20=20(let*=20((instructions=20(regexp-disasm=20= regexp=20case-table))=0A+=20=20=20=20=20=20=20=20=20(control-chars=20= '((?\b=20.=20?b)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(?\t=20.=20?t)=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(?\n=20.=20?n)=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(?\v=20= .=20?v)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(?\f=20.=20?f)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(?\r=20.=20?r)=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(?\e=20.=20= ?e)))=0A+=20=20=20=20=20=20=20=20=20(quote-byte=20(lambda=20(c)=0A+=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let=20= ((esc=20(assq=20c=20control-chars)))=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(cond=20(esc=20(string=20?\\=20= (cdr=20esc)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20((or=20(<=3D=20c=2031)=20(<=3D=20= #x7f=20c=20#xff))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(format=20"\\%03o"=20c))=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(t=20(string=20c))))))=0A+=20=20=20=20=20=20=20=20=20= (quote-string-char=20(lambda=20(c)=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(let=20((esc=20= (assq=20c=20control-chars)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(cond=20(esc=20= (string=20?\\=20(cdr=20esc)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= ((memq=20c=20'(?\\=20?\"))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (string=20?\\=20c))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20((or=20= (<=3D=20c=2031)=20(=3D=20c=20127)=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20(>=3D=20c=20#x3fff80))=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20(format=20"\\%03o"=20(logand=20c=20#xff)))=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(t=20(string=20c))))))=0A+=20=20=20=20=20=20=20=20= =20(quote-string=20(lambda=20(s)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(concat=20"\""=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20(mapconcat=20quote-string-char=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20;;=20Make=20multibyte,=20to=20distinguish=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20raw=20chars=20from=20= U+0080..00ff.=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (string-to-multibyte=20s)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20"")=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20"\"")))=0A+=20=20=20=20=20=20= =20=20=20(quote-range=20(lambda=20(range=20quote-char)=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(if=20(eq=20= (car=20range)=20(cdr=20range))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(funcall=20quote-char=20= (car=20range))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20(format=20"%s-%s"=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (funcall=20quote-char=20(car=20range))=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (funcall=20quote-char=20(cdr=20range))))))=0A+=20=20=20=20=20=20=20=20=20= (quote-range-uni=0A+=20=20=20=20=20=20=20=20=20=20(lambda=20(range)=20= (funcall=20quote-range=20range=20quote-byte)))=0A+=20=20=20=20=20=20=20=20= =20(quote-range-multi=0A+=20=20=20=20=20=20=20=20=20=20(lambda=20(range)=20= (funcall=20quote-range=20range=20#'string))))=0A+=20=20=20=20= (with-output-to-temp-buffer=20"*Regexp-disassemble*"=0A+=20=20=20=20=20=20= (with-current-buffer=20standard-output=0A+=20=20=20=20=20=20=20=20= (insert=20(format=20"Disassembly=20of=20regexp=20%s\n\n"=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(funcall=20= quote-string=20regexp)))=0A+=20=20=20=20=20=20=20=20(dolist=20(instr=20= instructions)=0A+=20=20=20=20=20=20=20=20=20=20(let*=20((addr=20(car=20= instr))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(op=20(cdr=20= instr))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(line=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(pcase=20op=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20((pred=20symbolp)=20= (symbol-name=20op))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(`(exact=20,s)=20(format=20"exact=20%s"=20(funcall=20= quote-string=20s)))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20(`(,(or=20'charset=20'charset-not)=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20,bitmap-pairs=20,classes=20= ,pairs)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= ;;=20FIXME:=20Maybe=20use=20a=20less=20ambiguous=20charset=20syntax.=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20;;=20Avoid=20= ranges=20when=20endpoints=20are=20adjacent.=0A+=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20;;=20What=20to=20do=20about=20= metachars=20like=20`]'=20and=20`-'?=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20(concat=20(format=20"%s=20[%s]"=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20(car=20op)=0A+=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (mapconcat=20quote-range-uni=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20bitmap-pairs=20""))=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(and=20= classes=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20(concat=20"=20[:"=0A+=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(mapconcat=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20#'symbol-name=20classes=20",")=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20":]"))=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(and=20= pairs=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20(concat=20"=20["=0A+=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20(mapconcat=20quote-range-multi=20pairs=20= "")=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20"]"))))=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(`(,(or=20= 'start-memory=20'stop-memory=20'duplicate)=20,n)=0A+=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20(format=20"%s=20group=20%d"=20= (car=20op)=20n))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20(`(,(or=20'jump=20'on-failure-jump=20'on-failure-keep-string-jump=0A= +=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20'on-failure-jump-loop=20'on-failure-jump-nastyloop=0A+=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= 'on-failure-jump-smart)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20,dest)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20(format=20"%s=20to=20%d"=20(car=20op)=20dest))=0A+=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(`(,(or=20= 'succeed-n=20'jump-n)=20,dest=20,val)=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(format=20"%s=20to=20%d,=20value=20%d"=20= (car=20op)=20dest=20val))=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20(`(set-number-at=20,dest=20,val)=0A+=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20;;=20We=20adjust=20the=20= destination=20address=20so=20that=20it=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20;;=20refers=20to=20the=20instruction,=20= not=20to=20the=20offset=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20;;=20of=20the=20number.=0A+=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(format=20"%s=20instr=20%d=20to=20value=20= %d"=20(car=20op)=20(-=20dest=203)=20val))=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(`(,(or=20'syntaxspec=20'notsyntaxspec)=20= ,syn)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= (format=20"%s=20%s"=20(car=20op)=20syn))=0A+=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20(`(,(or=20'categoryspec=20= 'notcategoryspec)=20,ch)=0A+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20(format=20"%s=20'%c'"=20(car=20op)=20ch))=0A+=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20(_=20(error=20= "unrecognised=20opcode:=20%S=20at=20%S"=20op=20addr)))))=0A+=20=20=20=20=20= =20=20=20=20=20=20=20(insert=20(format=20"%5d=20=20%s\n"=20addr=20= line))))))))=0A+=0A+(provide=20'regexp-disasm)=0A+=0A+;;;=20= regexp-disasm.el=20ends=20here=0Adiff=20--git=20a/src/regex-emacs.c=20= b/src/regex-emacs.c=0Aindex=200ae004e463..f12b1f9246=20100644=0A---=20= a/src/regex-emacs.c=0A+++=20b/src/regex-emacs.c=0A@@=20-196,7=20+196,9=20= @@=20#define=20BYTEWIDTH=208=20/*=20In=20bits.=20=20*/=0A=20/*=20These=20= are=20the=20command=20codes=20that=20appear=20in=20compiled=20regular=0A=20= =20=20=20expressions.=20=20Some=20opcodes=20are=20followed=20by=20= argument=20bytes.=20=20A=0A=20=20=20=20command=20code=20can=20specify=20= any=20interpretation=20whatsoever=20for=20its=0A-=20=20=20arguments.=20=20= Zero=20bytes=20may=20appear=20in=20the=20compiled=20regular=20= expression.=20=20*/=0A+=20=20=20arguments.=20=20Zero=20bytes=20may=20= appear=20in=20the=20compiled=20regular=20expression.=0A+=0A+=20=20=20Any=20= changes=20here=20should=20be=20reflected=20in=20regexp-disasm.el=20as=20= well.=20=20*/=0A=20=0A=20typedef=20enum=0A=20{=0A@@=20-1342,7=20+1344,8=20= @@=20#define=20RANGE_TABLE_WORK_ELT(work_area,=20i)=20= ((work_area).table[i])=0A=20=0A=20/*=20Bits=20used=20to=20implement=20= the=20multibyte-part=20of=20the=20various=20character=20classes=0A=20=20=20= =20such=20as=20[:alnum:]=20in=20a=20charset's=20range=20table.=20=20The=20= code=20currently=20assumes=0A-=20=20=20that=20only=20the=20low=2016=20= bits=20are=20used.=20=20*/=0A+=20=20=20that=20only=20the=20low=2016=20= bits=20are=20used.=0A+=20=20=20Keep=20this=20table=20in=20sync=20with=20= regexp-disasm--classes.=20=20*/=0A=20#define=20BIT_WORD=090x1=0A=20= #define=20BIT_LOWER=090x2=0A=20#define=20BIT_PUNCT=090x4=0Adiff=20--git=20= a/src/search.c=20b/src/search.c=0Aindex=20818bb4af24..a5804a17b6=20= 100644=0A---=20a/src/search.c=0A+++=20b/src/search.c=0A@@=20-3106,6=20= +3106,22=20@@=20record_unwind_save_match_data=20(void)=0A=20=09=09=09=20= Fmatch_data=20(Qnil,=20Qnil,=20Qnil));=0A=20}=0A=20=0A+DEFUN=20= ("internal--regexp-bytecode",=20Finternal__regexp_bytecode,=0A+=20=20=20=20= =20=20=20Sinternal__regexp_bytecode,=202,=202,=200,=0A+=20=20=20=20=20=20= =20doc:=20/*=20Return=20the=20compiled=20bytecode=20of=20REGEXP.=0A+If=20= CASE_TABLE=20is=20non-nil,=20use=20it=20as=20translation=20table=20for=20= ignoring=20case.=0A+The=20bytecode=20is=20returned=20as=20a=20string;=20= its=20format=20is=20implementation-dependent.=0A+Cached=20bytecode=20may=20= be=20returned=20if=20available.=20=20*/)=0A+=20=20(Lisp_Object=20regexp,=20= Lisp_Object=20case_table)=0A+{=0A+=20=20CHECK_STRING=20(regexp);=0A+=20=20= struct=20regexp_cache=20*cache_entry=20=3D=0A+=20=20=20=20= compile_pattern=20(regexp,=20NULL,=20case_table,=20false,=20true);=0A+=20= =20struct=20re_pattern_buffer=20*pb=20=3D=20&cache_entry->buf;=0A+=20=20= return=20make_unibyte_string=20(pb->buffer,=20pb->used);=0A+}=0A+=0A+=0A=20= /*=20Quote=20a=20string=20to=20deactivate=20reg-expr=20chars=20*/=0A=20=0A= =20DEFUN=20("regexp-quote",=20Fregexp_quote,=20Sregexp_quote,=201,=201,=20= 0,=0A@@=20-3400,6=20+3416,7=20@@=20syms_of_search=20(void)=0A=20=20=20= defsubr=20(&Smatch_end);=0A=20=20=20defsubr=20(&Smatch_data);=0A=20=20=20= defsubr=20(&Sset_match_data);=0A+=20=20defsubr=20= (&Sinternal__regexp_bytecode);=0A=20=20=20defsubr=20(&Sregexp_quote);=0A=20= =20=20defsubr=20(&Snewline_cache_check);=0A=20=0Adiff=20--git=20= a/src/syntax.h=20b/src/syntax.h=0Aindex=20a2ec3301ba..4817e4c288=20= 100644=0A---=20a/src/syntax.h=0A+++=20b/src/syntax.h=0A@@=20-37,6=20= +37,8=20@@=20#define=20Vstandard_syntax_table=20BVAR=20= (&buffer_defaults,=20syntax_table)=0A=20=20=20=20(CODE+FLAGS=20.=20= MATCHING-CHAR).=20=20MATCHING-CHAR=20can=20be=20nil=20if=20the=20char=0A=20= =20=20=20is=20not=20a=20kind=20of=20parenthesis.=0A=20=0A+=20=20=20Keep=20= this=20table=20in=20sync=20with=20regexp-disasm--syntax-codes.=0A+=0A=20=20= =20=20The=20low=208=20bits=20of=20CODE+FLAGS=20is=20a=20code,=20as=20= follows:=20=20*/=0A=20=0A=20enum=20syntaxcode=0A--=20=0A2.21.1=20(Apple=20= Git-122.3)=0A=0A= --Apple-Mail=_B666AE44-4B1F-4801-9DEB-12C5E92A1CD4--