@@ -193,28 +193,58 @@ FormatSpecifier parseSpecifier() {
193193 spec .widthFromArg = true ; // Means "has custom separator"
194194 advance (); // consume 'v'
195195
196+ System .err .println ("DEBUG Parser: Parsed %*v, next char: '" + current () + "'" );
197+
196198 // Now check for width after %*v
197199 if (match ('*' )) {
200+ System .err .println ("DEBUG Parser: Found * after %*v" );
198201 // Check for invalid positional after %*v*
199202 checkpoint = pos ;
200203 Integer posParam = parseNumber ();
201- if (posParam != null && peek (0 ) == '$' ) {
204+ System .err .println ("DEBUG Parser: After %*v*, number=" + posParam + ", current='" + current () + "'" );
205+
206+ if (posParam != null && match ('$' )) {
207+ System .err .println ("DEBUG Parser: Detected invalid %*v*N$ pattern" );
202208 // %*v*999$ is invalid
203- advance (); // consume $
204- while (!isAtEnd () && !Character .isLetter (current ())) {
205- advance ();
206- }
209+
210+ // Continue parsing to get the conversion character
207211 if (!isAtEnd ()) {
208212 spec .conversionChar = current ();
209213 advance ();
210214 }
215+
216+ spec .isValid = false ;
217+ spec .errorMessage = "INVALID" ;
218+ spec .endPos = pos ;
219+ spec .raw = input .substring (spec .startPos , spec .endPos );
220+ System .err .println ("DEBUG Parser: Returning invalid spec: " + spec .raw );
221+ return spec ;
222+ } else if (posParam != null ) {
223+ // ADDITIONAL CHANGE: Handle case where we have number but no $
224+ // This is still invalid - don't reset position
225+ System .err .println ("DEBUG Parser: Found number after %*v* but no $ - treating as invalid" );
226+
227+ // The number is part of the format, continue to find conversion char
228+ // Current position is after the number
229+ if (!isAtEnd ()) {
230+ // Skip any backslashes or other characters until we find a letter
231+ while (!isAtEnd () && !Character .isLetter (current ())) {
232+ advance ();
233+ }
234+ if (!isAtEnd ()) {
235+ spec .conversionChar = current ();
236+ advance ();
237+ }
238+ }
239+
211240 spec .isValid = false ;
212241 spec .errorMessage = "INVALID" ;
213242 spec .endPos = pos ;
214243 spec .raw = input .substring (spec .startPos , spec .endPos );
244+ System .err .println ("DEBUG Parser: Returning invalid spec: " + spec .raw );
215245 return spec ;
216246 } else {
217- pos = checkpoint ; // Reset
247+ pos = checkpoint ; // Reset only if no number was found
218248 spec .precisionFromArg = true ; // HACK: means second *
219249 }
220250 } else {
@@ -311,14 +341,44 @@ FormatSpecifier parseSpecifier() {
311341 }
312342 }
313343
314- // 7. Parse conversion character
344+ // 7. Parse conversion character
315345 if (isAtEnd ()) {
316346 spec .isValid = false ;
317347 spec .errorMessage = "MISSING" ;
318348 } else {
319- spec . conversionChar = current ();
349+ char firstChar = current ();
320350 advance ();
321- // System.err.println("DEBUG: Parsed conversion char '" + spec.conversionChar + "'");
351+
352+ // Check if this might be part of a positional parameter
353+ if (Character .isDigit (firstChar ) && !isAtEnd ()) {
354+ // Look ahead to see if we have more digits and a $
355+ int checkPos = pos ;
356+ while (!isAtEnd () && Character .isDigit (current ())) {
357+ advance ();
358+ }
359+
360+ if (!isAtEnd () && current () == '$' ) {
361+ // This is an invalid positional parameter at the conversion position
362+ advance (); // consume $
363+
364+ // Get the actual conversion character
365+ if (!isAtEnd ()) {
366+ spec .conversionChar = current ();
367+ advance ();
368+ } else {
369+ spec .conversionChar = firstChar ; // Use the first digit if nothing follows
370+ }
371+
372+ spec .isValid = false ;
373+ spec .errorMessage = "INVALID" ;
374+ } else {
375+ // Not a positional parameter, just use the first character
376+ pos = checkPos ; // Reset to after first char
377+ spec .conversionChar = firstChar ;
378+ }
379+ } else {
380+ spec .conversionChar = firstChar ;
381+ }
322382 }
323383
324384 spec .endPos = pos ;
@@ -500,4 +560,4 @@ void validateFlags(FormatSpecifier spec) {
500560 }
501561 }
502562 }
503- }
563+ }
0 commit comments