aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-03-13 14:04:01 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2019-03-13 14:04:01 -0300
commitdfebe439db76b5c9fd9b4e3877857e2449c8ad87 (patch)
treec31aa85dc53d1c0e0704060f313b682765dd459c
parentcf71a5ddc742692fad813f89f1c9ef53e1ffde0f (diff)
downloadlua-dfebe439db76b5c9fd9b4e3877857e2449c8ad87.tar.gz
lua-dfebe439db76b5c9fd9b4e3877857e2449c8ad87.tar.bz2
lua-dfebe439db76b5c9fd9b4e3877857e2449c8ad87.zip
New conversion specifier '%p' for 'string.format'
The call 'string.format("%p", val)' gives a Lua equivalent to the C API function 'lua_topointer'.
-rw-r--r--lstrlib.c5
-rw-r--r--manual/manual.of13
-rw-r--r--testes/strings.lua16
3 files changed, 31 insertions, 3 deletions
diff --git a/lstrlib.c b/lstrlib.c
index ab4258e5..6230cd0c 100644
--- a/lstrlib.c
+++ b/lstrlib.c
@@ -1185,6 +1185,11 @@ static int str_format (lua_State *L) {
1185 nb = l_sprintf(buff, MAX_ITEM, form, (LUAI_UACNUMBER)n); 1185 nb = l_sprintf(buff, MAX_ITEM, form, (LUAI_UACNUMBER)n);
1186 break; 1186 break;
1187 } 1187 }
1188 case 'p': {
1189 const void *p = lua_topointer(L, arg);
1190 nb = l_sprintf(buff, MAX_ITEM, form, p);
1191 break;
1192 }
1188 case 'q': { 1193 case 'q': {
1189 if (form[2] != '\0') /* modifiers? */ 1194 if (form[2] != '\0') /* modifiers? */
1190 return luaL_error(L, "specifier '%%q' cannot have modifiers"); 1195 return luaL_error(L, "specifier '%%q' cannot have modifiers");
diff --git a/manual/manual.of b/manual/manual.of
index 9c8ab033..2eb8773f 100644
--- a/manual/manual.of
+++ b/manual/manual.of
@@ -6751,8 +6751,7 @@ Returns a formatted version of its variable number of arguments
6751following the description given in its first argument (which must be a string). 6751following the description given in its first argument (which must be a string).
6752The format string follows the same rules as the @ANSI{sprintf}. 6752The format string follows the same rules as the @ANSI{sprintf}.
6753The only differences are that the conversion specifiers and modifiers 6753The only differences are that the conversion specifiers and modifiers
6754@T{*}, @id{h}, @id{L}, @id{l}, @id{n}, 6754@T{*}, @id{h}, @id{L}, @id{l}, and @id{n} are not supported
6755and @id{p} are not supported
6756and that there is an extra specifier, @id{q}. 6755and that there is an extra specifier, @id{q}.
6757 6756
6758The specifier @id{q} formats booleans, nil, numbers, and strings 6757The specifier @id{q} formats booleans, nil, numbers, and strings
@@ -6791,6 +6790,14 @@ it is converted to one following the same rules of @Lid{tostring}.
6791If the specifier has any modifier, 6790If the specifier has any modifier,
6792the corresponding string argument should not contain @x{embedded zeros}. 6791the corresponding string argument should not contain @x{embedded zeros}.
6793 6792
6793The specifier @id{p} formats the pointer
6794returned by @Lid{lua_topointer}.
6795That gives a unique string identifier for tables, userdata,
6796threads, strings, and functions.
6797For other values (numbers, nil, booleans),
6798this specifier results in a string representing
6799the pointer @id{NULL}.
6800
6794} 6801}
6795 6802
6796@LibEntry{string.gmatch (s, pattern [, init])| 6803@LibEntry{string.gmatch (s, pattern [, init])|
@@ -8768,7 +8775,7 @@ address space.)
8768} 8775}
8769 8776
8770@item{ 8777@item{
8771The constant @Lid{LUA_ERRGCMM} was removed. 8778The constant @id{LUA_ERRGCMM} was removed.
8772Errors in finalizers are never propagated; 8779Errors in finalizers are never propagated;
8773instead, they generate a warning. 8780instead, they generate a warning.
8774} 8781}
diff --git a/testes/strings.lua b/testes/strings.lua
index da53a87e..8bcbb391 100644
--- a/testes/strings.lua
+++ b/testes/strings.lua
@@ -153,6 +153,22 @@ else -- compatible coercion
153 assert(tostring(-1203 + 0.0) == "-1203") 153 assert(tostring(-1203 + 0.0) == "-1203")
154end 154end
155 155
156do -- tests for '%p' format
157 -- not much to test, as C does not specify what '%p' does.
158 -- ("The value of the pointer is converted to a sequence of printing
159 -- characters, in an implementation-defined manner.")
160 local null = string.format("%p", nil)
161 assert(string.format("%p", {}) ~= null)
162 assert(string.format("%p", 4) == null)
163 assert(string.format("%p", print) ~= null)
164 assert(string.format("%p", coroutine.running()) ~= null)
165 assert(string.format("%p", {}) ~= string.format("%p", {}))
166 assert(string.format("%p", string.rep("a", 10)) ==
167 string.format("%p", string.rep("a", 10))) -- short strings
168 assert(string.format("%p", string.rep("a", 300)) ~=
169 string.format("%p", string.rep("a", 300))) -- long strings
170 assert(#string.format("%90p", {}) == 90)
171end
156 172
157x = '"ílo"\n\\' 173x = '"ílo"\n\\'
158assert(string.format('%q%s', x, x) == '"\\"ílo\\"\\\n\\\\""ílo"\n\\') 174assert(string.format('%q%s', x, x) == '"\\"ílo\\"\\\n\\\\""ílo"\n\\')