2009.08.11
Applied Code Reading: GNU Plotutils
Robert, a UMLGraph user sent me an email describing a problem with the GNU plotutils SVG output on Firefox. I firmly believe that code reading is a lot easier than many think: one can easily fix most software problems without detailed knowledge of the underlying system. I therefore decided to practice what I preach.
Robert wrote.
"I've been playing with sequence diagrams and outputting to SVG format and noticed that the resulting SVG XML file isn't playing nicely with Firefox. After some experimenting and googling I found it is because the "stroke-dasharray='...'" entry intags is missing commas between array items. According to misc forum posts it seems that the spec requires commas, and Firefox is pedantic about this. Diagrams look fine aside from all lines being solid.
E.g.:should have been<line ... stroke-dasharray="0.05 0.05"/>I tried mangling the "dashwid" variable of my sequence diagram to include a comma (e.g. "dashwid = '0.05,';) but couldn't avoid upsetting pic2plot's parser.<line ... stroke-dasharray="0.05, 0.05"/>
So I'm not sure where the problem lies - is it sequence.pic? pic2plot? libplot?"
I found and fixed the problem through the following steps.
- Download the source code and unpack it.
- Search for the offending code.
For this I used grep and a short part of the erroneous
XML string to search through all the distribution's files with
the find and xargs idiom.
The results included three files:
find . -type f | xargs grep 'stroke-dashar'
./libplot/s_closepl.c
,./libplot/s_path.c
, and./test/plot2svg.xout
. Common sense indicates that the problem is ins_path.c
. Note that I didn't spend any time browsing the distribution's other 559 files (337,753 lines). -
Edit the file and search for the specific pattern.
Again, I didn't spend time browsing around the file's 560 lines, but
concentrated on the offending code.
From the above code it's easy to see that the second sprintf in the loop is responsible for printing the list. Adding a comma in the space separator string fixes the problem.
sprintf (page->point, "stroke-dasharray=\""); _update_buffer (page); for (i = 0; i < num_dashes; i++) { sprintf (page->point, "%.5g%s", dashbuf[i], i < num_dashes - 1 ? " " : "\""); _update_buffer (page); }
sprintf (page->point, "%.5g%s", dashbuf[i], i < num_dashes - 1 ? ", " : "\"");