15759b3d2Safresh1################################################################################ 25759b3d2Safresh1## 35759b3d2Safresh1## Version 3.x, Copyright (C) 2004-2013, Marcus Holland-Moritz. 45759b3d2Safresh1## Version 2.x, Copyright (C) 2001, Paul Marquess. 55759b3d2Safresh1## Version 1.x, Copyright (C) 1999, Kenneth Albanowski. 65759b3d2Safresh1## 75759b3d2Safresh1## This program is free software; you can redistribute it and/or 85759b3d2Safresh1## modify it under the same terms as Perl itself. 95759b3d2Safresh1## 105759b3d2Safresh1################################################################################ 115759b3d2Safresh1 125759b3d2Safresh1=provides 135759b3d2Safresh1 145759b3d2Safresh1__UNDEFINED__ 155759b3d2Safresh1pv_escape 165759b3d2Safresh1pv_pretty 175759b3d2Safresh1pv_display 185759b3d2Safresh1 195759b3d2Safresh1=implementation 205759b3d2Safresh1 215759b3d2Safresh1__UNDEFINED__ PERL_PV_ESCAPE_QUOTE 0x0001 225759b3d2Safresh1__UNDEFINED__ PERL_PV_PRETTY_QUOTE PERL_PV_ESCAPE_QUOTE 235759b3d2Safresh1__UNDEFINED__ PERL_PV_PRETTY_ELLIPSES 0x0002 245759b3d2Safresh1__UNDEFINED__ PERL_PV_PRETTY_LTGT 0x0004 255759b3d2Safresh1__UNDEFINED__ PERL_PV_ESCAPE_FIRSTCHAR 0x0008 265759b3d2Safresh1__UNDEFINED__ PERL_PV_ESCAPE_UNI 0x0100 275759b3d2Safresh1__UNDEFINED__ PERL_PV_ESCAPE_UNI_DETECT 0x0200 285759b3d2Safresh1__UNDEFINED__ PERL_PV_ESCAPE_ALL 0x1000 295759b3d2Safresh1__UNDEFINED__ PERL_PV_ESCAPE_NOBACKSLASH 0x2000 305759b3d2Safresh1__UNDEFINED__ PERL_PV_ESCAPE_NOCLEAR 0x4000 315759b3d2Safresh1__UNDEFINED__ PERL_PV_ESCAPE_RE 0x8000 325759b3d2Safresh1__UNDEFINED__ PERL_PV_PRETTY_NOCLEAR PERL_PV_ESCAPE_NOCLEAR 335759b3d2Safresh1 345759b3d2Safresh1__UNDEFINED__ PERL_PV_PRETTY_DUMP PERL_PV_PRETTY_ELLIPSES|PERL_PV_PRETTY_QUOTE 355759b3d2Safresh1__UNDEFINED__ PERL_PV_PRETTY_REGPROP PERL_PV_PRETTY_ELLIPSES|PERL_PV_PRETTY_LTGT|PERL_PV_ESCAPE_RE 365759b3d2Safresh1 375759b3d2Safresh1/* Hint: pv_escape 385759b3d2Safresh1 * Note that unicode functionality is only backported to 395759b3d2Safresh1 * those perl versions that support it. For older perl 405759b3d2Safresh1 * versions, the implementation will fall back to bytes. 415759b3d2Safresh1 */ 425759b3d2Safresh1 435759b3d2Safresh1#ifndef pv_escape 445759b3d2Safresh1#if { NEED pv_escape } 455759b3d2Safresh1 465759b3d2Safresh1char * 475759b3d2Safresh1pv_escape(pTHX_ SV *dsv, char const * const str, 485759b3d2Safresh1 const STRLEN count, const STRLEN max, 495759b3d2Safresh1 STRLEN * const escaped, const U32 flags) 505759b3d2Safresh1{ 515759b3d2Safresh1 const char esc = flags & PERL_PV_ESCAPE_RE ? '%' : '\\'; 525759b3d2Safresh1 const char dq = flags & PERL_PV_ESCAPE_QUOTE ? '"' : esc; 535759b3d2Safresh1 char octbuf[32] = "%123456789ABCDF"; 545759b3d2Safresh1 STRLEN wrote = 0; 555759b3d2Safresh1 STRLEN chsize = 0; 565759b3d2Safresh1 STRLEN readsize = 1; 57f3efcd01Safresh1#if defined(is_utf8_string) && defined(utf8_to_uvchr_buf) 585759b3d2Safresh1 bool isuni = flags & PERL_PV_ESCAPE_UNI ? 1 : 0; 595759b3d2Safresh1#endif 605759b3d2Safresh1 const char *pv = str; 615759b3d2Safresh1 const char * const end = pv + count; 625759b3d2Safresh1 octbuf[0] = esc; 635759b3d2Safresh1 645759b3d2Safresh1 if (!(flags & PERL_PV_ESCAPE_NOCLEAR)) 655759b3d2Safresh1 sv_setpvs(dsv, ""); 665759b3d2Safresh1 67f3efcd01Safresh1#if defined(is_utf8_string) && defined(utf8_to_uvchr_buf) 685759b3d2Safresh1 if ((flags & PERL_PV_ESCAPE_UNI_DETECT) && is_utf8_string((U8*)pv, count)) 695759b3d2Safresh1 isuni = 1; 705759b3d2Safresh1#endif 715759b3d2Safresh1 725759b3d2Safresh1 for (; pv < end && (!max || wrote < max) ; pv += readsize) { 735759b3d2Safresh1 const UV u = 74f3efcd01Safresh1#if defined(is_utf8_string) && defined(utf8_to_uvchr_buf) 75f3efcd01Safresh1 isuni ? utf8_to_uvchr_buf((U8*)pv, end, &readsize) : 765759b3d2Safresh1#endif 775759b3d2Safresh1 (U8)*pv; 785759b3d2Safresh1 const U8 c = (U8)u & 0xFF; 795759b3d2Safresh1 805759b3d2Safresh1 if (u > 255 || (flags & PERL_PV_ESCAPE_ALL)) { 815759b3d2Safresh1 if (flags & PERL_PV_ESCAPE_FIRSTCHAR) 825759b3d2Safresh1 chsize = my_snprintf(octbuf, sizeof octbuf, 835759b3d2Safresh1 "%" UVxf, u); 845759b3d2Safresh1 else 855759b3d2Safresh1 chsize = my_snprintf(octbuf, sizeof octbuf, 865759b3d2Safresh1 "%cx{%" UVxf "}", esc, u); 875759b3d2Safresh1 } else if (flags & PERL_PV_ESCAPE_NOBACKSLASH) { 885759b3d2Safresh1 chsize = 1; 895759b3d2Safresh1 } else { 905759b3d2Safresh1 if (c == dq || c == esc || !isPRINT(c)) { 915759b3d2Safresh1 chsize = 2; 925759b3d2Safresh1 switch (c) { 935759b3d2Safresh1 case '\\' : /* fallthrough */ 945759b3d2Safresh1 case '%' : if (c == esc) 955759b3d2Safresh1 octbuf[1] = esc; 965759b3d2Safresh1 else 975759b3d2Safresh1 chsize = 1; 985759b3d2Safresh1 break; 995759b3d2Safresh1 case '\v' : octbuf[1] = 'v'; break; 1005759b3d2Safresh1 case '\t' : octbuf[1] = 't'; break; 1015759b3d2Safresh1 case '\r' : octbuf[1] = 'r'; break; 1025759b3d2Safresh1 case '\n' : octbuf[1] = 'n'; break; 1035759b3d2Safresh1 case '\f' : octbuf[1] = 'f'; break; 1045759b3d2Safresh1 case '"' : if (dq == '"') 1055759b3d2Safresh1 octbuf[1] = '"'; 1065759b3d2Safresh1 else 1075759b3d2Safresh1 chsize = 1; 1085759b3d2Safresh1 break; 1095759b3d2Safresh1 default: chsize = my_snprintf(octbuf, sizeof octbuf, 1105759b3d2Safresh1 pv < end && isDIGIT((U8)*(pv+readsize)) 1115759b3d2Safresh1 ? "%c%03o" : "%c%o", esc, c); 1125759b3d2Safresh1 } 1135759b3d2Safresh1 } else { 1145759b3d2Safresh1 chsize = 1; 1155759b3d2Safresh1 } 1165759b3d2Safresh1 } 1175759b3d2Safresh1 if (max && wrote + chsize > max) { 1185759b3d2Safresh1 break; 1195759b3d2Safresh1 } else if (chsize > 1) { 1205759b3d2Safresh1 sv_catpvn(dsv, octbuf, chsize); 1215759b3d2Safresh1 wrote += chsize; 1225759b3d2Safresh1 } else { 1235759b3d2Safresh1 char tmp[2]; 1245759b3d2Safresh1 my_snprintf(tmp, sizeof tmp, "%c", c); 1255759b3d2Safresh1 sv_catpvn(dsv, tmp, 1); 1265759b3d2Safresh1 wrote++; 1275759b3d2Safresh1 } 1285759b3d2Safresh1 if (flags & PERL_PV_ESCAPE_FIRSTCHAR) 1295759b3d2Safresh1 break; 1305759b3d2Safresh1 } 1315759b3d2Safresh1 if (escaped != NULL) 1325759b3d2Safresh1 *escaped= pv - str; 1335759b3d2Safresh1 return SvPVX(dsv); 1345759b3d2Safresh1} 1355759b3d2Safresh1 1365759b3d2Safresh1#endif 1375759b3d2Safresh1#endif 1385759b3d2Safresh1 1395759b3d2Safresh1#ifndef pv_pretty 1405759b3d2Safresh1#if { NEED pv_pretty } 1415759b3d2Safresh1 1425759b3d2Safresh1char * 1435759b3d2Safresh1pv_pretty(pTHX_ SV *dsv, char const * const str, const STRLEN count, 1445759b3d2Safresh1 const STRLEN max, char const * const start_color, char const * const end_color, 1455759b3d2Safresh1 const U32 flags) 1465759b3d2Safresh1{ 1475759b3d2Safresh1 const U8 dq = (flags & PERL_PV_PRETTY_QUOTE) ? '"' : '%'; 1485759b3d2Safresh1 STRLEN escaped; 1495759b3d2Safresh1 1505759b3d2Safresh1 if (!(flags & PERL_PV_PRETTY_NOCLEAR)) 1515759b3d2Safresh1 sv_setpvs(dsv, ""); 1525759b3d2Safresh1 1535759b3d2Safresh1 if (dq == '"') 1545759b3d2Safresh1 sv_catpvs(dsv, "\""); 1555759b3d2Safresh1 else if (flags & PERL_PV_PRETTY_LTGT) 1565759b3d2Safresh1 sv_catpvs(dsv, "<"); 1575759b3d2Safresh1 1585759b3d2Safresh1 if (start_color != NULL) 1595759b3d2Safresh1 sv_catpv(dsv, D_PPP_CONSTPV_ARG(start_color)); 1605759b3d2Safresh1 1615759b3d2Safresh1 pv_escape(dsv, str, count, max, &escaped, flags | PERL_PV_ESCAPE_NOCLEAR); 1625759b3d2Safresh1 1635759b3d2Safresh1 if (end_color != NULL) 1645759b3d2Safresh1 sv_catpv(dsv, D_PPP_CONSTPV_ARG(end_color)); 1655759b3d2Safresh1 1665759b3d2Safresh1 if (dq == '"') 1675759b3d2Safresh1 sv_catpvs(dsv, "\""); 1685759b3d2Safresh1 else if (flags & PERL_PV_PRETTY_LTGT) 1695759b3d2Safresh1 sv_catpvs(dsv, ">"); 1705759b3d2Safresh1 1715759b3d2Safresh1 if ((flags & PERL_PV_PRETTY_ELLIPSES) && escaped < count) 1725759b3d2Safresh1 sv_catpvs(dsv, "..."); 1735759b3d2Safresh1 1745759b3d2Safresh1 return SvPVX(dsv); 1755759b3d2Safresh1} 1765759b3d2Safresh1 1775759b3d2Safresh1#endif 1785759b3d2Safresh1#endif 1795759b3d2Safresh1 1805759b3d2Safresh1#ifndef pv_display 1815759b3d2Safresh1#if { NEED pv_display } 1825759b3d2Safresh1 1835759b3d2Safresh1char * 1845759b3d2Safresh1pv_display(pTHX_ SV *dsv, const char *pv, STRLEN cur, STRLEN len, STRLEN pvlim) 1855759b3d2Safresh1{ 1865759b3d2Safresh1 pv_pretty(dsv, pv, cur, pvlim, NULL, NULL, PERL_PV_PRETTY_DUMP); 1875759b3d2Safresh1 if (len > cur && pv[cur] == '\0') 1885759b3d2Safresh1 sv_catpvs(dsv, "\\0"); 1895759b3d2Safresh1 return SvPVX(dsv); 1905759b3d2Safresh1} 1915759b3d2Safresh1 1925759b3d2Safresh1#endif 1935759b3d2Safresh1#endif 1945759b3d2Safresh1 1955759b3d2Safresh1=xsinit 1965759b3d2Safresh1 1975759b3d2Safresh1#define NEED_pv_escape 1985759b3d2Safresh1#define NEED_pv_pretty 1995759b3d2Safresh1#define NEED_pv_display 2005759b3d2Safresh1 2015759b3d2Safresh1=xsubs 2025759b3d2Safresh1 2035759b3d2Safresh1void 2045759b3d2Safresh1pv_escape_can_unicode() 2055759b3d2Safresh1 PPCODE: 206f3efcd01Safresh1#if defined(is_utf8_string) && defined(utf8_to_uvchr_buf) 2075759b3d2Safresh1 XSRETURN_YES; 2085759b3d2Safresh1#else 2095759b3d2Safresh1 XSRETURN_NO; 2105759b3d2Safresh1#endif 2115759b3d2Safresh1 2125759b3d2Safresh1void 2135759b3d2Safresh1pv_pretty() 2145759b3d2Safresh1 PREINIT: 2155759b3d2Safresh1 char *rv; 2165759b3d2Safresh1 PPCODE: 2175759b3d2Safresh1 EXTEND(SP, 8); 2185759b3d2Safresh1 ST(0) = sv_newmortal(); 2195759b3d2Safresh1 rv = pv_pretty(ST(0), "foobarbaz", 2205759b3d2Safresh1 9, 40, NULL, NULL, 0); 2215759b3d2Safresh1 ST(1) = sv_2mortal(newSVpv(rv, 0)); 2225759b3d2Safresh1 ST(2) = sv_newmortal(); 2235759b3d2Safresh1 rv = pv_pretty(ST(2), "pv_p\retty\n", 2245759b3d2Safresh1 10, 40, "left", "right", PERL_PV_PRETTY_LTGT); 2255759b3d2Safresh1 ST(3) = sv_2mortal(newSVpv(rv, 0)); 2265759b3d2Safresh1 ST(4) = sv_newmortal(); 2275759b3d2Safresh1 rv = pv_pretty(ST(4), "N\303\275 Batter\303\255", 2285759b3d2Safresh1 12, 20, NULL, NULL, PERL_PV_ESCAPE_UNI_DETECT); 2295759b3d2Safresh1 ST(5) = sv_2mortal(newSVpv(rv, 0)); 2305759b3d2Safresh1 ST(6) = sv_newmortal(); 2315759b3d2Safresh1 rv = pv_pretty(ST(6), "\303\201g\303\246tis Byrjun", 2325759b3d2Safresh1 15, 18, NULL, NULL, PERL_PV_ESCAPE_UNI_DETECT|PERL_PV_PRETTY_ELLIPSES); 2335759b3d2Safresh1 ST(7) = sv_2mortal(newSVpv(rv, 0)); 2345759b3d2Safresh1 XSRETURN(8); 2355759b3d2Safresh1 2365759b3d2Safresh1void 2375759b3d2Safresh1pv_display() 2385759b3d2Safresh1 PREINIT: 2395759b3d2Safresh1 char *rv; 2405759b3d2Safresh1 PPCODE: 2415759b3d2Safresh1 EXTEND(SP, 4); 2425759b3d2Safresh1 ST(0) = sv_newmortal(); 2435759b3d2Safresh1 rv = pv_display(ST(0), "foob\0rbaz", 9, 10, 20); 2445759b3d2Safresh1 ST(1) = sv_2mortal(newSVpv(rv, 0)); 2455759b3d2Safresh1 ST(2) = sv_newmortal(); 2465759b3d2Safresh1 rv = pv_display(ST(2), "pv_display", 10, 11, 5); 2475759b3d2Safresh1 ST(3) = sv_2mortal(newSVpv(rv, 0)); 2485759b3d2Safresh1 XSRETURN(4); 2495759b3d2Safresh1 2505759b3d2Safresh1=tests plan => 13 2515759b3d2Safresh1 2525759b3d2Safresh1my $uni = &Devel::PPPort::pv_escape_can_unicode(); 2535759b3d2Safresh1 2545759b3d2Safresh1# sanity check 255*9a4edab6Sbluhmok($uni ? ivers($]) >= ivers("5.006") : ivers($]) < ivers("5.008")); 2565759b3d2Safresh1 2575759b3d2Safresh1my @r; 2585759b3d2Safresh1 2595759b3d2Safresh1@r = &Devel::PPPort::pv_pretty(); 260de8cc8edSafresh1is($r[0], $r[1]); 261de8cc8edSafresh1is($r[0], "foobarbaz"); 262de8cc8edSafresh1is($r[2], $r[3]); 263de8cc8edSafresh1is($r[2], '<leftpv_p\retty\nright>'); 264de8cc8edSafresh1is($r[4], $r[5]); 265de8cc8edSafresh1if(ord("A") == 65) { 266de8cc8edSafresh1 is($r[4], $uni ? 'N\375 Batter\355' : 'N\303\275 Batter\303'); 267de8cc8edSafresh1} 268de8cc8edSafresh1else { 269de8cc8edSafresh1 skip("Skip for non-ASCII platform"); 270de8cc8edSafresh1} 271de8cc8edSafresh1is($r[6], $r[7]); 272de8cc8edSafresh1if(ord("A") == 65) { 273de8cc8edSafresh1 is($r[6], $uni ? '\301g\346tis Byrju...' : '\303\201g\303\246t...'); 274de8cc8edSafresh1} 275de8cc8edSafresh1else { 276de8cc8edSafresh1 skip("Skip for non-ASCII platform"); 277de8cc8edSafresh1} 2785759b3d2Safresh1 2795759b3d2Safresh1@r = &Devel::PPPort::pv_display(); 280de8cc8edSafresh1is($r[0], $r[1]); 281de8cc8edSafresh1is($r[0], '"foob\0rbaz"\0'); 282de8cc8edSafresh1is($r[2], $r[3]); 2835759b3d2Safresh1ok($r[2] eq '"pv_di"...\0' || 2845759b3d2Safresh1 $r[2] eq '"pv_d"...\0'); # some perl implementations are broken... :( 285