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 /*