aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias EngdegÄrd2022-08-08 12:39:12 +0200
committerMattias EngdegÄrd2022-08-08 13:12:47 +0200
commit14f0ebc9ac8d2f0f272bdb1eac4dd2ea0b50a0f4 (patch)
tree78a4c03d17437d7bb691784e665db23f546dd137
parent60738e569d24b74b9e6973225d143b3468bfc60f (diff)
downloademacs-14f0ebc9ac8d2f0f272bdb1eac4dd2ea0b50a0f4.tar.gz
emacs-14f0ebc9ac8d2f0f272bdb1eac4dd2ea0b50a0f4.zip
Turn large macros in print.c to functions
This is easier to read and maintain, and makes the state explicit. It is a pure refactoring; the compiled code should be equivalent. * src/print.c (PRINTPREPARE, PRINTFINISH): Replace with... (struct print_context, print_prepare, print_finish): ...these new functions and explicit state in a struct. (Fwrite_char, write_string, Fterpri, Fprin1, Fprin1_to_string) (Fprinc, Fprint): Adapt callers.
-rw-r--r--src/print.c276
1 files changed, 146 insertions, 130 deletions
diff --git a/src/print.c b/src/print.c
index 7303e847aa2..b2b35bd235f 100644
--- a/src/print.c
+++ b/src/print.c
@@ -91,107 +91,8 @@ bool print_output_debug_flag EXTERNALLY_VISIBLE = 1;
91 91
92/* Low level output routines for characters and strings. */ 92/* Low level output routines for characters and strings. */
93 93
94/* Lisp functions to do output using a stream
95 must have the stream in a variable called printcharfun
96 and must start with PRINTPREPARE, end with PRINTFINISH.
97 Use printchar to output one character,
98 or call strout to output a block of characters. */
99
100#define PRINTPREPARE \
101 ptrdiff_t old_point = -1, start_point = -1; \
102 ptrdiff_t old_point_byte = -1, start_point_byte = -1; \
103 specpdl_ref specpdl_count = SPECPDL_INDEX (); \
104 bool multibyte \
105 = !NILP (BVAR (current_buffer, enable_multibyte_characters)); \
106 Lisp_Object original = printcharfun; \
107 record_unwind_current_buffer (); \
108 specbind(Qprint__unreadable_callback_buffer, Fcurrent_buffer ()); \
109 if (NILP (printcharfun)) printcharfun = Qt; \
110 if (BUFFERP (printcharfun)) \
111 { \
112 if (XBUFFER (printcharfun) != current_buffer) \
113 Fset_buffer (printcharfun); \
114 printcharfun = Qnil; \
115 } \
116 if (MARKERP (printcharfun)) \
117 { \
118 ptrdiff_t marker_pos; \
119 if (! XMARKER (printcharfun)->buffer) \
120 error ("Marker does not point anywhere"); \
121 if (XMARKER (printcharfun)->buffer != current_buffer) \
122 set_buffer_internal (XMARKER (printcharfun)->buffer); \
123 marker_pos = marker_position (printcharfun); \
124 if (marker_pos < BEGV || marker_pos > ZV) \
125 signal_error ("Marker is outside the accessible " \
126 "part of the buffer", printcharfun); \
127 old_point = PT; \
128 old_point_byte = PT_BYTE; \
129 SET_PT_BOTH (marker_pos, \
130 marker_byte_position (printcharfun)); \
131 start_point = PT; \
132 start_point_byte = PT_BYTE; \
133 printcharfun = Qnil; \
134 } \
135 if (NILP (printcharfun)) \
136 { \
137 Lisp_Object string; \
138 if (NILP (BVAR (current_buffer, enable_multibyte_characters)) \
139 && ! print_escape_multibyte) \
140 specbind (Qprint_escape_multibyte, Qt); \
141 if (! NILP (BVAR (current_buffer, enable_multibyte_characters)) \
142 && ! print_escape_nonascii) \
143 specbind (Qprint_escape_nonascii, Qt); \
144 if (print_buffer != 0) \
145 { \
146 string = make_string_from_bytes (print_buffer, \
147 print_buffer_pos, \
148 print_buffer_pos_byte); \
149 record_unwind_protect (print_unwind, string); \
150 } \
151 else \
152 { \
153 int new_size = 1000; \
154 print_buffer = xmalloc (new_size); \
155 print_buffer_size = new_size; \
156 record_unwind_protect_void (print_free_buffer); \
157 } \
158 print_buffer_pos = 0; \
159 print_buffer_pos_byte = 0; \
160 } \
161 if (EQ (printcharfun, Qt) && ! noninteractive) \
162 setup_echo_area_for_printing (multibyte);
163
164#define PRINTFINISH \
165 if (NILP (printcharfun)) \
166 { \
167 if (print_buffer_pos != print_buffer_pos_byte \
168 && NILP (BVAR (current_buffer, enable_multibyte_characters)))\
169 { \
170 USE_SAFE_ALLOCA; \
171 unsigned char *temp = SAFE_ALLOCA (print_buffer_pos + 1); \
172 copy_text ((unsigned char *) print_buffer, temp, \
173 print_buffer_pos_byte, 1, 0); \
174 insert_1_both ((char *) temp, print_buffer_pos, \
175 print_buffer_pos, 0, 1, 0); \
176 SAFE_FREE (); \
177 } \
178 else \
179 insert_1_both (print_buffer, print_buffer_pos, \
180 print_buffer_pos_byte, 0, 1, 0); \
181 signal_after_change (PT - print_buffer_pos, 0, print_buffer_pos);\
182 } \
183 if (MARKERP (original)) \
184 set_marker_both (original, Qnil, PT, PT_BYTE); \
185 if (old_point >= 0) \
186 SET_PT_BOTH (old_point + (old_point >= start_point \
187 ? PT - start_point : 0), \
188 old_point_byte + (old_point_byte >= start_point_byte \
189 ? PT_BYTE - start_point_byte : 0)); \
190 unbind_to (specpdl_count, Qnil); \
191
192/* This is used to free the print buffer; we don't simply record xfree 94/* This is used to free the print buffer; we don't simply record xfree
193 since print_buffer can be reallocated during the printing. */ 95 since print_buffer can be reallocated during the printing. */
194
195static void 96static void
196print_free_buffer (void) 97print_free_buffer (void)
197{ 98{
@@ -201,13 +102,129 @@ print_free_buffer (void)
201 102
202/* This is used to restore the saved contents of print_buffer 103/* This is used to restore the saved contents of print_buffer
203 when there is a recursive call to print. */ 104 when there is a recursive call to print. */
204
205static void 105static void
206print_unwind (Lisp_Object saved_text) 106print_unwind (Lisp_Object saved_text)
207{ 107{
208 memcpy (print_buffer, SDATA (saved_text), SCHARS (saved_text)); 108 memcpy (print_buffer, SDATA (saved_text), SCHARS (saved_text));
209} 109}
210 110
111/* Lisp functions to do output using a stream must start with a call to
112 print_prepare, and end with calling print_finish.
113 Use printchar to output one character, or call strout to output a
114 block of characters. */
115
116/* State carried between print_prepare and print_finish. */
117struct print_context {
118 Lisp_Object printcharfun;
119 Lisp_Object old_printcharfun;
120 ptrdiff_t old_point, start_point;
121 ptrdiff_t old_point_byte, start_point_byte;
122 specpdl_ref specpdl_count;
123};
124
125static inline struct print_context
126print_prepare (Lisp_Object printcharfun)
127{
128 struct print_context pc = {
129 .old_printcharfun = printcharfun,
130 .old_point = -1,
131 .start_point = -1,
132 .old_point_byte = -1,
133 .start_point_byte = -1,
134 .specpdl_count = SPECPDL_INDEX (),
135 };
136 bool multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
137 record_unwind_current_buffer ();
138 specbind(Qprint__unreadable_callback_buffer, Fcurrent_buffer ());
139 if (NILP (printcharfun))
140 printcharfun = Qt;
141 if (BUFFERP (printcharfun))
142 {
143 if (XBUFFER (printcharfun) != current_buffer)
144 Fset_buffer (printcharfun);
145 printcharfun = Qnil;
146 }
147 if (MARKERP (printcharfun))
148 {
149 if (! XMARKER (printcharfun)->buffer)
150 error ("Marker does not point anywhere");
151 if (XMARKER (printcharfun)->buffer != current_buffer)
152 set_buffer_internal (XMARKER (printcharfun)->buffer);
153 ptrdiff_t marker_pos = marker_position (printcharfun);
154 if (marker_pos < BEGV || marker_pos > ZV)
155 signal_error ("Marker is outside the accessible part of the buffer",
156 printcharfun);
157 pc.old_point = PT;
158 pc.old_point_byte = PT_BYTE;
159 SET_PT_BOTH (marker_pos, marker_byte_position (printcharfun));
160 pc.start_point = PT;
161 pc.start_point_byte = PT_BYTE;
162 printcharfun = Qnil;
163 }
164 if (NILP (printcharfun))
165 {
166 if (NILP (BVAR (current_buffer, enable_multibyte_characters))
167 && ! print_escape_multibyte)
168 specbind (Qprint_escape_multibyte, Qt);
169 if (! NILP (BVAR (current_buffer, enable_multibyte_characters))
170 && ! print_escape_nonascii)
171 specbind (Qprint_escape_nonascii, Qt);
172 if (print_buffer != 0)
173 {
174 Lisp_Object string = make_string_from_bytes (print_buffer,
175 print_buffer_pos,
176 print_buffer_pos_byte);
177 record_unwind_protect (print_unwind, string);
178 }
179 else
180 {
181 int new_size = 1000;
182 print_buffer = xmalloc (new_size);
183 print_buffer_size = new_size;
184 record_unwind_protect_void (print_free_buffer);
185 }
186 print_buffer_pos = 0;
187 print_buffer_pos_byte = 0;
188 }
189 if (EQ (printcharfun, Qt) && ! noninteractive)
190 setup_echo_area_for_printing (multibyte);
191 pc.printcharfun = printcharfun;
192 return pc;
193}
194
195static inline void
196print_finish (struct print_context *pc)
197{
198 if (NILP (pc->printcharfun))
199 {
200 if (print_buffer_pos != print_buffer_pos_byte
201 && NILP (BVAR (current_buffer, enable_multibyte_characters)))
202 {
203 USE_SAFE_ALLOCA;
204 unsigned char *temp = SAFE_ALLOCA (print_buffer_pos + 1);
205 copy_text ((unsigned char *) print_buffer, temp,
206 print_buffer_pos_byte, 1, 0);
207 insert_1_both ((char *) temp, print_buffer_pos,
208 print_buffer_pos, 0, 1, 0);
209 SAFE_FREE ();
210 }
211 else
212 insert_1_both (print_buffer, print_buffer_pos,
213 print_buffer_pos_byte, 0, 1, 0);
214 signal_after_change (PT - print_buffer_pos, 0, print_buffer_pos);
215 }
216 if (MARKERP (pc->old_printcharfun))
217 set_marker_both (pc->old_printcharfun, Qnil, PT, PT_BYTE);
218 if (pc->old_point >= 0)
219 SET_PT_BOTH (pc->old_point
220 + (pc->old_point >= pc->start_point
221 ? PT - pc->start_point : 0),
222 pc->old_point_byte
223 + (pc->old_point_byte >= pc->start_point_byte
224 ? PT_BYTE - pc->start_point_byte : 0));
225 unbind_to (pc->specpdl_count, Qnil);
226}
227
211/* Print character CH to the stdio stream STREAM. */ 228/* Print character CH to the stdio stream STREAM. */
212 229
213static void 230static void
@@ -527,14 +544,14 @@ PRINTCHARFUN defaults to the value of `standard-output' (which see). */)
527 if (NILP (printcharfun)) 544 if (NILP (printcharfun))
528 printcharfun = Vstandard_output; 545 printcharfun = Vstandard_output;
529 CHECK_FIXNUM (character); 546 CHECK_FIXNUM (character);
530 PRINTPREPARE; 547 struct print_context pc = print_prepare (printcharfun);
531 printchar (XFIXNUM (character), printcharfun); 548 printchar (XFIXNUM (character), pc.printcharfun);
532 PRINTFINISH; 549 print_finish (&pc);
533 return character; 550 return character;
534} 551}
535 552
536/* Print the contents of a unibyte C string STRING using PRINTCHARFUN. 553/* Print the contents of a unibyte C string STRING using PRINTCHARFUN.
537 The caller should arrange to put this inside PRINTPREPARE and PRINTFINISH. 554 The caller should arrange to put this inside print_prepare and print_finish.
538 Do not use this on the contents of a Lisp string. */ 555 Do not use this on the contents of a Lisp string. */
539 556
540static void 557static void
@@ -550,9 +567,9 @@ print_c_string (char const *string, Lisp_Object printcharfun)
550static void 567static void
551write_string (const char *data, Lisp_Object printcharfun) 568write_string (const char *data, Lisp_Object printcharfun)
552{ 569{
553 PRINTPREPARE; 570 struct print_context pc = print_prepare (printcharfun);
554 print_c_string (data, printcharfun); 571 print_c_string (data, pc.printcharfun);
555 PRINTFINISH; 572 print_finish (&pc);
556} 573}
557 574
558 575
@@ -605,21 +622,21 @@ If PRINTCHARFUN is omitted or nil, the value of `standard-output' is used. */)
605 622
606 if (NILP (printcharfun)) 623 if (NILP (printcharfun))
607 printcharfun = Vstandard_output; 624 printcharfun = Vstandard_output;
608 PRINTPREPARE; 625 struct print_context pc = print_prepare (printcharfun);
609 626
610 if (NILP (ensure)) 627 if (NILP (ensure))
611 val = Qt; 628 val = Qt;
612 /* Difficult to check if at line beginning so abort. */ 629 /* Difficult to check if at line beginning so abort. */
613 else if (FUNCTIONP (printcharfun)) 630 else if (FUNCTIONP (pc.printcharfun))
614 signal_error ("Unsupported function argument", printcharfun); 631 signal_error ("Unsupported function argument", pc.printcharfun);
615 else if (noninteractive && !NILP (printcharfun)) 632 else if (noninteractive && !NILP (pc.printcharfun))
616 val = printchar_stdout_last == 10 ? Qnil : Qt; 633 val = printchar_stdout_last == 10 ? Qnil : Qt;
617 else 634 else
618 val = NILP (Fbolp ()) ? Qt : Qnil; 635 val = NILP (Fbolp ()) ? Qt : Qnil;
619 636
620 if (!NILP (val)) 637 if (!NILP (val))
621 printchar ('\n', printcharfun); 638 printchar ('\n', pc.printcharfun);
622 PRINTFINISH; 639 print_finish (&pc);
623 return val; 640 return val;
624} 641}
625 642
@@ -750,9 +767,9 @@ means "use default values for all the print-related settings". */)
750 if (!NILP (overrides)) 767 if (!NILP (overrides))
751 print_bind_overrides (overrides); 768 print_bind_overrides (overrides);
752 769
753 PRINTPREPARE; 770 struct print_context pc = print_prepare (printcharfun);
754 print (object, printcharfun, 1); 771 print (object, pc.printcharfun, 1);
755 PRINTFINISH; 772 print_finish (&pc);
756 773
757 return unbind_to (count, object); 774 return unbind_to (count, object);
758} 775}
@@ -787,11 +804,10 @@ A printed representation of an object is text which describes that object. */)
787 No need for specbind, since errors deactivate the mark. */ 804 No need for specbind, since errors deactivate the mark. */
788 Lisp_Object save_deactivate_mark = Vdeactivate_mark; 805 Lisp_Object save_deactivate_mark = Vdeactivate_mark;
789 806
790 Lisp_Object printcharfun = Vprin1_to_string_buffer; 807 struct print_context pc = print_prepare (Vprin1_to_string_buffer);
791 PRINTPREPARE; 808 print (object, pc.printcharfun, NILP (noescape));
792 print (object, printcharfun, NILP (noescape)); 809 /* Make Vprin1_to_string_buffer be the default buffer after print_finish */
793 /* Make Vprin1_to_string_buffer be the default buffer after PRINTFINISH */ 810 print_finish (&pc);
794 PRINTFINISH;
795 811
796 struct buffer *previous = current_buffer; 812 struct buffer *previous = current_buffer;
797 set_buffer_internal (XBUFFER (Vprin1_to_string_buffer)); 813 set_buffer_internal (XBUFFER (Vprin1_to_string_buffer));
@@ -836,15 +852,15 @@ is used instead. */)
836{ 852{
837 if (NILP (printcharfun)) 853 if (NILP (printcharfun))
838 printcharfun = Vstandard_output; 854 printcharfun = Vstandard_output;
839 PRINTPREPARE; 855 struct print_context pc = print_prepare (printcharfun);
840 if (STRINGP (object) 856 if (STRINGP (object)
841 && !string_intervals (object) 857 && !string_intervals (object)
842 && NILP (Vprint_continuous_numbering)) 858 && NILP (Vprint_continuous_numbering))
843 /* fast path for plain strings */ 859 /* fast path for plain strings */
844 print_string (object, printcharfun); 860 print_string (object, pc.printcharfun);
845 else 861 else
846 print (object, printcharfun, 0); 862 print (object, pc.printcharfun, 0);
847 PRINTFINISH; 863 print_finish (&pc);
848 return object; 864 return object;
849} 865}
850 866
@@ -875,11 +891,11 @@ is used instead. */)
875{ 891{
876 if (NILP (printcharfun)) 892 if (NILP (printcharfun))
877 printcharfun = Vstandard_output; 893 printcharfun = Vstandard_output;
878 PRINTPREPARE; 894 struct print_context pc = print_prepare (printcharfun);
879 printchar ('\n', printcharfun); 895 printchar ('\n', pc.printcharfun);
880 print (object, printcharfun, 1); 896 print (object, pc.printcharfun, 1);
881 printchar ('\n', printcharfun); 897 printchar ('\n', pc.printcharfun);
882 PRINTFINISH; 898 print_finish (&pc);
883 return object; 899 return object;
884} 900}
885 901