Commit 1ba4066d authored by xbe's avatar xbe Committed by Alastair Robertson

printf(): Allow length specifiers for integers

parent 7ae4de5e
#include <regex>
#include "printf.h"
#include "printf_format_types.h"
namespace bpftrace {
std::string verify_format_string(const std::string &fmt, std::vector<SizedType> args)
{
std::stringstream message;
std::regex re("%-?[0-9]*[a-zA-Z]");
const std::regex re("%-?[0-9]*[a-zA-Z]+");
auto tokens_begin = std::sregex_iterator(fmt.begin(), fmt.end(), re);
auto tokens_end = std::sregex_iterator();
......@@ -41,25 +42,14 @@ std::string verify_format_string(const std::string &fmt, std::vector<SizedType>
while (token_iter->str()[offset] >= '0' && token_iter->str()[offset] <= '9')
offset++;
char token = token_iter->str()[offset];
Type token_type;
switch (token)
const std::string token = token_iter->str().substr(offset);
const auto token_type_iter = printf_format_types.find(token);
if (token_type_iter == printf_format_types.end())
{
case 'd':
case 'u':
case 'x':
case 'X':
case 'p':
token_type = Type::integer;
break;
case 's':
token_type = Type::string;
break;
default:
message << "printf: Unknown format string token: %" << token << std::endl;
return message.str();
message << "printf: Unknown format string token: %" << token << std::endl;
return message.str();
}
const Type &token_type = token_type_iter->second;
if (arg_type != token_type)
{
......
#include <unordered_map>
#include "types.h"
namespace bpftrace {
// valid printf length + specifier combinations
// it's done like this because as of this writing, C++ doesn't have a builtin way to do
// compile time string concatenation. here is the Python 3 code that generates this map:
// #!/usr/bin/python3
// lengths = ("", "hh", "h", "l", "ll", "j", "z", "t")
// specifiers = ("d", "u", "x", "X", "p")
//
// print("{\"s\", Type::string},")
// print(",\n".join([f"{{\"{l+s}\", Type::integer}}" for l in lengths for s in specifiers]))
const std::unordered_map<std::string, Type> printf_format_types = {
{"s", Type::string},
{"d", Type::integer},
{"u", Type::integer},
{"x", Type::integer},
{"X", Type::integer},
{"p", Type::integer},
{"hhd", Type::integer},
{"hhu", Type::integer},
{"hhx", Type::integer},
{"hhX", Type::integer},
{"hhp", Type::integer},
{"hd", Type::integer},
{"hu", Type::integer},
{"hx", Type::integer},
{"hX", Type::integer},
{"hp", Type::integer},
{"ld", Type::integer},
{"lu", Type::integer},
{"lx", Type::integer},
{"lX", Type::integer},
{"lp", Type::integer},
{"lld", Type::integer},
{"llu", Type::integer},
{"llx", Type::integer},
{"llX", Type::integer},
{"llp", Type::integer},
{"jd", Type::integer},
{"ju", Type::integer},
{"jx", Type::integer},
{"jX", Type::integer},
{"jp", Type::integer},
{"zd", Type::integer},
{"zu", Type::integer},
{"zx", Type::integer},
{"zX", Type::integer},
{"zp", Type::integer},
{"td", Type::integer},
{"tu", Type::integer},
{"tx", Type::integer},
{"tX", Type::integer},
{"tp", Type::integer}
};
} // namespace bpftrace
......@@ -236,6 +236,57 @@ TEST(semantic_analyser, printf_format_int)
test("kprobe:f { printf(\"int: %X\", 1234) }", 0);
}
TEST(semantic_analyser, printf_format_int_with_length)
{
test("kprobe:f { printf(\"int: %d\", 1234) }", 0);
test("kprobe:f { printf(\"int: %u\", 1234) }", 0);
test("kprobe:f { printf(\"int: %x\", 1234) }", 0);
test("kprobe:f { printf(\"int: %X\", 1234) }", 0);
test("kprobe:f { printf(\"int: %p\", 1234) }", 0);
test("kprobe:f { printf(\"int: %hhd\", 1234) }", 0);
test("kprobe:f { printf(\"int: %hhu\", 1234) }", 0);
test("kprobe:f { printf(\"int: %hhx\", 1234) }", 0);
test("kprobe:f { printf(\"int: %hhX\", 1234) }", 0);
test("kprobe:f { printf(\"int: %hhp\", 1234) }", 0);
test("kprobe:f { printf(\"int: %hd\", 1234) }", 0);
test("kprobe:f { printf(\"int: %hu\", 1234) }", 0);
test("kprobe:f { printf(\"int: %hx\", 1234) }", 0);
test("kprobe:f { printf(\"int: %hX\", 1234) }", 0);
test("kprobe:f { printf(\"int: %hp\", 1234) }", 0);
test("kprobe:f { printf(\"int: %ld\", 1234) }", 0);
test("kprobe:f { printf(\"int: %lu\", 1234) }", 0);
test("kprobe:f { printf(\"int: %lx\", 1234) }", 0);
test("kprobe:f { printf(\"int: %lX\", 1234) }", 0);
test("kprobe:f { printf(\"int: %lp\", 1234) }", 0);
test("kprobe:f { printf(\"int: %lld\", 1234) }", 0);
test("kprobe:f { printf(\"int: %llu\", 1234) }", 0);
test("kprobe:f { printf(\"int: %llx\", 1234) }", 0);
test("kprobe:f { printf(\"int: %llX\", 1234) }", 0);
test("kprobe:f { printf(\"int: %llp\", 1234) }", 0);
test("kprobe:f { printf(\"int: %jd\", 1234) }", 0);
test("kprobe:f { printf(\"int: %ju\", 1234) }", 0);
test("kprobe:f { printf(\"int: %jx\", 1234) }", 0);
test("kprobe:f { printf(\"int: %jX\", 1234) }", 0);
test("kprobe:f { printf(\"int: %jp\", 1234) }", 0);
test("kprobe:f { printf(\"int: %zd\", 1234) }", 0);
test("kprobe:f { printf(\"int: %zu\", 1234) }", 0);
test("kprobe:f { printf(\"int: %zx\", 1234) }", 0);
test("kprobe:f { printf(\"int: %zX\", 1234) }", 0);
test("kprobe:f { printf(\"int: %zp\", 1234) }", 0);
test("kprobe:f { printf(\"int: %td\", 1234) }", 0);
test("kprobe:f { printf(\"int: %tu\", 1234) }", 0);
test("kprobe:f { printf(\"int: %tx\", 1234) }", 0);
test("kprobe:f { printf(\"int: %tX\", 1234) }", 0);
test("kprobe:f { printf(\"int: %tp\", 1234) }", 0);
}
TEST(semantic_analyser, printf_format_string)
{
test("kprobe:f { printf(\"str: %s\", \"mystr\") }", 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment