X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/535272bb73eff5a5db01301e5b60f6128d6dc788..436bc8e0a73e02ed0840633c4d4d4922a222db24:/src/print.c?ds=sidebyside diff --git a/src/print.c b/src/print.c index 8e5aab85c3..fc435efe7c 100644 --- a/src/print.c +++ b/src/print.c @@ -1,6 +1,6 @@ /* Lisp object printing and output streams. -Copyright (C) 1985-1986, 1988, 1993-1995, 1997-2011 +Copyright (C) 1985-1986, 1988, 1993-1995, 1997-2012 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -23,8 +23,8 @@ along with GNU Emacs. If not, see . */ #include #include #include "lisp.h" -#include "buffer.h" #include "character.h" +#include "buffer.h" #include "charset.h" #include "keyboard.h" #include "frame.h" @@ -55,10 +55,10 @@ static Lisp_Object Qfloat_output_format; #endif /* Avoid actual stack overflow in print. */ -static int print_depth; +static ptrdiff_t print_depth; /* Level of nesting inside outputting backquote in new style. */ -static int new_backquote_output; +static ptrdiff_t new_backquote_output; /* Detect most circularities to print finite output. */ #define PRINT_CIRCLE 200 @@ -86,21 +86,21 @@ static Lisp_Object Qprint_escape_multibyte, Qprint_escape_nonascii; N the object has been printed so we can refer to it as #N#. print_number_index holds the largest N already used. N has to be striclty larger than 0 since we need to distinguish -N. */ -static int print_number_index; +static ptrdiff_t print_number_index; static void print_interval (INTERVAL interval, Lisp_Object printcharfun); /* GDB resets this to zero on W32 to disable OutputDebugString calls. */ int print_output_debug_flag EXTERNALLY_VISIBLE = 1; -/* Low level output routines for characters and strings */ +/* Low level output routines for characters and strings. */ /* Lisp functions to do output using a stream must have the stream in a variable called printcharfun and must start with PRINTPREPARE, end with PRINTFINISH, and use PRINTDECLARE to declare common variables. Use PRINTCHAR to output one character, - or call strout to output a block of characters. */ + or call strout to output a block of characters. */ #define PRINTDECLARE \ struct buffer *old = current_buffer; \ @@ -157,7 +157,7 @@ int print_output_debug_flag EXTERNALLY_VISIBLE = 1; else \ { \ int new_size = 1000; \ - print_buffer = (char *) xmalloc (new_size); \ + print_buffer = xmalloc (new_size); \ print_buffer_size = new_size; \ free_print_buffer = 1; \ } \ @@ -173,14 +173,11 @@ int print_output_debug_flag EXTERNALLY_VISIBLE = 1; if (print_buffer_pos != print_buffer_pos_byte \ && NILP (BVAR (current_buffer, enable_multibyte_characters))) \ { \ - USE_SAFE_ALLOCA; \ - unsigned char *temp; \ - SAFE_ALLOCA (temp, unsigned char *, print_buffer_pos + 1); \ + unsigned char *temp = alloca (print_buffer_pos + 1); \ copy_text ((unsigned char *) print_buffer, temp, \ print_buffer_pos_byte, 1, 0); \ insert_1_both ((char *) temp, print_buffer_pos, \ print_buffer_pos, 0, 1, 0); \ - SAFE_FREE (); \ } \ else \ insert_1_both (print_buffer, print_buffer_pos, \ @@ -611,7 +608,7 @@ A printed representation of an object is text which describes that object. */) printcharfun = Vprin1_to_string_buffer; PRINTPREPARE; print (object, printcharfun, NILP (noescape)); - /* Make Vprin1_to_string_buffer be the default buffer after PRINTFINSH */ + /* Make Vprin1_to_string_buffer be the default buffer after PRINTFINISH */ PRINTFINISH; } @@ -718,8 +715,8 @@ You can call print while debugging emacs, and pass it this function to make it write to the debugging output. */) (Lisp_Object character) { - CHECK_CHARACTER (character); - putc ((int) XINT (character), stderr); + CHECK_NUMBER (character); + putc (XINT (character) & 0xFF, stderr); #ifdef WINDOWSNT /* Send the output to a debugger (nothing happens if there isn't one). */ @@ -856,7 +853,6 @@ print_error_message (Lisp_Object data, Lisp_Object stream, const char *context, { Lisp_Object errname, errmsg, file_error, tail; struct gcpro gcpro1; - int i; if (context != 0) write_string_1 (context, -1, stream); @@ -887,9 +883,8 @@ print_error_message (Lisp_Object data, Lisp_Object stream, const char *context, } else { - Lisp_Object error_conditions; + Lisp_Object error_conditions = Fget (errname, Qerror_conditions); errmsg = Fget (errname, Qerror_message); - error_conditions = Fget (errname, Qerror_conditions); file_error = Fmemq (Qfile_error, error_conditions); } @@ -903,22 +898,30 @@ print_error_message (Lisp_Object data, Lisp_Object stream, const char *context, if (!NILP (file_error) && CONSP (tail)) errmsg = XCAR (tail), tail = XCDR (tail); - if (STRINGP (errmsg)) - Fprinc (errmsg, stream); - else - write_string_1 ("peculiar error", -1, stream); + { + const char *sep = ": "; - for (i = 0; CONSP (tail); tail = XCDR (tail), i = 1) - { - Lisp_Object obj; + if (!STRINGP (errmsg)) + write_string_1 ("peculiar error", -1, stream); + else if (SCHARS (errmsg)) + Fprinc (errmsg, stream); + else + sep = NULL; - write_string_1 (i ? ", " : ": ", 2, stream); - obj = XCAR (tail); - if (!NILP (file_error) || EQ (errname, Qend_of_file)) - Fprinc (obj, stream); - else - Fprin1 (obj, stream); - } + for (; CONSP (tail); tail = XCDR (tail), sep = ", ") + { + Lisp_Object obj; + + if (sep) + write_string_1 (sep, 2, stream); + obj = XCAR (tail); + if (!NILP (file_error) + || EQ (errname, Qend_of_file) || EQ (errname, Quser_error)) + Fprinc (obj, stream); + else + Fprin1 (obj, stream); + } + } UNGCPRO; } @@ -940,43 +943,49 @@ print_error_message (Lisp_Object data, Lisp_Object stream, const char *context, * Given the above, the buffer must be least FLOAT_TO_STRING_BUFSIZE bytes. */ -void +int float_to_string (char *buf, double data) { char *cp; int width; + int len; /* Check for plus infinity in a way that won't lose if there is no plus infinity. */ if (data == data / 2 && data > 1.0) { - strcpy (buf, "1.0e+INF"); - return; + static char const infinity_string[] = "1.0e+INF"; + strcpy (buf, infinity_string); + return sizeof infinity_string - 1; } /* Likewise for minus infinity. */ if (data == data / 2 && data < -1.0) { - strcpy (buf, "-1.0e+INF"); - return; + static char const minus_infinity_string[] = "-1.0e+INF"; + strcpy (buf, minus_infinity_string); + return sizeof minus_infinity_string - 1; } /* Check for NaN in a way that won't fail if there are no NaNs. */ if (! (data * 0.0 >= 0.0)) { /* Prepend "-" if the NaN's sign bit is negative. The sign bit of a double is the bit that is 1 in -0.0. */ + static char const NaN_string[] = "0.0e+NaN"; int i; union { double d; char c[sizeof (double)]; } u_data, u_minus_zero; + int negative = 0; u_data.d = data; u_minus_zero.d = - 0.0; for (i = 0; i < sizeof (double); i++) if (u_data.c[i] & u_minus_zero.c[i]) { - *buf++ = '-'; + *buf = '-'; + negative = 1; break; } - strcpy (buf, "0.0e+NaN"); - return; + strcpy (buf + negative, NaN_string); + return negative + sizeof NaN_string - 1; } if (NILP (Vfloat_output_format) @@ -985,7 +994,7 @@ float_to_string (char *buf, double data) { /* Generate the fewest number of digits that represent the floating point value without losing information. */ - dtoastr (buf, FLOAT_TO_STRING_BUFSIZE - 2, 0, 0, data); + len = dtoastr (buf, FLOAT_TO_STRING_BUFSIZE - 2, 0, 0, data); /* The decimal point must be printed, or the byte compiler can get confused (Bug#8033). */ width = 1; @@ -1028,7 +1037,7 @@ float_to_string (char *buf, double data) if (cp[1] != 0) goto lose; - sprintf (buf, SSDATA (Vfloat_output_format), data); + len = sprintf (buf, SSDATA (Vfloat_output_format), data); } /* Make sure there is a decimal point with digit after, or an @@ -1045,14 +1054,18 @@ float_to_string (char *buf, double data) { cp[1] = '0'; cp[2] = 0; + len++; } else if (*cp == 0) { *cp++ = '.'; *cp++ = '0'; *cp++ = 0; + len += 2; } } + + return len; } @@ -1082,9 +1095,7 @@ print (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag) if (HASH_TABLE_P (Vprint_number_table)) { /* Remove unnecessary objects, which appear only once in OBJ; - that is, whose status is Qt. - Maybe a better way to do that is to copy elements to - a new hash table. */ + that is, whose status is Qt. */ struct Lisp_Hash_Table *h = XHASH_TABLE (Vprint_number_table); ptrdiff_t i; @@ -1124,15 +1135,15 @@ print_preprocess (Lisp_Object obj) int loop_count = 0; Lisp_Object halftail; - /* Give up if we go so deep that print_object will get an error. */ - /* See similar code in print_object. */ - if (print_depth >= PRINT_CIRCLE) - error ("Apparently circular structure being printed"); - /* Avoid infinite recursion for circular nested structure in the case where Vprint_circle is nil. */ if (NILP (Vprint_circle)) { + /* Give up if we go so deep that print_object will get an error. */ + /* See similar code in print_object. */ + if (print_depth >= PRINT_CIRCLE) + error ("Apparently circular structure being printed"); + for (i = 0; i < print_depth; i++) if (EQ (obj, being_printed[i])) return; @@ -1206,7 +1217,7 @@ print_preprocess (Lisp_Object obj) if (size & PSEUDOVECTOR_FLAG) size &= PSEUDOVECTOR_SIZE_MASK; for (i = 0; i < size; i++) - print_preprocess (XVECTOR (obj)->contents[i]); + print_preprocess (AREF (obj, i)); if (HASH_TABLE_P (obj)) { /* For hash tables, the key_and_value slot is past `size' because it needs to be marked specially in case @@ -1234,7 +1245,7 @@ static void print_check_string_charset_prop (INTERVAL interval, Lisp_Object stri #define PRINT_STRING_NON_CHARSET_FOUND 1 #define PRINT_STRING_UNSAFE_CHARSET_FOUND 2 -/* Bitwise or of the above macros. */ +/* Bitwise or of the above macros. */ static int print_check_string_result; static void @@ -1317,48 +1328,46 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag QUIT; - /* See similar code in print_preprocess. */ - if (print_depth >= PRINT_CIRCLE) - error ("Apparently circular structure being printed"); - /* Detect circularities and truncate them. */ - if (PRINT_CIRCLE_CANDIDATE_P (obj)) + if (NILP (Vprint_circle)) { - if (NILP (Vprint_circle) && NILP (Vprint_gensym)) - { - /* Simple but incomplete way. */ - int i; - for (i = 0; i < print_depth; i++) - if (EQ (obj, being_printed[i])) - { - sprintf (buf, "#%d", i); - strout (buf, -1, -1, printcharfun); - return; - } - being_printed[print_depth] = obj; - } - else + /* Simple but incomplete way. */ + int i; + + /* See similar code in print_preprocess. */ + if (print_depth >= PRINT_CIRCLE) + error ("Apparently circular structure being printed"); + + for (i = 0; i < print_depth; i++) + if (EQ (obj, being_printed[i])) + { + int len = sprintf (buf, "#%d", i); + strout (buf, len, len, printcharfun); + return; + } + being_printed[print_depth] = obj; + } + else if (PRINT_CIRCLE_CANDIDATE_P (obj)) + { + /* With the print-circle feature. */ + Lisp_Object num = Fgethash (obj, Vprint_number_table, Qnil); + if (INTEGERP (num)) { - /* With the print-circle feature. */ - Lisp_Object num = Fgethash (obj, Vprint_number_table, Qnil); - if (INTEGERP (num)) + EMACS_INT n = XINT (num); + if (n < 0) + { /* Add a prefix #n= if OBJ has not yet been printed; + that is, its status field is nil. */ + int len = sprintf (buf, "#%"pI"d=", -n); + strout (buf, len, len, printcharfun); + /* OBJ is going to be printed. Remember that fact. */ + Fputhash (obj, make_number (- n), Vprint_number_table); + } + else { - EMACS_INT n = XINT (num); - if (n < 0) - { /* Add a prefix #n= if OBJ has not yet been printed; - that is, its status field is nil. */ - sprintf (buf, "#%"pI"d=", -n); - strout (buf, -1, -1, printcharfun); - /* OBJ is going to be printed. Remember that fact. */ - Fputhash (obj, make_number (- n), Vprint_number_table); - } - else - { - /* Just print #n# if OBJ has already been printed. */ - sprintf (buf, "#%"pI"d#", n); - strout (buf, -1, -1, printcharfun); - return; - } + /* Just print #n# if OBJ has already been printed. */ + int len = sprintf (buf, "#%"pI"d#", n); + strout (buf, len, len, printcharfun); + return; } } } @@ -1368,16 +1377,17 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag switch (XTYPE (obj)) { case_Lisp_Int: - sprintf (buf, "%"pI"d", XINT (obj)); - strout (buf, -1, -1, printcharfun); + { + int len = sprintf (buf, "%"pI"d", XINT (obj)); + strout (buf, len, len, printcharfun); + } break; case Lisp_Float: { char pigbuf[FLOAT_TO_STRING_BUFSIZE]; - - float_to_string (pigbuf, XFLOAT_DATA (obj)); - strout (pigbuf, -1, -1, printcharfun); + int len = float_to_string (pigbuf, XFLOAT_DATA (obj)); + strout (pigbuf, len, len, printcharfun); } break; @@ -1447,15 +1457,16 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag when found in a multibyte string, always use a hex escape so it reads back as multibyte. */ char outbuf[50]; + int len; if (CHAR_BYTE8_P (c)) - sprintf (outbuf, "\\%03o", CHAR_TO_BYTE8 (c)); + len = sprintf (outbuf, "\\%03o", CHAR_TO_BYTE8 (c)); else { - sprintf (outbuf, "\\x%04x", c); + len = sprintf (outbuf, "\\x%04x", c); need_nonhex = 1; } - strout (outbuf, -1, -1, printcharfun); + strout (outbuf, len, len, printcharfun); } else if (! multibyte && SINGLE_BYTE_CHAR_P (c) && ! ASCII_BYTE_P (c) @@ -1466,8 +1477,8 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag print single-byte non-ASCII string chars using octal escapes. */ char outbuf[5]; - sprintf (outbuf, "\\%03o", c); - strout (outbuf, -1, -1, printcharfun); + int len = sprintf (outbuf, "\\%03o", c); + strout (outbuf, len, len, printcharfun); } else { @@ -1629,11 +1640,11 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag /* Detect circular list. */ if (NILP (Vprint_circle)) { - /* Simple but imcomplete way. */ + /* Simple but incomplete way. */ if (i != 0 && EQ (obj, halftail)) { - sprintf (buf, " . #%"pMd, i / 2); - strout (buf, -1, -1, printcharfun); + int len = sprintf (buf, " . #%"pMd, i / 2); + strout (buf, len, len, printcharfun); goto end_of_list; } } @@ -1697,7 +1708,8 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag else if (BOOL_VECTOR_P (obj)) { ptrdiff_t i; - register unsigned char c; + int len; + unsigned char c; struct gcpro gcpro1; ptrdiff_t size_in_chars = ((XBOOL_VECTOR (obj)->size + BOOL_VECTOR_BITS_PER_CHAR - 1) @@ -1707,8 +1719,8 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag PRINTCHAR ('#'); PRINTCHAR ('&'); - sprintf (buf, "%"pI"d", XBOOL_VECTOR (obj)->size); - strout (buf, -1, -1, printcharfun); + len = sprintf (buf, "%"pI"d", XBOOL_VECTOR (obj)->size); + strout (buf, len, len, printcharfun); PRINTCHAR ('\"'); /* Don't print more characters than the specified maximum. @@ -1759,9 +1771,10 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag } else if (WINDOWP (obj)) { + int len; strout ("#sequence_number)); - strout (buf, -1, -1, printcharfun); + len = sprintf (buf, "%d", XWINDOW (obj)->sequence_number); + strout (buf, len, len, printcharfun); if (!NILP (XWINDOW (obj)->buffer)) { strout (" on ", -1, -1, printcharfun); @@ -1771,10 +1784,11 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag } else if (TERMINALP (obj)) { + int len; struct terminal *t = XTERMINAL (obj); strout ("#id); - strout (buf, -1, -1, printcharfun); + len = sprintf (buf, "%d", t->id); + strout (buf, len, len, printcharfun); if (t->name) { strout (" on ", -1, -1, printcharfun); @@ -1787,6 +1801,7 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag struct Lisp_Hash_Table *h = XHASH_TABLE (obj); ptrdiff_t i; ptrdiff_t real_size, size; + int len; #if 0 strout ("#test)) @@ -1797,18 +1812,18 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag PRINTCHAR (' '); strout (SDATA (SYMBOL_NAME (h->weak)), -1, -1, printcharfun); PRINTCHAR (' '); - sprintf (buf, "%"pD"d/%"pD"d", h->count, ASIZE (h->next)); - strout (buf, -1, -1, printcharfun); + len = sprintf (buf, "%"pD"d/%"pD"d", h->count, ASIZE (h->next)); + strout (buf, len, len, printcharfun); } - sprintf (buf, " %p", h); - strout (buf, -1, -1, printcharfun); + len = sprintf (buf, " %p", h); + strout (buf, len, len, printcharfun); PRINTCHAR ('>'); #endif /* Implement a readable output, e.g.: #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */ /* Always print the size. */ - sprintf (buf, "#s(hash-table size %"pD"d", ASIZE (h->next)); - strout (buf, -1, -1, printcharfun); + len = sprintf (buf, "#s(hash-table size %"pD"d", ASIZE (h->next)); + strout (buf, len, len, printcharfun); if (!NILP (h->test)) { @@ -1881,12 +1896,24 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag } else if (FRAMEP (obj)) { + int len; + Lisp_Object frame_name = XFRAME (obj)->name; + strout ((FRAME_LIVE_P (XFRAME (obj)) ? "#name, printcharfun); - sprintf (buf, " %p", XFRAME (obj)); - strout (buf, -1, -1, printcharfun); + if (!STRINGP (frame_name)) + { + /* A frame could be too young and have no name yet; + don't crash. */ + if (SYMBOLP (frame_name)) + frame_name = Fsymbol_name (frame_name); + else /* can't happen: name should be either nil or string */ + frame_name = build_string ("*INVALID*FRAME*NAME*"); + } + print_string (frame_name, printcharfun); + len = sprintf (buf, " %p", XFRAME (obj)); + strout (buf, len, len, printcharfun); PRINTCHAR ('>'); } else if (FONTP (obj)) @@ -1960,7 +1987,7 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag for (i = 0; i < size; i++) { if (i) PRINTCHAR (' '); - tem = XVECTOR (obj)->contents[i]; + tem = AREF (obj, i); print_object (tem, printcharfun, escapeflag); } if (size < real_size) @@ -1982,8 +2009,8 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag strout ("in no buffer", -1, -1, printcharfun); else { - sprintf (buf, "at %"pD"d", marker_position (obj)); - strout (buf, -1, -1, printcharfun); + int len = sprintf (buf, "at %"pD"d", marker_position (obj)); + strout (buf, len, len, printcharfun); strout (" in ", -1, -1, printcharfun); print_string (BVAR (XMARKER (obj)->buffer, name), printcharfun); } @@ -1996,10 +2023,10 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag strout ("in no buffer", -1, -1, printcharfun); else { - sprintf (buf, "from %"pD"d to %"pD"d in ", - marker_position (OVERLAY_START (obj)), - marker_position (OVERLAY_END (obj))); - strout (buf, -1, -1, printcharfun); + int len = sprintf (buf, "from %"pD"d to %"pD"d in ", + marker_position (OVERLAY_START (obj)), + marker_position (OVERLAY_END (obj))); + strout (buf, len, len, printcharfun); print_string (BVAR (XMARKER (OVERLAY_START (obj))->buffer, name), printcharfun); } @@ -2014,10 +2041,12 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag case Lisp_Misc_Save_Value: strout ("#pointer, - XSAVE_VALUE (obj)->integer); - strout (buf, -1, -1, printcharfun); + { + int len = sprintf (buf, "ptr=%p int=%"pD"d", + XSAVE_VALUE (obj)->pointer, + XSAVE_VALUE (obj)->integer); + strout (buf, len, len, printcharfun); + } PRINTCHAR ('>'); break; @@ -2029,16 +2058,17 @@ print_object (Lisp_Object obj, register Lisp_Object printcharfun, int escapeflag default: badtype: { + int len; /* We're in trouble if this happens! Probably should just abort () */ strout ("#", -1, -1, printcharfun); } @@ -2143,7 +2173,7 @@ shared once again when the text is read back. */); Vprint_gensym = Qnil; DEFVAR_LISP ("print-circle", Vprint_circle, - doc: /* *Non-nil means print recursive structures using #N= and #N# syntax. + doc: /* Non-nil means print recursive structures using #N= and #N# syntax. If nil, printing proceeds recursively and may lead to `max-lisp-eval-depth' being exceeded or an error may occur: \"Apparently circular structure being printed.\" Also see @@ -2155,7 +2185,7 @@ where N is a positive decimal integer. */); Vprint_circle = Qnil; DEFVAR_LISP ("print-continuous-numbering", Vprint_continuous_numbering, - doc: /* *Non-nil means number continuously across print calls. + doc: /* Non-nil means number continuously across print calls. This affects the numbers printed for #N= labels and #M# references. See also `print-circle', `print-gensym', and `print-number-table'. This variable should not be set with `setq'; bind it with a `let' instead. */);