From d9fad198da41e1cd37600ae397146e27a413303d Mon Sep 17 00:00:00 2001 From: Jarkko Hietaniemi Date: Sat, 13 May 2006 01:28:49 +0300 Subject: [PATCH] Re: [PATCH] my_snprintf Message-ID: <4464E1F1.9010706@gmail.com> p4raw-id: //depot/perl@28183 --- embed.fnc | 3 + global.sym | 2 + perl.h | 3 + perlio.c | 12 +--- pod/perlapi.pod | 25 ++++++++ pp_ctl.c | 21 ++----- proto.h | 9 +++ regcomp.c | 6 +- sv.c | 18 ++---- toke.c | 6 +- universal.c | 6 +- util.c | 184 +++++++++++++++++++++++++++++++------------------------- 12 files changed, 156 insertions(+), 139 deletions(-) diff --git a/embed.fnc b/embed.fnc index 3fa7b93..98b980f 100644 --- a/embed.fnc +++ b/embed.fnc @@ -1687,6 +1687,9 @@ p |void |offer_nice_chunk |NN void *chunk|U32 chunk_size Apnod |int |my_sprintf |NN char *buffer|NN const char *pat|... #endif +Apnod |int |my_snprintf |NN char *buffer|const Size_t len|NN const char *format|... +Apnod |int |my_vsnprintf |NN char *buffer|const Size_t len|NN const char *format|va_list ap + px |void |my_clearenv #ifdef PERL_IMPLICIT_CONTEXT diff --git a/global.sym b/global.sym index 49c90bf..dfe7eda 100644 --- a/global.sym +++ b/global.sym @@ -713,5 +713,7 @@ Perl_ckwarn Perl_ckwarn_d Perl_new_warnings_bitfield Perl_my_sprintf +Perl_my_snprintf +Perl_my_vsnprintf Perl_my_cxt_init # ex: set ro: diff --git a/perl.h b/perl.h index f83cbf8..91e1b58 100644 --- a/perl.h +++ b/perl.h @@ -1449,6 +1449,9 @@ int sockatmark(int); # define my_sprintf Perl_my_sprintf #endif +#define my_snprintf Perl_my_snprintf +#define my_vsnprintf Perl_my_vsnprintf + /* Configure gets this right but the UTS compiler gets it wrong. -- Hal Morris */ #ifdef UTS diff --git a/perlio.c b/perlio.c index 288159c..ad2570e 100644 --- a/perlio.c +++ b/perlio.c @@ -479,11 +479,7 @@ PerlIO_debug(const char *fmt, ...) /* Use fixed buffer as sv_catpvf etc. needs SVs */ char buffer[1024]; const STRLEN len = my_sprintf(buffer, "%.40s:%" IVdf " ", s ? s : "(none)", (IV) CopLINE(PL_curcop)); -# ifdef USE_VSNPRINTF - const STRLEN len2 = vsnprintf(buffer+len, sizeof(buffer) - len, fmt, ap); -# else - const STRLEN len2 = vsprintf(buffer+len, fmt, ap); -# endif /* USE_VSNPRINTF */ + const STRLEN len2 = my_vsnprintf(buffer+len, sizeof(buffer) - len, fmt, ap); PerlLIO_write(PL_perlio_debug_fd, buffer, len + len2); #else const char *s = CopFILE(PL_curcop); @@ -5147,11 +5143,7 @@ int PerlIO_vsprintf(char *s, int n, const char *fmt, va_list ap) { dVAR; -#ifdef USE_VSNPRINTF - const int val = vsnprintf(s, n > 0 ? n : 0, fmt, ap); -#else - const int val = vsprintf(s, fmt, ap); -#endif /* #ifdef USE_VSNPRINTF */ + const int val = my_vsnprintf(s, n > 0 ? n : 0, fmt, ap); if (n >= 0) { if (strlen(s) >= (STRLEN) n) { dTHX; diff --git a/pod/perlapi.pod b/pod/perlapi.pod index d608eef..c3b6074 100644 --- a/pod/perlapi.pod +++ b/pod/perlapi.pod @@ -2245,6 +2245,19 @@ Fill the sv with current working directory =for hackers Found in file util.c +=item my_snprintf +X + +The C library C functionality, if available and +standards-compliant (uses C, actually). If the +C is not available, will unfortunately use the unsafe +C. Consider using C instead. + + int my_snprintf(char *buffer, const Size_t len, const char *format, ...) + +=for hackers +Found in file util.c + =item my_sprintf X @@ -2257,6 +2270,18 @@ need the wrapper function - usually this is a direct call to C. =for hackers Found in file util.c +=item my_vsnprintf +X + +The C library C if available and standards-compliant, +but if the C is not available, will unfortunately use +the unsafe C. Consider using C instead. + + int my_vsnprintf(char *buffer, const Size_t len, const char *format, va_list ap) + +=for hackers +Found in file util.c + =item new_version X diff --git a/pp_ctl.c b/pp_ctl.c index d335281..55ffb19 100644 --- a/pp_ctl.c +++ b/pp_ctl.c @@ -831,11 +831,7 @@ PP(pp_formline) /* Formats aren't yet marked for locales, so assume "yes". */ { STORE_NUMERIC_STANDARD_SET_LOCAL(); -#ifdef USE_SNPRINTF - snprintf(t, SvLEN(PL_formtarget) - (t - SvPVX(PL_formtarget)), fmt, (int) fieldsize, (int) arg & 255, value); -#else - sprintf(t, fmt, (int) fieldsize, (int) arg & 255, value); -#endif /* ifdef USE_SNPRINTF */ + my_snprintf(t, SvLEN(PL_formtarget) - (t - SvPVX(PL_formtarget)), fmt, (int) fieldsize, (int) arg & 255, value); RESTORE_NUMERIC_STANDARD(); } t += fieldsize; @@ -2773,13 +2769,8 @@ Perl_sv_compile_2op(pTHX_ SV *sv, OP** startop, const char *code, PAD** padp) len = SvCUR(sv); } else -#ifdef USE_SNPRINTF - len = snprintf(tmpbuf, sizeof(tbuf), "_<(%.10s_eval %lu)", code, - (unsigned long)++PL_evalseq); -#else - len = my_sprintf(tmpbuf, "_<(%.10s_eval %lu)", code, - (unsigned long)++PL_evalseq); -#endif /* ifdef USE_SNPRINTF */ + len = my_snprintf(tmpbuf, sizeof(tbuf), "_<(%.10s_eval %lu)", code, + (unsigned long)++PL_evalseq); SAVECOPFILE_FREE(&PL_compiling); CopFILE_set(&PL_compiling, tmpbuf+2); SAVECOPLINE(&PL_compiling); @@ -3461,11 +3452,7 @@ PP(pp_entereval) len = SvCUR(temp_sv); } else -#ifdef USE_SNPRINTF - len = snprintf(tmpbuf, sizeof(tbuf), "_<(eval %lu)", (unsigned long)++PL_evalseq); -#else - len = my_sprintf(tmpbuf, "_<(eval %lu)", (unsigned long)++PL_evalseq); -#endif /* ifdef USE_SNPRINTF */ + len = my_snprintf(tmpbuf, sizeof(tbuf), "_<(eval %lu)", (unsigned long)++PL_evalseq); SAVECOPFILE_FREE(&PL_compiling); CopFILE_set(&PL_compiling, tmpbuf+2); SAVECOPLINE(&PL_compiling); diff --git a/proto.h b/proto.h index 43a749a..07ee72d 100644 --- a/proto.h +++ b/proto.h @@ -4335,6 +4335,15 @@ PERL_CALLCONV int Perl_my_sprintf(char *buffer, const char *pat, ...) #endif +PERL_CALLCONV int Perl_my_snprintf(char *buffer, const Size_t len, const char *format, ...) + __attribute__nonnull__(1) + __attribute__nonnull__(3); + +PERL_CALLCONV int Perl_my_vsnprintf(char *buffer, const Size_t len, const char *format, va_list ap) + __attribute__nonnull__(1) + __attribute__nonnull__(3); + + PERL_CALLCONV void Perl_my_clearenv(pTHX); #ifdef PERL_IMPLICIT_CONTEXT diff --git a/regcomp.c b/regcomp.c index 6ba85bb..e98fcf9 100644 --- a/regcomp.c +++ b/regcomp.c @@ -6184,11 +6184,7 @@ Perl_save_re_context(pTHX) U32 i; for (i = 1; i <= rx->nparens; i++) { char digits[TYPE_CHARS(long)]; -#ifdef USE_SNPRINTF - const STRLEN len = snprintf(digits, sizeof(digits), "%lu", (long)i); -#else - const STRLEN len = my_sprintf(digits, "%lu", (long)i); -#endif /* #ifdef USE_SNPRINTF */ + const STRLEN len = my_snprintf(digits, sizeof(digits), "%lu", (long)i); GV *const *const gvp = (GV**)hv_fetch(PL_defstash, digits, len, 0); diff --git a/sv.c b/sv.c index 6c7071d..37c84f4 100644 --- a/sv.c +++ b/sv.c @@ -2660,13 +2660,8 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags) if (SvIOKp(sv)) { len = SvIsUV(sv) -#ifdef USE_SNPRINTF - ? snprintf(tbuf, sizeof(tbuf), "%"UVuf, (UV)SvUVX(sv)) - : snprintf(tbuf, sizeof(tbuf), "%"IVdf, (IV)SvIVX(sv)); -#else - ? my_sprintf(tbuf, "%"UVuf, (UV)SvUVX(sv)) - : my_sprintf(tbuf, "%"IVdf, (IV)SvIVX(sv)); -#endif /* #ifdef USE_SNPRINTF */ + ? my_snprintf(tbuf, sizeof(tbuf), "%"UVuf, (UV)SvUVX(sv)) + : my_snprintf(tbuf, sizeof(tbuf), "%"IVdf, (IV)SvIVX(sv)); } else { Gconvert(SvNVX(sv), NV_DIG, 0, tbuf); len = strlen(tbuf); @@ -9270,13 +9265,8 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV * --jhi */ #if defined(HAS_LONG_DOUBLE) elen = ((intsize == 'q') -# ifdef USE_SNPRINTF - ? snprintf(PL_efloatbuf, PL_efloatsize, ptr, nv) - : snprintf(PL_efloatbuf, PL_efloatsize, ptr, (double)nv)); -# else - ? my_sprintf(PL_efloatbuf, ptr, nv) - : my_sprintf(PL_efloatbuf, ptr, (double)nv)); -# endif /* #ifdef USE_SNPRINTF */ + ? my_snprintf(PL_efloatbuf, PL_efloatsize, ptr, nv) + : my_snprintf(PL_efloatbuf, PL_efloatsize, ptr, (double)nv)); #else elen = my_sprintf(PL_efloatbuf, ptr, nv); #endif diff --git a/toke.c b/toke.c index 173474c..9e340ba 100644 --- a/toke.c +++ b/toke.c @@ -5976,11 +5976,7 @@ Perl_yylex(pTHX) if (!PL_in_my_stash) { char tmpbuf[1024]; PL_bufptr = s; -#ifdef USE_SNPRINTF - snprintf(tmpbuf, sizeof(tmpbuf), "No such class %.1000s", PL_tokenbuf); -#else - sprintf(tmpbuf, "No such class %.1000s", PL_tokenbuf); -#endif /* #ifdef USE_SNPRINTF */ + my_snprintf(tmpbuf, sizeof(tmpbuf), "No such class %.1000s", PL_tokenbuf); yyerror(tmpbuf); } #ifdef PERL_MAD diff --git a/universal.c b/universal.c index 21f2c54..266613e 100644 --- a/universal.c +++ b/universal.c @@ -622,11 +622,7 @@ XS(XS_version_qv) if ( SvNOK(ver) ) /* may get too much accuracy */ { char tbuf[64]; -#ifdef USE_SNPRINTF - const STRLEN len = snprintf(tbuf, sizeof(tbuf), "%.9"NVgf, SvNVX(ver)); -#else - const STRLEN len = my_sprintf(tbuf, "%.9"NVgf, SvNVX(ver)); -#endif /* #ifdef USE_SNPRINTF */ + const STRLEN len = my_snprintf(tbuf, sizeof(tbuf), "%.9"NVgf, SvNVX(ver)); version = savepvn(tbuf, len); } else diff --git a/util.c b/util.c index fb461cc..82f7f82 100644 --- a/util.c +++ b/util.c @@ -4294,11 +4294,7 @@ Perl_upg_version(pTHX_ SV *ver) if ( SvNOK(ver) ) /* may get too much accuracy */ { char tbuf[64]; -#ifdef USE_SNPRINTF - const STRLEN len = snprintf(tbuf, sizeof(tbuf), "%.9"NVgf, SvNVX(ver)); -#else - const STRLEN len = my_sprintf(tbuf, "%.9"NVgf, SvNVX(ver)); -#endif /* #ifdef USE_SNPRINTF */ + const STRLEN len = my_snprintf(tbuf, sizeof(tbuf), "%.9"NVgf, SvNVX(ver)); version = savepvn(tbuf, len); } #ifdef SvVOK @@ -5215,38 +5211,21 @@ Perl_mem_log_alloc(const UV n, const UV typesize, const char *typename, Malloc_t gettimeofday(&tv, 0); { const STRLEN len = -# ifdef USE_SNPRINTF - snprintf(buf, - PERL_MEM_LOG_SPRINTF_BUF_SIZE, - "%10d.%06d: alloc: %s:%d:%s: %"IVdf" %"UVuf - " %s = %"IVdf": %"UVxf"\n", - (int)tv.tv_sec, (int)tv.tv_usec, - filename, linenumber, funcname, n, typesize, - typename, n * typesize, PTR2UV(newalloc)); -# else - my_sprintf(buf, - "%10d.%06d: alloc: %s:%d:%s: %"IVdf" %"UVuf - " %s = %"IVdf": %"UVxf"\n", - (int)tv.tv_sec, (int)tv.tv_usec, - filename, linenumber, funcname, n, typesize, - typename, n * typesize, PTR2UV(newalloc)); -# endif + my_snprintf(buf, + PERL_MEM_LOG_SPRINTF_BUF_SIZE, + "%10d.%06d: alloc: %s:%d:%s: %"IVdf" %"UVuf + " %s = %"IVdf": %"UVxf"\n", + (int)tv.tv_sec, (int)tv.tv_usec, + filename, linenumber, funcname, n, typesize, + typename, n * typesize, PTR2UV(newalloc)); # else const STRLEN len = -# ifdef USE_SNPRINTF - snprintf(buf, - PERL_MEM_LOG_SPRINTF_BUF_SIZE, - "alloc: %s:%d:%s: %"IVdf" %"UVuf - " %s = %"IVdf": %"UVxf"\n", - filename, linenumber, funcname, n, typesize, - typename, n * typesize, PTR2UV(newalloc)); -# else - my_sprintf(buf, - "alloc: %s:%d:%s: %"IVdf" %"UVuf - " %s = %"IVdf": %"UVxf"\n", - filename, linenumber, funcname, n, typesize, - typename, n * typesize, PTR2UV(newalloc)); -# endif + my_snprintf(buf, + PERL_MEM_LOG_SPRINTF_BUF_SIZE, + "alloc: %s:%d:%s: %"IVdf" %"UVuf + " %s = %"IVdf": %"UVxf"\n", + filename, linenumber, funcname, n, typesize, + typename, n * typesize, PTR2UV(newalloc)); # endif # ifdef PERL_MEM_LOG_ENV_FD s = PerlEnv_getenv("PERL_MEM_LOG_FD"); @@ -5280,42 +5259,23 @@ Perl_mem_log_realloc(const UV n, const UV typesize, const char *typename, Malloc gettimeofday(&tv, 0); { const STRLEN len = -# ifdef USE_SNPRINTF - snprintf(buf, - PERL_MEM_LOG_SPRINTF_BUF_SIZE, - "%10d.%06d: realloc: %s:%d:%s: %"IVdf" %"UVuf - " %s = %"IVdf": %"UVxf" -> %"UVxf"\n", - (int)tv.tv_sec, (int)tv.tv_usec, - filename, linenumber, funcname, n, typesize, - typename, n * typesize, PTR2UV(oldalloc), - PTR2UV(newalloc)); -# else - my_sprintf(buf, - "%10d.%06d: realloc: %s:%d:%s: %"IVdf" %"UVuf - " %s = %"IVdf": %"UVxf" -> %"UVxf"\n", - (int)tv.tv_sec, (int)tv.tv_usec, - filename, linenumber, funcname, n, typesize, - typename, n * typesize, PTR2UV(oldalloc), - PTR2UV(newalloc)); -# endif + my_snprintf(buf, + PERL_MEM_LOG_SPRINTF_BUF_SIZE, + "%10d.%06d: realloc: %s:%d:%s: %"IVdf" %"UVuf + " %s = %"IVdf": %"UVxf" -> %"UVxf"\n", + (int)tv.tv_sec, (int)tv.tv_usec, + filename, linenumber, funcname, n, typesize, + typename, n * typesize, PTR2UV(oldalloc), + PTR2UV(newalloc)); # else const STRLEN len = -# ifdef USE_SNPRINTF - snprintf(buf, - PERL_MEM_LOG_SPRINTF_BUF_SIZE, - "realloc: %s:%d:%s: %"IVdf" %"UVuf - " %s = %"IVdf": %"UVxf" -> %"UVxf"\n", - filename, linenumber, funcname, n, typesize, - typename, n * typesize, PTR2UV(oldalloc), - PTR2UV(newalloc)); -# else - my_sprintf(buf, - "realloc: %s:%d:%s: %"IVdf" %"UVuf - " %s = %"IVdf": %"UVxf" -> %"UVxf"\n", - filename, linenumber, funcname, n, typesize, - typename, n * typesize, PTR2UV(oldalloc), - PTR2UV(newalloc)); -# endif + my_snprintf(buf, + PERL_MEM_LOG_SPRINTF_BUF_SIZE, + "realloc: %s:%d:%s: %"IVdf" %"UVuf + " %s = %"IVdf": %"UVxf" -> %"UVxf"\n", + filename, linenumber, funcname, n, typesize, + typename, n * typesize, PTR2UV(oldalloc), + PTR2UV(newalloc)); # endif # ifdef PERL_MEM_LOG_ENV_FD s = PerlEnv_getenv("PERL_MEM_LOG_FD"); @@ -5349,20 +5309,12 @@ Perl_mem_log_free(Malloc_t oldalloc, const char *filename, const int linenumber, gettimeofday(&tv, 0); { const STRLEN len = -# ifdef USE_SNPRINTF - snprintf(buf, - PERL_MEM_LOG_SPRINTF_BUF_SIZE, - "%10d.%06d: free: %s:%d:%s: %"UVxf"\n", - (int)tv.tv_sec, (int)tv.tv_usec, - filename, linenumber, funcname, - PTR2UV(oldalloc)); -# else - my_sprintf(buf, - "%10d.%06d: free: %s:%d:%s: %"UVxf"\n", - (int)tv.tv_sec, (int)tv.tv_usec, - filename, linenumber, funcname, - PTR2UV(oldalloc)); -# endif + my_snprintf(buf, + PERL_MEM_LOG_SPRINTF_BUF_SIZE, + "%10d.%06d: free: %s:%d:%s: %"UVxf"\n", + (int)tv.tv_sec, (int)tv.tv_usec, + filename, linenumber, funcname, + PTR2UV(oldalloc)); # else const STRLEN len = my_sprintf(buf, @@ -5405,6 +5357,72 @@ Perl_my_sprintf(char *buffer, const char* pat, ...) } #endif +/* +=for apidoc my_snprintf + +The C library C functionality, if available and +standards-compliant (uses C, actually). If the +C is not available, will unfortunately use the unsafe +C. Consider using C instead. + +=cut +*/ +int +Perl_my_snprintf(char *buffer, const Size_t len, const char *format, ...) +/* Cannot do this using variadic macros because that is too unportable. */ +{ + dTHX; + int retval; + va_list ap; +#ifndef USE_VSNPRINTF + PERL_UNUSED_ARG(len); +#endif + va_start(ap, format); +#ifdef USE_VSNPRINTF + retval = vsnprintf(buffer, len, format, ap); +#else + retval = vsprintf(buffer, format, ap); +#endif + va_end(ap); + return retval; +} + +/* +=for apidoc my_vsnprintf + +The C library C if available and standards-compliant, +but if the C is not available, will unfortunately use +the unsafe C. Consider using C instead. + +=cut +*/ +int +Perl_my_vsnprintf(char *buffer, const Size_t len, const char *format, va_list ap) +/* Cannot do this using variadic macros because that is too unportable. */ +{ + dTHX; + int retval; +#ifndef USE_VSNPRINTF + PERL_UNUSED_ARG(len); +#endif +#ifdef NEED_VA_COPY + va_list apc; + Perl_va_copy(apc); +# ifdef USE_VSNPRINTF + retval = vsnprintf(buffer, len, format, apc); +# else + retval = vsprintf(buffer, format, apc); +# endif +#else +# ifdef USE_VSNPRINTF + retval = vsnprintf(buffer, len, format, ap); +# else + retval = vsprintf(buffer, format, ap); +# endif +#endif + return retval; +} + void Perl_my_clearenv(pTHX) { -- 2.7.4