X-Git-Url: https://cgit.sxemacs.org/?a=blobdiff_plain;f=src%2Fprint.c;h=d1d3c2ab5b8a7d351649296edcd60f99e4d49727;hb=16de74c3a0cabb8219672bb7a9c7fd72f2717572;hp=17c2fa8f037bc54ac848e838fd772a0af313bd66;hpb=d28db7f744455e7e376e2b7737e0f804456a686d;p=sxemacs diff --git a/src/print.c b/src/print.c index 17c2fa8..d1d3c2a 100644 --- a/src/print.c +++ b/src/print.c @@ -103,6 +103,8 @@ FILE *termscript; /* Stdio stream being used for copy of all output. */ int stdout_needs_newline; +void debug_backtrace(void); + static void std_handle_out_external(FILE * stream, Lisp_Object lstream, const Extbyte * extptr, Extcount extlen, @@ -132,26 +134,25 @@ std_handle_out_external(FILE * stream, Lisp_Object lstream, } -#define SXE_VSNPRINT_VA(ret,sbuf,buf,size,spec,tries,type,fmt,args) \ +#define SXE_VSNPRINT_VA(ret__,sbuf__,buf__,size__,spec__,tries__,type__,fmt__,args__) \ do { \ - --tries; \ - ret = vsnprintf((char*)buf,size,fmt,args); \ - if ( retval == 0 ) { \ + --tries__; \ + ret__ = vsnprintf((char*)buf__,size__,fmt__,args__); \ + if ( ret__ == 0 ) { \ /* Nothing to write */ \ break; \ - } else if ( ret < 0 ) { \ - XMALLOC_UNBIND(buf,size,spec); \ - size *= 2; \ - XMALLOC_OR_ALLOCA(buf,size,type); \ - ret = 0; \ - } else if ( ret > size ) { \ + } else if ( ret__ < 0 ) { \ + XMALLOC_UNBIND(buf__,size__,spec__); \ + size__ *= 2; \ + XMALLOC_OR_ALLOCA(buf__,size__,type__); \ + } else if ( (size_t)ret__ > (size_t)size__ ) { \ /* We need more space, so we need to allocate it */ \ - XMALLOC_UNBIND(buf,size,spec); \ - size = ret + 1; \ - XMALLOC_OR_ALLOCA(buf,size,type); \ - ret = 0; \ + XMALLOC_UNBIND(buf__,size__,spec__); \ + size__ = ret__ + 1; \ + XMALLOC_OR_ALLOCA(buf__,size__,type__); \ + ret__ = -1; \ } \ - } while( ret == 0 && tries > 0 ) + } while( ret__ < 0 && tries__ > 0 ) int write_fmt_str(Lisp_Object stream, const char* fmt, ...) @@ -159,8 +160,8 @@ int write_fmt_str(Lisp_Object stream, const char* fmt, ...) char *kludge; va_list args; int bufsize, retval, tries = 3; - /* write_fmt_str is used for small prints usually... */ - char buffer[64+1]; + /* write_fmt_str is used for small prints usually... */ + char buffer[64+1]; int speccount = specpdl_depth(); va_start(args, fmt); @@ -234,12 +235,12 @@ static int std_handle_out_va(FILE * stream, const char *fmt, va_list args) kludge = buffer; SXE_VSNPRINT_VA(retval,buffer,kludge,bufsize,speccount,tries,Bufbyte,fmt,args); - + if (retval == 0) /* nothing to write */ return retval; - use_fprintf = ! initialized ||fatal_error_in_progress || + use_fprintf = ! initialized ||fatal_error_in_progress || inhibit_non_essential_printing_operations; if (retval > 0) { @@ -291,9 +292,9 @@ int stdout_out(const char *fmt, ...) int retval; va_list args; va_start(args, fmt); - retval = std_handle_out_va(stdout, - (initialized && !fatal_error_in_progress - ? GETTEXT(fmt) : fmt), + retval = std_handle_out_va(stdout, + (initialized && !fatal_error_in_progress + ? GETTEXT(fmt) : fmt), args); va_end(args); return retval; @@ -305,9 +306,9 @@ DOESNT_RETURN fatal(const char *fmt, ...) va_start(args, fmt); stderr_out("\nSXEmacs: "); - std_handle_out_va(stderr, - (initialized && !fatal_error_in_progress - ? GETTEXT(fmt) : fmt), + std_handle_out_va(stderr, + (initialized && !fatal_error_in_progress + ? GETTEXT(fmt) : fmt), args); stderr_out("\n"); @@ -324,7 +325,7 @@ write_string_to_stdio_stream(FILE * stream, struct console *con, Lisp_Object coding_system, int must_flush) { Extcount extlen; - const Extbyte *extptr; + const Extbyte *extptr = NULL; /* #### yuck! sometimes this function is called with string data, and the following call may gc. */ @@ -332,26 +333,32 @@ write_string_to_stdio_stream(FILE * stream, struct console *con, Bufbyte *puta = (Bufbyte *) alloca(len); memcpy(puta, str + offset, len); - if (initialized && !inhibit_non_essential_printing_operations) + if (initialized && !inhibit_non_essential_printing_operations) { TO_EXTERNAL_FORMAT(DATA, (puta, len), ALLOCA, (extptr, extlen), coding_system); - else { + } + if( extptr == NULL ) { extptr = (Extbyte *) puta; extlen = (Bytecount) len; } } + if (stream) { std_handle_out_external(stream, Qnil, extptr, extlen, stream == stdout || stream == stderr, must_flush); - } else { + } else if(con != NULL) { assert(CONSOLE_TTY_P(con)); std_handle_out_external(0, CONSOLE_TTY_DATA(con)->outstream, extptr, extlen, CONSOLE_TTY_DATA(con)->is_stdio, must_flush); + } else { + error("Error attempting to write write '%s' with no stream nor console", str); + debug_backtrace(); + abort(); } } @@ -565,7 +572,7 @@ void write_hex_ptr(void* value, Lisp_Object stream) { char buf[sizeof(value)*2+1]; int n = snprintf(buf,sizeof(buf),"0x%p",value); - assert(n>=0 && n=0 && (size_t)n=0 && sz=0 && sz < maxlen); } /* added by jwz: don't allow "1.0" to print as "1"; that destroys @@ -969,14 +981,19 @@ void float_to_string(char *buf, fpfloat data) { Bufbyte *s = (Bufbyte *) buf; /* don't use signed chars here! isdigit() can't hack them! */ - if (*s == '-') + if (*s == '-') { s++; + maxlen--; + assert(maxlen>0); + } for (; *s; s++) /* if there's a non-digit, then there is a decimal point, or it's in exponential notation, both of which are ok. */ if (!isdigit(*s)) goto DONE_LABEL; /* otherwise, we need to hack it. */ + maxlen-=2; + assert(maxlen>0); *s++ = '.'; *s++ = '0'; *s = 0; @@ -985,6 +1002,7 @@ void float_to_string(char *buf, fpfloat data) /* Some machines print "0.4" as ".4". I don't like that. */ if (buf[0] == '.' || (buf[0] == '-' && buf[1] == '.')) { + assert(maxlen>0); int i; for (i = strlen(buf) + 1; i >= 0; i--) buf[i + 1] = buf[i]; @@ -994,16 +1012,17 @@ void float_to_string(char *buf, fpfloat data) #endif /* HAVE_FPFLOAT */ /* Print NUMBER to BUFFER. - This is equivalent to sprintf (buffer, "%ld", number), only much faster. + This is equivalent to snprintf (buffer, maxlen, "%ld", number), only much faster. BUFFER should accept 24 bytes. This should suffice for the longest numbers on 64-bit machines, including the `-' sign and the trailing '\0'. Returns a pointer to the trailing '\0'. */ -char *long_to_string(char *buffer, long number) +char *long_to_string(char *buffer, long number, int maxlen) { #if (SIZEOF_LONG != 4) && (SIZEOF_LONG != 8) /* Huh? */ - sprintf(buffer, "%ld", number); + int sz = snprintf(buffer, maxlen, "%ld", number); + assert(sz>=0 && sz < maxlen); return buffer + strlen(buffer); #else /* (SIZEOF_LONG == 4) || (SIZEOF_LONG == 8) */ char *p = buffer; @@ -1013,10 +1032,16 @@ char *long_to_string(char *buffer, long number) *p++ = '-'; number = -number; } -#define FROB(figure) do { \ - if (force || number >= figure) \ - *p++ = number / figure + '0', number %= figure, force = 1; \ - } while (0) +#define FROB(figure) \ + do { \ + if (force || number >= figure) { \ + *p++ = number / figure + '0'; \ + number %= figure; \ + force = 1; \ + --maxlen; \ + assert(maxlen>0); \ + } \ + } while (0) #if SIZEOF_LONG == 8 FROB(1000000000000000000L); FROB(100000000000000000L); @@ -1252,11 +1277,11 @@ printing_major_badness(Lisp_Object printcharfun, len = snprintf(buf, sizeof(buf), "%s object %p", badness_string, val); break; default: - len = snprintf(buf, sizeof(buf), "%s unknown badness %d", + len = snprintf(buf, sizeof(buf), "%s unknown badness %d", badness_string, badness); break; } - assert(len >= 0 && len < sizeof(buf)); + assert(len >= 0 && (size_t)len < sizeof(buf)); /* Don't abort or signal if called from debug_print() or already crashing */ @@ -1298,12 +1323,12 @@ print_internal(Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) output. */ #endif - /* Try out custom printing */ - if (UNLIKELY(!(bool)inhibit_autoloads && !(bool)nodumpfile) && + /* Try out custom printing */ + if (UNLIKELY(!(bool)inhibit_autoloads && !(bool)nodumpfile) && !EQ(Qnil, Vcustom_object_printer) && - !EQ(Qnil, apply1(Vcustom_object_printer, - Fcons(obj, Fcons(printcharfun, Qnil))))) { - return; + !EQ(Qnil, apply1(Vcustom_object_printer, + Fcons(obj, Fcons(printcharfun, Qnil))))) { + return; } /* Detect circularities and truncate them. @@ -1314,7 +1339,7 @@ print_internal(Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) if (EQ(obj, being_printed[i])) { char buf[32]; *buf = '#'; - long_to_string(buf + 1, i); + long_to_string(buf + 1, i, sizeof(buf)-1); write_c_string(buf, printcharfun); return; } @@ -1333,7 +1358,7 @@ print_internal(Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) /* ASCII Decimal representation uses 2.4 times as many bits as machine binary. */ char buf[3 * sizeof(EMACS_INT) + 5]; - long_to_string(buf, XINT(obj)); + long_to_string(buf, XINT(obj),sizeof(buf)); write_c_string(buf, printcharfun); break; } @@ -1688,15 +1713,22 @@ to 0. Bufbyte str[MAX_EMCHAR_LEN]; Bytecount len; int extlen; - const Extbyte *extptr; + const Extbyte *extptr = NULL; CHECK_CHAR_COERCE_INT(character); len = set_charptr_emchar(str, XCHAR(character)); TO_EXTERNAL_FORMAT(DATA, (str, len), ALLOCA, (extptr, extlen), Qterminal); - memcpy(alternate_do_string + alternate_do_pointer, extptr, extlen); - alternate_do_pointer += extlen; - alternate_do_string[alternate_do_pointer] = 0; + if ( extptr != NULL ) { + memcpy(alternate_do_string + alternate_do_pointer, extptr, extlen); + alternate_do_pointer += extlen; + alternate_do_string[alternate_do_pointer] = 0; + } else { + /* Better bad transcoding than nothing I guess... */ + memcpy(alternate_do_string + alternate_do_pointer, str, len); + alternate_do_pointer += len; + alternate_do_string[alternate_do_pointer] = 0; + } return character; } @@ -1715,8 +1747,8 @@ the output also will be logged to this file. */ (char_or_string, stdout_p, device)) { - FILE *file = 0; - struct console *con = 0; + FILE *file = NULL; + struct console *con = NULL; if (NILP(device)) { if (!NILP(stdout_p)) @@ -1832,7 +1864,6 @@ void debug_print(Lisp_Object debug_print_obj) /* Debugging kludge -- unbuffered */ /* This function provided for the benefit of the debugger. */ -void debug_backtrace(void); void debug_backtrace(void) { /* This function can GC */