📄 trio.c
字号:
if (flags & FLAGS_FIXED_SIZE)
return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
if (flags & (FLAGS_ALL_SIZES | FLAGS_LONGDOUBLE |
FLAGS_WIDECHAR | FLAGS_VARSIZE_PARAMETER))
return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
if ((format[index] == '6') &&
(format[index + 1] == '4'))
{
varsize = sizeof(trio_int64_t);
index += 2;
}
else if ((format[index] == '3') &&
(format[index + 1] == '2'))
{
varsize = sizeof(trio_int32_t);
index += 2;
}
else if ((format[index] == '1') &&
(format[index + 1] == '6'))
{
varsize = sizeof(trio_int16_t);
index += 2;
}
else if (format[index] == '8')
{
varsize = sizeof(trio_int8_t);
index++;
}
else
return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
flags |= FLAGS_FIXED_SIZE;
break;
#endif
#if defined(QUALIFIER_WIDECHAR)
case QUALIFIER_WIDECHAR:
flags |= FLAGS_WIDECHAR;
break;
#endif
#if defined(QUALIFIER_SIZE_T_UPPER)
case QUALIFIER_SIZE_T_UPPER:
break;
#endif
#if defined(QUALIFIER_QUOTE)
case QUALIFIER_QUOTE:
flags |= FLAGS_QUOTE;
break;
#endif
#if defined(QUALIFIER_STICKY)
case QUALIFIER_STICKY:
flags |= FLAGS_STICKY;
gotSticky = TRUE;
break;
#endif
#if defined(QUALIFIER_VARSIZE)
case QUALIFIER_VARSIZE:
flags |= FLAGS_VARSIZE_PARAMETER;
parameterPosition++;
if (positional)
varsize = parameterPosition;
else
{
varsize = currentParam;
currentParam = varsize + 1;
}
if (currentParam > maxParam)
maxParam = currentParam;
break;
#endif
#if defined(QUALIFIER_ROUNDING_UPPER)
case QUALIFIER_ROUNDING_UPPER:
flags |= FLAGS_ROUNDING;
break;
#endif
default:
/* Bail out completely to make the error more obvious */
return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
}
} /* while qualifier */
/*
* Parameters only need the type and value. The value is
* read later.
*/
if (flags & FLAGS_WIDTH_PARAMETER)
{
usedEntries[width] += 1;
parameters[pos].type = FORMAT_PARAMETER;
parameters[pos].flags = 0;
indices[width] = pos;
width = pos++;
}
if (flags & FLAGS_PRECISION_PARAMETER)
{
usedEntries[precision] += 1;
parameters[pos].type = FORMAT_PARAMETER;
parameters[pos].flags = 0;
indices[precision] = pos;
precision = pos++;
}
if (flags & FLAGS_BASE_PARAMETER)
{
usedEntries[base] += 1;
parameters[pos].type = FORMAT_PARAMETER;
parameters[pos].flags = 0;
indices[base] = pos;
base = pos++;
}
if (flags & FLAGS_VARSIZE_PARAMETER)
{
usedEntries[varsize] += 1;
parameters[pos].type = FORMAT_PARAMETER;
parameters[pos].flags = 0;
indices[varsize] = pos;
varsize = pos++;
}
indices[currentParam] = pos;
switch (format[index++])
{
#if defined(SPECIFIER_CHAR_UPPER)
case SPECIFIER_CHAR_UPPER:
flags |= FLAGS_WIDECHAR;
/* FALLTHROUGH */
#endif
case SPECIFIER_CHAR:
if (flags & FLAGS_LONG)
flags |= FLAGS_WIDECHAR;
else if (flags & FLAGS_SHORT)
flags &= ~FLAGS_WIDECHAR;
parameters[pos].type = FORMAT_CHAR;
break;
#if defined(SPECIFIER_STRING_UPPER)
case SPECIFIER_STRING_UPPER:
flags |= FLAGS_WIDECHAR;
/* FALLTHROUGH */
#endif
case SPECIFIER_STRING:
if (flags & FLAGS_LONG)
flags |= FLAGS_WIDECHAR;
else if (flags & FLAGS_SHORT)
flags &= ~FLAGS_WIDECHAR;
parameters[pos].type = FORMAT_STRING;
break;
case SPECIFIER_GROUP:
if (TYPE_SCAN == type)
{
int depth = 1;
parameters[pos].type = FORMAT_GROUP;
if (format[index] == QUALIFIER_CIRCUMFLEX)
index++;
if (format[index] == SPECIFIER_UNGROUP)
index++;
if (format[index] == QUALIFIER_MINUS)
index++;
/* Skip nested brackets */
while (format[index] != NIL)
{
if (format[index] == SPECIFIER_GROUP)
{
depth++;
}
else if (format[index] == SPECIFIER_UNGROUP)
{
if (--depth <= 0)
{
index++;
break;
}
}
index++;
}
}
break;
case SPECIFIER_INTEGER:
parameters[pos].type = FORMAT_INT;
break;
case SPECIFIER_UNSIGNED:
flags |= FLAGS_UNSIGNED;
parameters[pos].type = FORMAT_INT;
break;
case SPECIFIER_DECIMAL:
/* Disable base modifier */
flags &= ~FLAGS_BASE_PARAMETER;
base = BASE_DECIMAL;
parameters[pos].type = FORMAT_INT;
break;
case SPECIFIER_OCTAL:
flags |= FLAGS_UNSIGNED;
flags &= ~FLAGS_BASE_PARAMETER;
base = BASE_OCTAL;
parameters[pos].type = FORMAT_INT;
break;
#if defined(SPECIFIER_BINARY)
case SPECIFIER_BINARY_UPPER:
flags |= FLAGS_UPPER;
/* FALLTHROUGH */
case SPECIFIER_BINARY:
flags |= FLAGS_NILPADDING;
flags &= ~FLAGS_BASE_PARAMETER;
base = BASE_BINARY;
parameters[pos].type = FORMAT_INT;
break;
#endif
case SPECIFIER_HEX_UPPER:
flags |= FLAGS_UPPER;
/* FALLTHROUGH */
case SPECIFIER_HEX:
flags |= FLAGS_UNSIGNED;
flags &= ~FLAGS_BASE_PARAMETER;
base = BASE_HEX;
parameters[pos].type = FORMAT_INT;
break;
case SPECIFIER_FLOAT_E_UPPER:
flags |= FLAGS_UPPER;
/* FALLTHROUGH */
case SPECIFIER_FLOAT_E:
flags |= FLAGS_FLOAT_E;
parameters[pos].type = FORMAT_DOUBLE;
break;
case SPECIFIER_FLOAT_G_UPPER:
flags |= FLAGS_UPPER;
/* FALLTHROUGH */
case SPECIFIER_FLOAT_G:
flags |= FLAGS_FLOAT_G;
parameters[pos].type = FORMAT_DOUBLE;
break;
case SPECIFIER_FLOAT_F_UPPER:
flags |= FLAGS_UPPER;
/* FALLTHROUGH */
case SPECIFIER_FLOAT_F:
parameters[pos].type = FORMAT_DOUBLE;
break;
case SPECIFIER_POINTER:
if (sizeof(trio_pointer_t) == sizeof(trio_ulonglong_t))
flags |= FLAGS_QUAD;
else if (sizeof(trio_pointer_t) == sizeof(long))
flags |= FLAGS_LONG;
parameters[pos].type = FORMAT_POINTER;
break;
case SPECIFIER_COUNT:
parameters[pos].type = FORMAT_COUNT;
break;
#if defined(SPECIFIER_HEXFLOAT)
# if defined(SPECIFIER_HEXFLOAT_UPPER)
case SPECIFIER_HEXFLOAT_UPPER:
flags |= FLAGS_UPPER;
/* FALLTHROUGH */
# endif
case SPECIFIER_HEXFLOAT:
base = BASE_HEX;
parameters[pos].type = FORMAT_DOUBLE;
break;
#endif
#if defined(FORMAT_ERRNO)
case SPECIFIER_ERRNO:
parameters[pos].type = FORMAT_ERRNO;
break;
#endif
#if defined(SPECIFIER_USER_DEFINED_BEGIN)
case SPECIFIER_USER_DEFINED_BEGIN:
{
unsigned int max;
int without_namespace = TRUE;
parameters[pos].type = FORMAT_USER_DEFINED;
parameters[pos].user_name[0] = NIL;
tmpformat = (char *)&format[index];
while ((ch = format[index]))
{
index++;
if (ch == SPECIFIER_USER_DEFINED_END)
{
if (without_namespace)
{
/* We must get the handle first */
parameters[pos].type = FORMAT_PARAMETER;
parameters[pos].indexAfterSpecifier = index;
parameters[pos].flags = FLAGS_USER_DEFINED;
/* Adjust parameters for insertion of new one */
pos++;
usedEntries[currentParam] += 1;
parameters[pos].type = FORMAT_USER_DEFINED;
currentParam++;
indices[currentParam] = pos;
if (currentParam > maxParam)
maxParam = currentParam;
}
/* Copy the user data */
max = (unsigned int)(&format[index] - tmpformat);
if (max > MAX_USER_DATA)
max = MAX_USER_DATA;
trio_copy_max(parameters[pos].user_data,
max,
tmpformat);
break; /* while */
}
if (ch == SPECIFIER_USER_DEFINED_SEPARATOR)
{
without_namespace = FALSE;
/* Copy the namespace for later looking-up */
max = (int)(&format[index] - tmpformat);
if (max > MAX_USER_NAME)
max = MAX_USER_NAME;
trio_copy_max(parameters[pos].user_name,
max,
tmpformat);
tmpformat = (char *)&format[index];
}
}
if (ch != SPECIFIER_USER_DEFINED_END)
return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
}
break;
#endif /* defined(SPECIFIER_USER_DEFINED_BEGIN) */
default:
/* Bail out completely to make the error more obvious */
return TRIO_ERROR_RETURN(TRIO_EINVAL, index);
}
/* Count the number of times this entry has been used */
usedEntries[currentParam] += 1;
/* Find last sticky parameters */
if (gotSticky && !(flags & FLAGS_STICKY))
{
for (i = pos - 1; i >= 0; i--)
{
if (parameters[i].type == FORMAT_PARAMETER)
continue;
if ((parameters[i].flags & FLAGS_STICKY) &&
(parameters[i].type == parameters[pos].type))
{
/* Do not overwrite current qualifiers */
flags |= (parameters[i].flags & (unsigned long)~FLAGS_STICKY);
if (width == NO_WIDTH)
width = parameters[i].width;
if (precision == NO_PRECISION)
precision = parameters[i].precision;
if (base == NO_BASE)
base = parameters[i].base;
break;
}
}
}
parameters[pos].indexAfterSpecifier = index;
parameters[pos].flags = flags;
parameters[pos].width = width;
parameters[pos].precision = precision;
parameters[pos].base = (base == NO_BASE) ? BASE_DECIMAL : base;
parameters[pos].varsize = varsize;
pos++;
if (! positional)
parameterPosition++;
} /* if identifier */
} /* while format characters left */
for (num = 0; num <= maxParam; num++)
{
if (usedEntries[num] != 1)
{
if (usedEntries[num] == 0) /* gap detected */
return TRIO_ERROR_RETURN(TRIO_EGAP, num);
else /* double references detected */
return TRIO_ERROR_RETURN(TRIO_EDBLREF, num);
}
i = indices[num];
/*
* FORMAT_PARAMETERS are only present if they must be read,
* so it makes no sense to check the ignore flag (besides,
* the flags variable is not set for that particular type)
*/
if ((parameters[i].type != FORMAT_PARAMETER) &&
(parameters[i].flags & FLAGS_IGNORE))
continue; /* for all arguments */
/*
* The stack arguments are read according to ANSI C89
* default argument promotions:
*
* char = int
* short = int
* unsigned char = unsigned int
* unsigned short = unsigned int
* float = double
*
* In addition to the ANSI C89 these types are read (the
* default argument promotions of C99 has not been
* considered yet)
*
* long long
* long double
* size_t
* ptrdiff_t
* intmax_t
*/
switch (parameters[i].type)
{
case FORMAT_GROUP:
case FORMAT_STRING:
#if TRIO_WIDECHAR
if (flags & FLAGS_WIDECHAR)
{
parameters[i].data.wstring = (argarray == NULL)
? va_arg(*arglist, trio_wchar_t *)
: (trio_wchar_t *)(argarray[num]);
}
else
#endif
{
parameters[i].data.string = (argarray == NULL)
? va_arg(*arglist, char *)
: (char *)(argarray[num]);
}
break;
#if defined(FORMAT_USER_DEFINED)
case FORMAT_USER_DEFINED:
#endif
case FORMAT_POINTER:
case FORMAT_COUNT:
case FORMAT_UNKNOWN:
parameters[i].data.pointer = (argarray == NULL)
? va_arg(*arglist, trio_pointer_t )
: argarray[num];
break;
case FORMAT_CHAR:
case FORMAT_INT:
if (TYPE_SCAN == type)
{
if (argarray == NULL)
parameters[i].data.pointer =
(trio_pointer_t)va_arg(*arglist, trio_pointer_t);
else
{
if (parameters[i].type == FORMAT_CHAR)
parameters[i].data.pointer =
(trio_pointer_t)((char *)argarray[num]);
else if (parameters[i].flags & FLAGS_SHORT)
parameters[i].data.pointer =
(trio_pointer_t)((short *)argarray[num]);
else
parameters[i].data.pointer =
(trio_pointer_t)((int *)argarray[num]);
}
}
else
{
#if defined(QUALIFIER_VARSIZE) || defined(QUALIFIER_FIXED_SIZE)
if (parameters[i].flags
& (FLAGS_VARSIZE_PARAMETER | FLAGS_FIXED_SIZE))
{
if (parameters[i].flags & FLAGS_VARSIZE_PARAMETER)
{
/*
* Variable sizes are mapped onto the fixed sizes, in
* accordance with integer promotion.
*
* Please note that this may not be portable, as we
* only guess the size, not the layout of the numbers.
* For example, if int is little-endian, and long is
* big-endian, then this will fail.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -