An attempt to resuscitate cbrowser 0.8

I’ve had a number of issues with cbrowser, the graphical frontend for cscope. It doesn’t work on my system running Ubuntu 10.04 where tcl version 8.4.19 is installed (info patchlevel in tcl shell); don’t know if there’s a separate version for the tk component. Two glaring problems were encountered when attempting to examine the database generated from gnucash source code:

  1. Call tree functionality is broken
  2. Syntax highlighting caused the program (wish process) to consume 100% CPU time on a certain source file (specifically “gnucash-bin.c”)

The latest version of cbrowser that I was able to retrieve from a repository (don’t recall which) was labelled cbrowser_0.8-6_all, marked unstable. Diffing the version obtained from sourceforge, comparing two critical files, with the 0.8-6 version did not reveal any significant change in the code, at least I was not able to spot any changes. But the really bad news was that cbrowser is written in tcl, a language I had never heard of till last week. Before giving up, I decided to take a crack at it anyway, being a stubborn git and all. Learn just enough tcl and then hack away. With a huge amount of luck, I think I managed to recover some functionality but wonder how much of cbrowser is broken.

First, I went through the first ten odd items in the tcl tutorial [1] to get a feel for the language. The most important thing I learnt there was the “puts” command which I used extensively to trace execution path and print variables. The implementation of cbrowser uses tk and a library called megawidgets; my complete ignorance in the windowing kit made the task more difficult. Instead of attempting to educate myself on a GUI kit which I had no desire to learn, I decided to ignore it all … basically I just wanted to know where this thing “hanged”. If it got too complicated, I would have simply surrendered.

Fortunately, I got lucky.  Invoking the calltree facility from cbrowser generated the following error:

megawidget initialization error  :
expected integer but got "--1"
while executing ...

I suppose a tcl practitioner may find the error obvious, to me the error message gave no hint at the underlying mistake. Dozens of puts later, the culprit was traced to two statements in the Recompute function of the hierarchy widget (line 819 in hierarchy.tcl) :

incr txt_width -$x; incr txt_height -$y

In the version of tcl that I had this is not allowed — -$x evaluates to the string “–1” instead of an integer (1) which the incr command expects (the error message can be reproduced in tclsh). Trivial to the tcl-er perhaps, big news to me! With my limited tcl knowledge, I hacked the line into :

incr txt_width [expr - $x]; incr txt_height [expr - $y]

and calltree facility came back to life! (There is a similar statement on line 806.)

The syntax highlighting problem proved more challenging as I actually had to understand what the code was doing. I believe the problem is caused by an error in the comment_highlight function that is manifested in the execution of quote_highlight which is responsible for highlighting double-quoted phrases; both in ftcllib.tcl. The while loop in quote_highlight becomes eternal causing the CPU to hang. Examining the processing of the source gnucash-bin.c by printing variable values and understanding what they mean, the loop collapses upon encountering this string (line 87):

"You can also lookup and file bug reports at\n"

The quote_highlight relies on correct “markers” for the location of commented regions. These markers are generated from comment_highlight by searching for regular expression patterns using the search command of the text widget [2]. Now I may be wrong but I think the algorithm in comment_highlight is missing something because it’s unable to anticipate “//” within quoted strings; it thinks that “//” marks the start of a cpp comment. As a result the list of markers becomes corrupted.

Since I did not want to mess with the algorithm, I inserted the following grotesque hack into quote_highlight :

set sentinel 0
while {[set temp [$widget search -regexp -- $pattern $start $stop]] != ""} {
set sentinel [expr {$sentinel+1}]
if {$sentinel==1000} {break}

Luckily, it appeared that the function was able to continue correctly even though the marker was bad; the offending line is not highlighted. Warning: I don’t know how well these hacks will stand upon further testing.


Explore posts in the same categories: hacking

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: