rtoy / maxima

A Clone of Maxima's repo
Other
0 stars 0 forks source link

printf fails to output initial percent sign when tilde-m present #3653

Open rtoy opened 2 months ago

rtoy commented 2 months ago

Imported from SourceForge on 2024-07-08 11:05:12 Created by robert_dodier on 2024-05-08 23:54:08 Original: https://sourceforge.net/p/maxima/bugs/4302


When percent sign is the first character in the control string, and the control string contains tilde-m (Maxima pretty-printer formatting), printf fails to output the initial percent sign.

(%i1) printf (true, "% x = ~d~%", 123);     
% x = 123
(%o1)                                                                                                                       false
(%i2) printf (true, "% x = ~m~%", 123);     
 x = 123

Percent sign in other locations in the control string are output as expected.

There's some special case handling of percent in AFORMAT; tracing AFORMAT seems to show that the bug is actually in AFORMAT. However, grepping src/*.lisp seems to show that printf is the only way this bug is exposed to the user; the other uses of AFORMAT (there's just a few) don't have the potential to expose the bug, from what I can tell.

rtoy commented 2 months ago

Imported from SourceForge on 2024-07-08 11:05:13 Created by rtoy on 2024-05-19 00:46:06 Original: https://sourceforge.net/p/maxima/bugs/4302/#5dcc


It has something to do with dimension. I traced some functions when doing printf (true, "% x = ~m~%", 123); and this is what I see:

              6: (DIMENSION ((TEXT-STRING) #\% #\  #\x #\  #\= #\ )
                            NIL
                            MPAREN
                            MTEXT
                            0
                            0)
                7: (NFORMAT-CHECK ((TEXT-STRING) #\% #\  #\x #\  #\= #\ ))
                7: NFORMAT-CHECK returned
                     ((TEXT-STRING) #\% #\  #\x #\  #\= #\ )
                7: (DIMENSION-ATOM #:|% X = | NIL)
                7: DIMENSION-ATOM returned (#\  #\= #\  #\x #\ )

dimension calls nformat-check and uses the value from nformat-check for more processing. We see that nformat-check returns a string with "%". Then dimension calls dimension-atom via the (defun-prop (text-string dimension) in mformt.lisp. This seems to convert the string "# x =" to an uninterned symbol #:|% X = |. Not sure what happens after that.

More debugging needed.

rtoy commented 2 months ago

Imported from SourceForge on 2024-07-08 11:05:17 Created by rtoy on 2024-05-20 03:46:55 Original: https://sourceforge.net/p/maxima/bugs/4302/#5dcc/af64


Ok. It's caused by makestring. In particular, this bit of code at the end:

      (t (setq dummy (exploden atom))
         (cond
           ((null dummy) nil)
           ((char= #\$ (car dummy)) (cdr dummy))
           ((char= #\% (car dummy)) (cdr dummy)) ;;;*** HERE ***
           ($lispdisp (cons #\? dummy))
           (t dummy))))))

In this case, dummy is the list(#\% #\ #\x #\ #\= #\ ). Since (car dummy) is #\%, we return the rest of dummy, dropping the % character.

More investigation needed to see how this case differs from the other printf calls where % is printed.

git blame says that that line was last changed in commit [9780c82cec], but the it was still mostly there except a & was also dropped just like %.

rtoy commented 2 months ago

Imported from SourceForge on 2024-07-08 11:05:20 Created by robert_dodier on 2024-05-20 04:24:57 Original: https://sourceforge.net/p/maxima/bugs/4302/#4e53


Well, it's unnecessary for string output to get routed through this stuff constructing an uninterned symbol -- I guess that's probably a vestige left over from when Maxima strings were implemented as Lisp symbols. I don't know how to adjust the trip through DIMENSION-ATOM but anyway it seems like if the argument is a string, it should just be output as such. I don't know without looking which function has coerced the string to a list of characters, but anyway that seems unnecessary.

The bit in MAKESTRING about stripping off percent is for displaying nouns, I'm pretty sure.