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#55481: mostly nonrecursive printing [PATCH] Date: Tue, 17 May 2022 15:59:16 +0200 Message-ID: Mime-Version: 1.0 (Mac OS X Mail 14.0 \(3654.120.0.1.13\)) Content-Type: multipart/mixed; boundary="Apple-Mail=_1430A473-B862-48C1-9974-717A57E2E1B3" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="38402"; mail-complaints-to="usenet@ciao.gmane.io" To: 55481@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Tue May 17 16:18:38 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 1nqy20-0009hJ-3Z for geb-bug-gnu-emacs@m.gmane-mx.org; Tue, 17 May 2022 16:18:36 +0200 Original-Received: from localhost ([::1]:60302 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nqy1z-0005BE-2v for geb-bug-gnu-emacs@m.gmane-mx.org; Tue, 17 May 2022 10:18:35 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:45548) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nqxk4-0008F2-R2 for bug-gnu-emacs@gnu.org; Tue, 17 May 2022 10:00:06 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:35380) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1nqxk2-0002jc-Ne for bug-gnu-emacs@gnu.org; Tue, 17 May 2022 10:00:03 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1nqxk2-0005kw-Iz for bug-gnu-emacs@gnu.org; Tue, 17 May 2022 10:00:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Mattias =?UTF-8?Q?Engdeg=C3=A5rd?= Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 17 May 2022 14:00:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 55481 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch X-Debbugs-Original-To: bug-gnu-emacs@gnu.org Original-Received: via spool by submit@debbugs.gnu.org id=B.165279597322050 (code B ref -1); Tue, 17 May 2022 14:00:02 +0000 Original-Received: (at submit) by debbugs.gnu.org; 17 May 2022 13:59:33 +0000 Original-Received: from localhost ([127.0.0.1]:57510 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nqxjZ-0005ja-3d for submit@debbugs.gnu.org; Tue, 17 May 2022 09:59:33 -0400 Original-Received: from lists.gnu.org ([209.51.188.17]:56204) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nqxjX-0005jT-UE for submit@debbugs.gnu.org; Tue, 17 May 2022 09:59:32 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:45390) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nqxjU-0007Np-VV for bug-gnu-emacs@gnu.org; Tue, 17 May 2022 09:59:31 -0400 Original-Received: from mail238c50.megamailservers.eu ([91.136.10.248]:60682 helo=mail56c50.megamailservers.eu) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nqxjS-0002eJ-C7 for bug-gnu-emacs@gnu.org; Tue, 17 May 2022 09:59:28 -0400 X-Authenticated-User: mattiase@bredband.net DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=megamailservers.eu; s=maildub; t=1652795960; bh=PX3ROcn05FXR+pfz9dHFv917mApOW+G9Odmvkqm0gr0=; h=From:Subject:Date:To:From; b=k1uf34o2kot0FAxRYEnyVdGqLfDJxOm7AYb2Q5kHQJccdvYa8w/+5JkI1LxHm3cRa sARpOflmYTTCn0Sd6Vim3X+ZGPRfFv5FKBbOIcM/ZU5ZP5TR93VYfXAMJLxnVSwJnV Y8fUPwk/Z+BMhua0B8UXQOQhPOVcYcVlupr2k1fs= 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 mail56c50.megamailservers.eu (8.14.9/8.13.1) with ESMTP id 24HDxHPi022717 for ; Tue, 17 May 2022 13:59:19 +0000 X-Mailer: Apple Mail (2.3654.120.0.1.13) X-CTCH-RefID: str=0001.0A742F1C.6283AA37.008F, 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 Received-SPF: softfail client-ip=91.136.10.248; envelope-from=mattiase@acm.org; helo=mail56c50.megamailservers.eu X-Spam_score_int: -11 X-Spam_score: -1.2 X-Spam_bar: - X-Spam_report: (-1.2 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, SPF_HELO_NONE=0.001, SPF_SOFTFAIL=0.665, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=no autolearn_force=no X-Spam_action: no action 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:232450 Archived-At: --Apple-Mail=_1430A473-B862-48C1-9974-717A57E2E1B3 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii Printing deeply nested values typically crashes Emacs by running out of = C stack since the printer uses C recursion to traverse nested data = structures. This is a long-standing problem that keeps turning up; see = bug#52753 for one example. The attached patch eliminates most of the recursion: conses, vectors, = records, hash tables and char tables are now traversed without consuming = C stack. This should cover the vast majority of objects that form deep = structures. Of note: - Performance seems to be slightly improved (about 2.5 % faster for = printing a long list of symbols) but that's not really the point of the = patch. - The patch does not attempt to fix the bogus #N notation for circular = lists (bug#55395) but tries to stay bug-compatible for easier = comparison. - Some special syntax is context-conditional: (\, X) is only printed as = ,X if surrounded by a positive number of backquote forms. It's not clear = what we gain from this; using the special syntax for the backquote, = comma and comma-at forms unconditionally would simplify matter without = any apparent inconvenience to the user. Right now, the patch does not = remove recursion for printing these forms. - This patch does not address reading nested values, where a similar = problem exists. --Apple-Mail=_1430A473-B862-48C1-9974-717A57E2E1B3 Content-Disposition: attachment; filename=print-nonrec.diff Content-Type: application/octet-stream; x-unix-mode=0644; name="print-nonrec.diff" Content-Transfer-Encoding: quoted-printable diff=20--git=20a/src/print.c=20b/src/print.c=0Aindex=20= 55f4c2345a..da4869e8fb=20100644=0A---=20a/src/print.c=0A+++=20= b/src/print.c=0A@@=20-834,7=20+834,13=20@@=20DEFUN=20("princ",=20Fprinc,=20= Sprinc,=201,=202,=200,=0A=20=20=20if=20(NILP=20(printcharfun))=0A=20=20=20= =20=20printcharfun=20=3D=20Vstandard_output;=0A=20=20=20PRINTPREPARE;=0A= -=20=20print=20(object,=20printcharfun,=200);=0A+=20=20if=20(STRINGP=20= (object)=0A+=20=20=20=20=20=20&&=20!string_intervals=20(object)=0A+=20=20= =20=20=20=20&&=20NILP=20(Vprint_continuous_numbering))=0A+=20=20=20=20/*=20= fast=20path=20for=20plain=20strings=20*/=0A+=20=20=20=20print_string=20= (object,=20printcharfun);=0A+=20=20else=0A+=20=20=20=20print=20(object,=20= printcharfun,=200);=0A=20=20=20PRINTFINISH;=0A=20=20=20return=20object;=0A= =20}=0A@@=20-1249,7=20+1255,6=20@@=20print=20(Lisp_Object=20obj,=20= Lisp_Object=20printcharfun,=20bool=20escapeflag)=0A=20=20=20=20=20{=0A=20= =20=20=20=20=20=20/*=20Construct=20Vprint_number_table.=0A=20=09=20This=20= increments=20print_number_index=20for=20the=20objects=20added.=20=20*/=0A= -=20=20=20=20=20=20print_depth=20=3D=200;=0A=20=20=20=20=20=20=20= print_preprocess=20(obj);=0A=20=0A=20=20=20=20=20=20=20if=20= (HASH_TABLE_P=20(Vprint_number_table))=0A@@=20-1273,10=20+1278,7=20@@=20= print=20(Lisp_Object=20obj,=20Lisp_Object=20printcharfun,=20bool=20= escapeflag)=0A=20}=0A=20=0A=20#define=20PRINT_CIRCLE_CANDIDATE_P(obj)=09=09= =09=20=20=20\=0A-=20=20((STRINGP=20(obj)=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=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(string_intervals=20= (obj)=20=20=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-=09=20=20=20||=20print_depth=20>=201=09=09=09=09=20=20=20\=0A= -=09=20=20=20||=20!NILP=20(Vprint_continuous_numbering)))=09=20=20=20\=0A= +=20=20(STRINGP=20(obj)=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=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||=20CONSP=20(obj)=09=09=09=09=09=20=20=20\=0A=20=20=20= =20||=20(VECTORLIKEP=20(obj)=09=09=09=09=20=20=20\=0A=20=20=20=20=20=20=20= =20&&=20(VECTORP=20(obj)=20||=20COMPILEDP=20(obj)=09=09=20=20=20\=0A@@=20= -1287,6=20+1289,78=20@@=20#define=20PRINT_CIRCLE_CANDIDATE_P(obj)=09=09=09= =20=20=20\=0A=20=20=20=20=20=20=20=20&&=20SYMBOLP=20(obj)=09=09=09=09=09=20= =20=20\=0A=20=20=20=20=20=20=20=20&&=20!SYMBOL_INTERNED_P=20(obj)))=0A=20= =0A+/*=20The=20print=20preprocess=20stack,=20used=20to=20traverse=20data=20= structures.=20=20*/=0A+=0A+struct=20print_pp_entry=20{=0A+=20=20= ptrdiff_t=20n;=09=09=09/*=20number=20of=20values,=20or=200=20if=20a=20= single=20value=20*/=0A+=20=20union=20{=0A+=20=20=20=20Lisp_Object=20= value;=09=09/*=20when=20n=20=3D=200=20*/=0A+=20=20=20=20Lisp_Object=20= *values;=09/*=20when=20n=20>=200=20*/=0A+=20=20}=20u;=0A+};=0A+=0A= +struct=20print_pp_stack=20{=0A+=20=20struct=20print_pp_entry=20*stack;=09= =20/*=20base=20of=20stack=20*/=0A+=20=20ptrdiff_t=20size;=09=09=20/*=20= allocated=20size=20in=20entries=20*/=0A+=20=20ptrdiff_t=20sp;=09=09=09=20= /*=20current=20number=20of=20entries=20*/=0A+};=0A+=0A+static=20struct=20= print_pp_stack=20ppstack=20=3D=20{NULL,=200,=200};=0A+=0A+NO_INLINE=20= static=20void=0A+grow_pp_stack=20(void)=0A+{=0A+=20=20struct=20= print_pp_stack=20*ps=20=3D=20&ppstack;=0A+=20=20eassert=20(ps->sp=20=3D=3D= =20ps->size);=0A+=20=20ps->stack=20=3D=20xpalloc=20(ps->stack,=20= &ps->size,=201,=20-1,=20sizeof=20*ps->stack);=0A+=20=20eassert=20(ps->sp=20= <=20ps->size);=0A+}=0A+=0A+static=20inline=20void=0A+pp_stack_push_value=20= (Lisp_Object=20value)=0A+{=0A+=20=20if=20(ppstack.sp=20>=3D=20= ppstack.size)=0A+=20=20=20=20grow_pp_stack=20();=0A+=20=20= ppstack.stack[ppstack.sp++]=20=3D=20(struct=20print_pp_entry){.n=20=3D=20= 0,=0A+=09=09=09=09=09=09=09.u.value=20=3D=20value};=0A+}=0A+=0A+static=20= inline=20void=0A+pp_stack_push_values=20(Lisp_Object=20*values,=20= ptrdiff_t=20n)=0A+{=0A+=20=20eassume=20(n=20>=3D=200);=0A+=20=20if=20(n=20= =3D=3D=200)=0A+=20=20=20=20return;=0A+=20=20if=20(ppstack.sp=20>=3D=20= ppstack.size)=0A+=20=20=20=20grow_pp_stack=20();=0A+=20=20= ppstack.stack[ppstack.sp++]=20=3D=20(struct=20print_pp_entry){.n=20=3D=20= n,=0A+=09=09=09=09=09=09=09.u.values=20=3D=20values};=0A+}=0A+=0A+static=20= inline=20bool=0A+pp_stack_empty_p=20(void)=0A+{=0A+=20=20return=20= ppstack.sp=20<=3D=200;=0A+}=0A+=0A+static=20inline=20Lisp_Object=0A= +pp_stack_pop=20(void)=0A+{=0A+=20=20eassume=20(!pp_stack_empty_p=20());=0A= +=20=20struct=20print_pp_entry=20*e=20=3D=20&ppstack.stack[ppstack.sp=20= -=201];=0A+=20=20if=20(e->n=20=3D=3D=200)=09=09/*=20single=20value=20*/=0A= +=20=20=20=20{=0A+=20=20=20=20=20=20--ppstack.sp;=0A+=20=20=20=20=20=20= return=20e->u.value;=0A+=20=20=20=20}=0A+=20=20/*=20Array=20of=20values:=20= pop=20them=20left=20to=20right,=20which=20seems=20to=20be=20slightly=0A+=20= =20=20=20=20faster=20than=20right=20to=20left.=20=20*/=0A+=20=20e->n--;=0A= +=20=20if=20(e->n=20=3D=3D=200)=0A+=20=20=20=20--ppstack.sp;=09=09/*=20= last=20value=20consumed=20*/=0A+=20=20return=20(++e->u.values)[-1];=0A+}=0A= +=0A=20/*=20Construct=20Vprint_number_table=20for=20the=20print-circle=20= feature=0A=20=20=20=20according=20to=20the=20structure=20of=20OBJ.=20=20= OBJ=20itself=20and=20all=20its=20elements=0A=20=20=20=20will=20be=20= added=20to=20Vprint_number_table=20recursively=20if=20it=20is=20a=20= list,=0A@@=20-1298,86=20+1372,81=20@@=20#define=20= PRINT_CIRCLE_CANDIDATE_P(obj)=09=09=09=20=20=20\=0A=20static=20void=0A=20= print_preprocess=20(Lisp_Object=20obj)=0A=20{=0A-=20=20int=20i;=0A-=20=20= ptrdiff_t=20size;=0A-=20=20int=20loop_count=20=3D=200;=0A-=20=20= Lisp_Object=20halftail;=0A-=0A=20=20=20eassert=20(!NILP=20= (Vprint_circle));=0A+=20=20ptrdiff_t=20base_sp=20=3D=20ppstack.sp;=0A=20=0A= -=20=20print_depth++;=0A-=20=20halftail=20=3D=20obj;=0A-=0A-=20loop:=0A-=20= =20if=20(PRINT_CIRCLE_CANDIDATE_P=20(obj))=0A+=20=20for=20(;;)=0A=20=20=20= =20=20{=0A-=20=20=20=20=20=20if=20(!HASH_TABLE_P=20= (Vprint_number_table))=0A-=09Vprint_number_table=20=3D=20CALLN=20= (Fmake_hash_table,=20QCtest,=20Qeq);=0A-=0A-=20=20=20=20=20=20= Lisp_Object=20num=20=3D=20Fgethash=20(obj,=20Vprint_number_table,=20= Qnil);=0A-=20=20=20=20=20=20if=20(!NILP=20(num)=0A-=09=20=20/*=20If=20= Vprint_continuous_numbering=20is=20non-nil=20and=20OBJ=20is=20a=20= gensym,=0A-=09=20=20=20=20=20always=20print=20the=20gensym=20with=20a=20= number.=20=20This=20is=20a=20special=20for=0A-=09=20=20=20=20=20the=20= lisp=20function=20byte-compile-output-docform.=20=20*/=0A-=09=20=20||=20= (!NILP=20(Vprint_continuous_numbering)=0A-=09=20=20=20=20=20=20&&=20= SYMBOLP=20(obj)=0A-=09=20=20=20=20=20=20&&=20!SYMBOL_INTERNED_P=20= (obj)))=0A-=09{=20/*=20OBJ=20appears=20more=20than=20once.=20=20Let's=20= remember=20that.=20=20*/=0A-=09=20=20if=20(!FIXNUMP=20(num))=0A-=09=20=20= =20=20{=0A-=09=20=20=20=20=20=20print_number_index++;=0A-=09=20=20=20=20=20= =20/*=20Negative=20number=20indicates=20it=20hasn't=20been=20printed=20= yet.=20=20*/=0A-=09=20=20=20=20=20=20Fputhash=20(obj,=20make_fixnum=20(-=20= print_number_index),=0A-=09=09=09Vprint_number_table);=0A+=20=20=20=20=20= =20if=20(PRINT_CIRCLE_CANDIDATE_P=20(obj))=0A+=09{=0A+=09=20=20if=20= (!HASH_TABLE_P=20(Vprint_number_table))=0A+=09=20=20=20=20= Vprint_number_table=20=3D=20CALLN=20(Fmake_hash_table,=20QCtest,=20Qeq);=0A= +=0A+=09=20=20Lisp_Object=20num=20=3D=20Fgethash=20(obj,=20= Vprint_number_table,=20Qnil);=0A+=09=20=20if=20(!NILP=20(num)=0A+=09=20=20= =20=20=20=20/*=20If=20Vprint_continuous_numbering=20is=20non-nil=20and=20= OBJ=20is=20a=20gensym,=0A+=09=09=20always=20print=20the=20gensym=20with=20= a=20number.=20=20This=20is=20a=20special=20for=0A+=09=09=20the=20lisp=20= function=20byte-compile-output-docform.=20=20*/=0A+=09=20=20=20=20=20=20= ||=20(!NILP=20(Vprint_continuous_numbering)=0A+=09=09=20=20&&=20SYMBOLP=20= (obj)=0A+=09=09=20=20&&=20!SYMBOL_INTERNED_P=20(obj)))=0A+=09=20=20=20=20= {=20/*=20OBJ=20appears=20more=20than=20once.=20=20Let's=20remember=20= that.=20=20*/=0A+=09=20=20=20=20=20=20if=20(!FIXNUMP=20(num))=0A+=09=09{=0A= +=09=09=20=20print_number_index++;=0A+=09=09=20=20/*=20Negative=20number=20= indicates=20it=20hasn't=20been=20printed=20yet.=20=20*/=0A+=09=09=20=20= Fputhash=20(obj,=20make_fixnum=20(-=20print_number_index),=0A+=09=09=09=20= =20=20=20Vprint_number_table);=0A+=09=09}=0A=20=09=20=20=20=20}=0A-=09=20= =20print_depth--;=0A-=09=20=20return;=0A-=09}=0A-=20=20=20=20=20=20else=0A= -=09/*=20OBJ=20is=20not=20yet=20recorded.=20=20Let's=20add=20to=20the=20= table.=20=20*/=0A-=09Fputhash=20(obj,=20Qt,=20Vprint_number_table);=0A+=09= =20=20else=0A+=09=20=20=20=20{=0A+=09=20=20=20=20=20=20/*=20OBJ=20is=20= not=20yet=20recorded.=20=20Let's=20add=20to=20the=20table.=20=20*/=0A+=09= =20=20=20=20=20=20Fputhash=20(obj,=20Qt,=20Vprint_number_table);=0A=20=0A= -=20=20=20=20=20=20switch=20(XTYPE=20(obj))=0A-=09{=0A-=09case=20= Lisp_String:=0A-=09=20=20/*=20A=20string=20may=20have=20text=20= properties,=20which=20can=20be=20circular.=20=20*/=0A-=09=20=20= traverse_intervals_noorder=20(string_intervals=20(obj),=0A-=09=09=09=09=20= =20=20=20=20=20print_preprocess_string,=20NULL);=0A-=09=20=20break;=0A+=09= =20=20=20=20=20=20switch=20(XTYPE=20(obj))=0A+=09=09{=0A+=09=09case=20= Lisp_String:=0A+=09=09=20=20/*=20A=20string=20may=20have=20text=20= properties,=0A+=09=09=20=20=20=20=20which=20can=20be=20circular.=20*/=0A= +=09=09=20=20traverse_intervals_noorder=20(string_intervals=20(obj),=0A+=09= =09=09=09=09=20=20=20=20=20=20print_preprocess_string,=20NULL);=0A+=09=09= =20=20break;=0A=20=0A-=09case=20Lisp_Cons:=0A-=09=20=20/*=20Use=20= HALFTAIL=20and=20LOOP_COUNT=20to=20detect=20circular=20lists,=0A-=09=20=20= =20=20=20just=20as=20in=20print_object.=20=20*/=0A-=09=20=20if=20= (loop_count=20&&=20EQ=20(obj,=20halftail))=0A-=09=20=20=20=20break;=0A-=09= =20=20print_preprocess=20(XCAR=20(obj));=0A-=09=20=20obj=20=3D=20XCDR=20= (obj);=0A-=09=20=20loop_count++;=0A-=09=20=20if=20(!(loop_count=20&=20= 1))=0A-=09=20=20=20=20halftail=20=3D=20XCDR=20(halftail);=0A-=09=20=20= goto=20loop;=0A-=0A-=09case=20Lisp_Vectorlike:=0A-=09=20=20size=20=3D=20= ASIZE=20(obj);=0A-=09=20=20if=20(size=20&=20PSEUDOVECTOR_FLAG)=0A-=09=20=20= =20=20size=20&=3D=20PSEUDOVECTOR_SIZE_MASK;=0A-=09=20=20for=20(i=20=3D=20= (SUB_CHAR_TABLE_P=20(obj)=0A-=09=09=20=20=20=20?=20SUB_CHAR_TABLE_OFFSET=20= :=200);=20i=20<=20size;=20i++)=0A-=09=20=20=20=20print_preprocess=20= (AREF=20(obj,=20i));=0A-=09=20=20if=20(HASH_TABLE_P=20(obj))=0A-=09=20=20= =20=20{=20/*=20For=20hash=20tables,=20the=20key_and_value=20slot=20is=20= past=0A-=09=09=20`size'=20because=20it=20needs=20to=20be=20marked=20= specially=20in=20case=0A-=09=09=20the=20table=20is=20weak.=20=20*/=0A-=09= =20=20=20=20=20=20struct=20Lisp_Hash_Table=20*h=20=3D=20XHASH_TABLE=20= (obj);=0A-=09=20=20=20=20=20=20print_preprocess=20(h->key_and_value);=0A= -=09=20=20=20=20}=0A-=09=20=20break;=0A+=09=09case=20Lisp_Cons:=0A+=09=09= =20=20if=20(!NILP=20(XCDR=20(obj)))=0A+=09=09=20=20=20=20= pp_stack_push_value=20(XCDR=20(obj));=0A+=09=09=20=20obj=20=3D=20XCAR=20= (obj);=0A+=09=09=20=20continue;=0A=20=0A-=09default:=0A-=09=20=20break;=0A= +=09=09case=20Lisp_Vectorlike:=0A+=09=09=20=20{=0A+=09=09=20=20=20=20= struct=20Lisp_Vector=20*vec=20=3D=20XVECTOR=20(obj);=0A+=09=09=20=20=20=20= ptrdiff_t=20size=20=3D=20ASIZE=20(obj);=0A+=09=09=20=20=20=20if=20(size=20= &=20PSEUDOVECTOR_FLAG)=0A+=09=09=20=20=20=20=20=20size=20&=3D=20= PSEUDOVECTOR_SIZE_MASK;=0A+=09=09=20=20=20=20ptrdiff_t=20start=20=3D=20= (SUB_CHAR_TABLE_P=20(obj)=0A+=09=09=09=09=20=20=20=20=20=20=20?=20= SUB_CHAR_TABLE_OFFSET=20:=200);=0A+=09=09=20=20=20=20= pp_stack_push_values=20(vec->contents=20+=20start,=20size=20-=20start);=0A= +=09=09=20=20=20=20if=20(HASH_TABLE_P=20(obj))=0A+=09=09=20=20=20=20=20=20= {=0A+=09=09=09struct=20Lisp_Hash_Table=20*h=20=3D=20XHASH_TABLE=20(obj);=0A= +=09=09=09obj=20=3D=20h->key_and_value;=0A+=09=09=09continue;=0A+=09=09=20= =20=20=20=20=20}=0A+=09=09=20=20=20=20break;=0A+=09=09=20=20}=0A+=0A+=09=09= default:=0A+=09=09=20=20break;=0A+=09=09}=0A+=09=20=20=20=20}=0A=20=09}=0A= +=0A+=20=20=20=20=20=20if=20(ppstack.sp=20<=3D=20base_sp)=0A+=09break;=0A= +=20=20=20=20=20=20obj=20=3D=20pp_stack_pop=20();=0A=20=20=20=20=20}=0A-=20= =20print_depth--;=0A=20}=0A=20=0A=20DEFUN=20("print--preprocess",=20= Fprint_preprocess,=20Sprint_preprocess,=201,=201,=200,=0A@@=20-1569,162=20= +1638,6=20@@=20print_vectorlike=20(Lisp_Object=20obj,=20Lisp_Object=20= printcharfun,=20bool=20escapeflag,=0A=20=20=20=20=20=20=20}=0A=20=20=20=20= =20=20=20return=20true;=0A=20=0A-=20=20=20=20case=20PVEC_HASH_TABLE:=0A-=20= =20=20=20=20=20{=0A-=09struct=20Lisp_Hash_Table=20*h=20=3D=20XHASH_TABLE=20= (obj);=0A-=09/*=20Implement=20a=20readable=20output,=20e.g.:=0A-=09=20=20= #s(hash-table=20size=202=20test=20equal=20data=20(k1=20v1=20k2=20v2))=20= */=0A-=09/*=20Always=20print=20the=20size.=20=20*/=0A-=09int=20len=20=3D=20= sprintf=20(buf,=20"#s(hash-table=20size=20%"pD"d",=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= HASH_TABLE_SIZE=20(h));=0A-=09strout=20(buf,=20len,=20len,=20= printcharfun);=0A-=0A-=09if=20(!NILP=20(h->test.name))=0A-=09=20=20{=0A-=09= =20=20=20=20print_c_string=20("=20test=20",=20printcharfun);=0A-=09=20=20= =20=20print_object=20(h->test.name,=20printcharfun,=20escapeflag);=0A-=09= =20=20}=0A-=0A-=09if=20(!NILP=20(h->weak))=0A-=09=20=20{=0A-=09=20=20=20=20= print_c_string=20("=20weakness=20",=20printcharfun);=0A-=09=20=20=20=20= print_object=20(h->weak,=20printcharfun,=20escapeflag);=0A-=09=20=20}=0A= -=0A-=09print_c_string=20("=20rehash-size=20",=20printcharfun);=0A-=09= print_object=20(Fhash_table_rehash_size=20(obj),=0A-=09=09=20=20=20=20=20= =20printcharfun,=20escapeflag);=0A-=0A-=09print_c_string=20("=20= rehash-threshold=20",=20printcharfun);=0A-=09print_object=20= (Fhash_table_rehash_threshold=20(obj),=0A-=09=09=20=20=20=20=20=20= printcharfun,=20escapeflag);=0A-=0A-=09if=20(h->purecopy)=0A-=09=20=20{=0A= -=09=20=20=20=20print_c_string=20("=20purecopy=20",=20printcharfun);=0A-=09= =20=20=20=20print_object=20(h->purecopy=20?=20Qt=20:=20Qnil,=20= printcharfun,=20escapeflag);=0A-=09=20=20}=0A-=0A-=09print_c_string=20("=20= data=20",=20printcharfun);=0A-=0A-=09/*=20Print=20the=20data=20here=20as=20= a=20plist.=20*/=0A-=09ptrdiff_t=20real_size=20=3D=20HASH_TABLE_SIZE=20= (h);=0A-=09ptrdiff_t=20size=20=3D=20h->count;=0A-=0A-=09/*=20Don't=20= print=20more=20elements=20than=20the=20specified=20maximum.=20=20*/=0A-=09= if=20(FIXNATP=20(Vprint_length)=20&&=20XFIXNAT=20(Vprint_length)=20<=20= size)=0A-=09=20=20size=20=3D=20XFIXNAT=20(Vprint_length);=0A-=0A-=09= printchar=20('(',=20printcharfun);=0A-=09ptrdiff_t=20j=20=3D=200;=0A-=09= for=20(ptrdiff_t=20i=20=3D=200;=20i=20<=20real_size;=20i++)=0A-=20=20=20=20= =20=20=20=20=20=20{=0A-=20=20=20=20=20=20=20=20=20=20=20=20Lisp_Object=20= key=20=3D=20HASH_KEY=20(h,=20i);=0A-=09=20=20=20=20if=20(!EQ=20(key,=20= Qunbound))=0A-=09=20=20=20=20=20=20{=0A-=09=20=20=20=20=20=20=20=20if=20= (j++)=20printchar=20('=20',=20printcharfun);=0A-=09=20=20=20=20=20=20=20=20= print_object=20(key,=20printcharfun,=20escapeflag);=0A-=09=20=20=20=20=20= =20=20=20printchar=20('=20',=20printcharfun);=0A-=09=20=20=20=20=20=20=20= =20print_object=20(HASH_VALUE=20(h,=20i),=20printcharfun,=20escapeflag);=0A= -=09=09if=20(j=20=3D=3D=20size)=0A-=09=09=20=20break;=0A-=09=20=20=20=20=20= =20}=0A-=20=20=20=20=20=20=20=20=20=20}=0A-=0A-=09if=20(j=20<=20= h->count)=0A-=09=20=20{=0A-=09=20=20=20=20if=20(j)=0A-=09=20=20=20=20=20=20= printchar=20('=20',=20printcharfun);=0A-=09=20=20=20=20print_c_string=20= ("...",=20printcharfun);=0A-=09=20=20}=0A-=0A-=09print_c_string=20("))",=20= printcharfun);=0A-=20=20=20=20=20=20}=0A-=20=20=20=20=20=20return=20= true;=0A-=0A-=20=20=20=20case=20PVEC_RECORD:=0A-=20=20=20=20=20=20{=0A-=09= ptrdiff_t=20size=20=3D=20PVSIZE=20(obj);=0A-=0A-=09/*=20Don't=20print=20= more=20elements=20than=20the=20specified=20maximum.=20=20*/=0A-=09= ptrdiff_t=20n=0A-=09=20=20=3D=20(FIXNATP=20(Vprint_length)=20&&=20= XFIXNAT=20(Vprint_length)=20<=20size=0A-=09=20=20=20=20=20?=20XFIXNAT=20= (Vprint_length)=20:=20size);=0A-=0A-=09print_c_string=20("#s(",=20= printcharfun);=0A-=09for=20(ptrdiff_t=20i=20=3D=200;=20i=20<=20n;=20i=20= ++)=0A-=09=20=20{=0A-=09=20=20=20=20if=20(i)=20printchar=20('=20',=20= printcharfun);=0A-=09=20=20=20=20print_object=20(AREF=20(obj,=20i),=20= printcharfun,=20escapeflag);=0A-=09=20=20}=0A-=09if=20(n=20<=20size)=0A-=09= =20=20print_c_string=20("=20...",=20printcharfun);=0A-=09printchar=20= (')',=20printcharfun);=0A-=20=20=20=20=20=20}=0A-=20=20=20=20=20=20= return=20true;=0A-=0A-=20=20=20=20case=20PVEC_SUB_CHAR_TABLE:=0A-=20=20=20= =20case=20PVEC_COMPILED:=0A-=20=20=20=20case=20PVEC_CHAR_TABLE:=0A-=20=20= =20=20case=20PVEC_NORMAL_VECTOR:=0A-=20=20=20=20=20=20{=0A-=09ptrdiff_t=20= size=20=3D=20ASIZE=20(obj);=0A-=09if=20(COMPILEDP=20(obj))=0A-=09=20=20{=0A= -=09=20=20=20=20printchar=20('#',=20printcharfun);=0A-=09=20=20=20=20= size=20&=3D=20PSEUDOVECTOR_SIZE_MASK;=0A-=09=20=20}=0A-=09if=20= (CHAR_TABLE_P=20(obj)=20||=20SUB_CHAR_TABLE_P=20(obj))=0A-=09=20=20{=0A-=09= =20=20=20=20/*=20Print=20a=20char-table=20as=20if=20it=20were=20a=20= vector,=0A-=09=20=20=20=20=20=20=20lumping=20the=20parent=20and=20= default=20slots=20in=20with=20the=0A-=09=20=20=20=20=20=20=20character=20= slots.=20=20But=20add=20#^=20as=20a=20prefix.=20=20*/=0A-=0A-=09=20=20=20= =20/*=20Make=20each=20lowest=20sub_char_table=20start=20a=20new=20line.=0A= -=09=20=20=20=20=20=20=20Otherwise=20we'll=20make=20a=20line=20extremely=20= long,=20which=0A-=09=20=20=20=20=20=20=20results=20in=20slow=20= redisplay.=20=20*/=0A-=09=20=20=20=20if=20(SUB_CHAR_TABLE_P=20(obj)=0A-=09= =09&&=20XSUB_CHAR_TABLE=20(obj)->depth=20=3D=3D=203)=0A-=09=20=20=20=20=20= =20printchar=20('\n',=20printcharfun);=0A-=09=20=20=20=20print_c_string=20= ("#^",=20printcharfun);=0A-=09=20=20=20=20if=20(SUB_CHAR_TABLE_P=20= (obj))=0A-=09=20=20=20=20=20=20printchar=20('^',=20printcharfun);=0A-=09=20= =20=20=20size=20&=3D=20PSEUDOVECTOR_SIZE_MASK;=0A-=09=20=20}=0A-=09if=20= (size=20&=20PSEUDOVECTOR_FLAG)=0A-=09=20=20return=20false;=0A-=0A-=09= printchar=20('[',=20printcharfun);=0A-=0A-=09int=20idx=20=3D=20= SUB_CHAR_TABLE_P=20(obj)=20?=20SUB_CHAR_TABLE_OFFSET=20:=200;=0A-=09= Lisp_Object=20tem;=0A-=09ptrdiff_t=20real_size=20=3D=20size;=0A-=0A-=09= /*=20For=20a=20sub=20char-table,=20print=20heading=20non-Lisp=20data=20= first.=20=20*/=0A-=09if=20(SUB_CHAR_TABLE_P=20(obj))=0A-=09=20=20{=0A-=09= =20=20=20=20int=20i=20=3D=20sprintf=20(buf,=20"%d=20%d",=20= XSUB_CHAR_TABLE=20(obj)->depth,=0A-=09=09=09=20=20=20=20=20= XSUB_CHAR_TABLE=20(obj)->min_char);=0A-=09=20=20=20=20strout=20(buf,=20= i,=20i,=20printcharfun);=0A-=09=20=20}=0A-=0A-=09/*=20Don't=20print=20= more=20elements=20than=20the=20specified=20maximum.=20=20*/=0A-=09if=20= (FIXNATP=20(Vprint_length)=0A-=09=20=20=20=20&&=20XFIXNAT=20= (Vprint_length)=20<=20size)=0A-=09=20=20size=20=3D=20XFIXNAT=20= (Vprint_length);=0A-=0A-=09for=20(int=20i=20=3D=20idx;=20i=20<=20size;=20= i++)=0A-=09=20=20{=0A-=09=20=20=20=20if=20(i)=20printchar=20('=20',=20= printcharfun);=0A-=09=20=20=20=20tem=20=3D=20AREF=20(obj,=20i);=0A-=09=20= =20=20=20print_object=20(tem,=20printcharfun,=20escapeflag);=0A-=09=20=20= }=0A-=09if=20(size=20<=20real_size)=0A-=09=20=20print_c_string=20("=20= ...",=20printcharfun);=0A-=09printchar=20(']',=20printcharfun);=0A-=20=20= =20=20=20=20}=0A-=20=20=20=20=20=20return=20true;=0A-=0A=20=20=20=20=20= default:=0A=20=20=20=20=20=20=20break;=0A=20=20=20=20=20}=0A@@=20= -2103,32=20+2016,118=20@@=20named_escape=20(int=20i)=0A=20=20=20return=20= 0;=0A=20}=0A=20=0A+enum=20print_entry_type=20{=0A+=20=20PE_list,=09=09=09= /*=20print=20rest=20of=20list=20*/=0A+=20=20PE_rbrac,=09=09=09/*=20print=20= ")"=20*/=0A+=20=20PE_vector,=09=09=09/*=20print=20rest=20of=20vector=20= */=0A+=20=20PE_hash,=09=09=09/*=20print=20rest=20of=20hash=20data=20*/=0A= +};=0A+=0A+struct=20print_stack_entry=20{=0A+=20=20enum=20= print_entry_type=20type;=0A+=20=20union=20{=0A+=20=20=20=20struct=20{=0A= +=20=20=20=20=20=20Lisp_Object=20last;=09=09/*=20cons=20whose=20car=20= was=20just=20printed=20=20*/=0A+=20=20=20=20=20=20ptrdiff_t=20idx;=09=09= /*=20index=20of=20next=20element=20*/=0A+=20=20=20=20=20=20intmax_t=20= maxlen;=09=09/*=20max=20length=20(from=20Vprint_length)=20*/=0A+=20=20=20= =20=20=20/*=20state=20for=20Brent=20cycle=20detection=20*/=0A+=20=20=20=20= =20=20Lisp_Object=20tortoise;=20=20=20=20=20/*=20slow=20pointer=20*/=0A+=20= =20=20=20=20=20ptrdiff_t=20n;=09=09/*=20tortoise=20step=20countdown=20*/=0A= +=20=20=20=20=20=20ptrdiff_t=20m;=09=09/*=20tortoise=20step=20period=20= */=0A+=20=20=20=20}=20list;=0A+=20=20=20=20struct=20{=0A+=20=20=20=20=20=20= Lisp_Object=20obj;=09=09/*=20object=20to=20print=20after=20"=20.=20"=20= */=0A+=20=20=20=20}=20dotted_cdr;=0A+=20=20=20=20struct=20{=0A+=20=20=20=20= =20=20Lisp_Object=20obj;=09=09/*=20vector=20object=20*/=0A+=20=20=20=20=20= =20ptrdiff_t=20size;=09=09/*=20length=20of=20vector=20*/=0A+=20=20=20=20=20= =20ptrdiff_t=20idx;=09=09/*=20index=20of=20next=20element=20*/=0A+=20=20=20= =20=20=20const=20char=20*end;=09=09/*=20string=20to=20print=20at=20end=20= */=0A+=20=20=20=20=20=20bool=20truncated;=09=09/*=20whether=20to=20print=20= "..."=20before=20end=20*/=0A+=20=20=20=20}=20vector;=0A+=20=20=20=20= struct=20{=0A+=20=20=20=20=20=20Lisp_Object=20obj;=09=09/*=20hash-table=20= object=20*/=0A+=20=20=20=20=20=20ptrdiff_t=20nobjs;=09=09/*=20number=20= of=20keys=20and=20values=20to=20print=20*/=0A+=20=20=20=20=20=20= ptrdiff_t=20idx;=09=09/*=20index=20of=20key-value=20pair=20*/=0A+=20=20=20= =20=20=20ptrdiff_t=20printed;=09/*=20number=20of=20keys=20and=20values=20= printed=20*/=0A+=20=20=20=20=20=20bool=20truncated;=09=09/*=20whether=20= to=20print=20"..."=20before=20end=20*/=0A+=20=20=20=20}=20hash;=0A+=20=20= }=20u;=0A+};=0A+=0A+struct=20print_stack=20{=0A+=20=20struct=20= print_stack_entry=20*stack;=20=20/*=20base=20of=20stack=20*/=0A+=20=20= ptrdiff_t=20size;=09=09=20=20=20=20/*=20allocated=20size=20in=20entries=20= */=0A+=20=20ptrdiff_t=20sp;=09=09=09=20=20=20=20/*=20current=20number=20= of=20entries=20*/=0A+};=0A+=0A+static=20struct=20print_stack=20prstack=20= =3D=20{NULL,=200,=200};=0A+=0A+NO_INLINE=20static=20void=0A= +grow_print_stack=20(void)=0A+{=0A+=20=20struct=20print_stack=20*ps=20=3D=20= &prstack;=0A+=20=20eassert=20(ps->sp=20=3D=3D=20ps->size);=0A+=20=20= ps->stack=20=3D=20xpalloc=20(ps->stack,=20&ps->size,=201,=20-1,=20sizeof=20= *ps->stack);=0A+=20=20eassert=20(ps->sp=20<=20ps->size);=0A+}=0A+=0A= +static=20inline=20void=0A+print_stack_push=20(struct=20= print_stack_entry=20e)=0A+{=0A+=20=20if=20(prstack.sp=20>=3D=20= prstack.size)=0A+=20=20=20=20grow_print_stack=20();=0A+=20=20= prstack.stack[prstack.sp++]=20=3D=20e;=0A+}=0A+=0A+static=20void=0A= +print_stack_push_vector=20(const=20char=20*lbrac,=20const=20char=20= *rbrac,=0A+=09=09=09=20Lisp_Object=20obj,=20ptrdiff_t=20start,=20= ptrdiff_t=20size,=0A+=09=09=09=20Lisp_Object=20printcharfun)=0A+{=0A+=20=20= print_c_string=20(lbrac,=20printcharfun);=0A+=0A+=20=20ptrdiff_t=20= print_size=20=3D=20((FIXNATP=20(Vprint_length)=0A+=09=09=09=20=20=20&&=20= XFIXNAT=20(Vprint_length)=20<=20size)=0A+=09=09=09=20=20?=20XFIXNAT=20= (Vprint_length)=20:=20size);=0A+=20=20print_stack_push=20((struct=20= print_stack_entry){=0A+=20=20=20=20=20=20.type=20=3D=20PE_vector,=0A+=20=20= =20=20=20=20.u.vector.obj=20=3D=20obj,=0A+=20=20=20=20=20=20= .u.vector.size=20=3D=20print_size,=0A+=20=20=20=20=20=20.u.vector.idx=20= =3D=20start,=0A+=20=20=20=20=20=20.u.vector.end=20=3D=20rbrac,=0A+=20=20=20= =20=20=20.u.vector.truncated=20=3D=20(print_size=20<=20size),=0A+=20=20=20= =20});=0A+}=0A+=0A=20static=20void=0A=20print_object=20(Lisp_Object=20= obj,=20Lisp_Object=20printcharfun,=20bool=20escapeflag)=0A=20{=0A+=20=20= ptrdiff_t=20base_depth=20=3D=20print_depth;=0A+=20=20ptrdiff_t=20base_sp=20= =3D=20prstack.sp;=0A=20=20=20char=20buf[max=20(sizeof=20"from..to..in=20= "=20+=202=20*=20INT_STRLEN_BOUND=20(EMACS_INT),=0A=20=09=09max=20(sizeof=20= "=20.=20#"=20+=20INT_STRLEN_BOUND=20(intmax_t),=0A=20=09=09=20=20=20=20=20= max=20((sizeof=20"=20with=20data=200x"=0A=20=09=09=09=20=20=20+=20= (sizeof=20(uintmax_t)=20*=20CHAR_BIT=20+=204=20-=201)=20/=204),=0A=20=09=09= =09=20=2040)))];=0A=20=20=20current_thread->stack_top=20=3D=20buf;=0A+=0A= +=20print_obj:=0A=20=20=20maybe_quit=20();=0A=20=0A=20=20=20/*=20Detect=20= circularities=20and=20truncate=20them.=20=20*/=0A=20=20=20if=20(NILP=20= (Vprint_circle))=0A=20=20=20=20=20{=0A=20=20=20=20=20=20=20/*=20Simple=20= but=20incomplete=20way.=20=20*/=0A-=20=20=20=20=20=20int=20i;=0A-=0A=20=20= =20=20=20=20=20if=20(print_depth=20>=3D=20PRINT_CIRCLE)=0A=20=09error=20= ("Apparently=20circular=20structure=20being=20printed");=0A=20=0A-=20=20=20= =20=20=20for=20(i=20=3D=200;=20i=20<=20print_depth;=20i++)=0A+=20=20=20=20= =20=20for=20(int=20i=20=3D=200;=20i=20<=20print_depth;=20i++)=0A=20=09if=20= (BASE_EQ=20(obj,=20being_printed[i]))=0A=20=09=20=20{=0A=20=09=20=20=20=20= int=20len=20=3D=20sprintf=20(buf,=20"#%d",=20i);=0A=20=09=20=20=20=20= strout=20(buf,=20len,=20len,=20printcharfun);=0A-=09=20=20=20=20return;=0A= +=09=20=20=20=20goto=20next_obj;=0A=20=09=20=20}=0A=20=20=20=20=20=20=20= being_printed[print_depth]=20=3D=20obj;=0A=20=20=20=20=20}=0A@@=20= -2152,7=20+2151,7=20@@=20print_object=20(Lisp_Object=20obj,=20= Lisp_Object=20printcharfun,=20bool=20escapeflag)=0A=20=09=20=20=20=20=20=20= /*=20Just=20print=20#n#=20if=20OBJ=20has=20already=20been=20printed.=20=20= */=0A=20=09=20=20=20=20=20=20int=20len=20=3D=20sprintf=20(buf,=20= "#%"pI"d#",=20n);=0A=20=09=20=20=20=20=20=20strout=20(buf,=20len,=20len,=20= printcharfun);=0A-=09=20=20=20=20=20=20return;=0A+=09=20=20=20=20=20=20= goto=20next_obj;=0A=20=09=20=20=20=20}=0A=20=09}=0A=20=20=20=20=20}=0A@@=20= -2226,7=20+2225,8=20@@=20print_object=20(Lisp_Object=20obj,=20= Lisp_Object=20printcharfun,=20bool=20escapeflag)=0A=20=09=20=20for=20(i=20= =3D=200,=20i_byte=20=3D=200;=20i_byte=20<=20size_byte;)=0A=20=09=20=20=20= =20{=0A=20=09=20=20=20=20=20=20/*=20Here,=20we=20must=20convert=20each=20= multi-byte=20form=20to=20the=0A-=09=09=20corresponding=20character=20= code=20before=20handing=20it=20to=20printchar.=20=20*/=0A+=09=09=20= corresponding=20character=20code=20before=20handing=20it=20to=0A+=09=09=20= printchar.=20=20*/=0A=20=09=20=20=20=20=20=20int=20c=20=3D=20= fetch_string_char_advance=20(obj,=20&i,=20&i_byte);=0A=20=0A=20=09=20=20=20= =20=20=20maybe_quit=20();=0A@@=20-2246,7=20+2246,8=20@@=20print_object=20= (Lisp_Object=20obj,=20Lisp_Object=20printcharfun,=20bool=20escapeflag)=0A= =20=09=20=20=20=20=20=20else=20if=20(multibyte=0A=20=09=09=20=20=20=20=20= =20=20&&=20!=20ASCII_CHAR_P=20(c)=20&&=20print_escape_multibyte)=0A=20=09= =09{=0A-=09=09=20=20/*=20When=20requested,=20print=20multibyte=20chars=20= using=20hex=20escapes.=20=20*/=0A+=09=09=20=20/*=20When=20requested,=20= print=20multibyte=20chars=20using=0A+=09=09=20=20=20=20=20hex=20escapes.=20= =20*/=0A=20=09=09=20=20char=20outbuf[sizeof=20"\\x"=20+=20= INT_STRLEN_BOUND=20(c)];=0A=20=09=09=20=20int=20len=20=3D=20sprintf=20= (outbuf,=20"\\x%04x",=20c=20+=200u);=0A=20=09=09=20=20strout=20(outbuf,=20= len,=20len,=20printcharfun);=0A@@=20-2357,14=20+2358,22=20@@=20= print_object=20(Lisp_Object=20obj,=20Lisp_Object=20printcharfun,=20bool=20= escapeflag)=0A=20=09=20=20=20=20=20=20=20&&=20EQ=20(XCAR=20(obj),=20= Qquote))=0A=20=09{=0A=20=09=20=20printchar=20('\'',=20printcharfun);=0A-=09= =20=20print_object=20(XCAR=20(XCDR=20(obj)),=20printcharfun,=20= escapeflag);=0A+=09=20=20obj=20=3D=20XCAR=20(XCDR=20(obj));=0A+=09=20=20= --print_depth;=09/*=20tail=20recursion=20*/=0A+=09=20=20goto=20= print_obj;=0A=20=09}=0A=20=20=20=20=20=20=20else=20if=20(print_quoted=20= &&=20CONSP=20(XCDR=20(obj))=20&&=20NILP=20(XCDR=20(XCDR=20(obj)))=0A=20=09= =20=20=20=20=20=20=20&&=20EQ=20(XCAR=20(obj),=20Qfunction))=0A=20=09{=0A=20= =09=20=20print_c_string=20("#'",=20printcharfun);=0A-=09=20=20= print_object=20(XCAR=20(XCDR=20(obj)),=20printcharfun,=20escapeflag);=0A= +=09=20=20obj=20=3D=20XCAR=20(XCDR=20(obj));=0A+=09=20=20--print_depth;=09= /*=20tail=20recursion=20*/=0A+=09=20=20goto=20print_obj;=0A=20=09}=0A+=20= =20=20=20=20=20/*=20FIXME:=20Do=20we=20really=20need=20the=20= new_backquote_output=20gating=20of=0A+=09=20special=20syntax=20for=20= comma=20and=20comma-at?=20=20There=20is=20basically=20no=0A+=09=20= benefit=20from=20it=20at=20all,=20and=20it=20would=20be=20nice=20to=20= get=20rid=20of=0A+=09=20the=20recursion=20here=20without=20additional=20= complexity.=20=20*/=0A=20=20=20=20=20=20=20else=20if=20(print_quoted=20= &&=20CONSP=20(XCDR=20(obj))=20&&=20NILP=20(XCDR=20(XCDR=20(obj)))=0A=20=09= =20=20=20=20=20=20=20&&=20EQ=20(XCAR=20(obj),=20Qbackquote))=0A=20=09{=0A= @@=20-2374,9=20+2383,9=20@@=20print_object=20(Lisp_Object=20obj,=20= Lisp_Object=20printcharfun,=20bool=20escapeflag)=0A=20=09=20=20= new_backquote_output--;=0A=20=09}=0A=20=20=20=20=20=20=20else=20if=20= (print_quoted=20&&=20CONSP=20(XCDR=20(obj))=20&&=20NILP=20(XCDR=20(XCDR=20= (obj)))=0A-=09=20=20=20=20=20=20=20&&=20new_backquote_output=0A=20=09=20=20= =20=20=20=20=20&&=20(EQ=20(XCAR=20(obj),=20Qcomma)=0A-=09=09=20=20=20||=20= EQ=20(XCAR=20(obj),=20Qcomma_at)))=0A+=09=09=20=20=20||=20EQ=20(XCAR=20= (obj),=20Qcomma_at))=0A+=09=20=20=20=20=20=20=20&&=20= new_backquote_output)=0A=20=09{=0A=20=09=20=20print_object=20(XCAR=20= (obj),=20printcharfun,=20false);=0A=20=09=20=20new_backquote_output--;=0A= @@=20-2386,70=20+2395,135=20@@=20print_object=20(Lisp_Object=20obj,=20= Lisp_Object=20printcharfun,=20bool=20escapeflag)=0A=20=20=20=20=20=20=20= else=0A=20=09{=0A=20=09=20=20printchar=20('(',=20printcharfun);=0A-=0A=20= =09=20=20/*=20Negative=20values=20of=20print-length=20are=20invalid=20in=20= CL.=0A=20=09=20=20=20=20=20Treat=20them=20like=20nil,=20as=20CMUCL=20= does.=20=20*/=0A=20=09=20=20intmax_t=20print_length=20=3D=20(FIXNATP=20= (Vprint_length)=0A=20=09=09=09=09=20=20=20?=20XFIXNAT=20(Vprint_length)=0A= =20=09=09=09=09=20=20=20:=20INTMAX_MAX);=0A-=09=20=20Lisp_Object=20= objtail=20=3D=20Qnil;=0A-=09=20=20intmax_t=20i=20=3D=200;=0A-=09=20=20= FOR_EACH_TAIL_SAFE=20(obj)=0A+=09=20=20if=20(print_length=20=3D=3D=200)=0A= +=09=20=20=20=20print_c_string=20("...)",=20printcharfun);=0A+=09=20=20= else=0A=20=09=20=20=20=20{=0A-=09=20=20=20=20=20=20if=20(i=20!=3D=200)=0A= -=09=09{=0A-=09=09=20=20printchar=20('=20',=20printcharfun);=0A-=0A-=09=09= =20=20if=20(!NILP=20(Vprint_circle))=0A-=09=09=20=20=20=20{=0A-=09=09=20=20= =20=20=20=20/*=20With=20the=20print-circle=20feature.=09=20*/=0A-=09=09=20= =20=20=20=20=20Lisp_Object=20num=20=3D=20Fgethash=20(obj,=20= Vprint_number_table,=0A-=09=09=09=09=09=09=20=20Qnil);=0A-=09=09=20=20=20= =20=20=20if=20(FIXNUMP=20(num))=0A-=09=09=09{=0A-=09=09=09=20=20= print_c_string=20(".=20",=20printcharfun);=0A-=09=09=09=20=20= print_object=20(obj,=20printcharfun,=20escapeflag);=0A-=09=09=09=20=20= goto=20end_of_list;=0A-=09=09=09}=0A-=09=09=20=20=20=20}=0A-=09=09}=0A-=0A= -=09=20=20=20=20=20=20if=20(print_length=20<=3D=20i)=0A-=09=09{=0A-=09=09= =20=20print_c_string=20("...",=20printcharfun);=0A-=09=09=20=20goto=20= end_of_list;=0A-=09=09}=0A-=0A-=09=20=20=20=20=20=20i++;=0A-=09=20=20=20=20= =20=20print_object=20(XCAR=20(obj),=20printcharfun,=20escapeflag);=0A-=09= =20=20=20=20=20=20objtail=20=3D=20XCDR=20(obj);=0A+=09=20=20=20=20=20=20= print_stack_push=20((struct=20print_stack_entry){=0A+=09=09=20=20.type=20= =3D=20PE_list,=0A+=09=09=20=20.u.list.last=20=3D=20obj,=0A+=09=09=20=20= .u.list.maxlen=20=3D=20print_length,=0A+=09=09=20=20.u.list.idx=20=3D=20= 1,=0A+=09=09=20=20.u.list.tortoise=20=3D=20obj,=0A+=09=09=20=20.u.list.n=20= =3D=202,=0A+=09=09=20=20.u.list.m=20=3D=202,=0A+=09=09});=0A+=09=20=20=20= =20=20=20/*=20print=20the=20car=20*/=0A+=09=20=20=20=20=20=20obj=20=3D=20= XCAR=20(obj);=0A+=09=20=20=20=20=20=20goto=20print_obj;=0A=20=09=20=20=20= =20}=0A+=09}=0A+=20=20=20=20=20=20break;=0A=20=0A-=09=20=20/*=20OBJTAIL=20= non-nil=20here=20means=20it's=20the=20end=20of=20a=20dotted=20list=0A-=09= =20=20=20=20=20or=20FOR_EACH_TAIL_SAFE=20detected=20a=20circular=20list.=20= =20*/=0A-=09=20=20if=20(!NILP=20(objtail))=0A-=09=20=20=20=20{=0A-=09=20=20= =20=20=20=20print_c_string=20("=20.=20",=20printcharfun);=0A+=20=20=20=20= case=20Lisp_Vectorlike:=0A+=20=20=20=20=20=20/*=20First=20do=20all=20the=20= vectorlike=20types=20that=20have=20a=20readable=20syntax.=20=20*/=0A+=20=20= =20=20=20=20switch=20(PSEUDOVECTOR_TYPE=20(XVECTOR=20(obj)))=0A+=09{=0A+=09= case=20PVEC_NORMAL_VECTOR:=0A+=09=20=20{=0A+=09=20=20=20=20= print_stack_push_vector=20("[",=20"]",=20obj,=200,=20ASIZE=20(obj),=0A+=09= =09=09=09=20=20=20=20=20printcharfun);=0A+=09=20=20=20=20goto=20= next_obj;=0A+=09=20=20}=0A+=09case=20PVEC_RECORD:=0A+=09=20=20{=0A+=09=20= =20=20=20print_stack_push_vector=20("#s(",=20")",=20obj,=200,=20PVSIZE=20= (obj),=0A+=09=09=09=09=20=20=20=20=20printcharfun);=0A+=09=20=20=20=20= goto=20next_obj;=0A+=09=20=20}=0A+=09case=20PVEC_COMPILED:=0A+=09=20=20{=0A= +=09=20=20=20=20print_stack_push_vector=20("#[",=20"]",=20obj,=200,=20= PVSIZE=20(obj),=0A+=09=09=09=09=20=20=20=20=20printcharfun);=0A+=09=20=20= =20=20goto=20next_obj;=0A+=09=20=20}=0A+=09case=20PVEC_CHAR_TABLE:=0A+=09= =20=20{=0A+=09=20=20=20=20print_stack_push_vector=20("#^[",=20"]",=20= obj,=200,=20PVSIZE=20(obj),=0A+=09=09=09=09=20=20=20=20=20printcharfun);=0A= +=09=20=20=20=20goto=20next_obj;=0A+=09=20=20}=0A+=09case=20= PVEC_SUB_CHAR_TABLE:=0A+=09=20=20{=0A+=09=20=20=20=20/*=20Make=20each=20= lowest=20sub_char_table=20start=20a=20new=20line.=0A+=09=20=20=20=20=20=20= =20Otherwise=20we'll=20make=20a=20line=20extremely=20long,=20which=0A+=09= =20=20=20=20=20=20=20results=20in=20slow=20redisplay.=20=20*/=0A+=09=20=20= =20=20if=20(XSUB_CHAR_TABLE=20(obj)->depth=20=3D=3D=203)=0A+=09=20=20=20=20= =20=20printchar=20('\n',=20printcharfun);=0A+=09=20=20=20=20= print_c_string=20("#^^[",=20printcharfun);=0A+=09=20=20=20=20int=20n=20=3D= =20sprintf=20(buf,=20"%d=20%d",=0A+=09=09=09=20=20=20=20=20= XSUB_CHAR_TABLE=20(obj)->depth,=0A+=09=09=09=20=20=20=20=20= XSUB_CHAR_TABLE=20(obj)->min_char);=0A+=09=20=20=20=20strout=20(buf,=20= n,=20n,=20printcharfun);=0A+=09=20=20=20=20print_stack_push_vector=20= ("",=20"]",=20obj,=0A+=09=09=09=09=20=20=20=20=20SUB_CHAR_TABLE_OFFSET,=20= PVSIZE=20(obj),=0A+=09=09=09=09=20=20=20=20=20printcharfun);=0A+=09=20=20= =20=20goto=20next_obj;=0A+=09=20=20}=0A+=09case=20PVEC_HASH_TABLE:=0A+=09= =20=20{=0A+=09=20=20=20=20struct=20Lisp_Hash_Table=20*h=20=3D=20= XHASH_TABLE=20(obj);=0A+=09=20=20=20=20/*=20Implement=20a=20readable=20= output,=20e.g.:=0A+=09=20=20=20=20=20=20=20#s(hash-table=20size=202=20= test=20equal=20data=20(k1=20v1=20k2=20v2))=20*/=0A+=09=20=20=20=20/*=20= Always=20print=20the=20size.=20=20*/=0A+=09=20=20=20=20int=20len=20=3D=20= sprintf=20(buf,=20"#s(hash-table=20size=20%"pD"d",=0A+=09=09=09=20=20=20=20= =20=20=20HASH_TABLE_SIZE=20(h));=0A+=09=20=20=20=20strout=20(buf,=20len,=20= len,=20printcharfun);=0A=20=0A-=09=20=20=20=20=20=20if=20(CONSP=20= (objtail)=20&&=20NILP=20(Vprint_circle))=0A-=09=09{=0A-=09=09=20=20int=20= len=20=3D=20sprintf=20(buf,=20"#%"PRIdMAX,=20i=20>>=201);=0A-=09=09=20=20= strout=20(buf,=20len,=20len,=20printcharfun);=0A-=09=09=20=20goto=20= end_of_list;=0A-=09=09}=0A+=09=20=20=20=20if=20(!NILP=20(h->test.name))=0A= +=09=20=20=20=20=20=20{=0A+=09=09print_c_string=20("=20test=20",=20= printcharfun);=0A+=09=09print_object=20(h->test.name,=20printcharfun,=20= escapeflag);=0A+=09=20=20=20=20=20=20}=0A=20=0A-=09=20=20=20=20=20=20= print_object=20(objtail,=20printcharfun,=20escapeflag);=0A-=09=20=20=20=20= }=0A+=09=20=20=20=20if=20(!NILP=20(h->weak))=0A+=09=20=20=20=20=20=20{=0A= +=09=09print_c_string=20("=20weakness=20",=20printcharfun);=0A+=09=09= print_object=20(h->weak,=20printcharfun,=20escapeflag);=0A+=09=20=20=20=20= =20=20}=0A=20=0A-=09end_of_list:=0A-=09=20=20printchar=20(')',=20= printcharfun);=0A+=09=20=20=20=20print_c_string=20("=20rehash-size=20",=20= printcharfun);=0A+=09=20=20=20=20print_object=20(Fhash_table_rehash_size=20= (obj),=0A+=09=09=09=20=20printcharfun,=20escapeflag);=0A+=0A+=09=20=20=20= =20print_c_string=20("=20rehash-threshold=20",=20printcharfun);=0A+=09=20= =20=20=20print_object=20(Fhash_table_rehash_threshold=20(obj),=0A+=09=09=09= =20=20printcharfun,=20escapeflag);=0A+=0A+=09=20=20=20=20if=20= (h->purecopy)=0A+=09=20=20=20=20=20=20print_c_string=20("=20purecopy=20= t",=20printcharfun);=0A+=0A+=09=20=20=20=20print_c_string=20("=20data=20= (",=20printcharfun);=0A+=0A+=09=20=20=20=20ptrdiff_t=20size=20=3D=20= h->count;=0A+=09=20=20=20=20/*=20Don't=20print=20more=20elements=20than=20= the=20specified=20maximum.=20=20*/=0A+=09=20=20=20=20if=20(FIXNATP=20= (Vprint_length)=20&&=20XFIXNAT=20(Vprint_length)=20<=20size)=0A+=09=20=20= =20=20=20=20size=20=3D=20XFIXNAT=20(Vprint_length);=0A+=0A+=09=20=20=20=20= print_stack_push=20((struct=20print_stack_entry){=0A+=09=09.type=20=3D=20= PE_hash,=0A+=09=09.u.hash.obj=20=3D=20obj,=0A+=09=09.u.hash.nobjs=20=3D=20= size=20*=202,=0A+=09=09.u.hash.idx=20=3D=200,=0A+=09=09.u.hash.printed=20= =3D=200,=0A+=09=09.u.hash.truncated=20=3D=20(size=20<=20h->count),=0A+=09= =20=20=20=20=20=20});=0A+=09=20=20=20=20goto=20next_obj;=0A+=09=20=20}=0A= +=0A+=09default:=0A+=09=20=20break;=0A=20=09}=0A-=20=20=20=20=20=20= break;=0A=20=0A-=20=20=20=20case=20Lisp_Vectorlike:=0A=20=20=20=20=20=20=20= if=20(print_vectorlike=20(obj,=20printcharfun,=20escapeflag,=20buf))=0A=20= =09break;=0A=20=20=20=20=20=20=20FALLTHROUGH;=0A+=0A=20=20=20=20=20= default:=0A=20=20=20=20=20=20=20{=0A=20=09int=20len;=0A@@=20-2464,10=20= +2538,160=20@@=20print_object=20(Lisp_Object=20obj,=20Lisp_Object=20= printcharfun,=20bool=20escapeflag)=0A=20=09print_c_string=20(("=20Save=20= your=20buffers=20immediately"=0A=20=09=09=09=20"=20and=20please=20report=20= this=20bug>"),=0A=20=09=09=09printcharfun);=0A+=09break;=0A=20=20=20=20=20= =20=20}=0A=20=20=20=20=20}=0A-=0A=20=20=20print_depth--;=0A+=0A+=20= next_obj:=0A+=20=20if=20(prstack.sp=20>=20base_sp)=0A+=20=20=20=20{=0A+=20= =20=20=20=20=20/*=20Handle=20a=20continuation=20on=20the=20print=20= stack.=20=20*/=0A+=20=20=20=20=20=20struct=20print_stack_entry=20*e=20=3D=20= &prstack.stack[prstack.sp=20-=201];=0A+=20=20=20=20=20=20switch=20= (e->type)=0A+=09{=0A+=09case=20PE_list:=0A+=09=20=20{=0A+=09=20=20=20=20= /*=20after=20"("=20ELEM=20(*=20"=20"=20ELEM)=20*/=0A+=09=20=20=20=20= Lisp_Object=20next=20=3D=20XCDR=20(e->u.list.last);=0A+=09=20=20=20=20if=20= (NILP=20(next))=0A+=09=20=20=20=20=20=20{=0A+=09=09/*=20end=20of=20list:=20= print=20")"=20*/=0A+=09=09printchar=20(')',=20printcharfun);=0A+=09=09= --prstack.sp;=0A+=09=09--print_depth;=0A+=09=09goto=20next_obj;=0A+=09=20= =20=20=20=20=20}=0A+=09=20=20=20=20else=20if=20(CONSP=20(next))=0A+=09=20= =20=20=20=20=20{=0A+=09=09if=20(!NILP=20(Vprint_circle))=0A+=09=09=20=20= {=0A+=09=09=20=20=20=20/*=20With=20the=20print-circle=20feature.=20=20*/=0A= +=09=09=20=20=20=20Lisp_Object=20num=20=3D=20Fgethash=20(next,=20= Vprint_number_table,=0A+=09=09=09=09=09=09Qnil);=0A+=09=09=20=20=20=20if=20= (FIXNUMP=20(num))=0A+=09=09=20=20=20=20=20=20{=0A+=09=09=09= print_c_string=20("=20.=20",=20printcharfun);=0A+=09=09=09obj=20=3D=20= next;=0A+=09=09=09e->type=20=3D=20PE_rbrac;=0A+=09=09=09goto=20= print_obj;=0A+=09=09=20=20=20=20}=0A+=09=09}=0A+=0A+=09=09/*=20list=20= continues:=20print=20"=20"=20ELEM=20...=20*/=0A+=0A+=09=09printchar=20('=20= ',=20printcharfun);=0A+=0A+=09=09/*=20FIXME:=20We=20wouldn't=20need=20to=20= keep=20track=20of=20idx=20if=20we=0A+=09=09=20=20=20count=20down=20= maxlen=20instead,=20and=20maintain=20a=20separate=0A+=09=09=20=20=20= tortoise=20index=20if=20required.=20=20*/=0A+=09=09if=20(e->u.list.idx=20= >=3D=20e->u.list.maxlen)=0A+=09=09=20=20{=0A+=09=09=20=20=20=20= print_c_string=20("...)",=20printcharfun);=0A+=09=09=20=20=20=20= --prstack.sp;=0A+=09=09=20=20=20=20--print_depth;=0A+=09=09=20=20=20=20= goto=20next_obj;=0A+=09=09=20=20}=0A+=0A+=09=09e->u.list.last=20=3D=20= next;=0A+=09=09e->u.list.idx++;=0A+=09=09e->u.list.n--;=0A+=09=09if=20= (e->u.list.n=20=3D=3D=200)=0A+=09=09=20=20{=0A+=09=09=20=20=20=20/*=20= Double=20tortoise=20update=20period=20and=20teleport=20it.=20=20*/=0A+=09= =09=20=20=20=20e->u.list.m=20<<=3D=201;=0A+=09=09=20=20=20=20e->u.list.n=20= =3D=20e->u.list.m;=0A+=09=09=20=20=20=20e->u.list.tortoise=20=3D=20next;=0A= +=09=09=20=20}=0A+=09=09else=20if=20(BASE_EQ=20(next,=20= e->u.list.tortoise))=0A+=09=09=20=20{=0A+=09=09=20=20=20=20/*=20FIXME:=20= This=20#N=20tail=20index=20is=20bug-compatible=20with=0A+=09=09=20=20=20=20= =20=20=20previous=20implementations=20but=20actually=20nonsense;=0A+=09=09= =20=20=20=20=20=20=20see=20bug#55395.=20=20*/=0A+=09=09=20=20=20=20int=20= len=20=3D=20sprintf=20(buf,=20".=20#%"=20PRIdMAX=20")",=0A+=09=09=09=09=20= =20=20=20=20=20=20(e->u.list.idx=20>>=201)=20-=201);=0A+=09=09=20=20=20=20= strout=20(buf,=20len,=20len,=20printcharfun);=0A+=09=09=20=20=20=20= --prstack.sp;=0A+=09=09=20=20=20=20--print_depth;=0A+=09=09=20=20=20=20= goto=20next_obj;=0A+=09=09=20=20}=0A+=09=09obj=20=3D=20XCAR=20(next);=0A= +=09=20=20=20=20=20=20}=0A+=09=20=20=20=20else=0A+=09=20=20=20=20=20=20{=0A= +=09=09/*=20non-nil=20ending:=20print=20"=20.=20"=20ELEM=20")"=20*/=0A+=09= =09print_c_string=20("=20.=20",=20printcharfun);=0A+=09=09obj=20=3D=20= next;=0A+=09=09e->type=20=3D=20PE_rbrac;=0A+=09=20=20=20=20=20=20}=0A+=09= =20=20=20=20break;=0A+=09=20=20}=0A+=0A+=09case=20PE_rbrac:=0A+=09=20=20= printchar=20(')',=20printcharfun);=0A+=09=20=20--prstack.sp;=0A+=09=20=20= --print_depth;=0A+=09=20=20goto=20next_obj;=0A+=0A+=09case=20PE_vector:=0A= +=09=20=20if=20(e->u.vector.idx=20>=3D=20e->u.vector.size)=0A+=09=20=20=20= =20{=0A+=09=20=20=20=20=20=20if=20(e->u.vector.truncated)=0A+=09=09{=0A+=09= =09=20=20if=20(e->u.vector.idx=20>=200)=0A+=09=09=20=20=20=20printchar=20= ('=20',=20printcharfun);=0A+=09=09=20=20print_c_string=20("...",=20= printcharfun);=0A+=09=09}=0A+=09=20=20=20=20=20=20print_c_string=20= (e->u.vector.end,=20printcharfun);=0A+=09=20=20=20=20=20=20--prstack.sp;=0A= +=09=20=20=20=20=20=20--print_depth;=0A+=09=20=20=20=20=20=20goto=20= next_obj;=0A+=09=20=20=20=20}=0A+=09=20=20if=20(e->u.vector.idx=20>=200)=0A= +=09=20=20=20=20printchar=20('=20',=20printcharfun);=0A+=09=20=20obj=20=3D= =20AREF=20(e->u.vector.obj,=20e->u.vector.idx);=0A+=09=20=20= e->u.vector.idx++;=0A+=09=20=20break;=0A+=0A+=09case=20PE_hash:=0A+=09=20= =20if=20(e->u.hash.printed=20>=3D=20e->u.hash.nobjs)=0A+=09=20=20=20=20{=0A= +=09=20=20=20=20=20=20if=20(e->u.hash.truncated)=0A+=09=09{=0A+=09=09=20=20= if=20(e->u.hash.printed)=0A+=09=09=20=20=20=20printchar=20('=20',=20= printcharfun);=0A+=09=09=20=20print_c_string=20("...",=20printcharfun);=0A= +=09=09}=0A+=09=20=20=20=20=20=20print_c_string=20("))",=20= printcharfun);=0A+=09=20=20=20=20=20=20--prstack.sp;=0A+=09=20=20=20=20=20= =20--print_depth;=0A+=09=20=20=20=20=20=20goto=20next_obj;=0A+=09=20=20=20= =20}=0A+=0A+=09=20=20if=20(e->u.hash.printed)=0A+=09=20=20=20=20= printchar=20('=20',=20printcharfun);=0A+=0A+=09=20=20struct=20= Lisp_Hash_Table=20*h=20=3D=20XHASH_TABLE=20(e->u.hash.obj);=0A+=09=20=20= if=20((e->u.hash.printed=20&=201)=20=3D=3D=200)=0A+=09=20=20=20=20{=0A+=09= =20=20=20=20=20=20Lisp_Object=20key;=0A+=09=20=20=20=20=20=20ptrdiff_t=20= idx=20=3D=20e->u.hash.idx;=0A+=09=20=20=20=20=20=20while=20(BASE_EQ=20= ((key=20=3D=20HASH_KEY=20(h,=20idx)),=20Qunbound))=0A+=09=09idx++;=0A+=09= =20=20=20=20=20=20e->u.hash.idx=20=3D=20idx;=0A+=09=20=20=20=20=20=20obj=20= =3D=20key;=0A+=09=20=20=20=20}=0A+=09=20=20else=0A+=09=20=20=20=20{=0A+=09= =20=20=20=20=20=20obj=20=3D=20HASH_VALUE=20(h,=20e->u.hash.idx);=0A+=09=20= =20=20=20=20=20e->u.hash.idx++;=0A+=09=20=20=20=20}=0A+=09=20=20= e->u.hash.printed++;=0A+=09=20=20break;=0A+=09}=0A+=20=20=20=20=20=20= goto=20print_obj;=0A+=20=20=20=20}=0A+=20=20eassert=20(print_depth=20=3D=3D= =20base_depth);=0A=20}=0A=20=0C=0A=20=0Adiff=20--git=20= a/test/src/print-tests.el=20b/test/src/print-tests.el=0Aindex=20= b9b282e580..1b28fd19ee=20100644=0A---=20a/test/src/print-tests.el=0A+++=20= b/test/src/print-tests.el=0A@@=20-468,5=20+468,21=20@@=20= test-prin1-to-string-overrides=0A=20=20=20(should-error=20= (prin1-to-string=20'foo=20nil=20'((a=20.=20b)=20b)))=0A=20=20=20= (should-error=20(prin1-to-string=20'foo=20nil=20'((length=20.=2010)=20.=20= b))))=0A=20=0A+(ert-deftest=20print-deeply-nested=20()=0A+=20=20;;=20= Check=20that=20we=20can=20print=20a=20deeply=20nested=20data=20structure=20= correctly.=0A+=20=20(let=20((print-circle=20t))=0A+=20=20=20=20(let=20= ((levels=2010000)=0A+=20=20=20=20=20=20=20=20=20=20(x=20'a)=0A+=20=20=20=20= =20=20=20=20=20=20(prefix=20nil)=0A+=20=20=20=20=20=20=20=20=20=20= (suffix=20nil))=0A+=20=20=20=20=20=20(dotimes=20(_=20levels)=0A+=20=20=20= =20=20=20=20=20(setq=20x=20(list=20(vector=20(record=20'r=20x))))=0A+=20=20= =20=20=20=20=20=20(push=20"([#s(r=20"=20prefix)=0A+=20=20=20=20=20=20=20=20= (push=20")])"=20suffix))=0A+=20=20=20=20=20=20(let=20((expected=20= (concat=20(apply=20#'concat=20prefix)=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"a"=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(apply=20#'concat=20suffix))))=0A+=20=20=20=20=20=20=20=20(should=20= (equal=20(prin1-to-string=20x)=20expected))))))=0A+=0A=20(provide=20= 'print-tests)=0A=20;;;=20print-tests.el=20ends=20here=0A= --Apple-Mail=_1430A473-B862-48C1-9974-717A57E2E1B3--