📄 trio.c
字号:
if (sizeof(size_t) == sizeof(ULONGLONG)) flags |= FLAGS_QUAD; else if (sizeof(size_t) == sizeof(long)) flags |= FLAGS_LONG; break;#endif#if defined(QUALIFIER_PTRDIFF_T) case QUALIFIER_PTRDIFF_T: flags |= FLAGS_PTRDIFF_T; if (sizeof(ptrdiff_t) == sizeof(ULONGLONG)) flags |= FLAGS_QUAD; else if (sizeof(ptrdiff_t) == sizeof(long)) flags |= FLAGS_LONG; break;#endif#if defined(QUALIFIER_INTMAX_T) case QUALIFIER_INTMAX_T: flags |= FLAGS_INTMAX_T; if (sizeof(intmax_t) == sizeof(ULONGLONG)) flags |= FLAGS_QUAD; else if (sizeof(intmax_t) == sizeof(long)) flags |= FLAGS_LONG; break;#endif#if defined(QUALIFIER_QUAD) case QUALIFIER_QUAD: flags |= FLAGS_QUAD; 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; got_sticky = TRUE; break;#endif #if defined(QUALIFIER_VARSIZE) case QUALIFIER_VARSIZE: flags |= FLAGS_SIZE_PARAMETER; parameterPosition++; if (positional) varsize = parameterPosition; else { varsize = currentParam; currentParam = varsize + 1; } if (currentParam > maxParam) maxParam = currentParam; 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) {#if defined(TRIO_ERRORS) usedEntries[width] += 1;#endif parameters[pos].type = FORMAT_PARAMETER; indices[width] = pos; width = pos++; } if (flags & FLAGS_PRECISION_PARAMETER) {#if defined(TRIO_ERRORS) usedEntries[precision] += 1;#endif parameters[pos].type = FORMAT_PARAMETER; indices[precision] = pos; precision = pos++; } if (flags & FLAGS_BASE_PARAMETER) {#if defined(TRIO_ERRORS) usedEntries[base] += 1;#endif parameters[pos].type = FORMAT_PARAMETER; indices[base] = pos; base = pos++; } if (flags & FLAGS_SIZE_PARAMETER) {#if defined(TRIO_ERRORS) usedEntries[varsize] += 1;#endif parameters[pos].type = FORMAT_PARAMETER; indices[varsize] = pos; varsize = pos++; } indices[currentParam] = pos; switch (format[index++]) {#if defined(SPECIFIER_CHAR_UPPER) case SPECIFIER_CHAR_UPPER: flags |= FLAGS_LONG; /* FALLTHROUGH */#endif case SPECIFIER_CHAR: parameters[pos].type = FORMAT_CHAR; break;#if defined(SPECIFIER_STRING_UPPER) case SPECIFIER_STRING_UPPER: flags |= FLAGS_LONG; /* FALLTHROUGH */#endif case SPECIFIER_STRING: parameters[pos].type = FORMAT_STRING; break; case SPECIFIER_GROUP: if (TYPE_SCAN == type) { parameters[pos].type = FORMAT_GROUP; while (format[index]) { if (format[index++] == SPECIFIER_UNGROUP) break; /* while */ } } 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_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: 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++;# if defined(TRIO_ERRORS) usedEntries[currentParam] += 1;# endif 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; StrCopyMax(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; StrCopyMax(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); }#if defined(TRIO_ERRORS) /* Count the number of times this entry has been used */ usedEntries[currentParam] += 1;#endif /* Find last sticky parameters */ if (got_sticky && !(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 defined(TRIO_ERRORS) 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); }#endif 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: parameters[i].data.string = (arglist != NULL) ? va_arg(arglist, char *) : (char *)(argarray[num]); break; case FORMAT_POINTER: case FORMAT_COUNT: case FORMAT_USER_DEFINED: case FORMAT_UNKNOWN: parameters[i].data.pointer = (arglist != NULL) ? va_arg(arglist, void *) : argarray[num]; break; case FORMAT_CHAR: case FORMAT_INT: if (TYPE_SCAN == type) { if (arglist != NULL) parameters[i].data.pointer = (LONGEST *)va_arg(arglist, void *); else { if (parameters[i].type == FORMAT_CHAR) parameters[i].data.pointer = (LONGEST *)((char *)argarray[num]); else if (parameters[i].flags & FLAGS_SHORT) parameters[i].data.pointer = (LONGEST *)((short *)argarray[num]); else parameters[i].data.pointer = (LONGEST *)((int *)argarray[num]); } } else {#if defined(QUALIFIER_VARSIZE) if (parameters[i].flags & FLAGS_SIZE_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. */ parameters[i].flags &= ~FLAGS_ALL_VARSIZES; varsize = (int)parameters[parameters[i].varsize].data.number.as_unsigned; if (varsize <= (int)sizeof(int)) ; else if (varsize <= (int)sizeof(long)) parameters[i].flags |= FLAGS_LONG;#if defined(QUALIFIER_INTMAX_T) else if (varsize <= (int)sizeof(LONGLONG)) parameters[i].flags |= FLAGS_QUAD; else parameters[i].flags |= FLAGS_INTMAX_T;#else else parameters[i].flags |= FLAGS_QUAD;#endif }#endif /* defined(QUALIFIER_VARSIZE) */#if defined(QUALIFIER_SIZE_T) || defined(QUALIFIER_SIZE_T_UPPER) if (parameters[i].flags & FLAGS_SIZE_T) parameters[i].data.number.as_unsigned = (arglist != NULL) ? (LONGEST)va_arg(arglist, size_t) : (LONGEST)(*((size_t *)argarray[num])); else#endif#if defined(QUALIFIER_PTRDIFF_T) if (parameters[i].flags & FLAGS_PTRDIFF_T) parameters[i].data.number.as_unsigned = (arglist != NULL) ? (LONGEST)va_arg(arglist, ptrdiff_t) : (LONGEST)(*((ptrdiff_t *)argarray[num])); else#endif#if defined(QUALIFIER_INTMAX_T) if (parameters[i].flags & FLAGS_INTMAX_T) parameters[i].data.number.as_unsigned = (arglist != NULL) ? (LONGEST)va_arg(arglist, intmax_t) : (LONGEST)(*((intmax_t *)argarray[num])); else#endif if (parameters[i].flags & FLAGS_QUAD) parameters[i].data.number.as_unsigned = (arglist != NULL) ? (LONGEST)va_arg(arglist, ULONGLONG) : (LONGEST)(*((ULONGLONG *)argarray[num])); else if (parameters[i].flags & FLAGS_LONG) parameters[i].data.number.as_unsigned = (arglist != NULL) ? (LONGEST)va_arg(arglist, long) : (LONGEST)(*((long *)argarray[num])); else { if (arglist != NULL) parameters[i].data.number.as_unsigned = (LONGEST)va_arg(arglist, int); else { if (parameters[i].type == FORMAT_CHAR) parameters[i].data.number.as_unsigned = (LONGEST)(*((char *)argarray[num])); else if (parameters[i].flags & FLAGS_SHORT) parameters[i].data.number.as_unsigned = (LONGEST)(*((short *)argarray[num])); else parameters[i].data.number.as_unsigned = (LONGEST)(*((int *)argarray[num])); } } } break; case FORMAT_PARAMETER: /* * The parameter for the user-defined specifier is a pointer, * whereas the rest (width, precision, base) uses an integer. */ if (parameters[i].flags & FLAGS_USER_DEFINED) parameters[i].data.pointer = (arglist != NULL) ? va_arg(arglist, void *) : argarray[num]; else parameters[i].data.number.as_unsigned = (arglist != NULL) ? (LONGEST)va_arg(arglist, int) : (LONGEST)(*((int *)argarray[num])); break; case FORMAT_DOUBLE: if (TYPE_SCAN == type)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -