This source file includes following definitions.
- print_free_buffer
- print_unwind
- print_prepare
- print_finish
- printchar_to_stream
- printchar
- octalout
- strout
- print_string
- print_c_string
- write_string
- temp_output_buffer_setup
- print_bind_all_defaults
- print_create_variable_mapping
- print_bind_overrides
- DEFUN
- DEFUN
- debug_output_compilation_hack
- debug_print
- safe_debug_print
- debug_format
- DEFUN
- print_error_message
- float_to_string
- print
- grow_pp_stack
- pp_stack_push_value
- pp_stack_push_values
- pp_stack_empty_p
- pp_stack_pop
- print_preprocess
- DEFUN
- print_preprocess_string
- print_check_string_charset_prop
- print_prune_string_charset
- data_from_funcptr
- print_pointer
- print_vectorlike
- named_escape
- grow_print_stack
- print_stack_push
- print_stack_push_vector
- print_object
- print_interval
- init_print_once
- syms_of_print
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #include <config.h>
22 #include "sysstdio.h"
23
24 #include "lisp.h"
25 #include "character.h"
26 #include "coding.h"
27 #include "buffer.h"
28 #include "charset.h"
29 #include "frame.h"
30 #include "process.h"
31 #include "disptab.h"
32 #include "intervals.h"
33 #include "blockinput.h"
34 #include "xwidget.h"
35 #include "dynlib.h"
36
37 #include <c-ctype.h>
38 #include <float.h>
39 #include <ftoastr.h>
40 #include <math.h>
41
42 #if IEEE_FLOATING_POINT
43 # include <ieee754.h>
44 #endif
45
46 #ifdef WINDOWSNT
47 # include <sys/socket.h>
48 #endif
49
50 #ifdef HAVE_TREE_SITTER
51 #include "treesit.h"
52 #endif
53
54 struct terminal;
55
56
57 static ptrdiff_t print_depth;
58
59
60 static ptrdiff_t new_backquote_output;
61
62
63 #define PRINT_CIRCLE 200
64 static Lisp_Object being_printed[PRINT_CIRCLE];
65
66
67 static unsigned int printchar_stdout_last;
68
69 struct print_buffer
70 {
71 char *buffer;
72 ptrdiff_t size;
73 ptrdiff_t pos;
74 ptrdiff_t pos_byte;
75 };
76
77
78
79 static struct print_buffer print_buffer;
80
81
82
83
84
85
86
87
88
89 static ptrdiff_t print_number_index;
90 static void print_interval (INTERVAL interval, Lisp_Object printcharfun);
91
92
93 bool print_output_debug_flag EXTERNALLY_VISIBLE = 1;
94
95
96
97
98
99
100 static void
101 print_free_buffer (void)
102 {
103 xfree (print_buffer.buffer);
104 print_buffer.buffer = NULL;
105 }
106
107
108
109 static void
110 print_unwind (Lisp_Object saved_text)
111 {
112 memcpy (print_buffer.buffer, SDATA (saved_text), SCHARS (saved_text));
113 }
114
115
116
117
118
119
120
121 struct print_context
122 {
123 Lisp_Object printcharfun;
124 Lisp_Object old_printcharfun;
125 ptrdiff_t old_point, start_point;
126 ptrdiff_t old_point_byte, start_point_byte;
127 specpdl_ref specpdl_count;
128 };
129
130 static inline struct print_context
131 print_prepare (Lisp_Object printcharfun)
132 {
133 struct print_context pc = {
134 .old_printcharfun = printcharfun,
135 .old_point = -1,
136 .start_point = -1,
137 .old_point_byte = -1,
138 .start_point_byte = -1,
139 .specpdl_count = SPECPDL_INDEX (),
140 };
141 bool multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
142 record_unwind_current_buffer ();
143 specbind(Qprint__unreadable_callback_buffer, Fcurrent_buffer ());
144 if (NILP (printcharfun))
145 printcharfun = Qt;
146 if (BUFFERP (printcharfun))
147 {
148 if (XBUFFER (printcharfun) != current_buffer)
149 Fset_buffer (printcharfun);
150 printcharfun = Qnil;
151 }
152 if (MARKERP (printcharfun))
153 {
154 if (! XMARKER (printcharfun)->buffer)
155 error ("Marker does not point anywhere");
156 if (XMARKER (printcharfun)->buffer != current_buffer)
157 set_buffer_internal (XMARKER (printcharfun)->buffer);
158 ptrdiff_t marker_pos = marker_position (printcharfun);
159 if (marker_pos < BEGV || marker_pos > ZV)
160 signal_error ("Marker is outside the accessible part of the buffer",
161 printcharfun);
162 pc.old_point = PT;
163 pc.old_point_byte = PT_BYTE;
164 SET_PT_BOTH (marker_pos, marker_byte_position (printcharfun));
165 pc.start_point = PT;
166 pc.start_point_byte = PT_BYTE;
167 printcharfun = Qnil;
168 }
169 if (NILP (printcharfun))
170 {
171 if (NILP (BVAR (current_buffer, enable_multibyte_characters))
172 && ! print_escape_multibyte)
173 specbind (Qprint_escape_multibyte, Qt);
174 if (! NILP (BVAR (current_buffer, enable_multibyte_characters))
175 && ! print_escape_nonascii)
176 specbind (Qprint_escape_nonascii, Qt);
177 if (print_buffer.buffer != NULL)
178 {
179 Lisp_Object string = make_string_from_bytes (print_buffer.buffer,
180 print_buffer.pos,
181 print_buffer.pos_byte);
182 record_unwind_protect (print_unwind, string);
183 }
184 else
185 {
186 int new_size = 1000;
187 print_buffer.buffer = xmalloc (new_size);
188 print_buffer.size = new_size;
189 record_unwind_protect_void (print_free_buffer);
190 }
191 print_buffer.pos = 0;
192 print_buffer.pos_byte = 0;
193 }
194 if (EQ (printcharfun, Qt) && ! noninteractive)
195 setup_echo_area_for_printing (multibyte);
196 pc.printcharfun = printcharfun;
197 return pc;
198 }
199
200 static inline void
201 print_finish (struct print_context *pc)
202 {
203 if (NILP (pc->printcharfun))
204 {
205 if (print_buffer.pos != print_buffer.pos_byte
206 && NILP (BVAR (current_buffer, enable_multibyte_characters)))
207 {
208 USE_SAFE_ALLOCA;
209 unsigned char *temp = SAFE_ALLOCA (print_buffer.pos + 1);
210 copy_text ((unsigned char *) print_buffer.buffer, temp,
211 print_buffer.pos_byte, 1, 0);
212 insert_1_both ((char *) temp, print_buffer.pos,
213 print_buffer.pos, 0, 1, 0);
214 SAFE_FREE ();
215 }
216 else
217 insert_1_both (print_buffer.buffer, print_buffer.pos,
218 print_buffer.pos_byte, 0, 1, 0);
219 signal_after_change (PT - print_buffer.pos, 0, print_buffer.pos);
220 }
221 if (MARKERP (pc->old_printcharfun))
222 set_marker_both (pc->old_printcharfun, Qnil, PT, PT_BYTE);
223 if (pc->old_point >= 0)
224 SET_PT_BOTH (pc->old_point
225 + (pc->old_point >= pc->start_point
226 ? PT - pc->start_point : 0),
227 pc->old_point_byte
228 + (pc->old_point_byte >= pc->start_point_byte
229 ? PT_BYTE - pc->start_point_byte : 0));
230 unbind_to (pc->specpdl_count, Qnil);
231 }
232
233
234
235 static void
236 printchar_to_stream (unsigned int ch, FILE *stream)
237 {
238 Lisp_Object dv UNINIT;
239 ptrdiff_t i = 0, n = 1;
240 Lisp_Object coding_system = Vlocale_coding_system;
241 bool encode_p = false;
242
243 if (!NILP (Vcoding_system_for_write))
244 coding_system = Vcoding_system_for_write;
245 if (!NILP (coding_system))
246 encode_p = true;
247
248 if (CHAR_VALID_P (ch) && DISP_TABLE_P (Vstandard_display_table))
249 {
250 dv = DISP_CHAR_VECTOR (XCHAR_TABLE (Vstandard_display_table), ch);
251 if (VECTORP (dv))
252 {
253 n = ASIZE (dv);
254 goto next_char;
255 }
256 }
257
258 while (true)
259 {
260 if (ASCII_CHAR_P (ch))
261 {
262 putc (ch, stream);
263 #ifdef WINDOWSNT
264
265
266 if (print_output_debug_flag && stream == stderr)
267 OutputDebugString ((char []) {ch, '\0'});
268 #endif
269 }
270 else
271 {
272 unsigned char mbstr[MAX_MULTIBYTE_LENGTH];
273 int len = CHAR_STRING (ch, mbstr);
274 Lisp_Object encoded_ch =
275 make_multibyte_string ((char *) mbstr, 1, len);
276
277 if (encode_p)
278 encoded_ch = code_convert_string_norecord (encoded_ch,
279 coding_system, true);
280 fwrite (SSDATA (encoded_ch), 1, SBYTES (encoded_ch), stream);
281 #ifdef WINDOWSNT
282 if (print_output_debug_flag && stream == stderr)
283 OutputDebugString (SSDATA (encoded_ch));
284 #endif
285 }
286
287 i++;
288
289 next_char:
290 for (; i < n; i++)
291 if (CHARACTERP (AREF (dv, i)))
292 break;
293 if (! (i < n))
294 break;
295 ch = XFIXNAT (AREF (dv, i));
296 }
297 }
298
299
300
301
302
303
304 static void
305 printchar (unsigned int ch, Lisp_Object fun)
306 {
307 if (!NILP (fun) && !EQ (fun, Qt))
308 call1 (fun, make_fixnum (ch));
309 else
310 {
311 unsigned char str[MAX_MULTIBYTE_LENGTH];
312 int len = CHAR_STRING (ch, str);
313
314 maybe_quit ();
315
316 if (NILP (fun))
317 {
318 ptrdiff_t incr = len - (print_buffer.size - print_buffer.pos_byte);
319 if (incr > 0)
320 print_buffer.buffer = xpalloc (print_buffer.buffer,
321 &print_buffer.size,
322 incr, -1, 1);
323 memcpy (print_buffer.buffer + print_buffer.pos_byte, str, len);
324 print_buffer.pos += 1;
325 print_buffer.pos_byte += len;
326 }
327 else if (noninteractive)
328 {
329 printchar_stdout_last = ch;
330 if (DISP_TABLE_P (Vstandard_display_table))
331 printchar_to_stream (ch, stdout);
332 else
333 fwrite (str, 1, len, stdout);
334 noninteractive_need_newline = 1;
335 }
336 else
337 {
338 bool multibyte_p
339 = !NILP (BVAR (current_buffer, enable_multibyte_characters));
340
341 setup_echo_area_for_printing (multibyte_p);
342 insert_char (ch);
343 message_dolog ((char *) str, len, 0, multibyte_p);
344 }
345 }
346 }
347
348
349
350
351
352
353
354
355 static void
356 octalout (unsigned char c, unsigned char *data, ptrdiff_t i, ptrdiff_t size,
357 Lisp_Object printcharfun)
358 {
359 int digits = (c > '\77' || (i < size && '0' <= data[i] && data[i] <= '7')
360 ? 3
361 : c > '\7' ? 2 : 1);
362 printchar ('\\', printcharfun);
363 do
364 printchar ('0' + ((c >> (3 * --digits)) & 7), printcharfun);
365 while (digits != 0);
366 }
367
368
369
370
371
372
373
374
375
376
377
378 static void
379 strout (const char *ptr, ptrdiff_t size, ptrdiff_t size_byte,
380 Lisp_Object printcharfun)
381 {
382 if (NILP (printcharfun))
383 {
384 ptrdiff_t incr = size_byte - (print_buffer.size - print_buffer.pos_byte);
385 if (incr > 0)
386 print_buffer.buffer = xpalloc (print_buffer.buffer,
387 &print_buffer.size, incr, -1, 1);
388 memcpy (print_buffer.buffer + print_buffer.pos_byte, ptr, size_byte);
389 print_buffer.pos += size;
390 print_buffer.pos_byte += size_byte;
391 }
392 else if (noninteractive && EQ (printcharfun, Qt))
393 {
394 if (DISP_TABLE_P (Vstandard_display_table))
395 {
396 int len;
397 for (ptrdiff_t i = 0; i < size_byte; i += len)
398 {
399 int ch = string_char_and_length ((const unsigned char *) ptr + i,
400 &len);
401 printchar_to_stream (ch, stdout);
402 }
403 }
404 else
405 fwrite (ptr, 1, size_byte, stdout);
406
407 noninteractive_need_newline = 1;
408 }
409 else if (EQ (printcharfun, Qt))
410 {
411
412
413
414 int i;
415 bool multibyte_p
416 = !NILP (BVAR (current_buffer, enable_multibyte_characters));
417
418 setup_echo_area_for_printing (multibyte_p);
419 message_dolog (ptr, size_byte, 0, multibyte_p);
420
421 if (size == size_byte)
422 {
423 for (i = 0; i < size; ++i)
424 insert_char ((unsigned char) *ptr++);
425 }
426 else
427 {
428 int len;
429 for (i = 0; i < size_byte; i += len)
430 {
431 int ch = string_char_and_length ((const unsigned char *) ptr + i,
432 &len);
433 insert_char (ch);
434 }
435 }
436 }
437 else
438 {
439
440 ptrdiff_t i = 0;
441
442 if (size == size_byte)
443 {
444 while (i < size_byte)
445 {
446 int ch = ptr[i++];
447 printchar (ch, printcharfun);
448 }
449 }
450 else
451 {
452 while (i < size_byte)
453 {
454
455
456
457 int len, ch = (string_char_and_length
458 ((const unsigned char *) ptr + i, &len));
459 printchar (ch, printcharfun);
460 i += len;
461 }
462 }
463 }
464 }
465
466
467
468
469
470 static void
471 print_string (Lisp_Object string, Lisp_Object printcharfun)
472 {
473 if (EQ (printcharfun, Qt) || NILP (printcharfun))
474 {
475 ptrdiff_t chars;
476
477 if (print_escape_nonascii)
478 string = string_escape_byte8 (string);
479
480 if (STRING_MULTIBYTE (string))
481 chars = SCHARS (string);
482 else if (! print_escape_nonascii
483 && (EQ (printcharfun, Qt)
484 ? ! NILP (BVAR (&buffer_defaults, enable_multibyte_characters))
485 : ! NILP (BVAR (current_buffer, enable_multibyte_characters))))
486 {
487
488
489
490 Lisp_Object newstr;
491 ptrdiff_t bytes;
492
493 chars = SBYTES (string);
494 bytes = count_size_as_multibyte (SDATA (string), chars);
495 if (chars < bytes)
496 {
497 newstr = make_uninit_multibyte_string (chars, bytes);
498 str_to_multibyte (SDATA (newstr), SDATA (string), chars);
499 string = newstr;
500 }
501 }
502 else
503 chars = SBYTES (string);
504
505 if (EQ (printcharfun, Qt))
506 {
507
508 ptrdiff_t nbytes = SBYTES (string);
509
510
511
512 USE_SAFE_ALLOCA;
513 char *buffer = SAFE_ALLOCA (nbytes);
514 memcpy (buffer, SDATA (string), nbytes);
515
516 strout (buffer, chars, nbytes, printcharfun);
517
518 SAFE_FREE ();
519 }
520 else
521
522 strout (SSDATA (string), chars, SBYTES (string), printcharfun);
523 }
524 else
525 {
526
527
528 ptrdiff_t i;
529 ptrdiff_t size = SCHARS (string);
530 ptrdiff_t size_byte = SBYTES (string);
531 if (size == size_byte)
532 for (i = 0; i < size; i++)
533 printchar (SREF (string, i), printcharfun);
534 else
535 for (i = 0; i < size_byte; )
536 {
537
538
539 int len, ch = string_char_and_length (SDATA (string) + i, &len);
540 printchar (ch, printcharfun);
541 i += len;
542 }
543 }
544 }
545
546 DEFUN ("write-char", Fwrite_char, Swrite_char, 1, 2, 0,
547 doc:
548 )
549 (Lisp_Object character, Lisp_Object printcharfun)
550 {
551 if (NILP (printcharfun))
552 printcharfun = Vstandard_output;
553 CHECK_FIXNUM (character);
554 struct print_context pc = print_prepare (printcharfun);
555 printchar (XFIXNUM (character), pc.printcharfun);
556 print_finish (&pc);
557 return character;
558 }
559
560
561
562
563
564 static void
565 print_c_string (char const *string, Lisp_Object printcharfun)
566 {
567 ptrdiff_t len = strlen (string);
568 strout (string, len, len, printcharfun);
569 }
570
571
572
573
574 static void
575 write_string (const char *data, Lisp_Object printcharfun)
576 {
577 struct print_context pc = print_prepare (printcharfun);
578 print_c_string (data, pc.printcharfun);
579 print_finish (&pc);
580 }
581
582
583 void
584 temp_output_buffer_setup (const char *bufname)
585 {
586 specpdl_ref count = SPECPDL_INDEX ();
587 register struct buffer *old = current_buffer;
588 register Lisp_Object buf;
589
590 record_unwind_current_buffer ();
591
592 Fset_buffer (Fget_buffer_create (build_string (bufname), Qnil));
593
594 Fkill_all_local_variables (Qnil);
595 delete_all_overlays (current_buffer);
596 bset_directory (current_buffer, BVAR (old, directory));
597 bset_read_only (current_buffer, Qnil);
598 bset_filename (current_buffer, Qnil);
599 bset_undo_list (current_buffer, Qt);
600 eassert (current_buffer->overlays == NULL);
601 bset_enable_multibyte_characters
602 (current_buffer, BVAR (&buffer_defaults, enable_multibyte_characters));
603 specbind (Qinhibit_read_only, Qt);
604 specbind (Qinhibit_modification_hooks, Qt);
605 Ferase_buffer ();
606 XSETBUFFER (buf, current_buffer);
607
608 run_hook (Qtemp_buffer_setup_hook);
609
610 unbind_to (count, Qnil);
611
612 specbind (Qstandard_output, buf);
613 }
614
615 static void print (Lisp_Object, Lisp_Object, bool);
616 static void print_preprocess (Lisp_Object);
617 static void print_preprocess_string (INTERVAL, void *);
618 static void print_object (Lisp_Object, Lisp_Object, bool);
619
620 DEFUN ("terpri", Fterpri, Sterpri, 0, 2, 0,
621 doc:
622
623
624 )
625 (Lisp_Object printcharfun, Lisp_Object ensure)
626 {
627 Lisp_Object val;
628
629 if (NILP (printcharfun))
630 printcharfun = Vstandard_output;
631 struct print_context pc = print_prepare (printcharfun);
632
633 if (NILP (ensure))
634 val = Qt;
635
636 else if (FUNCTIONP (pc.printcharfun))
637 signal_error ("Unsupported function argument", pc.printcharfun);
638 else if (noninteractive && !NILP (pc.printcharfun))
639 val = printchar_stdout_last == 10 ? Qnil : Qt;
640 else
641 val = NILP (Fbolp ()) ? Qt : Qnil;
642
643 if (!NILP (val))
644 printchar ('\n', pc.printcharfun);
645 print_finish (&pc);
646 return val;
647 }
648
649 static Lisp_Object Vprint_variable_mapping;
650
651 static void
652 print_bind_all_defaults (void)
653 {
654 for (Lisp_Object vars = Vprint_variable_mapping; !NILP (vars);
655 vars = XCDR (vars))
656 {
657 Lisp_Object elem = XCDR (XCAR (vars));
658 specbind (XCAR (elem), XCAR (XCDR (elem)));
659 }
660 }
661
662 static void
663 print_create_variable_mapping (void)
664 {
665 Lisp_Object total[] = {
666 list3 (intern ("length"), intern ("print-length"), Qnil),
667 list3 (intern ("level"), intern ("print-level"), Qnil),
668 list3 (intern ("circle"), intern ("print-circle"), Qnil),
669 list3 (intern ("quoted"), intern ("print-quoted"), Qt),
670 list3 (intern ("escape-newlines"), intern ("print-escape-newlines"), Qnil),
671 list3 (intern ("escape-control-characters"),
672 intern ("print-escape-control-characters"), Qnil),
673 list3 (intern ("escape-nonascii"), intern ("print-escape-nonascii"), Qnil),
674 list3 (intern ("escape-multibyte"),
675 intern ("print-escape-multibyte"), Qnil),
676 list3 (intern ("charset-text-property"),
677 intern ("print-charset-text-property"), Qnil),
678 list3 (intern ("unreadeable-function"),
679 intern ("print-unreadable-function"), Qnil),
680 list3 (intern ("gensym"), intern ("print-gensym"), Qnil),
681 list3 (intern ("continuous-numbering"),
682 intern ("print-continuous-numbering"), Qnil),
683 list3 (intern ("number-table"), intern ("print-number-table"), Qnil),
684 list3 (intern ("float-format"), intern ("float-output-format"), Qnil),
685 list3 (intern ("integers-as-characters"),
686 intern ("print-integers-as-characters"), Qnil),
687 };
688
689 Vprint_variable_mapping = CALLMANY (Flist, total);
690 }
691
692 static void
693 print_bind_overrides (Lisp_Object overrides)
694 {
695 if (NILP (Vprint_variable_mapping))
696 print_create_variable_mapping ();
697
698 if (EQ (overrides, Qt))
699 print_bind_all_defaults ();
700 else if (!CONSP (overrides))
701 xsignal (Qwrong_type_argument, Qconsp);
702 else
703 {
704 while (!NILP (overrides))
705 {
706 Lisp_Object setting = XCAR (overrides);
707 if (EQ (setting, Qt))
708 print_bind_all_defaults ();
709 else if (!CONSP (setting))
710 xsignal (Qwrong_type_argument, Qconsp);
711 else
712 {
713 Lisp_Object key = XCAR (setting),
714 value = XCDR (setting);
715 Lisp_Object map = Fassq (key, Vprint_variable_mapping);
716 if (NILP (map))
717 xsignal2 (Qwrong_type_argument, Qsymbolp, map);
718 specbind (XCAR (XCDR (map)), value);
719 }
720
721 if (!NILP (XCDR (overrides)) && !CONSP (XCDR (overrides)))
722 xsignal (Qwrong_type_argument, Qconsp);
723 overrides = XCDR (overrides);
724 }
725 }
726 }
727
728 DEFUN ("prin1", Fprin1, Sprin1, 1, 3, 0,
729 doc:
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765 )
766 (Lisp_Object object, Lisp_Object printcharfun, Lisp_Object overrides)
767 {
768 specpdl_ref count = SPECPDL_INDEX ();
769
770 if (NILP (printcharfun))
771 printcharfun = Vstandard_output;
772 if (!NILP (overrides))
773 print_bind_overrides (overrides);
774
775 struct print_context pc = print_prepare (printcharfun);
776 print (object, pc.printcharfun, 1);
777 print_finish (&pc);
778
779 return unbind_to (count, object);
780 }
781
782
783 Lisp_Object Vprin1_to_string_buffer;
784
785 DEFUN ("prin1-to-string", Fprin1_to_string, Sprin1_to_string, 1, 3, 0,
786 doc:
787
788
789
790
791
792
793
794
795
796
797 )
798 (Lisp_Object object, Lisp_Object noescape, Lisp_Object overrides)
799 {
800 specpdl_ref count = SPECPDL_INDEX ();
801
802 specbind (Qinhibit_modification_hooks, Qt);
803
804 if (!NILP (overrides))
805 print_bind_overrides (overrides);
806
807
808
809
810 Lisp_Object save_deactivate_mark = Vdeactivate_mark;
811
812 struct print_context pc = print_prepare (Vprin1_to_string_buffer);
813 print (object, pc.printcharfun, NILP (noescape));
814
815 print_finish (&pc);
816
817 struct buffer *previous = current_buffer;
818 set_buffer_internal (XBUFFER (Vprin1_to_string_buffer));
819 object = Fbuffer_string ();
820 if (SBYTES (object) == SCHARS (object))
821 STRING_SET_UNIBYTE (object);
822
823
824
825
826 Ferase_buffer ();
827 set_buffer_internal (previous);
828
829 Vdeactivate_mark = save_deactivate_mark;
830
831 return unbind_to (count, object);
832 }
833
834 DEFUN ("princ", Fprinc, Sprinc, 1, 2, 0,
835 doc:
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855 )
856 (Lisp_Object object, Lisp_Object printcharfun)
857 {
858 if (NILP (printcharfun))
859 printcharfun = Vstandard_output;
860 struct print_context pc = print_prepare (printcharfun);
861 if (STRINGP (object)
862 && !string_intervals (object)
863 && NILP (Vprint_continuous_numbering))
864
865 print_string (object, pc.printcharfun);
866 else
867 print (object, pc.printcharfun, 0);
868 print_finish (&pc);
869 return object;
870 }
871
872 DEFUN ("print", Fprint, Sprint, 1, 2, 0,
873 doc:
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894 )
895 (Lisp_Object object, Lisp_Object printcharfun)
896 {
897 if (NILP (printcharfun))
898 printcharfun = Vstandard_output;
899 struct print_context pc = print_prepare (printcharfun);
900 printchar ('\n', pc.printcharfun);
901 print (object, pc.printcharfun, 1);
902 printchar ('\n', pc.printcharfun);
903 print_finish (&pc);
904 return object;
905 }
906
907 DEFUN ("flush-standard-output", Fflush_standard_output, Sflush_standard_output,
908 0, 0, 0,
909 doc:
910 )
911 (void)
912 {
913 fflush (stdout);
914 return Qnil;
915 }
916
917 DEFUN ("external-debugging-output", Fexternal_debugging_output, Sexternal_debugging_output, 1, 1, 0,
918 doc:
919
920 )
921 (Lisp_Object character)
922 {
923 CHECK_FIXNUM (character);
924 printchar_to_stream (XFIXNUM (character), stderr);
925 return character;
926 }
927
928
929
930
931 extern void debug_output_compilation_hack (bool) EXTERNALLY_VISIBLE;
932 void
933 debug_output_compilation_hack (bool x)
934 {
935 print_output_debug_flag = x;
936 }
937
938 DEFUN ("redirect-debugging-output", Fredirect_debugging_output, Sredirect_debugging_output,
939 1, 2,
940 "FDebug output file: \nP",
941 doc:
942
943
944 )
945 (Lisp_Object file, Lisp_Object append)
946 {
947
948
949 static int stderr_dup = STDERR_FILENO;
950 int fd = stderr_dup;
951
952 if (! NILP (file))
953 {
954 file = Fexpand_file_name (file, Qnil);
955
956 if (stderr_dup == STDERR_FILENO)
957 {
958 int n = fcntl (STDERR_FILENO, F_DUPFD_CLOEXEC, STDERR_FILENO + 1);
959 if (n < 0)
960 report_file_error ("dup", file);
961 stderr_dup = n;
962 }
963
964 fd = emacs_open (SSDATA (ENCODE_FILE (file)),
965 (O_WRONLY | O_CREAT
966 | (! NILP (append) ? O_APPEND : O_TRUNC)),
967 0666);
968 if (fd < 0)
969 report_file_error ("Cannot open debugging output stream", file);
970 }
971
972 fflush (stderr);
973 if (dup2 (fd, STDERR_FILENO) < 0)
974 report_file_error ("dup2", file);
975 if (fd != stderr_dup)
976 emacs_close (fd);
977 return Qnil;
978 }
979
980
981
982
983 void
984 debug_print (Lisp_Object arg)
985 {
986 Fprin1 (arg, Qexternal_debugging_output, Qnil);
987 fputs ("\r\n", stderr);
988 }
989
990 void safe_debug_print (Lisp_Object) EXTERNALLY_VISIBLE;
991 void
992 safe_debug_print (Lisp_Object arg)
993 {
994 int valid = valid_lisp_object_p (arg);
995
996 if (valid > 0)
997 debug_print (arg);
998 else
999 {
1000 EMACS_UINT n = XLI (arg);
1001 fprintf (stderr, "#<%s_LISP_OBJECT 0x%08"pI"x>\r\n",
1002 !valid ? "INVALID" : "SOME",
1003 n);
1004 }
1005 }
1006
1007
1008
1009
1010
1011 const char * debug_format (const char *, Lisp_Object) EXTERNALLY_VISIBLE;
1012 const char *
1013 debug_format (const char *fmt, Lisp_Object arg)
1014 {
1015 return SSDATA (CALLN (Fformat, build_string (fmt), arg));
1016 }
1017
1018
1019 DEFUN ("error-message-string", Ferror_message_string, Serror_message_string,
1020 1, 1, 0,
1021 doc:
1022
1023 )
1024 (Lisp_Object obj)
1025 {
1026 struct buffer *old = current_buffer;
1027 Lisp_Object value;
1028
1029
1030
1031
1032 if (CONSP (obj) && EQ (XCAR (obj), Qerror)
1033 && CONSP (XCDR (obj))
1034 && STRINGP (XCAR (XCDR (obj)))
1035 && NILP (XCDR (XCDR (obj))))
1036 return XCAR (XCDR (obj));
1037
1038 print_error_message (obj, Vprin1_to_string_buffer, 0, Qnil);
1039
1040 set_buffer_internal (XBUFFER (Vprin1_to_string_buffer));
1041 value = Fbuffer_string ();
1042
1043 Ferase_buffer ();
1044 set_buffer_internal (old);
1045
1046 return value;
1047 }
1048
1049
1050
1051
1052
1053
1054 void
1055 print_error_message (Lisp_Object data, Lisp_Object stream, const char *context,
1056 Lisp_Object caller)
1057 {
1058 Lisp_Object errname, errmsg, file_error, tail;
1059
1060 if (context != 0)
1061 write_string (context, stream);
1062
1063
1064
1065 if (!NILP (caller) && SYMBOLP (caller))
1066 {
1067 Lisp_Object cname = SYMBOL_NAME (caller);
1068 ptrdiff_t cnamelen = SBYTES (cname);
1069 USE_SAFE_ALLOCA;
1070 char *name = SAFE_ALLOCA (cnamelen);
1071 memcpy (name, SDATA (cname), cnamelen);
1072 message_dolog (name, cnamelen, 0, STRING_MULTIBYTE (cname));
1073 message_dolog (": ", 2, 0, 0);
1074 SAFE_FREE ();
1075 }
1076
1077 errname = Fcar (data);
1078
1079 if (EQ (errname, Qerror))
1080 {
1081 data = Fcdr (data);
1082 if (!CONSP (data))
1083 data = Qnil;
1084 errmsg = Fcar (data);
1085 file_error = Qnil;
1086 }
1087 else
1088 {
1089 Lisp_Object error_conditions = Fget (errname, Qerror_conditions);
1090 errmsg = Fget (errname, Qerror_message);
1091
1092 if (!NILP (Ffboundp (Qsubstitute_command_keys)))
1093 {
1094
1095
1096
1097 Lisp_Object subs = safe_call1 (Qsubstitute_command_keys, errmsg);
1098 if (!NILP (subs))
1099 errmsg = subs;
1100 }
1101
1102 file_error = Fmemq (Qfile_error, error_conditions);
1103 }
1104
1105
1106
1107 tail = Fcdr_safe (data);
1108
1109
1110
1111 if (!NILP (file_error) && CONSP (tail))
1112 errmsg = XCAR (tail), tail = XCDR (tail);
1113
1114 {
1115 const char *sep = ": ";
1116
1117 if (!STRINGP (errmsg))
1118 write_string ("peculiar error", stream);
1119 else if (SCHARS (errmsg))
1120 Fprinc (errmsg, stream);
1121 else
1122 sep = NULL;
1123
1124 FOR_EACH_TAIL (tail)
1125 {
1126 if (sep)
1127 write_string (sep, stream);
1128 sep = ", ";
1129 Lisp_Object obj = XCAR (tail);
1130 if (!NILP (file_error)
1131 || EQ (errname, Qend_of_file) || EQ (errname, Quser_error))
1132 Fprinc (obj, stream);
1133 else
1134 Fprin1 (obj, stream, Qnil);
1135 }
1136 }
1137 }
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156 int
1157 float_to_string (char *buf, double data)
1158 {
1159 char *cp;
1160 int width;
1161 int len;
1162
1163 if (isinf (data))
1164 {
1165 static char const minus_infinity_string[] = "-1.0e+INF";
1166 bool positive = 0 < data;
1167 strcpy (buf, minus_infinity_string + positive);
1168 return sizeof minus_infinity_string - 1 - positive;
1169 }
1170 #if IEEE_FLOATING_POINT
1171 if (isnan (data))
1172 {
1173 union ieee754_double u = { .d = data };
1174 uintmax_t hi = u.ieee_nan.mantissa0;
1175 return sprintf (buf, &"-%"PRIuMAX".0e+NaN"[!u.ieee_nan.negative],
1176 (hi << 31 << 1) + u.ieee_nan.mantissa1);
1177 }
1178 #endif
1179
1180 if (NILP (Vfloat_output_format)
1181 || !STRINGP (Vfloat_output_format))
1182 lose:
1183 {
1184
1185
1186 len = dtoastr (buf, FLOAT_TO_STRING_BUFSIZE - 2, 0, 0, data);
1187
1188
1189 width = 1;
1190 }
1191 else
1192 {
1193
1194
1195
1196 cp = SSDATA (Vfloat_output_format);
1197
1198 if (cp[0] != '%')
1199 goto lose;
1200 if (cp[1] != '.')
1201 goto lose;
1202
1203 cp += 2;
1204
1205
1206 width = -1;
1207 if ('0' <= *cp && *cp <= '9')
1208 {
1209 width = 0;
1210 do
1211 {
1212 width = (width * 10) + (*cp++ - '0');
1213 if (DBL_DIG < width)
1214 goto lose;
1215 }
1216 while (*cp >= '0' && *cp <= '9');
1217
1218
1219 if (width == 0 && *cp != 'f')
1220 goto lose;
1221 }
1222
1223 if (*cp != 'e' && *cp != 'f' && *cp != 'g')
1224 goto lose;
1225
1226 if (cp[1] != 0)
1227 goto lose;
1228
1229 len = sprintf (buf, SSDATA (Vfloat_output_format), data);
1230 }
1231
1232
1233
1234
1235
1236 if (width != 0)
1237 {
1238 for (cp = buf; *cp; cp++)
1239 if ((*cp < '0' || *cp > '9') && *cp != '-')
1240 break;
1241
1242 if (*cp == '.' && cp[1] == 0)
1243 {
1244 cp[1] = '0';
1245 cp[2] = 0;
1246 len++;
1247 }
1248 else if (*cp == 0)
1249 {
1250 *cp++ = '.';
1251 *cp++ = '0';
1252 *cp++ = 0;
1253 len += 2;
1254 }
1255 }
1256
1257 return len;
1258 }
1259
1260
1261 static void
1262 print (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
1263 {
1264 new_backquote_output = 0;
1265
1266
1267
1268
1269
1270 if (NILP (Vprint_continuous_numbering)
1271 || NILP (Vprint_number_table))
1272 {
1273 print_number_index = 0;
1274 Vprint_number_table = Qnil;
1275 }
1276
1277
1278 if (!NILP (Vprint_circle))
1279 {
1280
1281
1282 print_preprocess (obj);
1283
1284 if (HASH_TABLE_P (Vprint_number_table))
1285 {
1286
1287 struct Lisp_Hash_Table *h = XHASH_TABLE (Vprint_number_table);
1288 ptrdiff_t i;
1289
1290 for (i = 0; i < HASH_TABLE_SIZE (h); ++i)
1291 {
1292 Lisp_Object key = HASH_KEY (h, i);
1293 if (!BASE_EQ (key, Qunbound)
1294 && EQ (HASH_VALUE (h, i), Qt))
1295 Fremhash (key, Vprint_number_table);
1296 }
1297 }
1298 }
1299
1300 print_depth = 0;
1301 print_object (obj, printcharfun, escapeflag);
1302 }
1303
1304 #define PRINT_CIRCLE_CANDIDATE_P(obj) \
1305 (STRINGP (obj) \
1306 || CONSP (obj) \
1307 || (VECTORLIKEP (obj) \
1308 && (VECTORP (obj) || COMPILEDP (obj) \
1309 || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj) \
1310 || HASH_TABLE_P (obj) || FONTP (obj) \
1311 || RECORDP (obj))) \
1312 || (! NILP (Vprint_gensym) \
1313 && SYMBOLP (obj) \
1314 && !SYMBOL_INTERNED_P (obj)))
1315
1316
1317
1318 struct print_pp_entry {
1319 ptrdiff_t n;
1320 union {
1321 Lisp_Object value;
1322 Lisp_Object *values;
1323 } u;
1324 };
1325
1326 struct print_pp_stack {
1327 struct print_pp_entry *stack;
1328 ptrdiff_t size;
1329 ptrdiff_t sp;
1330 };
1331
1332 static struct print_pp_stack ppstack = {NULL, 0, 0};
1333
1334 NO_INLINE static void
1335 grow_pp_stack (void)
1336 {
1337 struct print_pp_stack *ps = &ppstack;
1338 eassert (ps->sp == ps->size);
1339 ps->stack = xpalloc (ps->stack, &ps->size, 1, -1, sizeof *ps->stack);
1340 eassert (ps->sp < ps->size);
1341 }
1342
1343 static inline void
1344 pp_stack_push_value (Lisp_Object value)
1345 {
1346 if (ppstack.sp >= ppstack.size)
1347 grow_pp_stack ();
1348 ppstack.stack[ppstack.sp++] = (struct print_pp_entry){.n = 0,
1349 .u.value = value};
1350 }
1351
1352 static inline void
1353 pp_stack_push_values (Lisp_Object *values, ptrdiff_t n)
1354 {
1355 eassume (n >= 0);
1356 if (n == 0)
1357 return;
1358 if (ppstack.sp >= ppstack.size)
1359 grow_pp_stack ();
1360 ppstack.stack[ppstack.sp++] = (struct print_pp_entry){.n = n,
1361 .u.values = values};
1362 }
1363
1364 static inline bool
1365 pp_stack_empty_p (void)
1366 {
1367 return ppstack.sp <= 0;
1368 }
1369
1370 static inline Lisp_Object
1371 pp_stack_pop (void)
1372 {
1373 eassume (!pp_stack_empty_p ());
1374 struct print_pp_entry *e = &ppstack.stack[ppstack.sp - 1];
1375 if (e->n == 0)
1376 {
1377 --ppstack.sp;
1378 return e->u.value;
1379 }
1380
1381
1382 e->n--;
1383 if (e->n == 0)
1384 --ppstack.sp;
1385 return (++e->u.values)[-1];
1386 }
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396 static void
1397 print_preprocess (Lisp_Object obj)
1398 {
1399 eassert (!NILP (Vprint_circle));
1400 ptrdiff_t base_sp = ppstack.sp;
1401
1402 for (;;)
1403 {
1404 if (PRINT_CIRCLE_CANDIDATE_P (obj))
1405 {
1406 if (!HASH_TABLE_P (Vprint_number_table))
1407 Vprint_number_table = CALLN (Fmake_hash_table, QCtest, Qeq);
1408
1409 Lisp_Object num = Fgethash (obj, Vprint_number_table, Qnil);
1410 if (!NILP (num)
1411
1412
1413
1414 || (!NILP (Vprint_continuous_numbering)
1415 && SYMBOLP (obj)
1416 && !SYMBOL_INTERNED_P (obj)))
1417 {
1418 if (!FIXNUMP (num))
1419 {
1420 print_number_index++;
1421
1422 Fputhash (obj, make_fixnum (- print_number_index),
1423 Vprint_number_table);
1424 }
1425 }
1426 else
1427 {
1428
1429 Fputhash (obj, Qt, Vprint_number_table);
1430
1431 switch (XTYPE (obj))
1432 {
1433 case Lisp_String:
1434
1435
1436 traverse_intervals_noorder (string_intervals (obj),
1437 print_preprocess_string, NULL);
1438 break;
1439
1440 case Lisp_Cons:
1441 if (!NILP (XCDR (obj)))
1442 pp_stack_push_value (XCDR (obj));
1443 obj = XCAR (obj);
1444 continue;
1445
1446 case Lisp_Vectorlike:
1447 {
1448 struct Lisp_Vector *vec = XVECTOR (obj);
1449 ptrdiff_t size = ASIZE (obj);
1450 if (size & PSEUDOVECTOR_FLAG)
1451 size &= PSEUDOVECTOR_SIZE_MASK;
1452 ptrdiff_t start = (SUB_CHAR_TABLE_P (obj)
1453 ? SUB_CHAR_TABLE_OFFSET : 0);
1454 pp_stack_push_values (vec->contents + start, size - start);
1455 if (HASH_TABLE_P (obj))
1456 {
1457 struct Lisp_Hash_Table *h = XHASH_TABLE (obj);
1458 obj = h->key_and_value;
1459 continue;
1460 }
1461 break;
1462 }
1463
1464 default:
1465 break;
1466 }
1467 }
1468 }
1469
1470 if (ppstack.sp <= base_sp)
1471 break;
1472 obj = pp_stack_pop ();
1473 }
1474 }
1475
1476 DEFUN ("print--preprocess", Fprint_preprocess, Sprint_preprocess, 1, 1, 0,
1477 doc:
1478
1479 )
1480 (Lisp_Object object)
1481 {
1482 if (!NILP (Vprint_circle))
1483 {
1484 print_number_index = 0;
1485 print_preprocess (object);
1486 }
1487 return Qnil;
1488 }
1489
1490 static void
1491 print_preprocess_string (INTERVAL interval, void *arg)
1492 {
1493 print_preprocess (interval->plist);
1494 }
1495
1496 static void print_check_string_charset_prop (INTERVAL interval, Lisp_Object string);
1497
1498 #define PRINT_STRING_NON_CHARSET_FOUND 1
1499 #define PRINT_STRING_UNSAFE_CHARSET_FOUND 2
1500
1501
1502 static int print_check_string_result;
1503
1504 static void
1505 print_check_string_charset_prop (INTERVAL interval, Lisp_Object string)
1506 {
1507 Lisp_Object val;
1508
1509 if (NILP (interval->plist)
1510 || (print_check_string_result == (PRINT_STRING_NON_CHARSET_FOUND
1511 | PRINT_STRING_UNSAFE_CHARSET_FOUND)))
1512 return;
1513 for (val = interval->plist; CONSP (val) && ! EQ (XCAR (val), Qcharset);
1514 val = XCDR (XCDR (val)));
1515 if (! CONSP (val))
1516 {
1517 print_check_string_result |= PRINT_STRING_NON_CHARSET_FOUND;
1518 return;
1519 }
1520 if (! (print_check_string_result & PRINT_STRING_NON_CHARSET_FOUND))
1521 {
1522 if (! EQ (val, interval->plist)
1523 || CONSP (XCDR (XCDR (val))))
1524 print_check_string_result |= PRINT_STRING_NON_CHARSET_FOUND;
1525 }
1526 if (! (print_check_string_result & PRINT_STRING_UNSAFE_CHARSET_FOUND))
1527 {
1528 ptrdiff_t charpos = interval->position;
1529 ptrdiff_t bytepos = string_char_to_byte (string, charpos);
1530 Lisp_Object charset = XCAR (XCDR (val));
1531
1532 for (ptrdiff_t i = 0; i < LENGTH (interval); i++)
1533 {
1534 int c = fetch_string_char_advance (string, &charpos, &bytepos);
1535 if (! ASCII_CHAR_P (c)
1536 && ! EQ (CHARSET_NAME (CHAR_CHARSET (c)), charset))
1537 {
1538 print_check_string_result |= PRINT_STRING_UNSAFE_CHARSET_FOUND;
1539 break;
1540 }
1541 }
1542 }
1543 }
1544
1545
1546 static Lisp_Object print_prune_charset_plist;
1547
1548 static Lisp_Object
1549 print_prune_string_charset (Lisp_Object string)
1550 {
1551 print_check_string_result = 0;
1552 traverse_intervals (string_intervals (string), 0,
1553 print_check_string_charset_prop, string);
1554 if (NILP (Vprint_charset_text_property)
1555 || ! (print_check_string_result & PRINT_STRING_UNSAFE_CHARSET_FOUND))
1556 {
1557 string = Fcopy_sequence (string);
1558 if (print_check_string_result & PRINT_STRING_NON_CHARSET_FOUND)
1559 {
1560 if (NILP (print_prune_charset_plist))
1561 print_prune_charset_plist = list1 (Qcharset);
1562 Fremove_text_properties (make_fixnum (0),
1563 make_fixnum (SCHARS (string)),
1564 print_prune_charset_plist, string);
1565 }
1566 else
1567 Fset_text_properties (make_fixnum (0), make_fixnum (SCHARS (string)),
1568 Qnil, string);
1569 }
1570 return string;
1571 }
1572
1573 #ifdef HAVE_MODULES
1574
1575
1576 static void const *
1577 data_from_funcptr (void (*funcptr) (void))
1578 {
1579
1580
1581
1582 return (void const *) funcptr;
1583 }
1584
1585
1586
1587 static void
1588 print_pointer (Lisp_Object printcharfun, char *buf, const char *prefix,
1589 const void *ptr)
1590 {
1591 uintptr_t ui = (uintptr_t) ptr;
1592
1593
1594
1595 uintmax_t up = ui;
1596
1597 int len = sprintf (buf, "%s 0x%" PRIxMAX, prefix, up);
1598 strout (buf, len, len, printcharfun);
1599 }
1600 #endif
1601
1602 static bool
1603 print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
1604 char *buf)
1605 {
1606
1607 switch (PSEUDOVECTOR_TYPE (XVECTOR (obj)))
1608 {
1609 case PVEC_BIGNUM:
1610 {
1611 ptrdiff_t size = bignum_bufsize (obj, 10);
1612 USE_SAFE_ALLOCA;
1613 char *str = SAFE_ALLOCA (size);
1614 ptrdiff_t len = bignum_to_c_string (str, size, obj, 10);
1615 strout (str, len, len, printcharfun);
1616 SAFE_FREE ();
1617 }
1618 return true;
1619
1620 case PVEC_BOOL_VECTOR:
1621 {
1622 EMACS_INT size = bool_vector_size (obj);
1623 ptrdiff_t size_in_bytes = bool_vector_bytes (size);
1624 ptrdiff_t real_size_in_bytes = size_in_bytes;
1625 unsigned char *data = bool_vector_uchar_data (obj);
1626
1627 int len = sprintf (buf, "#&%"pI"d\"", size);
1628 strout (buf, len, len, printcharfun);
1629
1630
1631
1632
1633 if (FIXNATP (Vprint_length)
1634 && XFIXNAT (Vprint_length) < size_in_bytes)
1635 size_in_bytes = XFIXNAT (Vprint_length);
1636
1637 for (ptrdiff_t i = 0; i < size_in_bytes; i++)
1638 {
1639 maybe_quit ();
1640 unsigned char c = data[i];
1641 if (c == '\n' && print_escape_newlines)
1642 print_c_string ("\\n", printcharfun);
1643 else if (c == '\f' && print_escape_newlines)
1644 print_c_string ("\\f", printcharfun);
1645 else if (c > '\177'
1646 || (print_escape_control_characters && c_iscntrl (c)))
1647 {
1648
1649 octalout (c, data, i + 1, size_in_bytes, printcharfun);
1650 }
1651 else
1652 {
1653 if (c == '\"' || c == '\\')
1654 printchar ('\\', printcharfun);
1655 printchar (c, printcharfun);
1656 }
1657 }
1658
1659 if (size_in_bytes < real_size_in_bytes)
1660 print_c_string (" ...", printcharfun);
1661 printchar ('\"', printcharfun);
1662 }
1663 return true;
1664
1665 default:
1666 break;
1667 }
1668
1669
1670
1671
1672 if (!NILP (Vprint_unreadable_function)
1673 && FUNCTIONP (Vprint_unreadable_function))
1674 {
1675 specpdl_ref count = SPECPDL_INDEX ();
1676
1677
1678 Lisp_Object func = Vprint_unreadable_function;
1679 specbind (Qprint_unreadable_function, Qnil);
1680
1681
1682
1683
1684
1685 if (!NILP (Vprint__unreadable_callback_buffer)
1686 && !NILP (Fbuffer_live_p (Vprint__unreadable_callback_buffer)))
1687 {
1688 record_unwind_current_buffer ();
1689 set_buffer_internal (XBUFFER (Vprint__unreadable_callback_buffer));
1690 }
1691 Lisp_Object result = CALLN (Ffuncall, func, obj,
1692 escapeflag? Qt: Qnil);
1693 unbind_to (count, Qnil);
1694
1695 if (!NILP (result))
1696 {
1697 if (STRINGP (result))
1698 print_string (result, printcharfun);
1699
1700 return true;
1701 }
1702 }
1703
1704
1705 switch (PSEUDOVECTOR_TYPE (XVECTOR (obj)))
1706 {
1707 case PVEC_MARKER:
1708 print_c_string ("#<marker ", printcharfun);
1709
1710 if (XMARKER (obj)->insertion_type != 0)
1711 print_c_string ("(moves after insertion) ", printcharfun);
1712 if (! XMARKER (obj)->buffer)
1713 print_c_string ("in no buffer", printcharfun);
1714 else
1715 {
1716 int len = sprintf (buf, "at %"pD"d in ", marker_position (obj));
1717 strout (buf, len, len, printcharfun);
1718 print_string (BVAR (XMARKER (obj)->buffer, name), printcharfun);
1719 }
1720 printchar ('>', printcharfun);
1721 break;
1722
1723 case PVEC_SYMBOL_WITH_POS:
1724 {
1725 struct Lisp_Symbol_With_Pos *sp = XSYMBOL_WITH_POS (obj);
1726 if (print_symbols_bare)
1727 print_object (sp->sym, printcharfun, escapeflag);
1728 else
1729 {
1730 print_c_string ("#<symbol ", printcharfun);
1731 if (BARE_SYMBOL_P (sp->sym))
1732 print_object (sp->sym, printcharfun, escapeflag);
1733 else
1734 print_c_string ("NOT A SYMBOL!!", printcharfun);
1735 if (FIXNUMP (sp->pos))
1736 {
1737 print_c_string (" at ", printcharfun);
1738 print_object (sp->pos, printcharfun, escapeflag);
1739 }
1740 else
1741 print_c_string (" NOT A POSITION!!", printcharfun);
1742 printchar ('>', printcharfun);
1743 }
1744 }
1745 break;
1746
1747 case PVEC_OVERLAY:
1748 print_c_string ("#<overlay ", printcharfun);
1749 if (! OVERLAY_BUFFER (obj))
1750 print_c_string ("in no buffer", printcharfun);
1751 else
1752 {
1753 int len = sprintf (buf, "from %"pD"d to %"pD"d in ",
1754 OVERLAY_START (obj),
1755 OVERLAY_END (obj));
1756 strout (buf, len, len, printcharfun);
1757 print_string (BVAR (OVERLAY_BUFFER (obj), name),
1758 printcharfun);
1759 }
1760 printchar ('>', printcharfun);
1761 break;
1762
1763 case PVEC_USER_PTR:
1764 {
1765 print_c_string ("#<user-ptr ", printcharfun);
1766 int i = sprintf (buf, "ptr=%p finalizer=%p",
1767 XUSER_PTR (obj)->p,
1768 (void *) XUSER_PTR (obj)->finalizer);
1769 strout (buf, i, i, printcharfun);
1770 printchar ('>', printcharfun);
1771 }
1772 break;
1773
1774 case PVEC_FINALIZER:
1775 print_c_string ("#<finalizer", printcharfun);
1776 if (NILP (XFINALIZER (obj)->function))
1777 print_c_string (" used", printcharfun);
1778 printchar ('>', printcharfun);
1779 break;
1780
1781 case PVEC_MISC_PTR:
1782 {
1783
1784
1785 int i = sprintf (buf, "#<ptr %p>", xmint_pointer (obj));
1786 strout (buf, i, i, printcharfun);
1787 }
1788 break;
1789
1790 case PVEC_PROCESS:
1791 if (escapeflag)
1792 {
1793 print_c_string ("#<process ", printcharfun);
1794 print_string (XPROCESS (obj)->name, printcharfun);
1795 printchar ('>', printcharfun);
1796 }
1797 else
1798 print_string (XPROCESS (obj)->name, printcharfun);
1799 break;
1800
1801 case PVEC_SUBR:
1802 print_c_string ("#<subr ", printcharfun);
1803 print_c_string (XSUBR (obj)->symbol_name, printcharfun);
1804 printchar ('>', printcharfun);
1805 break;
1806
1807 case PVEC_XWIDGET:
1808 #ifdef HAVE_XWIDGETS
1809 {
1810 if (NILP (XXWIDGET (obj)->buffer))
1811 print_c_string ("#<killed xwidget>", printcharfun);
1812 else
1813 {
1814 #ifdef USE_GTK
1815 int len = sprintf (buf, "#<xwidget %u %p>",
1816 XXWIDGET (obj)->xwidget_id,
1817 XXWIDGET (obj)->widget_osr);
1818 #else
1819 int len = sprintf (buf, "#<xwidget %u %p>",
1820 XXWIDGET (obj)->xwidget_id,
1821 XXWIDGET (obj)->xwWidget);
1822 #endif
1823 strout (buf, len, len, printcharfun);
1824 }
1825 break;
1826 }
1827 #else
1828 emacs_abort ();
1829 #endif
1830 case PVEC_XWIDGET_VIEW:
1831 print_c_string ("#<xwidget view", printcharfun);
1832 printchar ('>', printcharfun);
1833 break;
1834
1835 case PVEC_WINDOW:
1836 {
1837 int len = sprintf (buf, "#<window %"pI"d",
1838 XWINDOW (obj)->sequence_number);
1839 strout (buf, len, len, printcharfun);
1840 if (BUFFERP (XWINDOW (obj)->contents))
1841 {
1842 print_c_string (" on ", printcharfun);
1843 print_string (BVAR (XBUFFER (XWINDOW (obj)->contents), name),
1844 printcharfun);
1845 }
1846 printchar ('>', printcharfun);
1847 }
1848 break;
1849
1850 case PVEC_TERMINAL:
1851 {
1852 struct terminal *t = XTERMINAL (obj);
1853 int len = sprintf (buf, "#<terminal %d", t->id);
1854 strout (buf, len, len, printcharfun);
1855 if (t->name)
1856 {
1857 print_c_string (" on ", printcharfun);
1858 print_c_string (t->name, printcharfun);
1859 }
1860 printchar ('>', printcharfun);
1861 }
1862 break;
1863
1864 case PVEC_BUFFER:
1865 if (!BUFFER_LIVE_P (XBUFFER (obj)))
1866 print_c_string ("#<killed buffer>", printcharfun);
1867 else if (escapeflag)
1868 {
1869 print_c_string ("#<buffer ", printcharfun);
1870 print_string (BVAR (XBUFFER (obj), name), printcharfun);
1871 printchar ('>', printcharfun);
1872 }
1873 else
1874 print_string (BVAR (XBUFFER (obj), name), printcharfun);
1875 break;
1876
1877 case PVEC_WINDOW_CONFIGURATION:
1878 print_c_string ("#<window-configuration>", printcharfun);
1879 break;
1880
1881 case PVEC_FRAME:
1882 {
1883 void *ptr = XFRAME (obj);
1884 Lisp_Object frame_name = XFRAME (obj)->name;
1885
1886 print_c_string ((FRAME_LIVE_P (XFRAME (obj))
1887 ? "#<frame "
1888 : "#<dead frame "),
1889 printcharfun);
1890 if (!STRINGP (frame_name))
1891 {
1892
1893
1894 if (SYMBOLP (frame_name))
1895 frame_name = Fsymbol_name (frame_name);
1896 else
1897 frame_name = build_string ("*INVALID*FRAME*NAME*");
1898 }
1899 print_string (frame_name, printcharfun);
1900 int len = sprintf (buf, " %p>", ptr);
1901 strout (buf, len, len, printcharfun);
1902 }
1903 break;
1904
1905 case PVEC_FONT:
1906 {
1907 if (! FONT_OBJECT_P (obj))
1908 {
1909 if (FONT_SPEC_P (obj))
1910 print_c_string ("#<font-spec", printcharfun);
1911 else
1912 print_c_string ("#<font-entity", printcharfun);
1913 for (int i = 0; i < FONT_SPEC_MAX; i++)
1914 {
1915 printchar (' ', printcharfun);
1916 if (i < FONT_WEIGHT_INDEX || i > FONT_WIDTH_INDEX)
1917 print_object (AREF (obj, i), printcharfun, escapeflag);
1918 else
1919 print_object (font_style_symbolic (obj, i, 0),
1920 printcharfun, escapeflag);
1921 }
1922 }
1923 else
1924 {
1925 print_c_string ("#<font-object ", printcharfun);
1926 print_object (AREF (obj, FONT_NAME_INDEX), printcharfun,
1927 escapeflag);
1928 }
1929 printchar ('>', printcharfun);
1930 }
1931 break;
1932
1933 case PVEC_THREAD:
1934 print_c_string ("#<thread ", printcharfun);
1935 if (STRINGP (XTHREAD (obj)->name))
1936 print_string (XTHREAD (obj)->name, printcharfun);
1937 else
1938 {
1939 void *p = XTHREAD (obj);
1940 int len = sprintf (buf, "%p", p);
1941 strout (buf, len, len, printcharfun);
1942 }
1943 printchar ('>', printcharfun);
1944 break;
1945
1946 case PVEC_MUTEX:
1947 print_c_string ("#<mutex ", printcharfun);
1948 if (STRINGP (XMUTEX (obj)->name))
1949 print_string (XMUTEX (obj)->name, printcharfun);
1950 else
1951 {
1952 void *p = XMUTEX (obj);
1953 int len = sprintf (buf, "%p", p);
1954 strout (buf, len, len, printcharfun);
1955 }
1956 printchar ('>', printcharfun);
1957 break;
1958
1959 case PVEC_CONDVAR:
1960 print_c_string ("#<condvar ", printcharfun);
1961 if (STRINGP (XCONDVAR (obj)->name))
1962 print_string (XCONDVAR (obj)->name, printcharfun);
1963 else
1964 {
1965 void *p = XCONDVAR (obj);
1966 int len = sprintf (buf, "%p", p);
1967 strout (buf, len, len, printcharfun);
1968 }
1969 printchar ('>', printcharfun);
1970 break;
1971
1972 #ifdef HAVE_MODULES
1973 case PVEC_MODULE_FUNCTION:
1974 {
1975 print_c_string ("#<module function ", printcharfun);
1976 const struct Lisp_Module_Function *function = XMODULE_FUNCTION (obj);
1977 module_funcptr ptr = module_function_address (function);
1978 char const *file;
1979 char const *symbol;
1980 dynlib_addr (ptr, &file, &symbol);
1981
1982 if (symbol == NULL)
1983 print_pointer (printcharfun, buf, "at", data_from_funcptr (ptr));
1984 else
1985 print_c_string (symbol, printcharfun);
1986
1987 void *data = module_function_data (function);
1988 if (data != NULL)
1989 print_pointer (printcharfun, buf, " with data", data);
1990
1991 if (file != NULL)
1992 {
1993 print_c_string (" from ", printcharfun);
1994 print_c_string (file, printcharfun);
1995 }
1996
1997 printchar ('>', printcharfun);
1998 }
1999 break;
2000 #endif
2001 #ifdef HAVE_NATIVE_COMP
2002 case PVEC_NATIVE_COMP_UNIT:
2003 {
2004 struct Lisp_Native_Comp_Unit *cu = XNATIVE_COMP_UNIT (obj);
2005 print_c_string ("#<native compilation unit: ", printcharfun);
2006 print_string (cu->file, printcharfun);
2007 printchar (' ', printcharfun);
2008 print_object (cu->optimize_qualities, printcharfun, escapeflag);
2009 printchar ('>', printcharfun);
2010 }
2011 break;
2012 #endif
2013
2014 #ifdef HAVE_TREE_SITTER
2015 case PVEC_TS_PARSER:
2016 print_c_string ("#<treesit-parser for ", printcharfun);
2017 Lisp_Object language = XTS_PARSER (obj)->language_symbol;
2018
2019
2020 print_string (Fsymbol_name (language), printcharfun);
2021 printchar ('>', printcharfun);
2022 break;
2023 case PVEC_TS_NODE:
2024
2025
2026 print_c_string ("#<treesit-node", printcharfun);
2027 if (!treesit_node_uptodate_p (obj))
2028 {
2029 print_c_string ("-outdated>", printcharfun);
2030 break;
2031 }
2032 printchar (' ', printcharfun);
2033
2034
2035 bool named = treesit_named_node_p (XTS_NODE (obj)->node);
2036
2037
2038
2039
2040
2041 const char *delim1 = named ? "" : "\"";
2042 const char *delim2 = named ? "" : "\"";
2043 print_c_string (delim1, printcharfun);
2044 print_string (Ftreesit_node_type (obj), printcharfun);
2045 print_c_string (delim2, printcharfun);
2046 print_c_string (" in ", printcharfun);
2047 print_object (Ftreesit_node_start (obj), printcharfun, escapeflag);
2048 printchar ('-', printcharfun);
2049 print_object (Ftreesit_node_end (obj), printcharfun, escapeflag);
2050 printchar ('>', printcharfun);
2051 break;
2052 case PVEC_TS_COMPILED_QUERY:
2053 print_c_string ("#<treesit-compiled-query>", printcharfun);
2054 break;
2055 #endif
2056
2057 case PVEC_SQLITE:
2058 {
2059 print_c_string ("#<sqlite ", printcharfun);
2060 int i = sprintf (buf, "db=%p", XSQLITE (obj)->db);
2061 strout (buf, i, i, printcharfun);
2062 if (XSQLITE (obj)->is_statement)
2063 {
2064 i = sprintf (buf, " stmt=%p", XSQLITE (obj)->stmt);
2065 strout (buf, i, i, printcharfun);
2066 }
2067 print_c_string (" name=", printcharfun);
2068 print_c_string (XSQLITE (obj)->name, printcharfun);
2069 printchar ('>', printcharfun);
2070 }
2071 break;
2072
2073 default:
2074 emacs_abort ();
2075 }
2076
2077 return true;
2078 }
2079
2080 static char
2081 named_escape (int i)
2082 {
2083 switch (i)
2084 {
2085 case '\b': return 'b';
2086 case '\t': return 't';
2087 case '\n': return 'n';
2088 case '\f': return 'f';
2089 case '\r': return 'r';
2090 case ' ': return 's';
2091
2092
2093
2094 }
2095 return 0;
2096 }
2097
2098 enum print_entry_type
2099 {
2100 PE_list,
2101 PE_rbrac,
2102 PE_vector,
2103 PE_hash,
2104 };
2105
2106 struct print_stack_entry
2107 {
2108 enum print_entry_type type;
2109
2110 union
2111 {
2112 struct
2113 {
2114 Lisp_Object last;
2115 intmax_t maxlen;
2116
2117
2118
2119 Lisp_Object tortoise;
2120 ptrdiff_t n;
2121 ptrdiff_t m;
2122 intmax_t tortoise_idx;
2123 } list;
2124
2125 struct
2126 {
2127 Lisp_Object obj;
2128 } dotted_cdr;
2129
2130 struct
2131 {
2132 Lisp_Object obj;
2133 ptrdiff_t size;
2134 ptrdiff_t idx;
2135 const char *end;
2136 bool truncated;
2137 } vector;
2138
2139 struct
2140 {
2141 Lisp_Object obj;
2142 ptrdiff_t nobjs;
2143 ptrdiff_t idx;
2144 ptrdiff_t printed;
2145 bool truncated;
2146 } hash;
2147 } u;
2148 };
2149
2150 struct print_stack
2151 {
2152 struct print_stack_entry *stack;
2153 ptrdiff_t size;
2154 ptrdiff_t sp;
2155 };
2156
2157 static struct print_stack prstack = {NULL, 0, 0};
2158
2159 NO_INLINE static void
2160 grow_print_stack (void)
2161 {
2162 struct print_stack *ps = &prstack;
2163 eassert (ps->sp == ps->size);
2164 ps->stack = xpalloc (ps->stack, &ps->size, 1, -1, sizeof *ps->stack);
2165 eassert (ps->sp < ps->size);
2166 }
2167
2168 static inline void
2169 print_stack_push (struct print_stack_entry e)
2170 {
2171 if (prstack.sp >= prstack.size)
2172 grow_print_stack ();
2173 prstack.stack[prstack.sp++] = e;
2174 }
2175
2176 static void
2177 print_stack_push_vector (const char *lbrac, const char *rbrac,
2178 Lisp_Object obj, ptrdiff_t start, ptrdiff_t size,
2179 Lisp_Object printcharfun)
2180 {
2181 print_c_string (lbrac, printcharfun);
2182
2183 ptrdiff_t print_size = ((FIXNATP (Vprint_length)
2184 && XFIXNAT (Vprint_length) < size)
2185 ? XFIXNAT (Vprint_length) : size);
2186 print_stack_push ((struct print_stack_entry){
2187 .type = PE_vector,
2188 .u.vector.obj = obj,
2189 .u.vector.size = print_size,
2190 .u.vector.idx = start,
2191 .u.vector.end = rbrac,
2192 .u.vector.truncated = (print_size < size),
2193 });
2194 }
2195
2196 static void
2197 print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
2198 {
2199 ptrdiff_t base_depth = print_depth;
2200 ptrdiff_t base_sp = prstack.sp;
2201 char buf[max (sizeof "from..to..in " + 2 * INT_STRLEN_BOUND (EMACS_INT),
2202 max (sizeof " . #" + INT_STRLEN_BOUND (intmax_t),
2203 max ((sizeof " with data 0x"
2204 + (sizeof (uintmax_t) * CHAR_BIT + 4 - 1) / 4),
2205 40)))];
2206 current_thread->stack_top = buf;
2207
2208 print_obj:
2209 maybe_quit ();
2210
2211
2212 if (NILP (Vprint_circle))
2213 {
2214
2215 if (print_depth >= PRINT_CIRCLE)
2216 error ("Apparently circular structure being printed");
2217
2218 for (int i = 0; i < print_depth; i++)
2219 if (BASE_EQ (obj, being_printed[i]))
2220 {
2221 int len = sprintf (buf, "#%d", i);
2222 strout (buf, len, len, printcharfun);
2223 goto next_obj;
2224 }
2225 being_printed[print_depth] = obj;
2226 }
2227 else if (PRINT_CIRCLE_CANDIDATE_P (obj))
2228 {
2229
2230 Lisp_Object num = Fgethash (obj, Vprint_number_table, Qnil);
2231 if (FIXNUMP (num))
2232 {
2233 EMACS_INT n = XFIXNUM (num);
2234 if (n < 0)
2235 {
2236
2237 int len = sprintf (buf, "#%"pI"d=", -n);
2238 strout (buf, len, len, printcharfun);
2239
2240 Fputhash (obj, make_fixnum (- n), Vprint_number_table);
2241 }
2242 else
2243 {
2244
2245 int len = sprintf (buf, "#%"pI"d#", n);
2246 strout (buf, len, len, printcharfun);
2247 goto next_obj;
2248 }
2249 }
2250 }
2251
2252 print_depth++;
2253
2254 switch (XTYPE (obj))
2255 {
2256 case_Lisp_Int:
2257 {
2258 EMACS_INT i = XFIXNUM (obj);
2259 char escaped_name;
2260
2261 if (print_integers_as_characters && i >= 0 && i <= MAX_UNICODE_CHAR
2262 && ((escaped_name = named_escape (i))
2263 || graphic_base_p (i)))
2264 {
2265 printchar ('?', printcharfun);
2266 if (escaped_name)
2267 {
2268 printchar ('\\', printcharfun);
2269 i = escaped_name;
2270 }
2271 else if (escapeflag
2272 && (i == ';' || i == '\"' || i == '\'' || i == '\\'
2273 || i == '(' || i == ')'
2274 || i == '{' || i == '}'
2275 || i == '[' || i == ']'))
2276 printchar ('\\', printcharfun);
2277 printchar (i, printcharfun);
2278 }
2279 else
2280 {
2281 char *end = buf + sizeof buf;
2282 char *start = fixnum_to_string (i, buf, end);
2283 ptrdiff_t len = end - start;
2284 strout (start, len, len, printcharfun);
2285 }
2286 }
2287 break;
2288
2289 case Lisp_Float:
2290 {
2291 char pigbuf[FLOAT_TO_STRING_BUFSIZE];
2292 int len = float_to_string (pigbuf, XFLOAT_DATA (obj));
2293 strout (pigbuf, len, len, printcharfun);
2294 }
2295 break;
2296
2297 case Lisp_String:
2298 if (!escapeflag)
2299 print_string (obj, printcharfun);
2300 else
2301 {
2302 ptrdiff_t i, i_byte;
2303 ptrdiff_t size_byte;
2304
2305
2306 bool need_nonhex = false;
2307 bool multibyte = STRING_MULTIBYTE (obj);
2308
2309 if (! EQ (Vprint_charset_text_property, Qt))
2310 obj = print_prune_string_charset (obj);
2311
2312 if (string_intervals (obj))
2313 print_c_string ("#(", printcharfun);
2314
2315 printchar ('\"', printcharfun);
2316 size_byte = SBYTES (obj);
2317
2318 for (i = 0, i_byte = 0; i_byte < size_byte;)
2319 {
2320
2321
2322
2323 int c = fetch_string_char_advance (obj, &i, &i_byte);
2324
2325 maybe_quit ();
2326
2327 if (multibyte
2328 ? (CHAR_BYTE8_P (c) && (c = CHAR_TO_BYTE8 (c), true))
2329 : (SINGLE_BYTE_CHAR_P (c) && ! ASCII_CHAR_P (c)
2330 && print_escape_nonascii))
2331 {
2332
2333
2334
2335
2336 octalout (c, SDATA (obj), i_byte, size_byte, printcharfun);
2337 need_nonhex = false;
2338 }
2339 else if (multibyte
2340 && ! ASCII_CHAR_P (c) && print_escape_multibyte)
2341 {
2342
2343
2344 char outbuf[sizeof "\\x" + INT_STRLEN_BOUND (c)];
2345 int len = sprintf (outbuf, "\\x%04x", c + 0u);
2346 strout (outbuf, len, len, printcharfun);
2347 need_nonhex = true;
2348 }
2349 else
2350 {
2351
2352
2353
2354 if (c_isxdigit (c))
2355 {
2356 if (need_nonhex)
2357 print_c_string ("\\ ", printcharfun);
2358 printchar (c, printcharfun);
2359 }
2360 else if (c == '\n' && print_escape_newlines
2361 ? (c = 'n', true)
2362 : c == '\f' && print_escape_newlines
2363 ? (c = 'f', true)
2364 : c == '\"' || c == '\\')
2365 {
2366 printchar ('\\', printcharfun);
2367 printchar (c, printcharfun);
2368 }
2369 else if (print_escape_control_characters && c_iscntrl (c))
2370 octalout (c, SDATA (obj), i_byte, size_byte, printcharfun);
2371 else if (!multibyte
2372 && SINGLE_BYTE_CHAR_P (c)
2373 && !ASCII_CHAR_P (c))
2374 printchar (BYTE8_TO_CHAR (c), printcharfun);
2375 else
2376 printchar (c, printcharfun);
2377 need_nonhex = false;
2378 }
2379 }
2380 printchar ('\"', printcharfun);
2381
2382 if (string_intervals (obj))
2383 {
2384 traverse_intervals (string_intervals (obj),
2385 0, print_interval, printcharfun);
2386 printchar (')', printcharfun);
2387 }
2388 }
2389 break;
2390
2391 case Lisp_Symbol:
2392 {
2393 Lisp_Object name = SYMBOL_NAME (obj);
2394 ptrdiff_t size_byte = SBYTES (name);
2395
2396 char *p = SSDATA (name);
2397 bool signedp = *p == '-' || *p == '+';
2398 ptrdiff_t len;
2399 bool confusing =
2400
2401
2402 ((c_isdigit (p[signedp]) || p[signedp] == '.')
2403 && !NILP (string_to_number (p, 10, &len))
2404 && len == size_byte)
2405
2406
2407 || *p == '?'
2408 || *p == '.';
2409
2410 if (! NILP (Vprint_gensym)
2411 && !SYMBOL_INTERNED_IN_INITIAL_OBARRAY_P (obj))
2412 print_c_string ("#:", printcharfun);
2413 else if (size_byte == 0)
2414 {
2415 print_c_string ("##", printcharfun);
2416 break;
2417 }
2418
2419 ptrdiff_t i = 0;
2420 for (ptrdiff_t i_byte = 0; i_byte < size_byte; )
2421 {
2422
2423
2424 int c = fetch_string_char_advance (name, &i, &i_byte);
2425 maybe_quit ();
2426
2427 if (escapeflag)
2428 {
2429 if (c == '\"' || c == '\\' || c == '\''
2430 || c == ';' || c == '#' || c == '(' || c == ')'
2431 || c == ',' || c == '`'
2432 || c == '[' || c == ']' || c <= 040
2433 || c == NO_BREAK_SPACE
2434 || confusing)
2435 {
2436 printchar ('\\', printcharfun);
2437 confusing = false;
2438 }
2439 }
2440 printchar (c, printcharfun);
2441 }
2442 }
2443 break;
2444
2445 case Lisp_Cons:
2446
2447 if (FIXNUMP (Vprint_level)
2448 && print_depth > XFIXNUM (Vprint_level))
2449 print_c_string ("...", printcharfun);
2450 else if (print_quoted && CONSP (XCDR (obj)) && NILP (XCDR (XCDR (obj)))
2451 && EQ (XCAR (obj), Qquote))
2452 {
2453 printchar ('\'', printcharfun);
2454 obj = XCAR (XCDR (obj));
2455 --print_depth;
2456 goto print_obj;
2457 }
2458 else if (print_quoted && CONSP (XCDR (obj)) && NILP (XCDR (XCDR (obj)))
2459 && EQ (XCAR (obj), Qfunction))
2460 {
2461 print_c_string ("#'", printcharfun);
2462 obj = XCAR (XCDR (obj));
2463 --print_depth;
2464 goto print_obj;
2465 }
2466
2467
2468
2469
2470 else if (print_quoted && CONSP (XCDR (obj)) && NILP (XCDR (XCDR (obj)))
2471 && EQ (XCAR (obj), Qbackquote))
2472 {
2473 printchar ('`', printcharfun);
2474 new_backquote_output++;
2475 print_object (XCAR (XCDR (obj)), printcharfun, escapeflag);
2476 new_backquote_output--;
2477 }
2478 else if (print_quoted && CONSP (XCDR (obj)) && NILP (XCDR (XCDR (obj)))
2479 && (EQ (XCAR (obj), Qcomma)
2480 || EQ (XCAR (obj), Qcomma_at))
2481 && new_backquote_output)
2482 {
2483 print_object (XCAR (obj), printcharfun, false);
2484 new_backquote_output--;
2485 print_object (XCAR (XCDR (obj)), printcharfun, escapeflag);
2486 new_backquote_output++;
2487 }
2488 else
2489 {
2490 printchar ('(', printcharfun);
2491
2492
2493 intmax_t print_length = (FIXNATP (Vprint_length)
2494 ? XFIXNAT (Vprint_length)
2495 : INTMAX_MAX);
2496 if (print_length == 0)
2497 print_c_string ("...)", printcharfun);
2498 else
2499 {
2500 print_stack_push ((struct print_stack_entry){
2501 .type = PE_list,
2502 .u.list.last = obj,
2503 .u.list.maxlen = print_length,
2504 .u.list.tortoise = obj,
2505 .u.list.n = 2,
2506 .u.list.m = 2,
2507 .u.list.tortoise_idx = 0,
2508 });
2509
2510 obj = XCAR (obj);
2511 goto print_obj;
2512 }
2513 }
2514 break;
2515
2516 case Lisp_Vectorlike:
2517
2518 switch (PSEUDOVECTOR_TYPE (XVECTOR (obj)))
2519 {
2520 case PVEC_NORMAL_VECTOR:
2521 {
2522 print_stack_push_vector ("[", "]", obj, 0, ASIZE (obj),
2523 printcharfun);
2524 goto next_obj;
2525 }
2526 case PVEC_RECORD:
2527 {
2528 print_stack_push_vector ("#s(", ")", obj, 0, PVSIZE (obj),
2529 printcharfun);
2530 goto next_obj;
2531 }
2532 case PVEC_COMPILED:
2533 {
2534 print_stack_push_vector ("#[", "]", obj, 0, PVSIZE (obj),
2535 printcharfun);
2536 goto next_obj;
2537 }
2538 case PVEC_CHAR_TABLE:
2539 {
2540 print_stack_push_vector ("#^[", "]", obj, 0, PVSIZE (obj),
2541 printcharfun);
2542 goto next_obj;
2543 }
2544 case PVEC_SUB_CHAR_TABLE:
2545 {
2546
2547
2548
2549 if (XSUB_CHAR_TABLE (obj)->depth == 3)
2550 printchar ('\n', printcharfun);
2551 print_c_string ("#^^[", printcharfun);
2552 int n = sprintf (buf, "%d %d",
2553 XSUB_CHAR_TABLE (obj)->depth,
2554 XSUB_CHAR_TABLE (obj)->min_char);
2555 strout (buf, n, n, printcharfun);
2556 print_stack_push_vector ("", "]", obj,
2557 SUB_CHAR_TABLE_OFFSET, PVSIZE (obj),
2558 printcharfun);
2559 goto next_obj;
2560 }
2561 case PVEC_HASH_TABLE:
2562 {
2563 struct Lisp_Hash_Table *h = XHASH_TABLE (obj);
2564
2565
2566
2567 int len = sprintf (buf, "#s(hash-table size %"pD"d",
2568 HASH_TABLE_SIZE (h));
2569 strout (buf, len, len, printcharfun);
2570
2571 if (!NILP (h->test.name))
2572 {
2573 print_c_string (" test ", printcharfun);
2574 print_object (h->test.name, printcharfun, escapeflag);
2575 }
2576
2577 if (!NILP (h->weak))
2578 {
2579 print_c_string (" weakness ", printcharfun);
2580 print_object (h->weak, printcharfun, escapeflag);
2581 }
2582
2583 print_c_string (" rehash-size ", printcharfun);
2584 print_object (Fhash_table_rehash_size (obj),
2585 printcharfun, escapeflag);
2586
2587 print_c_string (" rehash-threshold ", printcharfun);
2588 print_object (Fhash_table_rehash_threshold (obj),
2589 printcharfun, escapeflag);
2590
2591 if (h->purecopy)
2592 print_c_string (" purecopy t", printcharfun);
2593
2594 print_c_string (" data (", printcharfun);
2595
2596 ptrdiff_t size = h->count;
2597
2598 if (FIXNATP (Vprint_length) && XFIXNAT (Vprint_length) < size)
2599 size = XFIXNAT (Vprint_length);
2600
2601 print_stack_push ((struct print_stack_entry){
2602 .type = PE_hash,
2603 .u.hash.obj = obj,
2604 .u.hash.nobjs = size * 2,
2605 .u.hash.idx = 0,
2606 .u.hash.printed = 0,
2607 .u.hash.truncated = (size < h->count),
2608 });
2609 goto next_obj;
2610 }
2611
2612 default:
2613 break;
2614 }
2615
2616 if (print_vectorlike (obj, printcharfun, escapeflag, buf))
2617 break;
2618 FALLTHROUGH;
2619
2620 default:
2621 {
2622 int len;
2623
2624
2625 print_c_string ("#<EMACS BUG: INVALID DATATYPE ", printcharfun);
2626 if (VECTORLIKEP (obj))
2627 len = sprintf (buf, "(PVEC 0x%08zx)", (size_t) ASIZE (obj));
2628 else
2629 len = sprintf (buf, "(0x%02x)", (unsigned) XTYPE (obj));
2630 strout (buf, len, len, printcharfun);
2631 print_c_string ((" Save your buffers immediately"
2632 " and please report this bug>"),
2633 printcharfun);
2634 break;
2635 }
2636 }
2637 print_depth--;
2638
2639 next_obj:
2640 if (prstack.sp > base_sp)
2641 {
2642
2643 struct print_stack_entry *e = &prstack.stack[prstack.sp - 1];
2644 switch (e->type)
2645 {
2646 case PE_list:
2647 {
2648
2649 Lisp_Object next = XCDR (e->u.list.last);
2650 if (NILP (next))
2651 {
2652
2653 printchar (')', printcharfun);
2654 --prstack.sp;
2655 --print_depth;
2656 goto next_obj;
2657 }
2658 else if (CONSP (next))
2659 {
2660 if (!NILP (Vprint_circle))
2661 {
2662
2663 Lisp_Object num = Fgethash (next, Vprint_number_table,
2664 Qnil);
2665 if (FIXNUMP (num))
2666 {
2667 print_c_string (" . ", printcharfun);
2668 obj = next;
2669 e->type = PE_rbrac;
2670 goto print_obj;
2671 }
2672 }
2673
2674
2675
2676 printchar (' ', printcharfun);
2677
2678 --e->u.list.maxlen;
2679 if (e->u.list.maxlen <= 0)
2680 {
2681 print_c_string ("...)", printcharfun);
2682 --prstack.sp;
2683 --print_depth;
2684 goto next_obj;
2685 }
2686
2687 e->u.list.last = next;
2688 e->u.list.n--;
2689 if (e->u.list.n == 0)
2690 {
2691
2692 e->u.list.tortoise_idx += e->u.list.m;
2693 e->u.list.m <<= 1;
2694 e->u.list.n = e->u.list.m;
2695 e->u.list.tortoise = next;
2696 }
2697 else if (BASE_EQ (next, e->u.list.tortoise))
2698 {
2699
2700
2701 int len = sprintf (buf, ". #%" PRIdMAX ")",
2702 e->u.list.tortoise_idx);
2703 strout (buf, len, len, printcharfun);
2704 --prstack.sp;
2705 --print_depth;
2706 goto next_obj;
2707 }
2708 obj = XCAR (next);
2709 }
2710 else
2711 {
2712
2713 print_c_string (" . ", printcharfun);
2714 obj = next;
2715 e->type = PE_rbrac;
2716 }
2717 break;
2718 }
2719
2720 case PE_rbrac:
2721 printchar (')', printcharfun);
2722 --prstack.sp;
2723 --print_depth;
2724 goto next_obj;
2725
2726 case PE_vector:
2727 if (e->u.vector.idx >= e->u.vector.size)
2728 {
2729 if (e->u.vector.truncated)
2730 {
2731 if (e->u.vector.idx > 0)
2732 printchar (' ', printcharfun);
2733 print_c_string ("...", printcharfun);
2734 }
2735 print_c_string (e->u.vector.end, printcharfun);
2736 --prstack.sp;
2737 --print_depth;
2738 goto next_obj;
2739 }
2740 if (e->u.vector.idx > 0)
2741 printchar (' ', printcharfun);
2742 obj = AREF (e->u.vector.obj, e->u.vector.idx);
2743 e->u.vector.idx++;
2744 break;
2745
2746 case PE_hash:
2747 if (e->u.hash.printed >= e->u.hash.nobjs)
2748 {
2749 if (e->u.hash.truncated)
2750 {
2751 if (e->u.hash.printed)
2752 printchar (' ', printcharfun);
2753 print_c_string ("...", printcharfun);
2754 }
2755 print_c_string ("))", printcharfun);
2756 --prstack.sp;
2757 --print_depth;
2758 goto next_obj;
2759 }
2760
2761 if (e->u.hash.printed)
2762 printchar (' ', printcharfun);
2763
2764 struct Lisp_Hash_Table *h = XHASH_TABLE (e->u.hash.obj);
2765 if ((e->u.hash.printed & 1) == 0)
2766 {
2767 Lisp_Object key;
2768 ptrdiff_t idx = e->u.hash.idx;
2769 while (BASE_EQ ((key = HASH_KEY (h, idx)), Qunbound))
2770 idx++;
2771 e->u.hash.idx = idx;
2772 obj = key;
2773 }
2774 else
2775 {
2776 obj = HASH_VALUE (h, e->u.hash.idx);
2777 e->u.hash.idx++;
2778 }
2779 e->u.hash.printed++;
2780 break;
2781 }
2782 goto print_obj;
2783 }
2784 eassert (print_depth == base_depth);
2785 }
2786
2787
2788
2789
2790
2791 static void
2792 print_interval (INTERVAL interval, Lisp_Object printcharfun)
2793 {
2794 if (NILP (interval->plist))
2795 return;
2796 printchar (' ', printcharfun);
2797 print_object (make_fixnum (interval->position), printcharfun, 1);
2798 printchar (' ', printcharfun);
2799 print_object (make_fixnum (interval->position + LENGTH (interval)),
2800 printcharfun, 1);
2801 printchar (' ', printcharfun);
2802 print_object (interval->plist, printcharfun, 1);
2803 }
2804
2805
2806
2807
2808 void
2809 init_print_once (void)
2810 {
2811
2812
2813 DEFSYM (Qexternal_debugging_output, "external-debugging-output");
2814
2815 defsubr (&Sexternal_debugging_output);
2816 }
2817
2818 void
2819 syms_of_print (void)
2820 {
2821 DEFSYM (Qtemp_buffer_setup_hook, "temp-buffer-setup-hook");
2822
2823 DEFVAR_LISP ("standard-output", Vstandard_output,
2824 doc:
2825
2826
2827
2828 );
2829 Vstandard_output = Qt;
2830 DEFSYM (Qstandard_output, "standard-output");
2831
2832 DEFVAR_LISP ("float-output-format", Vfloat_output_format,
2833 doc:
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847 );
2848 Vfloat_output_format = Qnil;
2849
2850 DEFVAR_BOOL ("print-integers-as-characters", print_integers_as_characters,
2851 doc:
2852
2853
2854
2855 );
2856 print_integers_as_characters = false;
2857
2858 DEFVAR_LISP ("print-length", Vprint_length,
2859 doc:
2860 );
2861 Vprint_length = Qnil;
2862
2863 DEFVAR_LISP ("print-level", Vprint_level,
2864 doc:
2865 );
2866 Vprint_level = Qnil;
2867
2868 DEFVAR_BOOL ("print-escape-newlines", print_escape_newlines,
2869 doc:
2870 );
2871 print_escape_newlines = 0;
2872
2873 DEFVAR_BOOL ("print-escape-control-characters", print_escape_control_characters,
2874 doc:
2875 );
2876 print_escape_control_characters = 0;
2877
2878 DEFVAR_BOOL ("print-escape-nonascii", print_escape_nonascii,
2879 doc:
2880
2881
2882
2883 );
2884 print_escape_nonascii = 0;
2885
2886 DEFVAR_BOOL ("print-escape-multibyte", print_escape_multibyte,
2887 doc:
2888
2889 );
2890 print_escape_multibyte = 0;
2891
2892 DEFVAR_BOOL ("print-quoted", print_quoted,
2893 doc:
2894 );
2895 print_quoted = true;
2896
2897 DEFVAR_LISP ("print-gensym", Vprint_gensym,
2898 doc:
2899
2900
2901
2902
2903 );
2904 Vprint_gensym = Qnil;
2905
2906 DEFVAR_LISP ("print-circle", Vprint_circle,
2907 doc:
2908
2909
2910
2911
2912
2913
2914
2915 );
2916 Vprint_circle = Qnil;
2917
2918 DEFVAR_LISP ("print-continuous-numbering", Vprint_continuous_numbering,
2919 doc:
2920
2921
2922 );
2923 Vprint_continuous_numbering = Qnil;
2924
2925 DEFVAR_LISP ("print-number-table", Vprint_number_table,
2926 doc:
2927
2928
2929
2930
2931
2932
2933
2934
2935 );
2936 Vprint_number_table = Qnil;
2937
2938 DEFVAR_LISP ("print-charset-text-property", Vprint_charset_text_property,
2939 doc:
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949 );
2950 Vprint_charset_text_property = Qdefault;
2951
2952 DEFVAR_BOOL ("print-symbols-bare", print_symbols_bare,
2953 doc:
2954
2955 );
2956 print_symbols_bare = false;
2957 DEFSYM (Qprint_symbols_bare, "print-symbols-bare");
2958
2959
2960 staticpro (&Vprin1_to_string_buffer);
2961
2962 defsubr (&Sprin1);
2963 defsubr (&Sprin1_to_string);
2964 defsubr (&Serror_message_string);
2965 defsubr (&Sprinc);
2966 defsubr (&Sprint);
2967 defsubr (&Sterpri);
2968 defsubr (&Swrite_char);
2969 defsubr (&Sredirect_debugging_output);
2970 defsubr (&Sprint_preprocess);
2971
2972 DEFSYM (Qprint_escape_multibyte, "print-escape-multibyte");
2973 DEFSYM (Qprint_escape_nonascii, "print-escape-nonascii");
2974
2975 print_prune_charset_plist = Qnil;
2976 staticpro (&print_prune_charset_plist);
2977
2978 DEFVAR_LISP ("print-unreadable-function", Vprint_unreadable_function,
2979 doc:
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989 );
2990 Vprint_unreadable_function = Qnil;
2991 DEFSYM (Qprint_unreadable_function, "print-unreadable-function");
2992
2993 DEFVAR_LISP ("print--unreadable-callback-buffer",
2994 Vprint__unreadable_callback_buffer,
2995 doc: );
2996 Vprint__unreadable_callback_buffer = Qnil;
2997 DEFSYM (Qprint__unreadable_callback_buffer,
2998 "print--unreadable-callback-buffer");
2999
3000 Funintern (Qprint__unreadable_callback_buffer, Qnil);
3001
3002 defsubr (&Sflush_standard_output);
3003
3004
3005 staticpro (&Vprint_variable_mapping);
3006 }