TRIO_PRIVATE int TrioParseQualifiers TRIO_ARGS4((type, format, offset, parameter), int type,
                                                TRIO_CONST char* format, int offset,
                                                trio_parameter_t* parameter)
{
	char ch;
	int dots = 0; /* Count number of dots in modifier part */
	char* tmpformat;

	parameter->beginOffset = offset - 1;
	parameter->flags = FLAGS_NEW;
	parameter->position = TrioGetPosition(format, &offset);

	/* Default values */
	parameter->width = NO_WIDTH;
	parameter->precision = NO_PRECISION;
	parameter->base = NO_BASE;
	parameter->varsize = NO_SIZE;

	while (TrioIsQualifier(format[offset]))
	{
		ch = format[offset++];

		switch (ch)
		{
			case QUALIFIER_SPACE:
				parameter->flags |= FLAGS_SPACE;
				break;

			case QUALIFIER_PLUS:
				parameter->flags |= FLAGS_SHOWSIGN;
				break;

			case QUALIFIER_MINUS:
				parameter->flags |= FLAGS_LEFTADJUST;
				parameter->flags &= ~FLAGS_NILPADDING;
				break;

			case QUALIFIER_ALTERNATIVE:
				parameter->flags |= FLAGS_ALTERNATIVE;
				break;

			case QUALIFIER_DOT:
				if (dots == 0) /* Precision */
				{
					dots++;

					/* Skip if no precision */
					if (QUALIFIER_DOT == format[offset])
						break;

					/* After the first dot we have the precision */
					parameter->flags |= FLAGS_PRECISION;
					if ((QUALIFIER_STAR == format[offset])
#if defined(QUALIFIER_PARAM)
					    || (QUALIFIER_PARAM == format[offset])
#endif
					)
					{
						offset++;
						parameter->flags |= FLAGS_PRECISION_PARAMETER;
						parameter->precision = TrioGetPosition(format, &offset);
					}
					else
					{
						parameter->precision =
						    trio_to_long(&format[offset], &tmpformat, BASE_DECIMAL);
						offset = (int)(tmpformat - format);
					}
				}
				else if (dots == 1) /* Base */
				{
					dots++;

					/* After the second dot we have the base */
					parameter->flags |= FLAGS_BASE;
					if ((QUALIFIER_STAR == format[offset])
#if defined(QUALIFIER_PARAM)
					    || (QUALIFIER_PARAM == format[offset])
#endif
					)
					{
						offset++;
						parameter->flags |= FLAGS_BASE_PARAMETER;
						parameter->base = TrioGetPosition(format, &offset);
					}
					else
					{
						parameter->base = trio_to_long(&format[offset], &tmpformat, BASE_DECIMAL);
						if (parameter->base > MAX_BASE)
							return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
						offset = (int)(tmpformat - format);
					}
				}
				else
				{
					return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
				}
				break; /* QUALIFIER_DOT */

#if defined(QUALIFIER_PARAM)
			case QUALIFIER_PARAM:
				parameter->type = TYPE_PRINT;
				/* FALLTHROUGH */
#endif
			case QUALIFIER_STAR:
				/* This has different meanings for print and scan */
				if (TYPE_PRINT == type)
				{
					/* Read with from parameter */
					int width = TrioGetPosition(format, &offset);
					parameter->flags |= (FLAGS_WIDTH | FLAGS_WIDTH_PARAMETER);
					if (NO_POSITION != width)
						parameter->width = width;
					/* else keep parameter->width = NO_WIDTH which != NO_POSITION */
				}
#if TRIO_FEATURE_SCANF
				else
				{
					/* Scan, but do not store result */
					parameter->flags |= FLAGS_IGNORE;
				}
#endif
				break; /* QUALIFIER_STAR */

			case '0':
				if (!(parameter->flags & FLAGS_LEFTADJUST))
					parameter->flags |= FLAGS_NILPADDING;
				/* FALLTHROUGH */
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
			case '7':
			case '8':
			case '9':
				parameter->flags |= FLAGS_WIDTH;
				/*
				 * &format[offset - 1] is used to "rewind" the read
				 * character from format
				 */
				parameter->width = trio_to_long(&format[offset - 1], &tmpformat, BASE_DECIMAL);
				offset = (int)(tmpformat - format);
				break;

			case QUALIFIER_SHORT:
				if (parameter->flags & FLAGS_SHORTSHORT)
					return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
				else if (parameter->flags & FLAGS_SHORT)
					parameter->flags |= FLAGS_SHORTSHORT;
				else
					parameter->flags |= FLAGS_SHORT;
				break;

			case QUALIFIER_LONG:
				if (parameter->flags & FLAGS_QUAD)
					return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
				else if (parameter->flags & FLAGS_LONG)
					parameter->flags |= FLAGS_QUAD;
				else
					parameter->flags |= FLAGS_LONG;
				break;

#if TRIO_FEATURE_LONGDOUBLE
			case QUALIFIER_LONG_UPPER:
				parameter->flags |= FLAGS_LONGDOUBLE;
				break;
#endif

#if TRIO_FEATURE_SIZE_T
			case QUALIFIER_SIZE_T:
				parameter->flags |= FLAGS_SIZE_T;
				/* Modify flags for later truncation of number */
				if (sizeof(size_t) == sizeof(trio_ulonglong_t))
					parameter->flags |= FLAGS_QUAD;
				else if (sizeof(size_t) == sizeof(long))
					parameter->flags |= FLAGS_LONG;
				break;
#endif

#if TRIO_FEATURE_PTRDIFF_T
			case QUALIFIER_PTRDIFF_T:
				parameter->flags |= FLAGS_PTRDIFF_T;
				if (sizeof(ptrdiff_t) == sizeof(trio_ulonglong_t))
					parameter->flags |= FLAGS_QUAD;
				else if (sizeof(ptrdiff_t) == sizeof(long))
					parameter->flags |= FLAGS_LONG;
				break;
#endif

#if TRIO_FEATURE_INTMAX_T
			case QUALIFIER_INTMAX_T:
				parameter->flags |= FLAGS_INTMAX_T;
				if (sizeof(trio_intmax_t) == sizeof(trio_ulonglong_t))
					parameter->flags |= FLAGS_QUAD;
				else if (sizeof(trio_intmax_t) == sizeof(long))
					parameter->flags |= FLAGS_LONG;
				break;
#endif

#if TRIO_FEATURE_QUAD
			case QUALIFIER_QUAD:
				parameter->flags |= FLAGS_QUAD;
				break;
#endif

#if TRIO_FEATURE_FIXED_SIZE
			case QUALIFIER_FIXED_SIZE:
				if (parameter->flags & FLAGS_FIXED_SIZE)
					return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);

				if (parameter->flags &
				    (FLAGS_ALL_SIZES | FLAGS_LONGDOUBLE | FLAGS_WIDECHAR | FLAGS_VARSIZE_PARAMETER))
					return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);

				if ((format[offset] == '6') && (format[offset + 1] == '4'))
				{
					parameter->varsize = sizeof(trio_int64_t);
					offset += 2;
				}
				else if ((format[offset] == '3') && (format[offset + 1] == '2'))
				{
					parameter->varsize = sizeof(trio_int32_t);
					offset += 2;
				}
				else if ((format[offset] == '1') && (format[offset + 1] == '6'))
				{
					parameter->varsize = sizeof(trio_int16_t);
					offset += 2;
				}
				else if (format[offset] == '8')
				{
					parameter->varsize = sizeof(trio_int8_t);
					offset++;
				}
				else
					return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);

				parameter->flags |= FLAGS_FIXED_SIZE;
				break;
#endif /* TRIO_FEATURE_FIXED_SIZE */

#if defined(QUALIFIER_WIDECHAR)
			case QUALIFIER_WIDECHAR:
				parameter->flags |= FLAGS_WIDECHAR;
				break;
#endif

#if TRIO_FEATURE_SIZE_T_UPPER
			case QUALIFIER_SIZE_T_UPPER:
				break;
#endif

#if TRIO_FEATURE_QUOTE
			case QUALIFIER_QUOTE:
				parameter->flags |= FLAGS_QUOTE;
				break;
#endif

#if TRIO_FEATURE_STICKY
			case QUALIFIER_STICKY:
				parameter->flags |= FLAGS_STICKY;
				break;
#endif

#if TRIO_FEATURE_VARSIZE
			case QUALIFIER_VARSIZE:
				parameter->flags |= FLAGS_VARSIZE_PARAMETER;
				break;
#endif

#if TRIO_FEATURE_ROUNDING
			case QUALIFIER_ROUNDING_UPPER:
				parameter->flags |= FLAGS_ROUNDING;
				break;
#endif

			default:
				/* Bail out completely to make the error more obvious */
				return TRIO_ERROR_RETURN(TRIO_EINVAL, offset);
		}

	} /* while qualifier */

	parameter->endOffset = offset;

	return 0;
}