← Commit list

4e0bfd8cf7

Daniel Stenberg
Daniel Stenberg
2026-04-21
SUCCESS Duration: 236s

Subject

mprintf: simplify parsefmt

Binary

No binary (build failed)

Architecture & Compiler Flags

Architecture: x86_64-linux-gnu Compiler: gcc (Ubuntu 11.4.0-1ubuntu1~22.04.3) 11.4.0

—

Build Log

(log yok)

Commit Diff GitHub →

lib/mprintf.c+261 -227
@@ -169,6 +169,261 @@ static int dollarstring(const char *p, const char **end)
#define PFMT_PRECARG 10 /* attempted to use same arg twice, for prec */
#define PFMT_MANYSEGS 11 /* maxed out output segments */
+static int parse_flags(const char **fmtp, unsigned int *flagsp, int use_dollar,
+ int *precp, int *widthp)
+{
+ const char *fmt = *fmtp;
+ bool loopit = TRUE;
+ unsigned int flags = 0;
+ int width = 0;
+ int precision = 0;
+
+ /* Handle the flags */
+ do {
+ switch(*fmt++) {
+ case ' ':
+ flags |= FLAGS_SPACE;
+ break;
+ case '+':
+ flags |= FLAGS_SHOWSIGN;
+ break;
+ case '-':
+ flags |= FLAGS_LEFT;
+ flags &= ~(unsigned int)FLAGS_PAD_NIL;
+ break;
+ case '#':
+ flags |= FLAGS_ALT;
+ break;
+ case '.':
+ if('*' == *fmt) {
+ /* The precision is picked from a specified parameter */
+ flags |= FLAGS_PRECPARAM;
+ fmt++;
+
+ if(use_dollar == DOLLAR_USE) {
+ precision = dollarstring(fmt, &fmt);
+ if(precision < 0)
+ /* illegal combo */
+ return PFMT_DOLLARPREC;
+ }
+ else
+ /* get it from the next argument */
+ precision = -1;
+ }
+ else {
+ bool is_neg;
+ curl_off_t num;
+ flags |= FLAGS_PREC;
+ is_neg = ('-' == *fmt);
+ if(is_neg)
+ fmt++;
+ if(curlx_str_number(&fmt, &num, INT_MAX))
+ return PFMT_PREC;
+ precision = (int)num;
+ if(is_neg)
+ precision = -precision;
+ }
+ if((flags & (FLAGS_PREC | FLAGS_PRECPARAM)) ==
+ (FLAGS_PREC | FLAGS_PRECPARAM))
+ /* it is not permitted to use both kinds of precision for the same
+ argument */
+ return PFMT_PRECMIX;
+ break;
+ case 'h':
+ flags |= FLAGS_SHORT;
+ break;
+#ifdef _WIN32
+ case 'I':
+ /* Non-ANSI integer extensions I32 I64 */
+ if((fmt[0] == '3') && (fmt[1] == '2')) {
+ flags |= FLAGS_LONG;
+ fmt += 2;
+ }
+ else if((fmt[0] == '6') && (fmt[1] == '4')) {
+ flags |= FLAGS_LONGLONG;
+ fmt += 2;
+ }
+ else {
+#if (SIZEOF_CURL_OFF_T > SIZEOF_LONG)
+ flags |= FLAGS_LONGLONG;
+#else
+ flags |= FLAGS_LONG;
+#endif
+ }
+ break;
+#endif /* _WIN32 */
+ case 'l':
+ if(flags & FLAGS_LONG)
+ flags |= FLAGS_LONGLONG;
+ else
+ flags |= FLAGS_LONG;
+ break;
+ case 'L':
+ flags |= FLAGS_LONGDOUBLE;
+ break;
+ case 'q':
+ flags |= FLAGS_LONGLONG;
+ break;
+ case 'z':
+ /* the code below generates a warning if -Wunreachable-code is
+ used */
+#if (SIZEOF_SIZE_T > SIZEOF_LONG)
+ flags |= FLAGS_LONGLONG;
+#else
+ flags |= FLAGS_LONG;
+#endif
+ break;
+ case 'O':
+#if (SIZEOF_CURL_OFF_T > SIZEOF_LONG)
+ flags |= FLAGS_LONGLONG;
+#else
+ flags |= FLAGS_LONG;
+#endif
+ break;
+ case '0':
+ if(!(flags & FLAGS_LEFT))
+ flags |= FLAGS_PAD_NIL;
+ FALLTHROUGH();
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': {
+ curl_off_t num;
+ flags |= FLAGS_WIDTH;
+ fmt--;
+ if(curlx_str_number(&fmt, &num, INT_MAX))
+ return PFMT_WIDTH;
+ width = (int)num;
+ break;
+ }
+ case '*': /* read width from argument list */
+ flags |= FLAGS_WIDTHPARAM;
+ if(use_dollar == DOLLAR_USE) {
+ width = dollarstring(fmt, &fmt);
+ if(width < 0)
+ /* illegal combo */
+ return PFMT_DOLLARWIDTH;
+ }
+ else
+ /* pick from the next argument */
+ width = -1;
+ break;
+ default:
+ loopit = FALSE;
+ fmt--;
+ break;
+ } /* switch */
+ } while(loopit); /* do */
+ *flagsp = flags;
+ *precp = precision;
+ *widthp = width;
+ *fmtp = fmt;
+ return PFMT_OK;
+}
+
+static bool parse_conversion(const char f, unsigned int *flagp,
+ FormatType *typep)
+{
+ unsigned int flags = *flagp;
+ FormatType type;
+ switch(f) {
+ case 'S':
+ flags = FLAGS_ALT;
+ type = MTYPE_STRING;
+ break;
+ case 's':
+ type = MTYPE_STRING;
+ break;
+ case 'n':
+ type = MTYPE_INTPTR;
+ break;
+ case 'p':
+ type = MTYPE_PTR;
+ break;
+ case 'd':
+ case 'i':
+ if(flags & FLAGS_LONGLONG)
+ type = MTYPE_LONGLONG;
+ else if(flags & FLAGS_LONG)
+ type = MTYPE_LONG;
+ else
+ type = MTYPE_INT;
+ break;
+ case 'u':
+ if(flags & FLAGS_LONGLONG)
+ type = MTYPE_LONGLONGU;
+ else if(flags & FLAGS_LONG)
+ type = MTYPE_LONGU;
+ else
+ type = MTYPE_INTU;
+ flags = FLAGS_UNSIGNED;
+ break;
+ case 'o':
+ if(flags & FLAGS_LONGLONG)
+ type = MTYPE_LONGLONGU;
+ else if(flags & FLAGS_LONG)
+ type = MTYPE_LONGU;
+ else
+ type = MTYPE_INTU;
+ flags = FLAGS_OCTAL | FLAGS_UNSIGNED;
+ break;
+ case 'x':
+ if(flags & FLAGS_LONGLONG)
+ type = MTYPE_LONGLONGU;
+ else if(flags & FLAGS_LONG)
+ type = MTYPE_LONGU;
+ else
+ type = MTYPE_INTU;
+ flags = FLAGS_HEX | FLAGS_UNSIGNED;
+ break;
+ case 'X':
+ if(flags & FLAGS_LONGLONG)
+ type = MTYPE_LONGLONGU;
+ else if(flags & FLAGS_LONG)
+ type = MTYPE_LONGU;
+ else
+ type = MTYPE_INTU;
+ flags |= FLAGS_HEX | FLAGS_UPPER | FLAGS_UNSIGNED;
+ break;
+ case 'c':
+ type = MTYPE_INT;
+ flags |= FLAGS_CHAR;
+ break;
+ case 'f':
+ type = MTYPE_DOUBLE;
+ break;
+ case 'e':
+ type = MTYPE_DOUBLE;
+ flags |= FLAGS_FLOATE;
+ break;
+ case 'E':
+ type = MTYPE_DOUBLE;
+ flags |= FLAGS_FLOATE | FLAGS_UPPER;
+ break;
+ case 'g':
+ type = MTYPE_DOUBLE;
+ flags |= FLAGS_FLOATG;
+ break;
+ case 'G':
+ type = MTYPE_DOUBLE;
+ flags |= FLAGS_FLOATG | FLAGS_UPPER;
+ break;
+ default:
+ /* invalid instruction, disregard and continue */
+ return TRUE;
+ } /* switch */
+
+ *flagp |= flags;
+ *typep = type;
+ return FALSE;
+}
+
+
static int parsefmt(const char *format,
struct outsegment *out,
struct va_input *in,
@@ -192,12 +447,12 @@ static int parsefmt(const char *format,
while(*fmt) {
if(*fmt == '%') {
struct va_input *iptr;
- bool loopit = TRUE;
FormatType type;
unsigned int flags = 0;
int width = 0;
int precision = 0;
int param = -1;
+ int rc;
fmt++;
outlen = (size_t)(fmt - start - 1);
if(*fmt == '%') {
@@ -232,233 +487,12 @@ static int parsefmt(const char *format,
use_dollar = DOLLAR_USE;
}
- /* Handle the flags */
- while(loopit) {
- switch(*fmt++) {
- case ' ':
- flags |= FLAGS_SPACE;
- break;
- case '+':
- flags |= FLAGS_SHOWSIGN;
- break;
- case '-':
- flags |= FLAGS_LEFT;
- flags &= ~(unsigned int)FLAGS_PAD_NIL;
- break;
- case '#':
- flags |= FLAGS_ALT;
- break;
- case '.':
- if('*' == *fmt) {
- /* The precision is picked from a specified parameter */
- flags |= FLAGS_PRECPARAM;
- fmt++;
-
- if(use_dollar == DOLLAR_USE) {
- precision = dollarstring(fmt, &fmt);
- if(precision < 0)
- /* illegal combo */
- return PFMT_DOLLARPREC;
- }
- else
- /* get it from the next argument */
- precision = -1;
- }
- else {
- bool is_neg;
- curl_off_t num;
- flags |= FLAGS_PREC;
- is_neg = ('-' == *fmt);
- if(is_neg)
- fmt++;
- if(curlx_str_number(&fmt, &num, INT_MAX))
- return PFMT_PREC;
- precision = (int)num;
- if(is_neg)
- precision = -precision;
- }
- if((flags & (FLAGS_PREC | FLAGS_PRECPARAM)) ==
- (FLAGS_PREC | FLAGS_PRECPARAM))
- /* it is not permitted to use both kinds of precision for the same
- argument */
- return PFMT_PRECMIX;
- break;
- case 'h':
- flags |= FLAGS_SHORT;
- break;
-#ifdef _WIN32
- case 'I':
- /* Non-ANSI integer extensions I32 I64 */
- if((fmt[0] == '3') && (fmt[1] == '2')) {
- flags |= FLAGS_LONG;
- fmt += 2;
- }
- else if((fmt[0] == '6') && (fmt[1] == '4')) {
- flags |= FLAGS_LONGLONG;
- fmt += 2;
- }
- else {
-#if (SIZEOF_CURL_OFF_T > SIZEOF_LONG)
- flags |= FLAGS_LONGLONG;
-#else
- flags |= FLAGS_LONG;
-#endif
- }
- break;
-#endif /* _WIN32 */
- case 'l':
- if(flags & FLAGS_LONG)
- flags |= FLAGS_LONGLONG;
- else
- flags |= FLAGS_LONG;
- break;
- case 'L':
- flags |= FLAGS_LONGDOUBLE;
- break;
- case 'q':
- flags |= FLAGS_LONGLONG;
- break;
- case 'z':
- /* the code below generates a warning if -Wunreachable-code is
- used */
-#if (SIZEOF_SIZE_T > SIZEOF_LONG)
- flags |= FLAGS_LONGLONG;
-#else
- flags |= FLAGS_LONG;
-#endif
- break;
- case 'O':
-#if (SIZEOF_CURL_OFF_T > SIZEOF_LONG)
- flags |= FLAGS_LONGLONG;
-#else
- flags |= FLAGS_LONG;
-#endif
- break;
- case '0':
- if(!(flags & FLAGS_LEFT))
- flags |= FLAGS_PAD_NIL;
- FALLTHROUGH();
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9': {
- curl_off_t num;
- flags |= FLAGS_WIDTH;
- fmt--;
- if(curlx_str_number(&fmt, &num, INT_MAX))
- return PFMT_WIDTH;
- width = (int)num;
- break;
- }
- case '*': /* read width from argument list */
- flags |= FLAGS_WIDTHPARAM;
- if(use_dollar == DOLLAR_USE) {
- width = dollarstring(fmt, &fmt);
- if(width < 0)
- /* illegal combo */
- return PFMT_DOLLARWIDTH;
- }
- else
- /* pick from the next argument */
- width = -1;
- break;
- default:
- loopit = FALSE;
- fmt--;
- break;
- } /* switch */
- } /* while */
-
- switch(*fmt) {
- case 'S':
- flags |= FLAGS_ALT;
- FALLTHROUGH();
- case 's':
- type = MTYPE_STRING;
- break;
- case 'n':
- type = MTYPE_INTPTR;
- break;
- case 'p':
- type = MTYPE_PTR;
- break;
- case 'd':
- case 'i':
- if(flags & FLAGS_LONGLONG)
- type = MTYPE_LONGLONG;
- else if(flags & FLAGS_LONG)
- type = MTYPE_LONG;
- else
- type = MTYPE_INT;
- break;
- case 'u':
- if(flags & FLAGS_LONGLONG)
- type = MTYPE_LONGLONGU;
- else if(flags & FLAGS_LONG)
- type = MTYPE_LONGU;
- else
- type = MTYPE_INTU;
- flags |= FLAGS_UNSIGNED;
- break;
- case 'o':
- if(flags & FLAGS_LONGLONG)
- type = MTYPE_LONGLONGU;
- else if(flags & FLAGS_LONG)
- type = MTYPE_LONGU;
- else
- type = MTYPE_INTU;
- flags |= FLAGS_OCTAL | FLAGS_UNSIGNED;
- break;
- case 'x':
- if(flags & FLAGS_LONGLONG)
- type = MTYPE_LONGLONGU;
- else if(flags & FLAGS_LONG)
- type = MTYPE_LONGU;
- else
- type = MTYPE_INTU;
- flags |= FLAGS_HEX | FLAGS_UNSIGNED;
- break;
- case 'X':
- if(flags & FLAGS_LONGLONG)
- type = MTYPE_LONGLONGU;
- else if(flags & FLAGS_LONG)
- type = MTYPE_LONGU;
- else
- type = MTYPE_INTU;
- flags |= FLAGS_HEX | FLAGS_UPPER | FLAGS_UNSIGNED;
- break;
- case 'c':
- type = MTYPE_INT;
- flags |= FLAGS_CHAR;
- break;
- case 'f':
- type = MTYPE_DOUBLE;
- break;
- case 'e':
- type = MTYPE_DOUBLE;
- flags |= FLAGS_FLOATE;
- break;
- case 'E':
- type = MTYPE_DOUBLE;
- flags |= FLAGS_FLOATE | FLAGS_UPPER;
- break;
- case 'g':
- type = MTYPE_DOUBLE;
- flags |= FLAGS_FLOATG;
- break;
- case 'G':
- type = MTYPE_DOUBLE;
- flags |= FLAGS_FLOATG | FLAGS_UPPER;
- break;
- default:
- /* invalid instruction, disregard and continue */
+ rc = parse_flags(&fmt, &flags, use_dollar, &precision, &width);
+ if(rc)
+ return rc;
+
+ if(parse_conversion(*fmt, &flags, &type))
continue;
- } /* switch */
if(flags & FLAGS_WIDTHPARAM) {
if(width < 0)