Thursday, December 21, 2006

UI Python Source for ZeroBugs Opened

As the song goes, when I was younger, so much younger than today...
[...] I found my code in tons of trouble,
Friends and colleagues came to me,
Speaking words of wisdom:
"Write in C."

But that was in the 90s. Today, as somewhat hinted by one of the Mac commercials, C++ GUI Programming is boring, unproductive and uncool. Using a scripting language like Python for UI development gets the job done faster.

But C++/Python hybrid programming is fucking awesome. And hybrid is the mantra of the decade.

This is the project that I was talking about in an older post, "Protoyping with Python".
Download the code archive here.

Why did I chose Python as the scripting language for ZeroBugs? My first thought was to use a well-known, popular language, and what won me over was the boost python library, which makes integration with C++ a breeze. The documentation at boost.org is very clear and easy to follow. By contrast, SWIG is a pig.

Wednesday, November 22, 2006

Why Open Source Does Not Work (For Me)

When freedom is compulsory, can it still be called freedom?
(anonymous ftp)


While I can't help applauding some practical consequences of the Open Source movement, I find the ideology behind it rather scatological.

As it stands, there is balance in the force. But not necessarily due to the quality of say, ahem, Linux, but thanks rather to the suckiness of some of the non-Open Source players. Apple stands proof that brilliant products are indeed possible in the world of proprietary designs.

I enjoy writing software and I take pride in my work. I am most happy when my code helps people solving practical problems. But I also enjoy getting paid for my work, at the fair market rate.

Yet the collaborative model of Open Source is effective. When people work together, they tend to become a distributed system with tolerance to faults, and with opportunities for major fun. What lacks is the opportunity (for the worker bees) to make a major buck. Once the Source goes Open it somewhat starts attracting more dung flies than worker bees.

What I would love to see is a system where people have fun building a cathedral right next to the bazaar.

The two-digit IQ-ers (merchants, thieves, and bums that frequent the bazaar) have to pay to enter the cathedral, and cathedral builders share the profits (which may be monetary or otherwise, as some may chose to contribute for good karma or posthumous glory, and have their source code shine in its eternal simplicity and elegance).

How can we achieve a development model that accommodates a pragmatic mix of open and closed source, thus satisfying the individual needs of the people involved?

There are technical and non-technical options. The possible non-technical include:
  1. have all contributors adhere to a honor system (weak, because we all know how human nature works);
  2. have everybody sign NDA-s and contracts (may quickly degenerate into "my lawyers against their lawyers" situations);
  3. have someone of good morals and notorious character appointed (elected?) leader, arbiter, gatekeeper and distributor of profits, after careful weighing every body's contribution (yeah right, look at our elected leaders).
You can easily see that a technical solution that enforces and self-polices the model might be a better alternative. How about, for example, have everybody design and code to interfaces? Then, each module owner is free to open up her implementation, or to keep it proprietary. The approach only works as long each contributor owns a meaningful component of the system, that can be put behind an interface. That's really not too much to ask, and it would benefit the designs. Team members will have to think in terms of the intent behind the abstraction, rather than the actual algorithms that implement it; crossing the interface barriers for the purpose of tweaking and hacking also becomes naturally discouraged.

The major challenge for this approach of mixing and matching open and closed modules is the lack of binary standards in environments such as C++ (the Itanium ABI is still young) and Linux. This fluidity is purposely perpetrated by Linux and GCC, and even enforced by the LGPL that prevents statical linkage as a workaround for runtime "platforms" that are as stable as quicksand.

In a future installment, I will go over my attempts to create a platform that allows a mix of open source and closed IP within the same project, when I started the Zero Debugger project.


Tuesday, November 14, 2006

I have recently discovered Linux Sabayon 3.1, and so far it's the only distro that works with my new Turion x2 DV6000z laptop. I still have some difficulties with the wireless, but I am hopeful that the 3.2 release scheduled for the 27-th will fix the issues. Give it a try, it simply rocks.

Saturday, November 04, 2006

Clever Design or Fancy Hack? You Decide.

When I started designing the Zero Debugger Engine a couple of years ago, I also slapped together a Gtk-based user interface plugin. The engine has an API for extending the debugger with plugins.

The purpose of my UI plugin was to drive the design of the API that the engine should expose. It was intended to be a throw away. There wasn't much design behind the UI, I thought of it more in terms of a test bed than even a prototype.

Yet as it happens so many many times in software (and in life), at some point I got stuck with it. Once I was ok with the engine API, I should've started working on the "real" UI plugin. Clean room design, right?

In the process of developing the engine and its C++ API which I dubbed the Zero Development Kit, it became evident that for some simple customizations C++ was overkill, and a scripted language API would be easier and more intuitive for most users. With this idea in mind, and with all the lessons learned from the "mock" UI, I started drafting a design of a Python-written UI.

But because Zero is my witching hours project, and most of the time I get distracted by annoying things such as having a day job, the Python UI had not seen the light of day until the last few months (see my previous post).

Meanwhile it was essential for the debugger to have an UI, to appeal to users as an interesting proposition... So the "throw away" UI project outlived its initial scope. But there was a problem:

The C++ written UI was based on gtk-- 1.2 (the ancestor of Gtkmm, a C++ wrapper for the Gtk library). I should've started with the newer technology, Gtkmm 2.x, but I was hoping to get someone interested in a business proposition, and their company was running on RedHat 7. But I also needed to show something that worked on the more modern Linux distros.

To cut to the chase, I decided to write some adaptation layers so that my initial code would compile both on gtk-- and Gtkmm. For classes such as Gtk::CTree, that have been completely replaced with Gtk::TreeView, Gtk::TreeModel and such, I just created a minimal implementation of CTree.

But there are also classes that have retained most of their interface in between the 1.2 and 2.x versions of the Gtkmm, give or take a couple of deprecated methods and some new ones. For example: the Gtk::Notebook class has a new family of overloaded methods, append_page. Concise and self-documenting, they allow one to write code such as:

void TabLayoutStrategy::add_registers_view(Widget& w)
{
rightBook_->append_page(w, "Registers");
}

To achieve the same effect in the old code I had to say:

void TabLayoutStrategy::add_registers_view(Widget& w)
{
rightBook_->pages().add(w);
rightBook_->pages().back()->set_tab_text("Registers");
}

Very verbose, and the simple intent to append a page with a given tab label text kind of gets lost...

The new append_page method can be implemented in the terms of the older API, like this:

struct Notebook_Adapt : public Gtk::Notebook
{
void append_page(Gtk::Widget& w, const Gtk::nstring& text)
{
this->add(w);
this->pages().back()->set_tab_text(text);
}
// ...
};


Now only if I could replace Gtk::Notebook with Notebook_Adapt in the gtkmm 1.2 compilation... and here's where the hack comes in: Notebook_Adapt does not add any member data to the Gtk::Notebook, just non-virtual methods. So a Notebook_Adapt class instance could be overlayed on existing Notebook instances, hmmm.
Enter the adapting pointer:

template<typename S, typename T >
class APtr
{
S* p_;

public:
explicit APtr(S* p) : p_(p) { }

T* operator->() const
{
BOOST_STATIC_ASSERT(sizeof(S) == sizeof(T));
return static_cast(p_);
}

S& operator*() { assert(p_); return *p_; }
const S& operator*() const { assert(p_); return *p_; }

operator const void*() const { return p_; }
};


Armed with this template, and a..., yuck, yeah, some precompiler help, I can now say:

#ifdef GTKMM_2
typedef Gtk::Notebook* NotebookPtr;
#else
typedef APtr NotebookPtr;
#endif
//
// ...
//
class TabLayoutStrategy : public LayoutStrategy
{
// ...
// ...
private:
// old:
// Gtk::Notebook* rightBook_;
// replaced with:
NotebookPtr rightBook_;
};


Inside of the class above, calls to:

rightBook_->append_page(widget, labelText);

now compile (i.e. are source-level compatible) with either gtk-- 1.2 or Gtkmm 2.x

Voila.

Sunday, October 29, 2006

Prototyping with Python



This is the new look and feel of the Zero Debugger User Interface that I was talking about in my previous post. I like the idea of having more "real estate" for the source code window.

The prototype is written using Glade and Python, which allow for rapid development, taking advantage of the PythonGate plugin that exposes the Zero API to Python.

Drop me a message if you would like to try out the Python code for yourself, I'll email it to you!
I finally got around to installing the i386 version Fedora 6, and building Zero on it. In the process, I figured out that a while ago I made an incorrect assumption about the CLONE and FORK events as reported by ptrace... Consequently Zero happened to hang (depending on the kernel version) while debugging multi-threaded programs, or code that called fork(). The problem is now fixed I will be rolling it out over the next couple of days.

I have fixed one bug reported by Marco Bacchetta (a "virtual dso read" error message popped up right at the beginning of the debugging session).

Also fixed a bug in processing command line arguments, and another one dealing with anonymous structs, both reported by Massimiliano Pagani. L'Italia è campione del Mondo!

And squashed a problem with detecting signal handler trampolines, when handler was being installed by sigaction().

Saturday, July 15, 2006

After a few frantic nights of debugging the debugger, I think I have a stable version again... (there are a few minor issues still, but no show stopper that I know of). Sheesh.

As I was cleaning up some code, I came upon a few warnings, where signed values are compared against unsigned. The types are well chosen IMHO, for example in one case the unsigned is a memory address, and the signed is a relative offset (which may be negative). The assertions are more informative than anything else. The code is prepared to deal with the case when the assertion fails, I am just curious to see whether my assumption that a given condition should never happen is correct (and it's not the end of the world if it isn't). I would call this a soft assert in case the term is not coined already.

Here's the code I came up with, that silences down the compiler warnings about signed vs. unsigned, and throws an exception rather than calling abort on failure.



#include <assert.h>
#include <limits>
#include <stdexcept>
#include <boost/format.hpp>


class assert_error : public std::logic_error
{
public:
assert_error(const char* file, size_t line)
: std::logic_error((boost::format(
"Assertion failed at: %1%:%2%") % file % line).str())
{ }
};



// Assert functions that avoid the signed vs. unsigned compiler warnings.
namespace detail
{
template<typename T, typename U, int>
struct numeric_assert
{
static bool gt(T lhs, U rhs) { return(lhs > rhs); }
static bool eq(T lhs, U rhs) { return(lhs == rhs); }
};
template<typename T, typename U>
struct numeric_assert<T, U, 1>
{
static bool gt(T lhs, U rhs)
{ return((lhs >= 0) && (static_cast<U>(lhs) > rhs)); }

static bool eq(T lhs, U rhs)
{ return((rhs >= 0) && (rhs == static_cast<U>(lhs))); }
};
template<typename T, typename U>
struct numeric_assert<T, U, -1>
{
static bool gt(T lhs, U rhs)
{ return((rhs < 0) || (lhs > static_cast<T>(rhs))); }

static bool eq(T lhs, U rhs)
{ return((rhs >= 0) && (lhs == static_cast<T>(rhs))); }
};
}
template<typename T, typename U>
void __assert_gt(T lhs, U rhs, const char* file, size_t line)
{
typedef detail::numeric_assert<T, U,
std::numeric_limits<T>::is_signed -
std::numeric_limits<U>::is_signed> Assert;
if (!Assert::gt(lhs, rhs))
{
throw assert_error(file, line);
}
}


template<typename T, typename U>
void __assert_eq(T lhs, U rhs, const char* file, size_t line)
{
typedef detail::numeric_assert<T, U,
std::numeric_limits<T>::is_signed -
std::numeric_limits<U>::is_signed> Assert;
if (!Assert::eq(lhs, rhs))
{
throw assert_error(file, line);
}
}
#define assert_gt(x,y) __assert_gt((x), (y), __FILE__, __LINE__)
#define assert_eq(x,y) __assert_eq((x), (y), __FILE__, __LINE__)




Oh, and the sed command I was talking about the other day is:

sed -e 's/</\&lt;/g; s/>/\&gt;/g'


Specializing the templates for double and float is left as an exercise for the reader.

Monday, July 10, 2006

Oops. Found quite a few issues with the Zero UI. The builds that I posted on my site on July 8th have a few known issues. Nobody has complained yet, though.

Anyway, here's a piece of code that I wrote in the process of fixing things.


/**
* Pick the first available monospace font in a widget's
* Pango context
*/
bool
get_monospace_font(Pango::FontDescription& font, Gtk::Widget& w)
{
bool success = false;

if (Glib::RefPtr<Pango::Context> ctxt = w.get_pango_context())
{
Glib::ArrayHandle<Glib::RefPtr<Pango::FontFamily> > ff =
ctxt->list_families();

Glib::ArrayHandle<Glib::RefPtr<
Pango::FontFamily> >::const_iterator
i = ff.begin(), end = ff.end();

for (; i != end; ++i)
{
if ((*i)->is_monospace())
{
font = Pango::FontDescription((*i)->get_name());

w.ensure_style();
if (Glib::RefPtr <Gtk::Style> style = w.get_style())
{
font.merge(style->get_font(), false);
}
if (Glib::RefPtr<Pango::Font> f = ctxt->load_font(font))
{
font = f->describe();
}
success = true;
break;
}
}
}
return success;
}



Note to self: write a sed script for "fixing" templates and pointers in code snippets posted on this blog.

Second note to self: make a custom T-shirt on Zazzle, printed with said sed script.

Friday, July 07, 2006

ZeroBugs' New Look


I am experimenting with the UI for the Zero debugger (www.zero-bugs.com) The new look and feel allows for several source files / disassembly views. This should alleviate the screen flickering that I have previously experienced with the gtksourceviewmm widget.

Monday, June 26, 2006

My debugger for C++/Linux finally went live this past weekend, at www.zero-bugs.com. Next, I will be testing it with the SUSE and Ubuntu distros.

The FreeBSD port requires quite a bit of work, because of the way multithreading is implemented in their kernel. I have stubbed out the support for FreeBSD in my debugger engine back in November, but the main focus has been Linux, and there is only one of me...

Also, following the development GNU C++ compiler and testing with the recent releases takes time, even with a suite of automated testing. Hopefully, now that I have an alpha release out, I will be getting feedback that will drive my testing / bug-fixing process; of course, "zero-bugs" is a dream :)

Last edit: Mon, Feb 19 2007
Wow! Time really flies like an arrow (and fruit flies like a peach).

Since the ZeroBugs debugger was first published on the internet, I have added crucial features such as Python scripting, tabbed code views, customizable hot keys, and have fixed ... er... more than zero bugs; went thru several Linux distros, and met some interesting people in the process.
Time goes by so fast when one is busy!

Saturday, May 13, 2006


Three weekends ago my friend Andrei Alexandrescu got married. The reason I am only writing about it now is that it took me so much to recover. That's how wild the party was.
The whimpy advocates of extreme programming have no idea what an extreme party the good ole C++ school can throw.

I can hardly wait to attend his speach on the 17th, at the Northwest C++ Users Group (see http://www.nwcpp.org/). I just want to see how married life changed him (for the better).

At his reception we met Eric Niebler, a badass contributor to BOOST (http://www.boost.org/) which whom we shared a table. I am not sure I want to sit next to him ever again. He is so intimidatingly smart that in order to not lose face I had to mention that my wife went to Princeton.

Anyway, we decided after a few beers that C# is to C++ what hip-hop is to jazz, and those punks that rap to .NET beats airwaved out of Redmond have no class whatsoever. We will invent a secret handshake to recognize eachother, and plan for keeping legacy C++ code in place, to preserve job security and world domination. Well, I resisted learning Java so far, and I'll see how well I do without cluttering my mind with C#. I think anyone who has not programmed in any other language but C# is a f***** moron ('member how back in the hayday we had an inflation of "HTML programmers"?)

I have been developping a debugger for C++ on Linux for the last three years or so, and it is close to being released now (see http://zero-bugs.com/). I am doing a lot of testing (and some tune-ups for the x86_64) it should be ready for download as soon as I get the license terms ok-ed by the lawyers...

So stay tuned and watch for the secret handshake.
And wait, I need to ask my wife to help me spell-check this post...

Saturday, January 07, 2006

As the title of this blog may suggest, one of my favorite pastimes is to sit around the house in my boxers and program my computers.

The next best is to surf the internet on the jøn (I have a wireless linux laptøp); but today I went for a change and took a magazine to the bathroom (to read). The said magazine is no other but the recently defunct C/C++ Users Journal.

I went (as usual) straight to my friend's Andrei Alexandrescu column, Generic<Programming>. Almost a page and a half into the article, I was relieved. Andrei is human, after all; he writes funny stuff every once in a while. Although I wonder if his great humor is always intentional. Let's take this paragraph, for example:

[...]the output pattern on an already-trained net involves quite expensive matrix multiplications and nonlinear math functions (such as exponentials) that aren't cheap.
Now let's assume that we have a problem in which input patterns tend to be quite repetitive[...]


This reading is almost as entertaining as this description of the Metacity window manager that I found online:

Metacity is a lightweight window manager written by Havoc Pennington from Red Hat. The first version was 2.3, which was released in 2001 .


Some people start counting with 0, some start at 1, some simply go with 2.3 That's okay, but remember:
the Lord spake, saying, 'First shalt thou take out the Holy Pin. Then, shalt thou count to three. No more. No less. Three shalt be the number thou shalt count, and the number of the counting shall be three.

The Holidays are over, Happy New Year and let's get back to werk :)

This week I have decided to give a make-over to my ancient Dell Inspiron 8000. I upgraded from RedHat 7.2 (yes, I know, I know...) to Fedora Core 4, and bought a Linksys WPC 54G v3 wireless card.

After downloading and installing ndiswrapper 1.7, I proceeded to configure the wireless connection.

The Windows NT driver that came with the card was installed properly by ndiswrapper, and the "iwlist scan" command promptly discovered my home network; then I tried using iwconfig to set the ESSID.

And I got into a problem here: iwconfig would report success, yet the SSID remained unchanged (off/any), and the address of the access point was all zeroed.

I tried setting the address point address by hand, no dice.

I googled the matter until 3 AM, when I decided to write my own C program for resetting the network ID on the card.

And, guess what? After running the code, the card auto-magically connected to my access point!
I have not tried using encryption yet. Our house is far enough from the street, and the closest neighbor is out of range for the Apple AirPort that we use... so no need to be paranoid.

Anyway, here's the program that made it all work:


/* -*- tab-width: 4; indent-tabs-mode: nil; -*-
vim: tabstop=4:softtabstop=4:expandtab:shiftwidth=4
*/
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <wireless.h>


static const char* default_dev[] = { "wlan0", NULL };


int main(int argc, const char* argv[])
{
int result = 0;
const char* device = NULL;

int s = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
if (s == -1)
{
fprintf(stderr, "socket: %s\n", strerror(errno));
result = -1;
}
else
{
struct iwreq req;

/* Reset the SSID for all devices given
as command line arguments; if no device
specified, reset the default device
*/
if (!(++argv, --argc))
{
argc = 1, argv = default_dev;
}

for (; argc; --argc, ++argv)
{
device = *argv;

/* init request structure */
memset(&req, 0, sizeof req);
strncpy(req.ifr_ifrn.ifrn_name,
device, sizeof req.ifr_ifrn.ifrn_name);

memset(&req.u.essid, 0, sizeof req.u.essid);

if (ioctl(s, SIOCSIWESSID, &req) < 0)
{
fprintf(stderr,
"ioctl: %s: %s\n", device, strerror(errno));

result = -2;
}
}

close(s);
}
return result;
}

After compiling it with the command
gcc -static essid.c -o /sbin/essid-reset ,
I have added to my system the following scripts:

/etc/sysconfig/network-scripts/ifcfg-wlan0

DEVICE=wlan0
BOOTPROTO=dhcp
ONBOOT=yes
TYPE=Ethernet

USERCTL=no
PEERDNS=yes
IPV6INIT=no


and:
/etc/init.d/wlan

#!/bin/sh

case "$action" in
start)
/sbin/essid-reset;;
stop)
ifdown wlan0;
rmmod ndiswrapper;;
esac