in sources/printf.c [237:316]
static void printf_iterator_set_type_char(printf_iterator *iterator, char c) {
Contract(iterator);
Contract(iterator->sem_type == SEM_TYPE_PENDING);
Contract(iterator->state == PRINTF_STATE_TYPE);
CSTR_OF_CHAR(type_string, c);
// '-' works with all possible type specifications.
printf_flags valid_flags = PRINTF_FLAGS_MINUS;
bool_t allows_length_specifier;
switch (c) {
case 'd': case 'i': {
allows_length_specifier = true;
valid_flags |= PRINTF_FLAGS_PLUS;
valid_flags |= PRINTF_FLAGS_SPACE;
valid_flags |= PRINTF_FLAGS_ZERO;
valid_flags |= PRINTF_FLAGS_COMMA;
if (iterator->length == PRINTF_LENGTH_LONG_LONG) {
iterator->sem_type = SEM_TYPE_LONG_INTEGER;
} else {
iterator->sem_type = SEM_TYPE_INTEGER;
}
break;
}
case 'u':
allows_length_specifier = true;
valid_flags |= PRINTF_FLAGS_ZERO;
if (iterator->length == PRINTF_LENGTH_LONG_LONG) {
iterator->sem_type = SEM_TYPE_LONG_INTEGER;
} else {
iterator->sem_type = SEM_TYPE_INTEGER;
}
break;
case 'f': case 'e': case 'E': case 'g': case 'G':
allows_length_specifier = false;
valid_flags |= PRINTF_FLAGS_ZERO;
valid_flags |= PRINTF_FLAGS_BANG;
valid_flags |= PRINTF_FLAGS_HASH;
iterator->sem_type = SEM_TYPE_REAL;
break;
case 'x': case 'X': case 'o':
allows_length_specifier = true;
valid_flags |= PRINTF_FLAGS_ZERO;
valid_flags |= PRINTF_FLAGS_HASH;
if (iterator->length == PRINTF_LENGTH_LONG_LONG) {
iterator->sem_type = SEM_TYPE_LONG_INTEGER;
} else {
iterator->sem_type = SEM_TYPE_INTEGER;
}
break;
case 's':
allows_length_specifier = false;
valid_flags |= PRINTF_FLAGS_BANG;
iterator->sem_type = SEM_TYPE_TEXT;
break;
case 'c': case 'z': case 'p': case 'n': case 'q': case 'Q': case 'w': {
// NOTE: 'c' could be supported with codegen changes. It is presently
// disallowed because it requires a TEXT argument when used in an SQL
// context, yet it requires an integer argument when used via
// `sqlite3_mprintf`. The code generator currently cannot handle the
// latter case correctly.
printf_iterator_error(iterator, "CQL0416: type specifier not allowed in CQL", type_string);
return;
}
default:
printf_iterator_error(iterator, "CQL0417: unrecognized type specifier", type_string);
return;
}
if ((iterator->flags | valid_flags) != valid_flags) {
printf_iterator_error(iterator, "CQL0418: type specifier combined with inappropriate flags", type_string);
return;
}
if (iterator->length != PRINTF_LENGTH_DEFAULT && !allows_length_specifier) {
printf_iterator_error(iterator, "CQL0419: type specifier cannot be combined with length specifier", type_string);
return;
}
}