Hacks > Egomania: Love Me. I do.
Egomania is a command-line shell. It is simplistic and fast. Attempts are made at stability, but developing on Linux makes that impossible. It is the next evolutionary step in the dingOS shell line (gile-shell, oxSHELL, TITS, now Egomania).
It has a builtin command editor (of original design) and tab-completion. There is bulitin help and configuration system.
Before we get to the details of implementation, you may just want to download and try Egomania:
These are just notes about the design of the Egomania shell. The shell was designed in a rather ad-hoc, in-situ way.
Garbage Collection (and fun memory!):
Reading over the code, you may notice that there is no use of free(). You may also think that that would cause one massive memory leak. That's wrong, since the allocation is managed in alloc.c. It is the garbage collector — if you strech that term to it's maximum — in the most basic sense.
The design of the GC revolves around one simple idea: in a shell, nearly all allocation is temporary, and will need destruction at one point. So, a very generalised mark-and-sweep method has been employed here. Upon allocation, a segment of memory is entered into a table (adding 5 bytes to the memory used). The table holds two things about each segment: it's starting address, and a mark. If the mark is set to UNMARK (0x00), when the reaper (ego_alloc_reap()) is called, it will be free()'d and removed from the table. If the mark is set to MARK (0x11), then the memory is not free()'d until the program exits (the OS takes care of that for us). The mark can be changed by sending a valid pointer (in both the table and in memory) to the mark()/unmark() functions, accordingly.
ego_alloc_reap() is called as the first call in the main loop. Henceforth, after every command (when the loop repeats — it is infinite) ego_alloc_reap() is called, and all unneeded memory is free()'d.
In <ego.h> malloc() and realloc() (along with strdup() — for a reason) are #undef'd then #define'd to ego_malloc and ego_realloc (and ego_strdup), respectively. The use is entirely transparent to any code. These #defines set the mark to UNMARK by default. malloc_m() and realloc_m() set MARK by default.
This makes coding different section of the shell a bit easier, since you never have to keep track of what memory you use. The code will do it for you, and that is definitely faster than doing it manually.
Garbage Collection: http://www.jwz.org/doc/gc.html
The command '_cfgdmp' in Egomania will dump the configuration data to the screen. Each entry is made of two parts: a name and a value or address.
This is quite simple, really. Essentially all this is is a table of names and memory addresses that contain data for the shell. It's easier to lookup on the table than to try and remember several global variables (which have to be declared in every scope). C is a rather cumbersome (yet powerful) language. It's faster lookup to use the variables, but the config system adds a level of organisation to it.
The names take on a directory-like structure. Right now, it's kind of useless, it just helps me keep everything straight when I'm coding. At one point, it may be significant, to make faster searching code (directory trees, anyone?). A name like '/user/environment/prompt' (the actual name for the user prompt) breaks down in this manner:
/user It has something to do with the user... /environment It is part of their environment... /prompt It is the unparsed string for their prompt.