Mercurial > hg > xemacs-beta
comparison src/print.c @ 276:6330739388db r21-0b36
Import from CVS: tag r21-0b36
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:30:37 +0200 |
parents | c5d627a313b1 |
children | 90d73dddcdc4 |
comparison
equal
deleted
inserted
replaced
275:a68ae4439f57 | 276:6330739388db |
---|---|
175 ccoff = bytecount_to_charcount (newnonreloc, offset); | 175 ccoff = bytecount_to_charcount (newnonreloc, offset); |
176 cclen = bytecount_to_charcount (newnonreloc + offset, len); | 176 cclen = bytecount_to_charcount (newnonreloc + offset, len); |
177 | 177 |
178 if (LSTREAMP (function)) | 178 if (LSTREAMP (function)) |
179 { | 179 { |
180 /* Lstream_write() could easily cause GC inside of it, if the | |
181 stream is a print-stream. (It will call output_string() | |
182 recursively.) This is probably the fastest way to fix this | |
183 problem. (alloca() is very fast on machines that have it | |
184 built-in, and you avoid some nasty problems with recursion | |
185 that could result from using a static buffer somewhere.) | |
186 | |
187 The other possibility is to inhibit GC, but that of course | |
188 would require an unwind-protect, which is usually a lot | |
189 slower than the small amount of memcpy()ing that happens | |
190 here. */ | |
191 if (STRINGP (reloc)) | 180 if (STRINGP (reloc)) |
192 { | 181 { |
193 Bufbyte *copied = (Bufbyte *) alloca (len); | 182 /* Protect against Lstream_write() causing a GC and |
194 memcpy (copied, newnonreloc + offset, len); | 183 relocating the string. For small strings, we do it by |
195 Lstream_write (XLSTREAM (function), copied, len); | 184 alloc'ing the string and using a copy; for large strings, |
185 we inhibit GC. Now that print_streams are dead, this | |
186 case should happen very rarely anyway. */ | |
187 if (len < 65536) | |
188 { | |
189 Bufbyte *copied = alloca_array (Bufbyte, len); | |
190 memcpy (copied, newnonreloc + offset, len); | |
191 Lstream_write (XLSTREAM (function), copied, len); | |
192 } | |
193 else | |
194 { | |
195 int speccount = specpdl_depth (); | |
196 record_unwind_protect (restore_gc_inhibit, | |
197 make_int (gc_currently_forbidden)); | |
198 gc_currently_forbidden = 1; | |
199 Lstream_write (XLSTREAM (function), newnonreloc + offset, len); | |
200 unbind_to (speccount, Qnil); | |
201 } | |
196 } | 202 } |
197 else | 203 else |
198 Lstream_write (XLSTREAM (function), newnonreloc + offset, len); | 204 Lstream_write (XLSTREAM (function), newnonreloc + offset, len); |
199 | 205 |
200 if (print_unbuffered) | 206 if (print_unbuffered) |
245 } | 251 } |
246 | 252 |
247 UNGCPRO; | 253 UNGCPRO; |
248 } | 254 } |
249 | 255 |
250 struct print_stream | |
251 { | |
252 FILE *file; | |
253 Lisp_Object fun; | |
254 }; | |
255 | |
256 #define get_print_stream(stream) \ | |
257 ((struct print_stream *) Lstream_data (stream)) | |
258 | |
259 DEFINE_LSTREAM_IMPLEMENTATION ("print", lstream_print, | |
260 sizeof (struct print_stream)); | |
261 | |
262 static Lisp_Object | |
263 make_print_output_stream (FILE *file, Lisp_Object fun) | |
264 { | |
265 Lstream *str = Lstream_new (lstream_print, "w"); | |
266 struct print_stream *ps = get_print_stream (str); | |
267 Lisp_Object val; | |
268 | |
269 Lstream_set_character_mode (str); | |
270 ps->file = file; | |
271 ps->fun = fun; | |
272 XSETLSTREAM (val, str); | |
273 return val; | |
274 } | |
275 | |
276 /* #### This isn't being used anywhere at the moment. Is it supposed | |
277 to be? */ | |
278 #if 0 | |
279 static void | |
280 reset_print_stream (Lstream *str, FILE *file, Lisp_Object fun) | |
281 { | |
282 struct print_stream *ps = get_print_stream (str); | |
283 | |
284 Lstream_reopen (str); | |
285 ps->file = file; | |
286 ps->fun = fun; | |
287 } | |
288 #endif | |
289 | |
290 static Lisp_Object | |
291 print_marker (Lisp_Object obj, void (*markobj) (Lisp_Object)) | |
292 { | |
293 return get_print_stream (XLSTREAM (obj))->fun; | |
294 } | |
295 | |
296 static int | |
297 print_writer (Lstream *stream, CONST unsigned char *data, size_t size) | |
298 { | |
299 struct print_stream *ps = get_print_stream (stream); | |
300 | |
301 if (ps->file) | |
302 { | |
303 write_string_to_stdio_stream (ps->file, 0, data, 0, size, | |
304 FORMAT_TERMINAL); | |
305 /* Make sure it really gets written now. */ | |
306 if (print_unbuffered) | |
307 fflush (ps->file); | |
308 } | |
309 else | |
310 output_string (ps->fun, data, Qnil, 0, size); | |
311 return size; | |
312 } | |
313 | |
314 static Lisp_Object | 256 static Lisp_Object |
315 canonicalize_printcharfun (Lisp_Object printcharfun) | 257 canonicalize_printcharfun (Lisp_Object printcharfun) |
316 { | 258 { |
317 if (NILP (printcharfun)) | 259 if (NILP (printcharfun)) |
318 printcharfun = Vstandard_output; | 260 printcharfun = Vstandard_output; |
324 #endif | 266 #endif |
325 } | 267 } |
326 return printcharfun; | 268 return printcharfun; |
327 } | 269 } |
328 | 270 |
271 /* Now that print_streams are dead, I wonder if the following two | |
272 functions are needed as separate entities. */ | |
329 | 273 |
330 static Lisp_Object | 274 static Lisp_Object |
331 print_prepare (Lisp_Object printcharfun) | 275 print_prepare (Lisp_Object printcharfun) |
332 { | 276 { |
333 FILE *stdio_stream = 0; | |
334 | |
335 /* Emacs won't print whilst GCing, but an external debugger might */ | 277 /* Emacs won't print whilst GCing, but an external debugger might */ |
336 if (gc_in_progress) | 278 if (gc_in_progress) |
337 return Qnil; | 279 return Qnil; |
338 | 280 |
339 printcharfun = canonicalize_printcharfun (printcharfun); | 281 printcharfun = canonicalize_printcharfun (printcharfun); |
340 if (NILP (printcharfun)) | |
341 { | |
342 stdio_stream = stdout; | |
343 } | |
344 #if 0 /* Don't bother */ | |
345 else if (SUBRP (indirect_function (printcharfun, 0)) | |
346 && (XSUBR (indirect_function (printcharfun, 0)) | |
347 == Sexternal_debugging_output)) | |
348 { | |
349 stdio_stream = stderr; | |
350 } | |
351 #endif | |
352 if (!CONSP (Vprint_gensym)) | 282 if (!CONSP (Vprint_gensym)) |
353 Vprint_gensym_alist = Qnil; | 283 Vprint_gensym_alist = Qnil; |
354 | 284 |
355 return make_print_output_stream (stdio_stream, printcharfun); | 285 return printcharfun; |
356 } | 286 } |
357 | 287 |
358 static void | 288 static void |
359 print_finish (Lisp_Object stream) | 289 print_finish (Lisp_Object stream) |
360 { | 290 { |
362 if (gc_in_progress) | 292 if (gc_in_progress) |
363 return; | 293 return; |
364 | 294 |
365 if (!CONSP (Vprint_gensym)) | 295 if (!CONSP (Vprint_gensym)) |
366 Vprint_gensym_alist = Qnil; | 296 Vprint_gensym_alist = Qnil; |
367 | |
368 Lstream_delete (XLSTREAM (stream)); | |
369 } | 297 } |
370 | 298 |
371 #if 1 /* Prefer space over "speed" */ | 299 #if 1 /* Prefer space over "speed" */ |
372 #define write_char_internal(string_of_length_1, stream) \ | 300 #define write_char_internal(string_of_length_1, stream) \ |
373 write_string_1 ((CONST Bufbyte *) (string_of_length_1), 1, (stream)) | 301 write_string_1 ((CONST Bufbyte *) (string_of_length_1), 1, (stream)) |
546 second argument NOESCAPE is non-nil. | 474 second argument NOESCAPE is non-nil. |
547 */ | 475 */ |
548 (object, noescape)) | 476 (object, noescape)) |
549 { | 477 { |
550 /* This function can GC */ | 478 /* This function can GC */ |
551 Lisp_Object result = Qnil; | |
552 Lstream *stream; | 479 Lstream *stream; |
553 struct gcpro gcpro1; | 480 struct gcpro gcpro1; |
554 | 481 |
555 /* We avoid creating a new stream for every invocation of | 482 /* We avoid creating a new stream for every invocation of |
556 prin1_to_string, for better memory usage. */ | 483 prin1_to_string, for better memory usage. #### Is it necessary? */ |
557 | 484 |
558 if (NILP (Vprin1_to_string_stream)) | 485 if (NILP (Vprin1_to_string_stream)) |
559 Vprin1_to_string_stream = make_resizing_buffer_output_stream (); | 486 Vprin1_to_string_stream = make_resizing_buffer_output_stream (); |
560 stream = XLSTREAM (Vprin1_to_string_stream); | 487 stream = XLSTREAM (Vprin1_to_string_stream); |
561 Lstream_rewind (stream); | 488 Lstream_rewind (stream); |
562 | 489 |
563 /* In case a caller forgot to protect. */ | 490 /* In case a caller forgot to protect. */ |
564 GCPRO1 (object); | 491 GCPRO1 (object); |
565 print_depth = 0; | 492 print_depth = 0; |
493 if (!CONSP (Vprint_gensym)) | |
494 Vprint_gensym_alist = Qnil; | |
566 print_internal (object, Vprin1_to_string_stream, NILP (noescape)); | 495 print_internal (object, Vprin1_to_string_stream, NILP (noescape)); |
496 if (!CONSP (Vprint_gensym)) | |
497 Vprint_gensym_alist = Qnil; | |
567 Lstream_flush (stream); | 498 Lstream_flush (stream); |
568 UNGCPRO; | 499 UNGCPRO; |
569 result = make_string (resizing_buffer_stream_ptr (stream), | 500 return make_string (resizing_buffer_stream_ptr (stream), |
570 Lstream_byte_count (stream)); | 501 Lstream_byte_count (stream)); |
571 return result; | |
572 } | 502 } |
573 | 503 |
574 DEFUN ("princ", Fprinc, 1, 2, 0, /* | 504 DEFUN ("princ", Fprinc, 1, 2, 0, /* |
575 Output the printed representation of OBJECT, any Lisp object. | 505 Output the printed representation of OBJECT, any Lisp object. |
576 No quoting characters are used; no delimiters are printed around | 506 No quoting characters are used; no delimiters are printed around |
622 Convert an error value (ERROR-SYMBOL . DATA) to an error message. | 552 Convert an error value (ERROR-SYMBOL . DATA) to an error message. |
623 */ | 553 */ |
624 (data)) | 554 (data)) |
625 { | 555 { |
626 /* This function can GC */ | 556 /* This function can GC */ |
627 | |
628 /* This should maybe use Vprin1_to_string_stream... However, it's | |
629 called sufficiently rarely, so I don't think it should matter. */ | |
630 Lisp_Object stream = make_resizing_buffer_output_stream (); | 557 Lisp_Object stream = make_resizing_buffer_output_stream (); |
631 struct gcpro gcpro1; | 558 struct gcpro gcpro1; |
632 GCPRO1 (stream); | 559 GCPRO1 (stream); |
633 | 560 |
634 print_error_message (data, stream); | 561 print_error_message (data, stream); |
1001 } | 928 } |
1002 UNGCPRO; | 929 UNGCPRO; |
1003 return; | 930 return; |
1004 } | 931 } |
1005 | 932 |
933 /* Print NUMBER to BUFFER. The digits are first written in reverse | |
934 order (the least significant digit first), and are then reversed. | |
935 This is equivalent to sprintf(buffer, "%ld", number), only much | |
936 faster. */ | |
937 void | |
938 long_to_string (char *buffer, long number) | |
939 { | |
940 char *p; | |
941 int i, l; | |
942 | |
943 if (number < 0) | |
944 { | |
945 *buffer++ = '-'; | |
946 number = -number; | |
947 } | |
948 p = buffer; | |
949 /* Print the digits to the string. */ | |
950 do | |
951 { | |
952 *p++ = number % 10 + '0'; | |
953 number /= 10; | |
954 } | |
955 while (number); | |
956 /* And reverse them. */ | |
957 l = p - buffer - 1; | |
958 for (i = l/2; i >= 0; i--) | |
959 { | |
960 char c = buffer[i]; | |
961 buffer[i] = buffer[l - i]; | |
962 buffer[l - i] = c; | |
963 } | |
964 buffer[l + 1] = '\0'; | |
965 } | |
1006 | 966 |
1007 static void | 967 static void |
1008 default_object_printer (Lisp_Object obj, Lisp_Object printcharfun, | 968 default_object_printer (Lisp_Object obj, Lisp_Object printcharfun, |
1009 int escapeflag) | 969 int escapeflag) |
1010 { | 970 { |
1085 case Lisp_Type_Int_Odd: | 1045 case Lisp_Type_Int_Odd: |
1086 #else | 1046 #else |
1087 case Lisp_Type_Int: | 1047 case Lisp_Type_Int: |
1088 #endif | 1048 #endif |
1089 { | 1049 { |
1090 sprintf (buf, "%ld", (long) XINT (obj)); | 1050 long_to_string (buf, XINT (obj)); |
1091 write_c_string (buf, printcharfun); | 1051 write_c_string (buf, printcharfun); |
1092 break; | 1052 break; |
1093 } | 1053 } |
1094 | 1054 |
1095 case Lisp_Type_Char: | 1055 case Lisp_Type_Char: |
1716 DEFSUBR (Fwith_output_to_temp_buffer); | 1676 DEFSUBR (Fwith_output_to_temp_buffer); |
1717 #endif /* not standalone */ | 1677 #endif /* not standalone */ |
1718 } | 1678 } |
1719 | 1679 |
1720 void | 1680 void |
1721 lstream_type_create_print (void) | |
1722 { | |
1723 LSTREAM_HAS_METHOD (print, writer); | |
1724 LSTREAM_HAS_METHOD (print, marker); | |
1725 } | |
1726 | |
1727 void | |
1728 vars_of_print (void) | 1681 vars_of_print (void) |
1729 { | 1682 { |
1730 alternate_do_pointer = 0; | 1683 alternate_do_pointer = 0; |
1731 | 1684 |
1732 DEFVAR_LISP ("standard-output", &Vstandard_output /* | 1685 DEFVAR_LISP ("standard-output", &Vstandard_output /* |