From 6a4ce2b6c03f5c2a44621116154867ef8ab48b2e Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Wed, 29 May 2024 15:20:31 +0000 Subject: Let's [9c258a841a|fix] the %p/%z/%t type specifiers, so they behave like C in scripts, and document them --- doc/format.n | 5 ++++- generic/tclStringObj.c | 13 ++++++++++--- tests/format.test | 6 +++--- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/doc/format.n b/doc/format.n index eb64491..b647349 100644 --- a/doc/format.n +++ b/doc/format.n @@ -133,7 +133,7 @@ it must be a numeric string. .SS "OPTIONAL SIZE MODIFIER" .PP The fifth part of a conversion specifier is a size modifier, -which must be \fBll\fR, \fBh\fR, \fBl\fR, or \fBL\fR. +which must be \fBll\fR, \fBh\fR, \fBl\fR, \fBz\fR, \fBt\fR, or \fBL\fR. If it is \fBll\fR it specifies that an integer value is taken without truncation for conversion to a formatted substring. If it is \fBh\fR it specifies that an integer value is @@ -141,6 +141,9 @@ truncated to a 16-bit range before converting. This option is rarely useful. If it is \fBl\fR it specifies that the integer value is truncated to the same range as that produced by the \fBwide()\fR function of the \fBexpr\fR command (at least a 64-bit range). +If it is \fBz\fR or \fBt\fR it specifies that the integer value is +truncated to the range determined by the value of the \fBpointerSize\fR +element of the \fBtcl_platform\fR array. If it is \fBL\fR it specifies that an integer or double value is taken without truncation for conversion to a formatted substring. If neither \fBh\fR nor \fBl\fR nor \fBL\fR are present, the integer value is diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 980bf22..494451d 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -2457,8 +2457,15 @@ Tcl_AppendFormatToObj( format += step; step = TclUtfToUniChar(format, &ch); } - } else if ((ch == 't') || (ch == 'z') || (ch == 'q') || (ch == 'j') - || (ch == 'L')) { + } else if ((ch == 't') || (ch == 'z')) { + format += step; + step = TclUtfToUniChar(format, &ch); +#ifndef TCL_WIDE_INT_IS_LONG + if (sizeof(void *) > sizeof(int)) { + useWide = 1; + } +#endif + } else if ((ch == 'q') || (ch == 'j') || (ch == 'L')) { format += step; step = TclUtfToUniChar(format, &ch); useBig = 1; @@ -2534,7 +2541,7 @@ Tcl_AppendFormatToObj( Tcl_Size toAppend; #ifndef TCL_WIDE_INT_IS_LONG - if (ch == 'p') { + if ((ch == 'p') && (sizeof(void *) > sizeof(int))) { useWide = 1; } #endif diff --git a/tests/format.test b/tests/format.test index 4accb33..9f69fc0 100644 --- a/tests/format.test +++ b/tests/format.test @@ -389,17 +389,17 @@ test format-8.23 {error conditions} { test format-8.24 {Undocumented formats} -body { format "%zd %td %d" [expr {2**30}] [expr {2**30}] [expr {2**30}] } -result {1073741824 1073741824 1073741824} -test format-8.25 {Undocumented formats} -constraints pointerIs64bit -body { +test format-8.25 {Other formats} -constraints pointerIs64bit -body { format "%zd %td %lld" [expr {2**33}] [expr {2**33}] [expr {2**33}] } -result {8589934592 8589934592 8589934592} # Since "%p" is equivalent to "%#llx" in 64-bit platforms and equivalent # to "%#x" in 32-bit platforms, it are really not useful in scripts, # therefore they are not documented. It's intended use is through the # function Tcl_AppendPrintfToObj (et al). -test format-8.26 {Undocumented formats} -body { +test format-8.26 {Other formats} -body { format "%p %#x" [expr {2**31}] [expr {2**31}] } -result {0x80000000 0x80000000} -test format-8.27 {Undocumented formats} -constraints pointerIs64bit -body { +test format-8.27 {Other formats} -constraints pointerIs64bit -body { format "%p %#llx" [expr {2**33}] [expr {2**33}] } -result {0x200000000 0x200000000} test format-8.28 {Internal use of TCL_COMBINE flag should not be visible at script level} { -- cgit v0.12 From 19592f48720d9e5acc55f0b9086d0a9c380b82a1 Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Thu, 30 May 2024 21:26:39 +0000 Subject: Let's [9c258a841a|fix] the j%j/%q type specifiers, so they behave like C in scripts, and document them --- doc/format.n | 12 +++++------- generic/tclStringObj.c | 8 +++++++- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/doc/format.n b/doc/format.n index b647349..b0a0107 100644 --- a/doc/format.n +++ b/doc/format.n @@ -138,19 +138,17 @@ If it is \fBll\fR it specifies that an integer value is taken without truncation for conversion to a formatted substring. If it is \fBh\fR it specifies that an integer value is truncated to a 16-bit range before converting. This option is rarely useful. -If it is \fBl\fR it specifies that the integer value is -truncated to the same range as that produced by the \fBwide()\fR +If it is \fBl\fR (or \fBj\fR or \fBq\fR) it specifies that the integer value +is truncated to the same range as that produced by the \fBwide()\fR function of the \fBexpr\fR command (at least a 64-bit range). If it is \fBz\fR or \fBt\fR it specifies that the integer value is truncated to the range determined by the value of the \fBpointerSize\fR element of the \fBtcl_platform\fR array. If it is \fBL\fR it specifies that an integer or double value is taken without truncation for conversion to a formatted substring. -If neither \fBh\fR nor \fBl\fR nor \fBL\fR are present, the integer value is -truncated to the same range as that produced by the \fBint()\fR -function of the \fBexpr\fR command (at least a 32-bit range, but -determined by the value of the \fBwordSize\fR element of the -\fBtcl_platform\fR array). +If neither of those are present, the integer value is +truncated to the range determined by the value of the +\fBwordSize\fR element of the \fBtcl_platform\fR array). .SS "MANDATORY CONVERSION TYPE" .PP The last thing in a conversion specifier is an alphabetic character diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 494451d..b4da1a9 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -2457,6 +2457,12 @@ Tcl_AppendFormatToObj( format += step; step = TclUtfToUniChar(format, &ch); } + } else if ((ch == 'q') || (ch == 'j')) { + format += step; + step = TclUtfToUniChar(format, &ch); +#ifndef TCL_WIDE_INT_IS_LONG + useWide = 1; +#endif } else if ((ch == 't') || (ch == 'z')) { format += step; step = TclUtfToUniChar(format, &ch); @@ -2465,7 +2471,7 @@ Tcl_AppendFormatToObj( useWide = 1; } #endif - } else if ((ch == 'q') || (ch == 'j') || (ch == 'L')) { + } else if (ch == 'L') { format += step; step = TclUtfToUniChar(format, &ch); useBig = 1; -- cgit v0.12