Skip to content

Commit 1b6dd8d

Browse files
committed
lib: cbprintf: refactor handling of dynamic format flags
Format width and precision can be extracted from arguments. A negative value is interpreted by changing flag state and using the non-negative value. Refactor pull_va_args() so the raw value from the stack is preserved in the state so it can be packed, deferring the interpretation to point-of-use. Signed-off-by: Peter Bigot <[email protected]>
1 parent 5b156fc commit 1b6dd8d

File tree

1 file changed

+44
-43
lines changed

1 file changed

+44
-43
lines changed

lib/os/cbprintf_complete.c

Lines changed: 44 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1318,54 +1318,16 @@ static void pull_va_args(struct cbprintf_state *state)
13181318
struct conversion *const conv = &state->conv;
13191319
union argument_value *const value = &state->value;
13201320

1321-
state->width = -1;
1322-
state->precision = -1;
1323-
1324-
/* If dynamic width is specified, process it, otherwise set
1325-
* with if present.
1326-
*/
13271321
if (conv->width_star) {
13281322
state->width = va_arg(state->ap, int);
1329-
1330-
if (state->width < 0) {
1331-
conv->flag_dash = true;
1332-
state->width = -state->width;
1333-
}
1334-
} else if (conv->width_present) {
1335-
state->width = conv->width_value;
1323+
} else {
1324+
state->width = -1;
13361325
}
13371326

1338-
/* If dynamic precision is specified, process it, otherwise
1339-
* set precision if present. For floating point where
1340-
* precision is not present use 6.
1341-
*/
13421327
if (conv->prec_star) {
1343-
int arg = va_arg(state->ap, int);
1344-
1345-
if (arg < 0) {
1346-
conv->prec_present = false;
1347-
} else {
1348-
state->precision = arg;
1349-
}
1350-
} else if (conv->prec_present) {
1351-
state->precision = conv->prec_value;
1352-
}
1353-
1354-
/* Reuse width and precision memory in conv for value
1355-
* padding counts.
1356-
*/
1357-
conv->pad0_value = 0;
1358-
conv->pad0_pre_exp = 0;
1359-
1360-
/* FP conversion requires knowing the precision. */
1361-
if (IS_ENABLED(CONFIG_CBPRINTF_FP_SUPPORT)
1362-
&& (conv->specifier_cat == SPECIFIER_FP)
1363-
&& !conv->prec_present) {
1364-
if (conv->specifier_a) {
1365-
state->precision = FRACTION_HEX;
1366-
} else {
1367-
state->precision = 6;
1368-
}
1328+
state->precision = va_arg(state->ap, int);
1329+
} else {
1330+
state->precision = -1;
13691331
}
13701332

13711333
enum specifier_cat_enum specifier_cat
@@ -1510,6 +1472,45 @@ int cbvprintf(cbprintf_cb out, void *ctx, const char *fp, va_list ap)
15101472
fp = extract_conversion(conv, sp);
15111473
pull_va_args(&state);
15121474

1475+
/* Apply flag changes for negative width argument or
1476+
* copy out format value.
1477+
*/
1478+
if (conv->width_star) {
1479+
if (state.width < 0) {
1480+
conv->flag_dash = true;
1481+
state.width = -state.width;
1482+
}
1483+
} else if (conv->width_present) {
1484+
state.width = conv->width_value;
1485+
}
1486+
1487+
/* Apply flag changes for negative precision argument */
1488+
if (conv->prec_star) {
1489+
if (state.precision < 0) {
1490+
conv->prec_present = false;
1491+
state.precision = -1;
1492+
}
1493+
} else if (conv->prec_present) {
1494+
state.precision = conv->prec_value;
1495+
}
1496+
1497+
/* Reuse width and precision memory in conv for value
1498+
* padding counts.
1499+
*/
1500+
conv->pad0_value = 0;
1501+
conv->pad0_pre_exp = 0;
1502+
1503+
/* FP conversion requires knowing the precision. */
1504+
if (IS_ENABLED(CONFIG_CBPRINTF_FP_SUPPORT)
1505+
&& (conv->specifier_cat == SPECIFIER_FP)
1506+
&& !conv->prec_present) {
1507+
if (conv->specifier_a) {
1508+
state.precision = FRACTION_HEX;
1509+
} else {
1510+
state.precision = 6;
1511+
}
1512+
}
1513+
15131514
/* We've now consumed all arguments related to this
15141515
* specification. If the conversion is invalid, or is
15151516
* something we don't support, then output the original

0 commit comments

Comments
 (0)