Wednesday, 30 June 2010

Programmers are suckers for a meme

Many Open Source projects have and IRC # for developers. The NetSurf project is no different. During a discussion someone jokingly suggested that one contributor should be asked to take the FizzBuzz test. Can you guess what happened next?

Ten minutes later Michael Drake posted this solid example in C which is where it all ought to have ended.


Being programmers, of course this had a predictable result. The original question, the reason for asking it and any the serious point being made in the original article were discarded. Just so everyone (including myself) could play silly buggers over our lunch break. Coders, it would seem, simply like to produce a solution even if it is only for fun.

None of these programs took more than ten minutes (except the JAVA monstrosity), are reproduced with permission and I am to blame for none of them (ok maybe just the one ;-).

First up was Rob Kendrick with the classic solution in C (his day job is as a support team lead which seems to make those programmers who cannot do this seem even more scary bad.)


Next was Daniel Silverstone who turned this Lua solution out very quickly and berated the rest of us for not following the rules ;-)


The final C solution was my own uber silly sieve implementation


Peter Howkins decided the world required a solution in PHP


When pointed out that his solution stopped at 50 he presented this vastly superior and obviously idiomatic solution


Finally after a long time James Shaw caused mental anguish and wailing with this abomination unto Nuggin.


With Luck everyone has now got it out of their system and we will never have to put up with this again (yeah right). And now you also know why Open Source projects sometimes take ages to release ;-)

Thursday, 27 May 2010

Ex Phone

I went to the Linux Plumbers Conference (LPC) last year (which was very interesting and productive). While I was there Qualcomm were in attendance giving out penguin mints and running a competition. The lucky winners of this draw were to receive an ADP1 Android phone. So I dutifully filled in the entry form, handed it in and thought no more about it.

In the break after attending a particularly interesting workshop on the last day of the conference several other people congratulated me on winning the Qualcomm draw, this was the first I knew about it! I went in search of the nice people from Qualcomm and sure enough they handed over an ADP1 after getting a couple of photos.

Once I returned home I switched to using ADP1 as my phone and started experimenting with Android kernel stuff. Then one day the Wi-Fi stopped working which while odd could be overcome by repeatedly unloading and reloading the driver until it worked once more. Then one day the USB stopped working, no more ADB, no more console, no more debugging, no more hacking.

Then one day it turned itself off and never came back. I have been forced to return to using a hand me down, very kindly given to me by Daniel Silverstone. Alas it is not a smart phone of any kind and my finances do not allow for me to spend the money to replace it.

I have repeatedly tried to contact Qualcomm open source to see if there is any kind of warranty I might be able to use to get the phone repaired alas all the contact addresses I have are now simply returning SMTP errors.

So this is pretty much a tale without a happy ending, unless anyone out there knows the right people to contact? Perhaps someone at Google maybe? I only revisit the subject at all because of the recent announcement of an Android 2.1 based edition for these devices which reminded me I like to play with these things.

Sunday, 25 April 2010

XCB programming is hard

I have been looking at writing a program with XCB today. I seem to pick projects that are an exercise in undocumented frustration.

All I wanted to do was have an x window open and be able to plot an arbitrary changeable image to it (no I am not writing yet another image viewer!). The XCB documentation seems to be a cross between "good luck with that" and some rather erratic doxygen output.

The utility libraries are rather skimpy on examples and its tiresome worrying that when you feed any of the xcb function names into Google (web or codesearch) there are very, very few hits beyond the freedesktop API docs.

My favourite has to be the xcb_image_create documentation, go on I challenge anyone to follow that logic without going and reading the sources! The answer (afaict) is that if you pass a pointer in base that pointer will be freed by xcb_image_destroy otherwise the data pointer will be used, unless the bytes value is too small in which case memory will be allocated with malloc and the passed pointer ignored.
Anyhow, I have succeeded and the result is below, mainly so I do not loose it :-)

/* XCB application drawing an updating bitmap in a window
*
* Inspired by the xcb black rectangle in a window example
*
* Copyright 2010 V. R. Sanders, released under the MIT licence
*/

/* compile with:
* gcc -Wall -lxcb-icccm -lxcb -lxcb-image -o disp disp.c
*/

#include <string.h>

#include <xcb/xcb.h>
#include <xcb/xcb_image.h>
#include <xcb/xcb_atom.h>
#include <xcb/xcb_icccm.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>

static xcb_format_t *
find_format (xcb_connection_t * c, uint8_t depth, uint8_t bpp)
{
const xcb_setup_t *setup = xcb_get_setup(c);
xcb_format_t *fmt = xcb_setup_pixmap_formats(setup);
xcb_format_t *fmtend = fmt + xcb_setup_pixmap_formats_length(setup);
for(; fmt != fmtend; ++fmt)
if((fmt->depth == depth) && (fmt->bits_per_pixel == bpp)) {
/* printf("fmt %p has pad %d depth %d, bpp %d\n",
fmt,fmt->scanline_pad, depth,bpp); */
return fmt;
}
return 0;
}

void
fillimage(unsigned char *p, int width, int height)
{
int i, j;
for(i=0; i < width; i++)
{
for(j=0; j < height; j++)
{
if((i < 256)&&(j < 256))
{
*p++=rand()%256; // blue
*p++=rand()%256; // green
*p++=rand()%256; // red
} else {
*p++=i%256; // blue
*p++=j%256; // green
if(i < 256)
*p++=i%256; // red
else if(j < 256)
*p++=j%256; // red
else
*p++=(256-j)%256; // red
}
p++; /* unused byte */
}
}
}

xcb_image_t *
CreateTrueColorImage(xcb_connection_t *c,
int width,
int height)
{
const xcb_setup_t *setup = xcb_get_setup(c);
unsigned char *image32=(unsigned char *)malloc(width*height*4);
xcb_format_t *fmt = find_format(c, 24, 32);
if (fmt == NULL)
return NULL;

fillimage(image32, width, height);

return xcb_image_create(width,
height,
XCB_IMAGE_FORMAT_Z_PIXMAP,
fmt->scanline_pad,
fmt->depth,
fmt->bits_per_pixel,
0,
setup->image_byte_order,
XCB_IMAGE_ORDER_LSB_FIRST,
image32,
width*height*4,
image32);
}

int
main (int argc, char **argv)
{
xcb_connection_t *c;
xcb_screen_t *s;
xcb_window_t w;
xcb_pixmap_t pmap;
xcb_gcontext_t gc;
xcb_generic_event_t *e;
uint32_t mask;
uint32_t values[2];
int done=0;
xcb_image_t *image;
uint8_t *image32;
xcb_expose_event_t *ee;
char *title="Hello World!";
xcb_size_hints_t *hints;

/* open connection with the server */
c = xcb_connect (NULL, NULL);

if (!c) {
printf ("Cannot open display\n");
exit (1);
}

s = xcb_setup_roots_iterator (xcb_get_setup (c)).data;

/* printf("root depth %d\n",s->root_depth); */

/* create image */
image = CreateTrueColorImage(c, 640, 480);
if (image == NULL) {
printf ("Cannot create iamge\n");
xcb_disconnect(c);
return 1;
}
image32 = image->data;

/* create window */
mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
values[0] = s->white_pixel;
values[1] = XCB_EVENT_MASK_EXPOSURE |
XCB_EVENT_MASK_KEY_PRESS |
XCB_EVENT_MASK_BUTTON_PRESS;

w = xcb_generate_id (c);
xcb_create_window (c, XCB_COPY_FROM_PARENT, w, s->root,
10, 10, image->width, image->height, 1,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
s->root_visual,
mask, values);

/* set title on window */
xcb_set_wm_name(c, w, STRING, strlen(title), title);

/* set size hits on window */
hints = xcb_alloc_size_hints();
xcb_size_hints_set_max_size(hints, image->width,image->height);
xcb_size_hints_set_min_size(hints, image->width,image->height);
xcb_set_wm_size_hints(c, w, WM_NORMAL_HINTS, hints);

/* create backing pixmap */
pmap = xcb_generate_id(c);
xcb_create_pixmap(c, 24, pmap, w, image->width, image->height);

/* create pixmap plot gc */
mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND;
values[0] = s->black_pixel;
values[1] = 0xffffff;

gc = xcb_generate_id (c);
xcb_create_gc (c, gc, pmap, mask, values);

/* put the image into the pixmap */
xcb_image_put(c, pmap, gc, image, 0, 0, 0);

/* show the window */
xcb_map_window (c, w);
xcb_flush (c);

/* event loop */
while (!done && (e = xcb_wait_for_event (c))) {
switch (e->response_type) {
case XCB_EXPOSE:
ee=(xcb_expose_event_t *)e;
/* printf ("expose %d,%d - %d,%d\n",
ee->x,ee->y,ee->width,ee->height); */
xcb_copy_area(c, pmap, w, gc,
ee->x,
ee->y,
ee->x,
ee->y,
ee->width,
ee->height);
xcb_flush (c);
image32+=16;
break;

case XCB_KEY_PRESS:
/* exit on keypress */
done = 1;
break;

case XCB_BUTTON_PRESS:
fillimage(image->data, image->width, image->height);
memset(image->data, 0, image32 - image->data);
xcb_image_put(c, pmap, gc, image, 0, 0, 0);
xcb_copy_area(c, pmap, w, gc, 0,0,0,0,image->width,image->height);
xcb_flush (c);
break;
}
free (e);
}

/* free pixmap */
xcb_free_pixmap(c, pmap);

/* close connection to server */
xcb_disconnect (c);

return 0;
}




Friday, 16 April 2010

Claudia black makes this look good

OK maybe the title is a bit of a reach, but she is pretty and my topic is dull.

It is the school holidays and between entertaining the kids I have been experimenting with the vala (see there is the link to the title) language. Overall I really like it, building a usable graphical GTK application is a snap and that side of it works well.

Unfortunately, and here comes a a whole pile of fail, the documentation is lacking, not just poor but mostly non-existent. You rapidly discover yourself using the Glib and GTK library documentation to try and infer how things work.

Underneath, the vala compiler is clever, it is really a c code generator. It takes your vala source file converts it to c and compiles it. When it works smoothly it works very well, when something is not quite right you can end up with a large pile of pieces complete with the C compiler spitting out cryptic nonsense.

This is all exasperated to new heights of madness when you want to access a simple c library. I say simple because if you want to access a Glib based library its easy and "there is an app for that". Because vala is object oriented c interfaces must be described as an object. This description is performed using vapi files. The file format is documented by the simple approach of "we already wrapped a load of libs go look at their vapi files"

For my small starter project I wanted to access a tiny c library I had written. The entire interface described in a single header header (excluding copyright) is:
typedef enum motor_dir {
motor_off = 0,
motor_forward = 1,
motor_back = 2,
motor_brake = 3,
} motor_dir;

int edgerbtarm_init(void);
int edgerbtarm_close(void);
void edgerbtarm_ctrl_motor(int motorn, motor_dir direction);

Yes that is it! one enum, an initialise a finalise and a single operation function. The vapi file I came up with after a great deal of trial, error and head scratching was.
[CCode(cheader_filename = "libedgerbtarm.h",
lower_case_cprefix = "edgerbtarm_",
cprefix = "")]
namespace edgerbtarm {
[CCode(cprefix = "motor_")]
public enum motor_dir {
off,
forward,
back,
brake
}

public int init();
public int close();
public void ctrl_motor(int motorn, motor_dir direction);
}
This seemed to work until I tried to use the motor_dir type within my vala code at which point the c compiler started throwing errors about undeclared macros
arm.vala.c:297: error: ‘EDGERBTARM_TYPE_MOTOR_DIR’ undeclared (first use in this function)
I struggled for some time and finally ended up asking my friend Enrico for help. He initially suggested I simply use an int instead of the motor_dir type and cast when I needed to. This approch worked and let me compile the program, it did however seem a bit grubby and removed the type safety of the enum.

Then Enrico came up with the "correct" solution. the enum description in the in the vapi file needed an extra parameter so vala would know the enum did not have a Glib type...yeah it was obvious to me too :-/

so by altering the vapi file enum declaration to
[CCode(cprefix = "motor_", has_type_id = false)]
public enum motor_dir {
off,
forward,
back,
brake
}
Everything works as you might expect and the motor_dir enum can be used as a type within the vala program with no more fuss.

So the outcome of all this is that while vala is an interesting language which I may well use again in future, one should be aware that it is still very immature as a solution and has nowhere near enough documentation especially round the awkward stuff where it needs it most.

Monday, 8 March 2010

Music hath charms to soothe a savage breast, to soften rocks, or bend a knotted oak.

Since I last mentioned music back in January I have accumulated another ten albums and unlike last time where there were only a couple of stand outs, this time I have he opposite problem.

The unordered list:

Justin Sandercoe - "Small town eyes"

I am learning to play the guitar, I have been using Justins' course, it is very very good, this album? Also very good. If you like melodic guitar lead music with varied influences this is for you. A couple of tracks made me immediately think of some Crowded House riffs (which is not a bad thing). Only minor niggle is the uneven levels on some of the louder pieces, but it really is a minor observation on an otherwise fine first album.

Molly Lewis - "I made you a CD, but I eated it."

Although this is only a short selection of original material from Molly, it is a very promising first album. I really like her voice and although a ukulele is not generally the most well respected of instruments, in her hands, it has an odd charm. This album is available from DFTBA records.

Rhett and Link - "Up to this point"

A pair of talented comedians who use music very effectively to highlight their humour. I originally stumbled across them on youtube and decided to take a punt. The album is 27 short pieces which fit together surprisingly well. Difficult to categorise but think a cross between Flight of the Choncords and Jonathan Coulton with a dash of youtube immediacy.

They Might Be Giants - "Flood", "Apollo 18" and "John Henry"

Strictly a replacement of the old tapes which have completely disintegrated in the intervening couple of decades since first purchased. Flood is still one of my favourite albums ever, certainly in my top 10. If you do not know them TMBG are just ace, please try their music!

Seasick Steve - "Started out with nothin and i still got most of it left"

Well its a kinda fun album primarily based on blues electric "guitar" (some of the instruments are little more than a stick with a nail in and a guitar pickup.) Nothing bad, easy to get along with, definitely worth a listen.

La Roux - "La Roux"

This synth pop album was on remainder in ASDA and I took a gamble. Its OK I guess and for 3quid I cannot really complain.

Red Hot Chili Peppers - "By the way"

Not their best, but competent enough.

Aqua - "Aquarium" , "Aquarius"

Um...yes, I have a soft spot for 90's cheese OK? Nothing more than a gross self indulgence of my silly side. But they are fun ;-)


So that is my new music since January all 166 tracks of it . Most of it pretty good, certainly no lemons (well aside from the Aqua but that is supposed to be silly!)

Oh and The XX has really grown on me from last time and I am looking forward to their next release.







Squashfs

Well my last post elicited a response from Mr Lougher the squashfs author. Just not one I was expecting. Apparently he did receive one of my emails (I sent five in total) to which he has not replied as I have accidentally come across as critical.

This is absolutely not my intent and I wish to publicly say that, It would have perhaps been more constructive to actually tell me this by email and this misunderstanding could have been avoided.

For reference The final email in the series is reproduced below, if I have been overly unhelpful please let me know in the comments so I can avoid this mistake in future.

Hi, we are using Squashfs and have come across several issues. We
initialy tried to use the Debian source package of the 4.0 release but
then moved to using the the CVS edition which fixed some bugs but had
issues of its own.

Couple of things to start with:

- The commit you made recently titled "Change get_basename() to use
getcwd rather than getting the PWD env var." does not seem to be
what you intended?
http://squashfs.cvs.sourceforge.net/viewvc/squashfs/squashfs/squashfs-tools/mksquashfs.c?r1=1.145&r2=1.146

- I would like to assist in improving these tools so they work better
for our use cases. To aid in this have you considered updating the
revision control system the project is kept in? an SVN or GIT
repository is much easier to work with than CVS.

- I will probably assist with maintainership of the Debian and Ubuntu
packages (I am a Debian Developer ) and would
like to bring a couple of patches to your attention, one to avoid a
division by zero error and a second to enable building with
alternative libc. These are both attached to this mail.

- The tools currently make a number of assumptions about structure
alignment which are incorrect on some architectures. I am crafting
a patch to address this which should make the tools work correctly
on ARM (they currently simply segfault).

I hope this is seen as constructive and we can work together to
improve this software. If you do not feel you want to interact with me
and choose to take a differnt route, please let me know at your earliest
conveniance.

I do hope that Mr. Lougher will accept that I intended to be helpful and constructive and not cause offence. I have chosen to use the blog format for this as that is the form I made the previous complaint and also email between myself and Mr. Lougher appears somewhat erratic.

It should be noted that some of there points have already been addressed, however there are several more issues which I hope to be able to contribute towards.


Wednesday, 3 March 2010

Limited Success

I spent the day working with Daniel. He has been trying to get the correct runes for a GCC build in a strange environment. Turns out all he needed was me to throw stupid ideas at him until one caused him to examine some of the generated intermediate symbol maps...

Turns out that busybox awk fails in an interesting way which (eventually) causes half the symbols to be missing in the stage 1 libgcc.so object. Switched to using gawk and managed a successful build.

Seems to be a relatively good time for solutions, last week I managed to make squashfs-tools work on ARM. Unfortunately the author seems to be completely unresponsive to my (repeated) emails (if anyone wants the patch series feel free to mail me). The main issue with the tools is their complete blind assumption that a c structure can simply be cast to an arbitrary character array and get sensible results.

The structure casting method simply does not work on ARM (or indeed any platform which has alignment restrictions) without at least adhering to some minimal rules, primary among these is that the structure *must* be aligned to a word (32bit) boundary and that if you have 16bit or 8bit quantities within the structure they may cause gaps between members i.e. the structures are not packed by default.

No this behaviour is not a bug, it is perfectly acceptable by the c standard. Just because on x86 the practice of arbitrary casting works does not mean it is safe or sensible. Nonetheless many programmers simply do not want to believe its wrong.

Anyhow, rant over, back to work!