Skip to content

Commit e4e761c

Browse files
committed
fix sprintf WIP
1 parent c828f83 commit e4e761c

File tree

2 files changed

+60
-82
lines changed

2 files changed

+60
-82
lines changed

src/main/java/org/perlonjava/operators/SprintfFormatParser.java

Lines changed: 29 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -141,54 +141,46 @@ FormatSpecifier parseSpecifier() {
141141
break;
142142
}
143143
}
144-
// // ADD THIS DEBUG LINE:
145-
// System.err.println("DEBUG: After flags: pos=" + pos + ", flags='" + spec.flags + "', next char='" + current() + "'");
146144

147-
// 2.5 Parse vector flag (THIS IS CORRECT POSITION)
145+
// 2.5 Parse vector flag if it appears after flags
148146
if (!isAtEnd() && current() == 'v') {
149147
spec.vectorFlag = true;
150148
advance();
151-
// // ADD THIS DEBUG LINE:
152-
// System.err.println("DEBUG: Vector flag found, pos=" + pos + ", next char='" + current() + "'");
153149
}
154150

155-
// 3. Parse width - SPECIAL HANDLING FOR VECTOR
156-
if (spec.vectorFlag && match('*')) {
157-
// For vector format, * means custom separator, not width!
158-
spec.widthFromArg = true; // Repurpose this to mean "custom separator"
151+
// 3. Parse width (and handle %*v formats)
152+
if (!spec.vectorFlag && match('*')) {
153+
// Could be regular width or %*v format
154+
if (!isAtEnd() && current() == 'v') {
155+
// This is %*v format - * is for custom separator
156+
spec.vectorFlag = true;
157+
spec.widthFromArg = true; // Means "has custom separator"
158+
advance(); // consume 'v'
159159

160-
// Now parse the actual width if present
161-
spec.width = parseNumber(); // This will parse the "2" in %*v2d
162-
} else if (match('*')) {
163-
spec.widthFromArg = true;
164-
// Check for parameter index
165-
checkpoint = pos;
166-
Integer widthParam = parseNumber();
167-
if (widthParam != null && match('$')) {
168-
spec.widthArgIndex = widthParam;
160+
// Now check for width after %*v
161+
if (match('*')) {
162+
// %*v*d format
163+
spec.precisionFromArg = true; // HACK: means second *
164+
} else {
165+
spec.width = parseNumber();
166+
}
169167
} else {
170-
pos = checkpoint; // Reset
168+
// Regular * for width
169+
spec.widthFromArg = true;
170+
checkpoint = pos;
171+
Integer widthParam = parseNumber();
172+
if (widthParam != null && match('$')) {
173+
spec.widthArgIndex = widthParam;
174+
} else {
175+
pos = checkpoint;
176+
}
171177
}
178+
} else if (spec.vectorFlag && match('*')) {
179+
// %v*d format - * is for width
180+
spec.widthFromArg = true;
181+
// Don't set precisionFromArg here
172182
} else {
173183
spec.width = parseNumber();
174-
// // ADD THIS DEBUG LINE:
175-
// System.err.println("DEBUG: Width parsed: " + spec.width + ", pos=" + pos + ", next char='" + current() + "'");
176-
}
177-
178-
if (!isAtEnd() && current() == 'v') {
179-
spec.vectorFlag = true;
180-
advance();
181-
// System.err.println("DEBUG: Vector flag found after width, pos=" + pos);
182-
183-
// // ADD THIS: For %*v formats, parse additional width
184-
if (spec.widthFromArg) {
185-
// The * was for separator, now parse the actual width
186-
Integer width2 = parseNumber();
187-
if (width2 != null) {
188-
spec.width = width2;
189-
// System.err.println("DEBUG: Parsed width after vector: " + spec.width);
190-
}
191-
}
192184
}
193185

194186
// Check for spaces in the format (invalid)

src/main/java/org/perlonjava/operators/SprintfOperator.java

Lines changed: 31 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -143,67 +143,53 @@ private static String processFormatSpecifier(
143143
// Get the value to format
144144
RuntimeScalar value = (RuntimeScalar) list.elements.get(args.valueArgIndex);
145145

146-
// For vector formats with %*v, we need special handling
147-
if (spec.vectorFlag && spec.widthFromArg) {
148-
// Only treat as separator if * came BEFORE v
149-
// Check the raw format to see the order
150-
int starPos = spec.raw.indexOf('*');
151-
int vPos = spec.raw.indexOf('v');
152-
153-
if (starPos < vPos) {
154-
// This is %*v format - * is separator
155-
// System.err.println("DEBUG: Processing %*v format (separator)");
156-
146+
// Special handling for %*v formats where * is the separator
147+
if (spec.vectorFlag) {
148+
// Check if this is %*v format (custom separator)
149+
if (spec.widthFromArg && spec.raw.matches(".*\\*v.*")) {
150+
// %*v format - * is for separator
157151
String separator = ".";
158-
int sepArgIndex;
159-
160-
if (spec.widthArgIndex != null) {
161-
sepArgIndex = spec.widthArgIndex - 1;
162-
} else {
163-
sepArgIndex = argIndex;
164-
}
165-
166-
// System.err.println("DEBUG: sepArgIndex=" + sepArgIndex);
152+
int sepArgIndex = argIndex;
167153

168154
if (sepArgIndex < list.size()) {
169155
separator = ((RuntimeScalar) list.elements.get(sepArgIndex)).toString();
170-
// System.err.println("DEBUG: Got separator: '" + separator + "'");
171156
}
172157

173-
// For %*v formats, we need to get the value from the correct position
174-
int actualValueIndex;
175-
if (spec.parameterIndex != null) {
176-
actualValueIndex = spec.parameterIndex - 1;
158+
int actualWidth = 0;
159+
int valueIndex;
160+
161+
if (spec.precisionFromArg) {
162+
// %*v*d format - second * is for width
163+
int widthArgIndex = sepArgIndex + 1;
164+
if (widthArgIndex < list.size()) {
165+
actualWidth = ((RuntimeScalar) list.elements.get(widthArgIndex)).getInt();
166+
}
167+
valueIndex = widthArgIndex + 1;
177168
} else {
178-
// Skip past the separator argument
179-
actualValueIndex = argIndex + 1;
169+
// %*vd or %*v2d format
170+
actualWidth = spec.width != null ? spec.width : 0;
171+
valueIndex = sepArgIndex + 1;
180172
}
181173

182-
if (actualValueIndex >= list.size()) {
174+
if (valueIndex >= list.size()) {
183175
return handleMissingArgument(spec, args);
184176
}
177+
value = (RuntimeScalar) list.elements.get(valueIndex);
185178

186-
// Update value to the correct argument
187-
value = (RuntimeScalar) list.elements.get(actualValueIndex);
188-
189-
// System.err.println("DEBUG: Calling formatVectorString with width=" + spec.width + ", separator='" + separator + "'");
190-
191-
// Format with custom separator - use spec.width which has the actual width
192-
return formatter.formatVectorString(value, spec.flags, spec.width != null ? spec.width : 0,
179+
return formatter.formatVectorString(value, spec.flags, actualWidth,
193180
args.precision, spec.conversionChar, separator);
181+
} else if (spec.widthFromArg) {
182+
// %v*d format - * is for width, not separator
183+
// Use default separator and get width from args
184+
return formatter.formatVectorString(value, spec.flags, args.width,
185+
args.precision, spec.conversionChar);
194186
} else {
195-
// This is %v*d format - * is width, handle normally
196-
// System.err.println("DEBUG: Processing %v*d format (width from arg)");
197-
// Fall through to normal formatting
187+
// Regular vector format
188+
return formatter.formatVectorString(value, spec.flags, args.width,
189+
args.precision, spec.conversionChar);
198190
}
199-
}
200-
201-
// Format the value using the appropriate formatter
202-
if (spec.vectorFlag) {
203-
// System.err.println("DEBUG: Processing vector format: " + spec.raw);
204-
return formatter.formatVectorString(value, spec.flags, args.width,
205-
args.precision, spec.conversionChar);
206191
} else {
192+
// Non-vector format
207193
return formatter.formatValue(value, spec.flags, args.width,
208194
args.precision, spec.conversionChar);
209195
}

0 commit comments

Comments
 (0)