I have been working on a Firefox extension which will provide multiple workspaces within a single window.
You can find the source repository here.
To download version 0.2 Right click > Save link as here.
Note that version 0.2 supports only 2 workspaces. If you're unhappy with that try Version 0.3rc1 is available here.
I have tried 0.3rc1 on Firefox version 3.0.6. Version 0.2 is known to work in 3.0.6 and 3.5.6 (I hope it implies that it will work in all intermediate releases).
If you are interested you are welcome to test/enhance the extension. For any bug reports/queries/suggestions contact me.
A TODO list should be up shortly.
Showing posts with label programming. Show all posts
Showing posts with label programming. Show all posts
Sunday, January 10, 2010
Friday, April 10, 2009
Why compilers should start looking into comments!!!
/* Fix for BUG: 1313 */
jumpFlag = 0; /* Set jumpFlag to 1 */
jumpFlag = 0; /* Set jumpFlag to 1 */
Posted by
Balagopal
Thursday, December 18, 2008
Using procfs for debug information
In a kernel module we can dynamically create entries under /proc . Each entry (file or directory) under /proc is represented in kernel by a struct proc_dir_entry. This structure is dynamically allocated by various functions used to create directory entries. Here are some useful examples :-
To create a directory "home" under /proc
struct proc_dir_entry *home = proc_mkdir("home", NULL);
To create directory "kitchen" under /proc/home
struct proc_dir_entry *kitchen = proc_mkdir("kitchen", home);
Ok that was enough fun creating directories. Directories can only help that much. What we really want is some files which can be read to get some information from kernel. To create files, we have to specify name of the file, it's permissions, it's parent directory, and a function which will generate data to be given to user through that file. To create a file "name" under /proc/home.
struct proc_dir_entry *name = create_proc_read_entry("name", 0444, home, proc_read_name, NULL);
proc_read_name is the function which generates data
static int proc_read_name(char *page, char **start, off_t off, int count, int *eof, void *data)
{
u32 nbytes = 0;
/* Never worry about off or count, or else you will get a headache */
*start = NULL; /* We don't want kernel to use *start */
/* Here we print entire contents of file into page */
nbytes = sprintf(page, "Rama Nivas\n");
/* Signal EOF */
*eof = 1;
/* Size of file */
return nbytes;
}
These files can only handle PAGE_SIZE amount of data (actually more is possible but the effort is not worth it). If you have more than PAGE_SIZE bytes, it's better to split data across files.
To create a directory "home" under /proc
struct proc_dir_entry *home = proc_mkdir("home", NULL);
To create directory "kitchen" under /proc/home
struct proc_dir_entry *kitchen = proc_mkdir("kitchen", home);
Ok that was enough fun creating directories. Directories can only help that much. What we really want is some files which can be read to get some information from kernel. To create files, we have to specify name of the file, it's permissions, it's parent directory, and a function which will generate data to be given to user through that file. To create a file "name" under /proc/home.
struct proc_dir_entry *name = create_proc_read_entry("name", 0444, home, proc_read_name, NULL);
proc_read_name is the function which generates data
static int proc_read_name(char *page, char **start, off_t off, int count, int *eof, void *data)
{
u32 nbytes = 0;
/* Never worry about off or count, or else you will get a headache */
*start = NULL; /* We don't want kernel to use *start */
/* Here we print entire contents of file into page */
nbytes = sprintf(page, "Rama Nivas\n");
/* Signal EOF */
*eof = 1;
/* Size of file */
return nbytes;
}
These files can only handle PAGE_SIZE amount of data (actually more is possible but the effort is not worth it). If you have more than PAGE_SIZE bytes, it's better to split data across files.
Posted by
Balagopal
Kermit scripting - 2
A kermit script consists of kermit commands that have to be executed. To
execute a kermit script use
Arguments can be passed to script as
These arguments can be referenced within the script as \%1, \%2 etc.
Here \%1 = arg1 and \%2 = arg2
execute a kermit script use
$kermit + kscript
Arguments can be passed to script as
$kermit + kscript arg1 arg2
These arguments can be referenced within the script as \%1, \%2 etc.
Here \%1 = arg1 and \%2 = arg2
Conditionals
kermit scripts support conditional execution using "if" and looping
using "while".
if ! equal \%1 "" {
# Some piece of code to be executed when first argument is non-null
}
I have never actually used a "while" but here is one example I found
in a script.
while ! \F_eof(\m(f)) {
fread \m(f) l
out \m(l)\13
in 60 >
}
Posted by
Balagopal
Wednesday, December 17, 2008
Kermit Scripting
In embedded systems development, kermit is commonly used to communicate to boards through serial port. Many of interactive dialog sessions between user and board can be automated using kermit scripts. If kscript is a file containing a kermit script it can be run by the following command "kermit -y kscript"
To wait for a particular prompt and then issue a command
input 1000 bash$
lineout ls
Will wait for the prompt "bash$" to appear and then issue the "ls" command to board through serial port
minput <timeout> <s1> <s2> ...
Used to Wait for any of the given string
Ex:
minput 1000 bash$ >
First, define some variables
define delay 1000
define prompt bash$
define command ls
And use it
input \m(delay) \m(prompt)
lineout \m(command)
set session-log timestamped-text
log session kermit-log.txt
Here are some very useful kermit scripting commands
Basic interaction
To wait for a particular prompt and then issue a command
input 1000 bash$
lineout ls
Will wait for the prompt "bash$" to appear and then issue the "ls" command to board through serial port
minput <timeout> <s1> <s2> ...
Used to Wait for any of the given string
Ex:
minput 1000 bash$ >
Variables
First, define some variables
define delay 1000
define prompt bash$
define command ls
And use it
input \m(delay) \m(prompt)
lineout \m(command)
And when finally you are finished use
exit 0 "Over and out"
To add timestamped logging to kermit
set session-log timestamped-text
log session kermit-log.txt
Posted by
Balagopal
Tuesday, September 23, 2008
Rambo mode of Linux kernel
Ok this is interesting......
Kernel enters *Rambo* mode in out_of_memory() :mm/oom_kill.c
and what does it stand for..well, kernel starts to "shoot down" processes hoping to increase amount of free memory in the system.
Kernel enters *Rambo* mode in out_of_memory() :mm/oom_kill.c
and what does it stand for..well, kernel starts to "shoot down" processes hoping to increase amount of free memory in the system.
Posted by
Balagopal
Tuesday, September 16, 2008
Bug fixing
Two ways to fix a bug
1. Change the implementation to match the spec.
2. Change the spec to match the implementation.
Posted by
Balagopal
Monday, September 15, 2008
Created a blogger template!!!
I created a blogger template with 2-column layout. You can watch a demo here.
Posted by
Balagopal
Saturday, August 30, 2008
Design documents
Code and design are maintained as separate files in almost all software projects. A major task faced by all IT firms is ensuring the consistency between the source code and the corresponding design document. Code maintainers confused by inconsistent design documents are commonplace. Literate programming might be the first step towards a solution.
Posted by
Balagopal
Exposing module internals using seq_file interface
Learn all about seq_file interface here
http://www.xenotime.net/linux/doc/seq_file_howto.txt
The seq_file mechanism provides a more straightforward, non-iterator style, interface. A driver writer may simply define show() with operations that output data to proc file.
First of all, we have to create a file in /proc. For this, we have to call create_proc_entry in our module initialization function.
struct proc_dir_entry *foo = create_proc_entry("foo", 0, NULL); /* This will create "/proc/foo" */
Then initialize the proc file operations structure
foo->proc_fops = &foo_proc_operations;
where foo_proc_operations is defined as,
static struct file_operations foo_proc_operations = {
.open = foo_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
seq_read, seq_lseek, and single_release are functions defined by Linux seq_file core.
Within foo_proc_open we have to call single_open() and pass it "show()", the function performing actual display.
return single_open(file, foo_proc_show, NULL);
Within foo_proc_show, we can use seq_{putc|puts|printf} to output data to "/proc/foo". These functions work like normal putc|puts|printf.
static int foo_proc_show(struct seq_file *m, void *v)
{
seq_puts(m, "Hello from foo\n"); /* write to our proc file */
return 0;
}
And finally don't forget to remove the proc file by calling,
remove_proc_entry("foo", NULL);
http://www.xenotime.net/linux/doc/seq_file_howto.txt
The seq_file mechanism provides a more straightforward, non-iterator style, interface. A driver writer may simply define show() with operations that output data to proc file.
First of all, we have to create a file in /proc. For this, we have to call create_proc_entry in our module initialization function.
struct proc_dir_entry *foo = create_proc_entry("foo", 0, NULL); /* This will create "/proc/foo" */
Then initialize the proc file operations structure
foo->proc_fops = &foo_proc_operations;
where foo_proc_operations is defined as,
static struct file_operations foo_proc_operations = {
.open = foo_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
seq_read, seq_lseek, and single_release are functions defined by Linux seq_file core.
Within foo_proc_open we have to call single_open() and pass it "show()", the function performing actual display.
return single_open(file, foo_proc_show, NULL);
Within foo_proc_show, we can use seq_{putc|puts|printf} to output data to "/proc/foo". These functions work like normal putc|puts|printf.
static int foo_proc_show(struct seq_file *m, void *v)
{
seq_puts(m, "Hello from foo\n"); /* write to our proc file */
return 0;
}
And finally don't forget to remove the proc file by calling,
remove_proc_entry("foo", NULL);
Posted by
Balagopal
Sunday, February 10, 2008
back blogging....Feels like heaven
I'm back. Somehow got my system up and running after a long time.
Some very interesting LJ articles for your reading pleasure...
inside linux packet filter I
inside linux packet filter II
these articles describe the path of a network packet up the Linux kernel protocol stack.(And also describes how packet sockets are implemented).
Oh..and my new years resolution was - "Atleast one blog/month" ;-)
Some very interesting LJ articles for your reading pleasure...
inside linux packet filter I
inside linux packet filter II
these articles describe the path of a network packet up the Linux kernel protocol stack.(And also describes how packet sockets are implemented).
Oh..and my new years resolution was - "Atleast one blog/month" ;-)
Posted by
Balagopal
Monday, July 30, 2007
Random Walking
What is the probability that two random walkers starting from a point meet each other during their walk?
We consider random walks in 1, 2 and 3 dimensions.
A 1d random walk can be thought of as a random walk along a long street(Similar to number line), where at each point he may choose to proceed in the same direction or reverse his direction.
A 2d random walk can be thought of as a random walk on a 2d grid, where at each point he may choose any one of four directions(forward, backward, left and right).
Similarly a random walker walking in 3d space has 6 options at each point(Four directions of 2d walk plus up and down).
I wrote a python program to simulate random walks in 1, 2 and 3 dimensions.
The function randwalk simulates a random walk in any dimension. The dimension is determined by the parameter update which is a function which returns the new position of a random walker given his old position. The limit parameter limits the no: of steps taken by a random walker(Random walkers won't walk forever:-) ).
I obtained the following results.
Two 1d random walkers meet about 95% of time at an average of about 1 move before meeting each other.
Two 2d random walkers meet about 60-70% of time at an average of about 20 moves before meeting each other.
Two 3d random walkers meet about 30-35% of time at an average of about 10 moves (This is surprising) before meeting each other.
The above simulation is not very realistic. It assumes that both random walkers walk the same distance at the same pace.
Also, in real life, random walkers don't choose directions randomly. Instead, they may prefer one path over another according to their tastes and preferences.
We consider random walks in 1, 2 and 3 dimensions.
A 1d random walk can be thought of as a random walk along a long street(Similar to number line), where at each point he may choose to proceed in the same direction or reverse his direction.
A 2d random walk can be thought of as a random walk on a 2d grid, where at each point he may choose any one of four directions(forward, backward, left and right).
Similarly a random walker walking in 3d space has 6 options at each point(Four directions of 2d walk plus up and down).
I wrote a python program to simulate random walks in 1, 2 and 3 dimensions.
The function randwalk simulates a random walk in any dimension. The dimension is determined by the parameter update which is a function which returns the new position of a random walker given his old position. The limit parameter limits the no: of steps taken by a random walker(Random walkers won't walk forever:-) ).
I obtained the following results.
Two 1d random walkers meet about 95% of time at an average of about 1 move before meeting each other.
Two 2d random walkers meet about 60-70% of time at an average of about 20 moves before meeting each other.
Two 3d random walkers meet about 30-35% of time at an average of about 10 moves (This is surprising) before meeting each other.
The above simulation is not very realistic. It assumes that both random walkers walk the same distance at the same pace.
Also, in real life, random walkers don't choose directions randomly. Instead, they may prefer one path over another according to their tastes and preferences.
References
Introduction to probability, Charles M. Grinstead and J . Laurie Snell
Posted by
Balagopal
Tuesday, July 17, 2007
magic with ImageMagick
ImageMagick is a set of command line utilities for manipulating images, very useful for performing some transformation on multiple images (For individual images, visual editors like GIMP may be a better choice).
A friend of mine had 57 images (of 2272x1704 !!!) consuming 61MB of disk space. We had to find a way to resize all of them to 1024x768.
Once I got all 57 images into my_images, the following commands did the job.
$cd my_images
$mkdir conv
$for i in *.jpg
>do
>convert -resize 1024x768 $i conv/$i
>done
And now 6MB is enough..
The convert command is just one of many tools provided by ImageMagick. It converts an input image to create an output image according to the options given to it.
The syntax is
convert options infile outfile
The resize option is used to...(you know what)
convert has got like a million options (for rotating, blurring, cropping, etc..).One option even allows to specify an affine transformation matrix to transform the image(Phewwww, Who's going to use that).
Another cool tool is montage which is used to create a composite image from many images.
For ex:-
To create an image that consists of a thumbnail preview of all 57 images in my_images..
$montage -geometry 128x128+8+8 -tile 8x8 -background gray *.jpg conv/all.jpg
The syntax is
montage options infile1 infile2 ... infilen outfile
The geometry option specifies size of each tile (128x128) and spacing between tiles(+8+8).
The tile option specifies no: of rows of tiles and no: of tiles in each row.
The choice of 8x8 for tile option is not arbitrary. It allows a maximum of 64 tiles in one file (and I want all 57 thumbnails in one file), if there are more than 64 input files then thumbnails will be split across multiple files.
The problem
A friend of mine had 57 images (of 2272x1704 !!!) consuming 61MB of disk space. We had to find a way to resize all of them to 1024x768.
A solution
Once I got all 57 images into my_images, the following commands did the job.
$cd my_images
$mkdir conv
$for i in *.jpg
>do
>convert -resize 1024x768 $i conv/$i
>done
And now 6MB is enough..
The convert command is just one of many tools provided by ImageMagick. It converts an input image to create an output image according to the options given to it.
The syntax is
convert options infile outfile
The resize option is used to...(you know what)
More info..
convert has got like a million options (for rotating, blurring, cropping, etc..).One option even allows to specify an affine transformation matrix to transform the image(Phewwww, Who's going to use that).
Another cool tool is montage which is used to create a composite image from many images.
For ex:-
To create an image that consists of a thumbnail preview of all 57 images in my_images..
$montage -geometry 128x128+8+8 -tile 8x8 -background gray *.jpg conv/all.jpg
The syntax is
montage options infile1 infile2 ... infilen outfile
The geometry option specifies size of each tile (128x128) and spacing between tiles(+8+8).
The tile option specifies no: of rows of tiles and no: of tiles in each row.
The choice of 8x8 for tile option is not arbitrary. It allows a maximum of 64 tiles in one file (and I want all 57 thumbnails in one file), if there are more than 64 input files then thumbnails will be split across multiple files.
Posted by
Balagopal
Sunday, July 15, 2007
GCC Extensions
Gcc provides some cool extensions to the C language. The following, I think, are very useful.
Just like you can initialize structure variables by specifying name of structure members, you can initialize array elements by specifying indices(You can even specify ranges).
For ex:-
int id[256] = { ['A' ... 'Z'] = 1, ['a' ... 'z'] = 1, ['0' ... '9'] = 1, ['_'] = 1 };
The __func__ variable contains the name of the current function. This comes in handy when you want to print debugging messages of the form,
func-name : msg
The following macro accomplishes this task
#define DEBUGP(format, ...) fprintf(stderr,"%s : " format,__func__, ## __VA_ARGS__)
Note that you can't pass a char * variable directly to DEBUGP to print it.Instead use
DEBUGP("%s", c); /* print the message in c */
Designated Initializers for arrays
Just like you can initialize structure variables by specifying name of structure members, you can initialize array elements by specifying indices(You can even specify ranges).
For ex:-
int id[256] = { ['A' ... 'Z'] = 1, ['a' ... 'z'] = 1, ['0' ... '9'] = 1, ['_'] = 1 };
__func__ variable
The __func__ variable contains the name of the current function. This comes in handy when you want to print debugging messages of the form,
func-name : msg
The following macro accomplishes this task
#define DEBUGP(format, ...) fprintf(stderr,"%s : " format,__func__, ## __VA_ARGS__)
Note that you can't pass a char * variable directly to DEBUGP to print it.Instead use
DEBUGP("%s", c); /* print the message in c */
Posted by
Balagopal
Subscribe to:
Posts (Atom)