glibc: Parsing a Template String 如何解析printf格式化
Posted rtoax
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了glibc: Parsing a Template String 如何解析printf格式化相关的知识,希望对你有一定的参考价值。
https://www.gnu.org/software/libc/manual//html_node/Parsing-a-Template-String.html#:~:text=12.10%20Parsing%20a%20Template%20String%20You%20can%20use,the%20user%E2%80%99s%20program%2C%20which%20could%20cause%20a%20crash.
#include <stdio.h>
#include <printf.h>
static void fmt_parse(const char *fmt)
{
int i;
int argtypes[1024] = {0};
size_t ret = parse_printf_format(fmt, 1024, argtypes);
printf("===========================\\n");
printf("%s\\n", fmt);
for(i=0;i<ret;i++) {
switch(argtypes[i]) {
#define _CASE(i, v, intro) \\
case v: \\
printf("\\t%d is %s\\n", i, intro); \\
break;
_CASE(i, PA_INT, "int");
_CASE(i, PA_INT|PA_FLAG_LONG, "long int");
_CASE(i, PA_INT|PA_FLAG_SHORT, "short int");
_CASE(i, PA_INT|PA_FLAG_LONG_LONG, "long long int");
_CASE(i, PA_CHAR, "char");
_CASE(i, PA_WCHAR, "wchar");
_CASE(i, PA_STRING, "string");
_CASE(i, PA_WSTRING, "wstring");
_CASE(i, PA_POINTER, "pointer");
_CASE(i, PA_FLOAT, "float");
_CASE(i, PA_DOUBLE, "double");
_CASE(i, PA_DOUBLE|PA_FLAG_LONG_DOUBLE, "long double");
_CASE(i, PA_LAST, "LAST");
default:
printf("\\t%d unknown(%d).\\n", i, argtypes[i]);
break;
}
}
}
const char *test_fmts[] = {
"1.%d 2.%u 3.%x",
"1.%2d 2.%2u 3.%2x",
"1.%-d 2.%-u 3.%-x",
"1.%-2d 2.%-2u 3.%-2x",
"1.%ld 2.%lu 3.%lx",
"1.%2ld 2.%2lu 3.%2lx",
"1.%-ld 2.%-lu 3.%-lx",
"1.%-2ld 2.%-2lu 3.%-2lx %lld %-lld %2lld %-2lld",
"1.%s 2.%S 3.%c 4.%C",
"1.%-s 2.%-S 3.%-c 4.%-C",
"1.%10s 2.%10S 3.%c 4.%C",
"1.%-10s 2.%-10S 3.%c 4.%C",
"1.%f 2.%lf %llf",
"1.%-f 2.%-lf",
"1.%2f 2.%2lf",
"1.%.2f 2.%.2lf %llf %-llf %2llf %-2llf",
"%10.2f %2.lf %-2.lf %-.10lf",
"%p %x %0x %#02x %#02lx",
NULL,
};
int main()
{
int i = 0;
while(test_fmts[i]) {
fmt_parse(test_fmts[i++]);
}
}
12.12.10 Parsing a Template String
You can use the function parse_printf_format
to obtain information about the number and types of arguments that are expected by a given template string. This function permits interpreters that provide interfaces to printf
to avoid passing along invalid arguments from the user’s program, which could cause a crash.
All the symbols described in this section are declared in the header file printf.h.
Function: size_t parse_printf_format (const char *template, size_t n, int *argtypes)
Preliminary: | MT-Safe locale | AS-Safe | AC-Safe | See POSIX Safety Concepts.
This function returns information about the number and types of arguments expected by the printf
template string template. The information is stored in the array argtypes; each element of this array describes one argument. This information is encoded using the various ‘PA_’ macros, listed below.
The argument n specifies the number of elements in the array argtypes. This is the maximum number of elements that parse_printf_format
will try to write.
parse_printf_format
returns the total number of arguments required by template. If this number is greater than n, then the information returned describes only the first n arguments. If you want information about additional arguments, allocate a bigger array and call parse_printf_format
again.
The argument types are encoded as a combination of a basic type and modifier flag bits.
Macro: int PA_FLAG_MASK
This macro is a bitmask for the type modifier flag bits. You can write the expression (argtypes[i] & PA_FLAG_MASK)
to extract just the flag bits for an argument, or (argtypes[i] & ~PA_FLAG_MASK)
to extract just the basic type code.
Here are symbolic constants that represent the basic types; they stand for integer values.
PA_INT
This specifies that the base type is int
.
PA_CHAR
This specifies that the base type is int
, cast to char
.
PA_STRING
This specifies that the base type is char *
, a null-terminated string.
PA_POINTER
This specifies that the base type is void *
, an arbitrary pointer.
PA_FLOAT
This specifies that the base type is float
.
PA_DOUBLE
This specifies that the base type is double
.
PA_LAST
You can define additional base types for your own programs as offsets from PA_LAST
. For example, if you have data types ‘foo’ and ‘bar’ with their own specialized printf
conversions, you could define encodings for these types as:
#define PA_FOO PA_LAST #define PA_BAR (PA_LAST + 1)
Here are the flag bits that modify a basic type. They are combined with the code for the basic type using inclusive-or.
PA_FLAG_PTR
If this bit is set, it indicates that the encoded type is a pointer to the base type, rather than an immediate value. For example, ‘PA_INT|PA_FLAG_PTR’ represents the type ‘int *’.
PA_FLAG_SHORT
If this bit is set, it indicates that the base type is modified with short
. (This corresponds to the ‘h’ type modifier.)
PA_FLAG_LONG
If this bit is set, it indicates that the base type is modified with long
. (This corresponds to the ‘l’ type modifier.)
PA_FLAG_LONG_LONG
If this bit is set, it indicates that the base type is modified with long long
. (This corresponds to the ‘L’ type modifier.)
PA_FLAG_LONG_DOUBLE
This is a synonym for PA_FLAG_LONG_LONG
, used by convention with a base type of PA_DOUBLE
to indicate a type of long double
.
Next: Example of Parsing, Previous: Variable Arguments Output, Up: Formatted Output [Contents][Index]
12.12.11 Example of Parsing a Template String
https://www.gnu.org/software/libc/manual//html_node/Example-of-Parsing.html
Here is an example of decoding argument types for a format string. We assume this is part of an interpreter which contains arguments of type NUMBER
, CHAR
, STRING
and STRUCTURE
(and perhaps others which are not valid here).
/* Test whether the nargs specified objects
in the vector args are valid
for the format string format:
if so, return 1.
If not, return 0 after printing an error message. */
int
validate_args (char *format, int nargs, OBJECT *args)
{
int *argtypes;
int nwanted;
/* Get the information about the arguments.
Each conversion specification must be at least two characters
long, so there cannot be more specifications than half the
length of the string. */
argtypes = (int *) alloca (strlen (format) / 2 * sizeof (int));
nwanted = parse_printf_format (format, nargs, argtypes);
/* Check the number of arguments. */
if (nwanted > nargs)
{
error ("too few arguments (at least %d required)", nwanted);
return 0;
}
/* Check the C type wanted for each argument
and see if the object given is suitable. */
for (i = 0; i < nwanted; i++)
{
int wanted;
if (argtypes[i] & PA_FLAG_PTR)
wanted = STRUCTURE;
else
switch (argtypes[i] & ~PA_FLAG_MASK)
{
case PA_INT:
case PA_FLOAT:
case PA_DOUBLE:
wanted = NUMBER;
break;
case PA_CHAR:
wanted = CHAR;
break;
case PA_STRING:
wanted = STRING;
break;
case PA_POINTER:
wanted = STRUCTURE;
break;
}
if (TYPE (args[i]) != wanted)
{
error ("type mismatch for arg number %d", i);
return 0;
}
}
return 1;
}
以上是关于glibc: Parsing a Template String 如何解析printf格式化的主要内容,如果未能解决你的问题,请参考以下文章
[vue/no-parsing-error] Parsing error: x-invalid-end-tag 提示报错
[vue/no-parsing-error] Parsing error: x-invalid-end-tag 提示报错
[vue/no-parsing-error] Parsing error: x-invalid-end-tag.eslint-plugin-vue
leetcode1106. Parsing A Boolean Expression
Expected a key while parsing a block mapping.
Error parsing XML: not well-formed (invalid token) 报错+R文件消失解决的方法