Skip to content

Commit ad547d8

Browse files
committed
fix sprintf WIP
1 parent 36d5713 commit ad547d8

File tree

2 files changed

+41
-22
lines changed

2 files changed

+41
-22
lines changed

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

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,11 @@ FormatSpecifier parseSpecifier() {
146146
int savePos = pos;
147147
boolean hasInvalidSpace = false;
148148

149+
// Check for vector flag 'v' here (after width, before precision)
150+
if (match('v')) {
151+
spec.vectorFlag = true;
152+
}
153+
149154
// 3. Parse width
150155
if (match('*')) {
151156
spec.widthFromArg = true;
@@ -226,17 +231,6 @@ FormatSpecifier parseSpecifier() {
226231
}
227232
}
228233

229-
// 6. Parse vector flag
230-
if (match('v')) {
231-
spec.vectorFlag = true;
232-
233-
// For vector formats, we need to handle the complex syntax
234-
// Skip any combination of spaces, dots, digits, and * until we find a letter
235-
while (!isAtEnd() && !Character.isLetter(current())) {
236-
advance();
237-
}
238-
}
239-
240234
// 7. Parse conversion character
241235
if (isAtEnd()) {
242236
spec.isValid = false;

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

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public static RuntimeScalar sprintf(RuntimeScalar runtimeScalar, RuntimeList lis
2727
result.append((String) element);
2828
} else if (element instanceof SprintfFormatParser.FormatSpecifier spec) {
2929

30-
// System.err.println("DEBUG Operator: spec.raw=" + spec.raw + ", isValid=" + spec.isValid + ", errorMessage=" + spec.errorMessage);
30+
// // System.err.println("DEBUG Operator: spec.raw=" + spec.raw + ", isValid=" + spec.isValid + ", errorMessage=" + spec.errorMessage);
3131

3232
// Handle %%
3333
if (spec.conversionChar == '%') {
@@ -84,7 +84,7 @@ public static RuntimeScalar sprintf(RuntimeScalar runtimeScalar, RuntimeList lis
8484
WarnDie.warn(new RuntimeScalar(spec.invalidLengthModifierWarning), new RuntimeScalar(""));
8585
}
8686

87-
// System.err.println("DEBUG: Processing valid spec: " + spec.raw);
87+
// // System.err.println("DEBUG: Processing valid spec: " + spec.raw);
8888

8989
// The rest of the valid format processing continues here...
9090
int savedArgIndex = argIndex;
@@ -146,6 +146,7 @@ public static RuntimeScalar sprintf(RuntimeScalar runtimeScalar, RuntimeList lis
146146
} else {
147147
valueArgIndex = argIndex++;
148148
}
149+
// System.err.println("DEBUG sprintf: before MISSING check - valueArgIndex=" + valueArgIndex + ", list.size=" + list.size() + ", vectorFlag=" + spec.vectorFlag);
149150
if (valueArgIndex >= list.size()) {
150151
if (spec.conversionChar == 'n') {
151152
// %n is a no-op for now - just continue without throwing
@@ -185,8 +186,17 @@ public static RuntimeScalar sprintf(RuntimeScalar runtimeScalar, RuntimeList lis
185186
// Format the value
186187
String formatted;
187188
if (spec.vectorFlag) {
189+
// System.err.println("DEBUG sprintf: vector format, valueArgIndex=" + valueArgIndex + ", list.size=" + list.size());
190+
// System.err.println("DEBUG sprintf: value type=" + value.type + ", value=" + value + ", toString()=" + value.toString());
191+
192+
// Check if it's a VSTRING
193+
if (value.type == RuntimeScalarType.VSTRING) {
194+
// System.err.println("DEBUG sprintf: This is a VSTRING!");
195+
}
196+
188197
formatted = formatVectorString(value, spec.flags, width,
189198
precision, spec.conversionChar);
199+
// System.err.println("DEBUG sprintf: formatVectorString returned: '" + formatted + "'");
190200
} else {
191201
formatted = formatValue(value, spec.flags, width,
192202
precision, spec.conversionChar);
@@ -208,12 +218,20 @@ private static boolean isInvalidSpecifier(char c) {
208218
// List of invalid specifiers that should return "INVALID"
209219
return "CHIKMVWYJLNPQRSTZ".indexOf(c) >= 0;
210220
}
211-
212221
private static String formatVectorString(RuntimeScalar value, String flags, int width,
213222
int precision, char conversionChar) {
214-
// Check if this is a version object
223+
try {
224+
// System.err.println("DEBUG formatVectorString: Start - type=" + value.type + ", precision=" + precision);
225+
215226
String str;
216-
if (value.isBlessed() && NameNormalizer.getBlessStr(value.blessId).equals("version")) {
227+
boolean isVersionObject = false;
228+
229+
// Check for VSTRING type first
230+
if (value.type == RuntimeScalarType.VSTRING) {
231+
// VSTRINGs should be handled as byte sequences
232+
str = value.toString();
233+
// Don't treat it as a version object
234+
} else if (value.isBlessed() && NameNormalizer.getBlessStr(value.blessId).equals("version")) {
217235
// Extract the version string from the version object
218236
RuntimeHash versionObj = value.hashDeref();
219237
str = versionObj.get("version").toString();
@@ -263,7 +281,11 @@ private static String formatVectorString(RuntimeScalar value, String flags, int
263281
}
264282

265283
int byteValue = bytes[i] & 0xFF;
284+
// System.err.println("DEBUG formatVectorString: Processing byte[" + i + "]=" + byteValue);
285+
266286
String formatted = formatVectorValue(byteValue, flags, precision, conversionChar);
287+
// System.err.println("DEBUG formatVectorString: Formatted to: " + formatted);
288+
267289
result.append(formatted);
268290
}
269291

@@ -279,7 +301,12 @@ private static String formatVectorString(RuntimeScalar value, String flags, int
279301
}
280302

281303
return formatted;
304+
} catch (Exception e) {
305+
// System.err.println("ERROR in formatVectorString: " + e);
306+
e.printStackTrace();
307+
throw e;
282308
}
309+
}
283310

284311
private static boolean isVersionObject(RuntimeScalar value) {
285312
// Check if this is a version object by looking at its string representation
@@ -362,6 +389,7 @@ private static String formatVectorValue(int byteValue, String flags, int precisi
362389
formatted = String.valueOf(byteValue);
363390
}
364391

392+
// System.err.println("DEBUG sprintf: calling formatVectorString with precision=" + precision);
365393
// Apply precision padding
366394
if (precision > 0) {
367395
String prefix = "";
@@ -381,12 +409,9 @@ private static String formatVectorValue(int byteValue, String flags, int precisi
381409
}
382410

383411
// Pad the numeric part
384-
if (number.length() < precision - (flags.contains("#") && (conversionChar == 'o' || conversionChar == 'x' || conversionChar == 'X' || conversionChar == 'b' || conversionChar == 'B') && byteValue != 0 ? prefix.length() : 0)) {
385-
int padWidth = precision;
386-
if (flags.contains("#") && byteValue != 0 && (conversionChar == 'o' || conversionChar == 'x' || conversionChar == 'X' || conversionChar == 'b' || conversionChar == 'B')) {
387-
padWidth = precision; // Don't subtract prefix for padding calculation
388-
}
389-
number = String.format("%0" + padWidth + "s", number);
412+
if (number.length() < precision) {
413+
int padWidth = precision - number.length();
414+
number = "0".repeat(padWidth) + number;
390415
}
391416

392417
formatted = prefix + number;

0 commit comments

Comments
 (0)