<?xml version='1.0' encoding='UTF-8'?><rss xmlns:atom='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' version='2.0'><channel><atom:id>tag:blogger.com,1999:blog-3569666675299554168</atom:id><lastBuildDate>Fri, 13 Nov 2009 20:20:03 +0000</lastBuildDate><title>Bits and Pieces</title><description>A notebook for various random stuff.</description><link>http://bnpcs.blogspot.com/</link><managingEditor>noreply@blogger.com (Andrew Yourtchenko)</managingEditor><generator>Blogger</generator><openSearch:totalResults>39</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3569666675299554168.post-5884790738849910003</guid><pubDate>Tue, 03 Nov 2009 01:09:00 +0000</pubDate><atom:updated>2009-11-03T02:11:36.121+01:00</atom:updated><title>Recording sound and video from a webcam</title><description>I've found a lot of questions on the internet on how to record the sound and video at the same time from the webcam. Here's the magic incantation that worked well for me (it assumes you do not have any video capture devices besides the webcam and already have one ALSA soundcard besides the mic of the webcam - if not, adjust accordingly). This is a single long line:&lt;br /&gt;&lt;br /&gt;mencoder tv:// -tv driver=v4l:width=320:height=240:device=/dev/video0:fps=30:forceaudio:alsa:adevice=hw.1 -ovc lavc threads=2 -ffourcc xvid  -oac mp3lame -lameopts cbr=128  -o recording.avi&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3569666675299554168-5884790738849910003?l=bnpcs.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bnpcs.blogspot.com/2009/11/recording-sound-and-video-from-webcam.html</link><author>noreply@blogger.com (Andrew Yourtchenko)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3569666675299554168.post-7191273136845416572</guid><pubDate>Sat, 13 Jun 2009 22:58:00 +0000</pubDate><atom:updated>2009-06-14T01:01:23.517+02:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>debian</category><category domain='http://www.blogger.com/atom/ns#'>howto</category><category domain='http://www.blogger.com/atom/ns#'>ubuntu</category><title>configure: error: C++ preprocessor "/lib/cpp" fails sanity check</title><description>A fairly odd message, especially given that 'which cpp' shows another location.&lt;br /&gt;&lt;br /&gt;The solution is:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;sudo aptitude install build-essential&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3569666675299554168-7191273136845416572?l=bnpcs.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bnpcs.blogspot.com/2009/06/configure-error-c-preprocessor-libcpp.html</link><author>noreply@blogger.com (Andrew Yourtchenko)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3569666675299554168.post-3297819090287144241</guid><pubDate>Wed, 27 May 2009 23:05:00 +0000</pubDate><atom:updated>2009-05-28T03:05:48.449+02:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>programming</category><category domain='http://www.blogger.com/atom/ns#'>math</category><title>F*ctor - a 0-dimensional Turing tarpit.</title><description>Following a post of one of my friends to the http://manage.yore.ma/eso/, I felt a bit inspired, &lt;br /&gt;so I wanted to write up something fun. So, here's the experiment - an imaginary language which holds the entire program and data memory in a single variable! &lt;br /&gt;&lt;br /&gt;The F*ctor machine has only other elements are a single instruction, and a single variable which holds the Program, and Data, and the machine state, in just a single natural number X. The "single instruction", however, is a bit difficult to describe, so I will attempt to describe it in terms of smaller "micro-operations" - they do not really change nor are visible to the user, they are here mostly for the sake of explanation. The temp variable in the pseudocode is just for the sake of ease of comprehension.&lt;br /&gt;&lt;br /&gt;The machine can really efficiently calculate Prime(N) (being the Nth prime, that is Prime(0) == 2; Prime(1) == 3, Prime(2) == 5, etc.)&lt;br /&gt;&lt;br /&gt;Also it can count how many times is the given number divisible by some prime: CountPrime(V, P); CountPrime(2,2) == 1, CountPrime(9,3) == 2; CountPrime(13,3) == 0.&lt;br /&gt;&lt;br /&gt;Finally, the third operation is the destructive divide: DivideBy(V, P) - try to integer-divide V in-place by a prime P ith no remainder, and return True if we were successful, and False if no remainder-free division is possible.&lt;br /&gt;&lt;br /&gt;The remaining operations that comprise the single cycle are some trivial arithmetics.&lt;br /&gt;&lt;br /&gt;the single cycle of execution:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;one_cycle(X) {&lt;br /&gt;  local CurrentP = CountPrime(X, 3);&lt;br /&gt;  while(DivideBy(&amp;X, 2)) {&lt;br /&gt;    if(not DivideBy(&amp;X, Prime(CountPrime(X, Prime(CurrentP))))) {&lt;br /&gt;      return X * 3 * 3;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;  return X * 2^CountPrime(X, Prime(CurrentP)) * 3;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So running the program consists of repeatedly executed "X = one_cycle(X)".&lt;br /&gt;&lt;br /&gt;If we take a closer look, then this is nothing more than a folded version of &lt;a href="http://en.wikipedia.org/wiki/OISC#Reverse-subtract_and_skip_if_borrow"&gt;Reverse-subtract and skip if borrow&lt;/a&gt; single-instruction machine, with "memory contents" at location N being the number of times the X is divisible by Nth prime number. As it is visible, the accumulator is memory-mapped at 0 (see these divisions/multiplications by 2?) and the program counter is memory-mapped at 1 (see the multiplications either by 3 or by 9 ?)&lt;br /&gt;&lt;br /&gt;So, unless I made a bug somewhere in the logic, we have a Turing-complete absract machine squashed into a single variable.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3569666675299554168-3297819090287144241?l=bnpcs.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bnpcs.blogspot.com/2009/05/fctor-0-dimensional-turing-tarpit.html</link><author>noreply@blogger.com (Andrew Yourtchenko)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3569666675299554168.post-370498975965429607</guid><pubDate>Sat, 16 May 2009 01:57:00 +0000</pubDate><atom:updated>2009-05-16T04:01:55.184+02:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>hci</category><category domain='http://www.blogger.com/atom/ns#'>opencv</category><title>A "nod" X11 linux interface</title><description>Today I wanted to spend the evening doing something different and fun, and came up with an idea to play around with some of the &lt;a href="http://sourceforge.net/projects/opencvlibrary/"&gt;opencv&lt;/a&gt;'s functions. Well, did not play that much - just slightly tweaked the facedetect.c, to get what I called a "nod interface".&lt;br /&gt;&lt;br /&gt;When you compile and launch the program, it pops up the screen with the video. If all goes well and you are sitting in front of your camera, you should see a circle around your face. If you do not see it - move closer and/or get a smoother background.&lt;br /&gt;&lt;br /&gt;The few lines of pretty silly code that I've added does the following: calculates the two averages of the last N points of the center of the detected face object - "fast" (N=4) and "smooth" (N=8).&lt;br /&gt;&lt;br /&gt;If you don't move your head the delta between these will be almost 0 - it gets forced down to zero by a simple check against the threshold.&lt;br /&gt;&lt;br /&gt;If you nod - then obviously the "fast" average moves down faster than the "smooth" one - so if you nod energetic enough, the computer will notice it and will send a few "arrow down" synthetic events via the XTest X11 extension. If you manage to "nod up" (unnatural, but somewhat doable) - then it will send the equivalent number of "arrow up" events.&lt;br /&gt;&lt;br /&gt;The counter-movement (returning the head back after the nod) is compensated by another simple logic - it's needed to have at least 4 "zero-delta" cycles in order to let the detected delta through.&lt;br /&gt;&lt;br /&gt;The end result is that with some amount of luck you might manage to read things from your laptop hands-free. Should be good for reading the /. threads :-)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://employees.org/~andin/nod-interface.c"&gt;this file&lt;/a&gt; is the tweaked facedetect.c - the long line to feed to the compiler is in the comments in the beginning.&lt;br /&gt;&lt;br /&gt;Depending on the speed of your computer, you might need to adjust some of the thresholds.&lt;br /&gt;&lt;br /&gt;Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3569666675299554168-370498975965429607?l=bnpcs.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bnpcs.blogspot.com/2009/05/nod-x11-linux-interface.html</link><author>noreply@blogger.com (Andrew Yourtchenko)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3569666675299554168.post-4625131753242901510</guid><pubDate>Thu, 07 May 2009 01:12:00 +0000</pubDate><atom:updated>2009-05-07T03:13:23.128+02:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>music</category><title>Hercules DJ Console RMX linux midi drivers</title><description>Yay! Open source and all. Get the MIDI out of the RMX.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://ts.hercules.com/eng/index.php?pg=view_files&amp;gid=2&amp;fid=28&amp;pid=215&amp;cid=1"&gt;Grab them here&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3569666675299554168-4625131753242901510?l=bnpcs.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bnpcs.blogspot.com/2009/05/hercules-dj-console-rmx-linux-midi.html</link><author>noreply@blogger.com (Andrew Yourtchenko)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3569666675299554168.post-7368120303847685816</guid><pubDate>Sat, 02 May 2009 04:09:00 +0000</pubDate><atom:updated>2009-05-02T06:13:28.758+02:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>minilight</category><category domain='http://www.blogger.com/atom/ns#'>renderer</category><title>A very compact renderer</title><description>Been a while since I babbled something here.&lt;br /&gt;&lt;br /&gt;So to ensure I'm still alive and kicking - here's something neat: a renderer in under 600 lines of code.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.hxa.name/minilight/"&gt;Minilight&lt;/a&gt; has a bunch of implementations in various languages.&lt;br /&gt;&lt;br /&gt;A very nice toy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3569666675299554168-7368120303847685816?l=bnpcs.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bnpcs.blogspot.com/2009/05/compact-and-fast-renderer.html</link><author>noreply@blogger.com (Andrew Yourtchenko)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3569666675299554168.post-1809671274681428626</guid><pubDate>Sat, 04 Apr 2009 19:15:00 +0000</pubDate><atom:updated>2009-04-04T21:59:40.986+02:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>cosimus</category><title>Linear interpolation code for smoothing out the Z-movement</title><description>Today I've got a dead-simple but pretty cute piece of code in. It has to do with smooth avatar movement when walking. The map of heights is stored with the resolution of 1 meter, while in the viewer it's smoothed out. This creates a "staircase"-like effect when walking on the slope.&lt;br /&gt;&lt;br /&gt;The simple solution which I went to is to do the linear interpolation, with the following &lt;br /&gt;approach. First we look at the heightmap "from the top" - just looking at its X and Y coordinates. And logically we split the X-Y space into a bunch of 1-sized squares. So we always &lt;br /&gt;have our x,y point for which we are calculating, inside one of these small tiles. So we can zoom into this tile and take further look: &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    (x0,y0)  (x0+1, y0)&lt;br /&gt;     |      /&lt;br /&gt;     v     v&lt;br /&gt;     +-----+---&gt; X&lt;br /&gt;     |\ 1 /|&lt;br /&gt;     | \ / |&lt;br /&gt;     |4 + 2|&lt;br /&gt;     | / \ |&lt;br /&gt;     |/ 3 \|&lt;br /&gt;     +-----+ &lt;-- (x0+1, y0+1)&lt;br /&gt;     |&lt;br /&gt;     v&lt;br /&gt;     Y&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;in this picture - the corners of the square are the integer X, Y values which have the data.&lt;br /&gt;&lt;br /&gt;The point in the center is the "virtual" point which is used to split the square into four triangles - it's x,y coordinates are simply X0+0.5, Y0+0.5.&lt;br /&gt;&lt;br /&gt;Then we can pretty simply find which of the triangles holds our "interesting" point - now it's all dead simple - find the equation of the plane that passes through the three points the coordinates of which we know (the Z coordinate of the "center" point is the average of the Z coordinates of all 4 corners) - and then simply substitute the X, Y into the equation, to get Z straight away.&lt;br /&gt;&lt;br /&gt;I don't have walking animations yet - for now I simply set the Z coordinate of the avatar, which gets its butt approximately at ground level :-) While running around, if one would measure by the proportions to the real world, the staircase effect is reduced to almost unnoticeable ~10cm if we relate to the real-world body proportions. And I hope that once I get the avatar's butt out of the ground, it should be even better visually.&lt;br /&gt;&lt;br /&gt;Now, the obvious question - why 4 triangles, instead of 2 ? Because if you take the following layout:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;0---*&lt;br /&gt;|   |&lt;br /&gt;*---0&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;and the "*" is "high" an "0" is "low" - depending on the choice to cut this X-Y box, you get either a pit, or a spike. 4 triangles handle this case noticeably better.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3569666675299554168-1809671274681428626?l=bnpcs.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bnpcs.blogspot.com/2009/04/linear-interpolation-code-for-smoothing.html</link><author>noreply@blogger.com (Andrew Yourtchenko)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3569666675299554168.post-5437888739826672534</guid><pubDate>Mon, 30 Mar 2009 00:40:00 +0000</pubDate><atom:updated>2009-03-30T02:54:32.365+02:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>cosimus</category><title>Cosimus now with avatar shapes and clothing</title><description>Today I took a brute-force approach to solving the missing avatar clothing problem that &lt;br /&gt;I was chasing for a few days - simply by creating my own set of the default clothing and wearables.&lt;br /&gt;It's just the standard set of items which are uploaded by the viewer in the case it does not find them - so for the secondlifers, it's Ruth in white clothing :)&lt;br /&gt;&lt;br /&gt;Alongside, I've put a very simple moving logic - only forward, in the direction that the avatar faces. This required some rudimentary support for something the called "scene" in opensim - or at least my interpretation of it. For now, I am taking the assumption "Agent == Avatar", it probably will change sometime in the future. However, I already put the "clientstack-independent scene" atop the SMV one - to represent the qualities that are (or should be) fundamental to any avatar system - X, Y, Z position, AgentID - I'll use the UUIDs for representing the "entity" for now, and the "label" - some text that identifies the avatar as seen in-world. &lt;br /&gt;&lt;br /&gt;The rest of the platform-dependent details go into a table called "Blob" which is at the moment SMV-specific data about the avatar (like, local object ID, which is needed for the viewer, as each avatar has its own local id to be drawn correctly). &lt;br /&gt;&lt;br /&gt;Possibly exposing a "local avatar id" might have been a better move for the platform-independent record, and having the clientstack-specific lookup tables.. But I will see in the future what is better. In any case, each clientstack registers its own event handler functions, which are called per-avatar in case the need arises (this indeed raises some additional possibilities for optimization in the future).&lt;br /&gt;&lt;br /&gt;Alongside the minor infra mods, the loginserver config is now in the config file (main.lua), as well as the serializable state to facilitate trivial no-outage restarts is inside a separate file.&lt;br /&gt;&lt;br /&gt;Interestingly enough, there seems to be something odd with the object update packet - the omvviewer tends to hard-hang the laptop - I am not sure which part is causing that. And somehow I managed to get some green text atop the avatar at one occasion, which was funny.&lt;br /&gt;&lt;br /&gt;As the vacation time is over now for me, most definitely the speed of the development will suffer - I'll only have some late nights, which are also good to be used for sleep, but I am pretty happy with the progress so far.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3569666675299554168-5437888739826672534?l=bnpcs.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bnpcs.blogspot.com/2009/03/cosimus-now-with-avatar-shapes-and.html</link><author>noreply@blogger.com (Andrew Yourtchenko)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3569666675299554168.post-4493386584467394900</guid><pubDate>Sun, 29 Mar 2009 11:42:00 +0000</pubDate><atom:updated>2009-03-29T13:56:39.255+02:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>cosimus</category><title>Cosimus - a little toolkit for metaverse experiments</title><description>The past two weeks I've been on holiday - so this translated for doing various things that I did not have time to do before. One of those things was completing the chunk of coding needed to at least start with my little metaverse experiment.&lt;br /&gt;&lt;br /&gt;The result is at http://github.com/ayourtch/cosimus/tree/master - and will suffer the periodic commits from now on, depending on my so called "spare time" :)&lt;br /&gt;&lt;br /&gt;It's a start of the simulator code for the 3d simulator, for now I've started with the SecondLife(tm) protocol, as it's something I had in the beginning of the works.&lt;br /&gt;&lt;br /&gt;For now it is a custom Lua interpreter, with a few libraries linked in and initialized by default, and the application code in prototype phase is being written in Lua. This gives the much faster speed of the development compared to C (a long while ago, while checking the speed of development on Perl vs. C I found about 10x difference - in favour of Perl, of course. I did not do any personal measurements now, but from a gut feeling it should be about the same). Much later, as needed, I'll push the performance-critical pieces of the code downwards to C. &lt;br /&gt;&lt;br /&gt;For now the thing does not do all that much - these few days I've been mostly dealing with the inventory/asset code, appears there are some magic tweaks still needed - from the behaviour it seems like I am triggering some data corruptions in the client inventory code.. &lt;br /&gt;&lt;br /&gt;From the cool features that are already there - the inventory/asset library loading is done from zipfiles, which means easier handling of them for the consumer. Another fun feature - or rather design choice - is that all the communication via the components that is possible to be networked in the distributed setup, will be also networked in the standalone setup, with the simple servers doing the job from within the executable itself. So it is "batteries included", and a single code path to debug.&lt;br /&gt;&lt;br /&gt;...Now, back to coding :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3569666675299554168-4493386584467394900?l=bnpcs.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bnpcs.blogspot.com/2009/03/cosimus-little-toolkit-for-metaverse.html</link><author>noreply@blogger.com (Andrew Yourtchenko)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3569666675299554168.post-5873664205701102162</guid><pubDate>Wed, 11 Mar 2009 00:28:00 +0000</pubDate><atom:updated>2009-03-11T01:31:14.613+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>zettair</category><category domain='http://www.blogger.com/atom/ns#'>ubuntu</category><title>Compiling zettair on ubuntu</title><description>The first compile throws a bunch of errors, due to missing zlib, among them:&lt;br /&gt;&lt;br /&gt;‘Z_NO_FLUSH’ undeclared&lt;br /&gt;&lt;br /&gt;solution - sudo apt-get install zlib1g-dev, then rerun configure script, and all compiles fine.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3569666675299554168-5873664205701102162?l=bnpcs.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bnpcs.blogspot.com/2009/03/compiling-zettair-on-ubuntu.html</link><author>noreply@blogger.com (Andrew Yourtchenko)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3569666675299554168.post-7212640369306263902</guid><pubDate>Tue, 10 Mar 2009 22:46:00 +0000</pubDate><atom:updated>2009-03-11T00:42:26.371+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>zettair</category><title>Zettair is back alive</title><description>Hooray! &lt;a href="http://www.seg.rmit.edu.au/zettair/"&gt;Zettair&lt;/a&gt; folks down in Oz have revived the development. "in-development" version now online.&lt;br /&gt;&lt;br /&gt;Let's see what we have (with a brutal diff -rc across the directories :-) Disclaimer: this is not necessarily a complete list, at least in the autoconf part - the diff was fairly boring and long. &lt;br /&gt;Alternatively, I might have missed it in the set of whitelist changes or did not get a clue it was important...:)&lt;br /&gt;&lt;br /&gt;configure script got what looks a 64-bit "kfreebsd". Probably inherited with a newer version of autotools, but an interesting beast nonetheless, if I read it well, it is &lt;a href="http://www.debian.org/ports/kfreebsd-gnu/"&gt;here&lt;/a&gt;. GNU userland running on top of freebsd kernel.. The other tweaks belong to &lt;a href="http://www.dragonflybsd.org/"&gt;dragonflybsd&lt;/a&gt;. I heard about Hammer filesystem, but haven't tried the OS yet. Might be interesting. All depends on the H/w support.&lt;br /&gt;&lt;br /&gt;index.h: &lt;br /&gt;&lt;br /&gt;option INDEX_NEW_VOCAB is gone, INDEX_NEW_PARSEBUF (dictate how large the postings hashtable is) appeared. &lt;br /&gt;&lt;br /&gt;INDEX_NEW_NO_OFFSETS - build the index without offsets. Probably not very interesting for me... &lt;br /&gt;&lt;br /&gt;INDEX_NEW_QTHREADS - how many query threads to allow. Now I wonder if this allows for simultaneous query and indexing - that'd be sweet. My experiments with the previous version running separate processes were not terribly successful. With threads indeed it might be a different story.&lt;br /&gt;&lt;br /&gt;some other similar parameter changes to index_load (as opposed to index_new)&lt;br /&gt;&lt;br /&gt;index_cleanup is gone.&lt;br /&gt;&lt;br /&gt;INDEX_SEARCH_DYNAMIC_RANK - provide the text describing the rank to be used as well as the rank parameters. Interesting, probably a bit too advanced for my needs.&lt;br /&gt;&lt;br /&gt;autogenerated code for the metrics is obviously now parametrized.&lt;br /&gt;&lt;br /&gt;mutexes for various pieces (For multithreading)&lt;br /&gt;&lt;br /&gt;vocab_vector structure is simplified (looks like thanks to getting rid of multiple files)&lt;br /&gt;&lt;br /&gt;a lot of multithreaded-oriented code&lt;br /&gt;&lt;br /&gt;a hacko-fix in makeindex_append_docno to get around the fact that zettair can't handle docno-s bigger than a pagesize&lt;br /&gt;&lt;br /&gt;vocabury operations seem to be simplified - previously the memory management was more sophisticated.&lt;br /&gt;&lt;br /&gt;This completes the list - again, very probably I missed something important - if so, drop me a note in the comments.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3569666675299554168-7212640369306263902?l=bnpcs.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bnpcs.blogspot.com/2009/03/zettair-is-back-alive.html</link><author>noreply@blogger.com (Andrew Yourtchenko)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3569666675299554168.post-712372158224200921</guid><pubDate>Mon, 09 Mar 2009 21:55:00 +0000</pubDate><atom:updated>2009-03-09T23:08:39.396+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>llsd</category><category domain='http://www.blogger.com/atom/ns#'>ragel</category><title>LLSD scanning with ragel-made parser.</title><description>I've written a while ago about the &lt;a href="http://www.complang.org/ragel/"&gt;Ragel&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Today evening (literally in about 4 hours), I tried it and cooked a semi-functional parser for &lt;a href="http://tools.ietf.org/html/draft-hamrick-llsd"&gt;LLSD XML serialization&lt;/a&gt;. Yes, the code below was cranked from scratch in just a few hours :)&lt;br /&gt;&lt;br /&gt;What's nice is that it is can parse the data by chunks of practically any size, so could be used to grab the data over a slower TCP connection. And - the base64 decoding is included! Things that would need to be done in order to make it usable include proper error handling and a better approach to handle possibly large data - right now it is kind of dumb...&lt;br /&gt;&lt;br /&gt;Here's the result of running it over the sample XML from the draft:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ ./a.out `cat ../sample.llsd`&lt;br /&gt;Array start&lt;br /&gt;Integer: '42'&lt;br /&gt;UUID: '6bad258e06f04a87a659493117c9c162'&lt;br /&gt;Map start&lt;br /&gt;String: 'cold'&lt;br /&gt;Map member with key 'hot':'cold'&lt;br /&gt;Undef&lt;br /&gt;Map member with key 'higgs_boson_rest_mass':'&lt;undef&gt;'&lt;br /&gt;URI: 'https://example.org/r/6bad258e-06f0-4a87-a659-493117c9c162'&lt;br /&gt;Map member with key 'info_page':'https://example.org/r/6bad258e-06f0-4a87-a659-493117c9c162'&lt;br /&gt;Date: '2008-10-13T19:00.00Z'&lt;br /&gt;Map member with key 'status_report_due_by':'2008-10-13T19:00.00Z'&lt;br /&gt;Map end&lt;br /&gt;Array end&lt;br /&gt;result = 1&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And here goes the .rl code in case you're curious (maybe you need to "view source" in case it gets garbled):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#include &lt;string.h&gt;&lt;br /&gt;#include &lt;stdio.h&gt;&lt;br /&gt;#include &lt;stdlib.h&gt;&lt;br /&gt;&lt;br /&gt;typedef struct llsd_scanner {&lt;br /&gt;  char *accum;&lt;br /&gt;  int accum_size;&lt;br /&gt;  int accum_index;&lt;br /&gt;&lt;br /&gt;  char *key_accum;&lt;br /&gt;  int key_accum_size;&lt;br /&gt;  int key_accum_index;&lt;br /&gt;&lt;br /&gt;  unsigned char *bin_accum;&lt;br /&gt;  int bin_accum_size;&lt;br /&gt;  int bin_accum_index;&lt;br /&gt;  unsigned char b64chars[4];&lt;br /&gt;&lt;br /&gt;  // ragel variables&lt;br /&gt;  int *stack;&lt;br /&gt;  int stack_size;&lt;br /&gt;  int top;&lt;br /&gt;  int act;&lt;br /&gt;  int cs;&lt;br /&gt;  unsigned char *ts, *te;&lt;br /&gt;  &lt;br /&gt;} llsd_scanner_t;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;static const char cd64[]="|$$$}rstuvwxyz{$$$$$$$&gt;?@ABCDEFGHIJKLMNOPQRSTUVW$$$$$$XYZ[\\]^_`abcdefghijklmnopq";&lt;br /&gt;&lt;br /&gt;static void llsd_scanner_putb64char(llsd_scanner_t *scanner, int index, unsigned char v)&lt;br /&gt;{&lt;br /&gt;  v = (unsigned char) ((v &lt; 43 || v &gt; 122) ? 0 : cd64[ v - 43 ]);&lt;br /&gt;  if( v ) {&lt;br /&gt;    v = (unsigned char) ((v == '$') ? 0 : v - 61);&lt;br /&gt;  }&lt;br /&gt;  if (v) {&lt;br /&gt;    scanner-&gt;b64chars[index] = (unsigned char) (v - 1);&lt;br /&gt;  } else {&lt;br /&gt;    scanner-&gt;b64chars[index] = v;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;static void b64decodeblock( unsigned char in[4], unsigned char out[3] )&lt;br /&gt;{   &lt;br /&gt;    out[ 0 ] = (unsigned char ) (in[0] &lt;&lt; 2 | in[1] &gt;&gt; 4);&lt;br /&gt;    out[ 1 ] = (unsigned char ) (in[1] &lt;&lt; 4 | in[2] &gt;&gt; 2);&lt;br /&gt;    out[ 2 ] = (unsigned char ) (((in[2] &lt;&lt; 6) &amp; 0xc0) | in[3]);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;static int append_binchars(llsd_scanner_t *scanner)&lt;br /&gt;{&lt;br /&gt;  if (scanner-&gt;bin_accum_index + 4 &lt; scanner-&gt;bin_accum_size) {&lt;br /&gt;    b64decodeblock(scanner-&gt;b64chars, &amp;scanner-&gt;bin_accum[scanner-&gt;bin_accum_index]);&lt;br /&gt;    scanner-&gt;bin_accum_index += 3;&lt;br /&gt;    return -1;&lt;br /&gt;  } else {&lt;br /&gt;    printf("Bin accumulator overflow!");&lt;br /&gt;    return 0;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;static void clear_accum(char *accum, int *accum_index)&lt;br /&gt;{&lt;br /&gt;  *accum_index = 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;static int append_accum(char *accum, int accum_size, int *accum_index, unsigned char c)&lt;br /&gt;{&lt;br /&gt;  if (*accum_index &lt; accum_size-1) {&lt;br /&gt;    accum[(*accum_index)++] = c;&lt;br /&gt;    return -1;&lt;br /&gt;  } else {&lt;br /&gt;    return 0;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;static void terminate_accum(char *accum, int *accum_index)&lt;br /&gt;{&lt;br /&gt;  accum[*accum_index] = 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;%%{&lt;br /&gt;&lt;br /&gt;        machine LLSDScanner;&lt;br /&gt;&lt;br /&gt;        access scanner-&gt;;&lt;br /&gt;       &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        action terminate_accum { &lt;br /&gt;            terminate_accum(scanner-&gt;accum, &amp;scanner-&gt;accum_index); &lt;br /&gt;            printf("Accumulated: '%s'\n", scanner-&gt;accum); &lt;br /&gt;        }&lt;br /&gt;        action clear_accum { &lt;br /&gt;            clear_accum(scanner-&gt;accum, &amp;scanner-&gt;accum_index); &lt;br /&gt;            clear_accum(scanner-&gt;bin_accum, &amp;scanner-&gt;bin_accum_index); &lt;br /&gt;        }&lt;br /&gt;        action append_accum { &lt;br /&gt;            append_accum(scanner-&gt;accum, scanner-&gt;accum_size, &amp;(scanner-&gt;accum_index), fc);&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        action print_key_accum { &lt;br /&gt;            terminate_accum(scanner-&gt;key_accum, &amp;scanner-&gt;key_accum_index); &lt;br /&gt;            // printf("Key Accumulated: '%s'\n", scanner-&gt;key_accum); &lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        action clear_key_accum { &lt;br /&gt;            clear_accum(scanner-&gt;key_accum, &amp;scanner-&gt;key_accum_index); &lt;br /&gt;        }&lt;br /&gt;        action append_key_accum { &lt;br /&gt;            append_accum(scanner-&gt;key_accum, scanner-&gt;key_accum_size, &amp;scanner-&gt;key_accum_index, fc); &lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        action convert_string { &lt;br /&gt;            terminate_accum(scanner-&gt;accum, &amp;scanner-&gt;accum_index);&lt;br /&gt;            printf("String: '%s'\n", scanner-&gt;accum); &lt;br /&gt;        }&lt;br /&gt;        action convert_uuid { &lt;br /&gt;            terminate_accum(scanner-&gt;accum, &amp;scanner-&gt;accum_index);&lt;br /&gt;            printf("UUID: '%s'\n", scanner-&gt;accum); &lt;br /&gt;        }&lt;br /&gt;        action convert_uri { &lt;br /&gt;            terminate_accum(scanner-&gt;accum, &amp;scanner-&gt;accum_index);&lt;br /&gt;            printf("URI: '%s'\n", scanner-&gt;accum); &lt;br /&gt;        }&lt;br /&gt;        action convert_base64 { &lt;br /&gt;            terminate_accum(scanner-&gt;bin_accum, &amp;(scanner-&gt;bin_accum_index)); &lt;br /&gt;            printf("Binary Accumulated: '%s'\n", scanner-&gt;bin_accum); &lt;br /&gt;        }&lt;br /&gt;        action convert_date { &lt;br /&gt;            terminate_accum(scanner-&gt;accum, &amp;(scanner-&gt;accum_index)); &lt;br /&gt;            printf("Date: '%s'\n", scanner-&gt;accum); &lt;br /&gt;        }&lt;br /&gt;        action convert_integer { &lt;br /&gt;            terminate_accum(scanner-&gt;accum, &amp;(scanner-&gt;accum_index)); &lt;br /&gt;            printf("Integer: '%s'\n", scanner-&gt;accum); &lt;br /&gt;        }&lt;br /&gt;        action convert_real { &lt;br /&gt;            terminate_accum(scanner-&gt;accum, &amp;(scanner-&gt;accum_index)); &lt;br /&gt;            printf("Real: '%s'\n", scanner-&gt;accum); &lt;br /&gt;        }&lt;br /&gt;        action convert_undef { &lt;br /&gt;            terminate_accum(scanner-&gt;accum, &amp;(scanner-&gt;accum_index)); &lt;br /&gt;            strcpy(scanner-&gt;accum, "&lt;undef&gt;");&lt;br /&gt;            printf("Undef\n"); &lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        action assign_map_member { &lt;br /&gt;            printf("Map member with key '%s':'%s'\n", scanner-&gt;key_accum, scanner-&gt;accum); &lt;br /&gt;        }&lt;br /&gt;    &lt;br /&gt;        one_or_two = /[12]/ @append_accum;&lt;br /&gt;        zero_or_one = /[01]/ @append_accum;&lt;br /&gt;        zero_to_nine = /[0-9]/ @append_accum;&lt;br /&gt;        zero_to_two = /[0-2]/ @append_accum;&lt;br /&gt;        zero_to_three = /[0-3]/ @append_accum;&lt;br /&gt;        zero_to_five = /[0-5]/ @append_accum;&lt;br /&gt;        dot = '.' @append_accum;&lt;br /&gt;        dash = '-' @append_accum;&lt;br /&gt;        colon = ':' @append_accum;&lt;br /&gt;        dot_or_colon = /[.:]/ @append_accum;&lt;br /&gt;        letter_T = 'T' @append_accum;&lt;br /&gt;        letter_Z = 'Z' @append_accum;&lt;br /&gt;&lt;br /&gt;        date_fullyear = one_or_two . zero_to_nine . zero_to_nine . zero_to_nine;&lt;br /&gt;        date_month = zero_or_one . zero_to_nine;&lt;br /&gt;        date_mday = zero_to_three . zero_to_nine;&lt;br /&gt;        time_hour = zero_to_two . zero_to_nine;&lt;br /&gt;        time_minute = zero_to_five . zero_to_nine;&lt;br /&gt;        time_sec = zero_to_five . zero_to_nine;&lt;br /&gt;        time_secfrac = dot . zero_to_nine;&lt;br /&gt;        full_date = date_fullyear . dash . date_month . dash . date_mday;&lt;br /&gt;        partial_time = ( time_hour . colon . time_minute . colon . time_sec . time_secfrac |  time_hour . colon . time_minute . dot_or_colon . time_sec );&lt;br /&gt;        date_time = full_date . letter_T . partial_time . letter_Z;&lt;br /&gt;&lt;br /&gt;        maybe_space = space*;&lt;br /&gt;&lt;br /&gt;        some_string_char = /[^&lt;]/ @append_accum;&lt;br /&gt;        some_string = some_string_char*;&lt;br /&gt;&lt;br /&gt;        some_key_string_char = /[^&lt;]/ @append_key_accum;&lt;br /&gt;        some_key_string = some_key_string_char*;&lt;br /&gt;&lt;br /&gt;        # base64 parsing. Base64 characters come in series of 4&lt;br /&gt;&lt;br /&gt;        base64_char = [ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+=/];&lt;br /&gt;        action base64_one { llsd_scanner_putb64char(scanner, 0, fc); }&lt;br /&gt;        action base64_two { llsd_scanner_putb64char(scanner, 1, fc); }&lt;br /&gt;        action base64_three { llsd_scanner_putb64char(scanner, 2, fc); }&lt;br /&gt;        action base64_four { llsd_scanner_putb64char(scanner, 3, fc); }&lt;br /&gt;        action base64_four_chars { append_binchars(scanner); }&lt;br /&gt;&lt;br /&gt;        base64_first_char = base64_char @base64_one;&lt;br /&gt;        base64_second_char = base64_char @base64_two;&lt;br /&gt;        base64_third_char = base64_char @base64_three;&lt;br /&gt;        base64_fourth_char = base64_char @base64_four;&lt;br /&gt;&lt;br /&gt;        base64_four_chars = maybe_space . base64_first_char . maybe_space . base64_second_char . maybe_space . &lt;br /&gt;                            base64_third_char . maybe_space . base64_fourth_char @base64_four_chars;&lt;br /&gt;&lt;br /&gt;        base64_string = base64_four_chars+;&lt;br /&gt;&lt;br /&gt;        tag_start = maybe_space . '&lt;';&lt;br /&gt;        tag_end_nospace = '&lt;/';&lt;br /&gt;        tag_end = maybe_space . tag_end_nospace;&lt;br /&gt;&lt;br /&gt;        llsd_tag = /llsd&gt;/i;&lt;br /&gt;&lt;br /&gt;        undef_tag = /undef\/&gt;/i;&lt;br /&gt;        boolean_tag = /boolean&gt;/i;&lt;br /&gt;        integer_tag = /integer&gt;/i;&lt;br /&gt;        real_tag = /real&gt;/i;&lt;br /&gt;        uuid_tag = /uuid&gt;/i;&lt;br /&gt;        string_tag = /string&gt;/i;&lt;br /&gt;        date_tag = /date&gt;/i;&lt;br /&gt;        uri_tag = /uri&gt;/i;&lt;br /&gt;        binary_tag = /binary/i . (space . /encoding="base64"/i)? . '&gt;';&lt;br /&gt;&lt;br /&gt;        key_tag = /key&gt;/i;&lt;br /&gt;        map_tag = /map&gt;/i;&lt;br /&gt;        array_tag = /array&gt;/i;&lt;br /&gt;&lt;br /&gt;        action call_array { &lt;br /&gt;            printf("Array start\n");&lt;br /&gt;            fcall array_element; &lt;br /&gt;        }&lt;br /&gt;        action call_map { &lt;br /&gt;            printf("Map start\n");&lt;br /&gt;            fcall map_element; &lt;br /&gt;        }&lt;br /&gt;        action return_from_map { &lt;br /&gt;            printf("Map end\n");&lt;br /&gt;            fret; &lt;br /&gt;        }&lt;br /&gt;        action return_from_array { &lt;br /&gt;            printf("Array end\n");&lt;br /&gt;            fret; &lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        real_number = /[0-9]*/ @append_accum;&lt;br /&gt;        integer_number = /[0-9]*/ @append_accum;&lt;br /&gt;&lt;br /&gt;        hex_char = /[0-9a-fA-F]/ @append_accum;&lt;br /&gt;        uuid_val = hex_char{8,8} . '-'? . hex_char{4,4} . '-'? . hex_char{4,4} . '-'? . hex_char{4,4} . '-'? . hex_char{12,12};&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        action error { printf("Error!\n"); } &lt;br /&gt;        some_element = tag_start . (undef_tag @convert_undef&lt;br /&gt;                  | boolean_tag @clear_accum . ('true'|'false') . tag_end . boolean_tag&lt;br /&gt;                  | integer_tag @clear_accum . integer_number . tag_end . integer_tag @convert_integer&lt;br /&gt;                  | real_tag @clear_accum . real_number . tag_end . real_tag @convert_real&lt;br /&gt;                  | uuid_tag @clear_accum . uuid_val . tag_end . uuid_tag @convert_uuid&lt;br /&gt;                  | string_tag @clear_accum . some_string . tag_end_nospace . string_tag @convert_string&lt;br /&gt;                  | date_tag @clear_accum . date_time . tag_end . date_tag @convert_date&lt;br /&gt;                  | uri_tag @clear_accum . some_string . tag_end . uri_tag @convert_uri&lt;br /&gt;                  | binary_tag @clear_accum . base64_string . tag_end . binary_tag @convert_base64&lt;br /&gt;                  | array_tag @call_array &lt;br /&gt;                  | map_tag @call_map &lt;br /&gt;                  );&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        array_element := (some_element)* . tag_end . array_tag @return_from_array;&lt;br /&gt;&lt;br /&gt;        map_key_start = tag_start . key_tag @clear_key_accum;&lt;br /&gt;&lt;br /&gt;        map_key_end = '&lt;/' . key_tag @print_key_accum;&lt;br /&gt;&lt;br /&gt;        map_member = map_key_start . some_key_string . map_key_end . some_element @assign_map_member;&lt;br /&gt;&lt;br /&gt;        map_element := (map_member)* . tag_end . map_tag @return_from_map;&lt;br /&gt;&lt;br /&gt;        body = (some_element)?;&lt;br /&gt;&lt;br /&gt;        xml_preamble = /xml[^&gt;]*/i . '&gt;';&lt;br /&gt;&lt;br /&gt;        llsd_body = tag_start . ( '?' . xml_preamble . tag_start )? . llsd_tag . body . tag_end . llsd_tag; &lt;br /&gt;&lt;br /&gt;        main := llsd_body @{ res = 1; };&lt;br /&gt;&lt;br /&gt;}%%&lt;br /&gt;&lt;br /&gt;%% write data;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;void llsd_scanner_free(llsd_scanner_t *scanner)&lt;br /&gt;{&lt;br /&gt;  if(scanner-&gt;stack) { free(scanner-&gt;stack); }&lt;br /&gt;  if(scanner-&gt;key_accum) { free(scanner-&gt;key_accum); }&lt;br /&gt;  if(scanner-&gt;accum) { free(scanner-&gt;accum); }&lt;br /&gt;  if(scanner-&gt;bin_accum) { free(scanner-&gt;bin_accum); }&lt;br /&gt;  free(scanner);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;llsd_scanner_t *llsd_scanner_alloc(int key_accum_size, int accum_size, int bin_accum_size, int stack_size) &lt;br /&gt;{&lt;br /&gt;   int failure = 0;&lt;br /&gt;   llsd_scanner_t *scanner = calloc(1, sizeof(llsd_scanner_t));&lt;br /&gt;   if (scanner) {&lt;br /&gt;     scanner-&gt;bin_accum = malloc(bin_accum_size); &lt;br /&gt;     if (scanner-&gt;bin_accum) { &lt;br /&gt;       scanner-&gt;bin_accum_size = bin_accum_size;&lt;br /&gt;       scanner-&gt;accum = malloc(accum_size);&lt;br /&gt;       if (scanner-&gt;accum) {&lt;br /&gt;         scanner-&gt;accum_size = accum_size;&lt;br /&gt;         scanner-&gt;key_accum = malloc(key_accum_size);&lt;br /&gt;         if (scanner-&gt;key_accum) {&lt;br /&gt;           scanner-&gt;key_accum_size = key_accum_size;&lt;br /&gt;           scanner-&gt;stack = calloc(sizeof(int), stack_size);&lt;br /&gt;           if(scanner-&gt;stack) {&lt;br /&gt;             scanner-&gt;stack_size = stack_size;&lt;br /&gt;             %% write init;&lt;br /&gt;           } else {&lt;br /&gt;             failure = 1;&lt;br /&gt;           }&lt;br /&gt;         } else {&lt;br /&gt;           failure = 1;&lt;br /&gt;         }&lt;br /&gt;       } else {&lt;br /&gt;         failure = 1;&lt;br /&gt;       }&lt;br /&gt;     } else {&lt;br /&gt;       failure = 1;&lt;br /&gt;     }&lt;br /&gt;     if (failure) {&lt;br /&gt;       llsd_scanner_free(scanner);&lt;br /&gt;       scanner = NULL;&lt;br /&gt;     }&lt;br /&gt;   }&lt;br /&gt;   return scanner;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int llsd_scanner_run(llsd_scanner_t *scanner, char *chunk)&lt;br /&gt;{&lt;br /&gt;    char *p = chunk;&lt;br /&gt;    char *pe = chunk + strlen(chunk);&lt;br /&gt;    int res = 0;&lt;br /&gt;    // printf("Running parser on: %s, curr state: %i\n", chunk, scanner-&gt;cs);&lt;br /&gt;    %% write exec;&lt;br /&gt;    if (scanner-&gt;cs &amp;&amp; res == 0) {&lt;br /&gt;      res = -1;&lt;br /&gt;    }&lt;br /&gt;    return res;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;int main( int argc, char **argv )&lt;br /&gt;{&lt;br /&gt;  int res = 0;&lt;br /&gt;  int i = 1;&lt;br /&gt;  llsd_scanner_t *scan;&lt;br /&gt;  if ( argc &gt; 1 ) {&lt;br /&gt;    scan = llsd_scanner_alloc(1000, 1000, 32768, 100);&lt;br /&gt;    while(i &lt; argc) {&lt;br /&gt;      res = llsd_scanner_run(scan, argv[i]);&lt;br /&gt;      if (res == 0) {&lt;br /&gt;        printf("Error on chunk %d\n", i);&lt;br /&gt;        i = argc;&lt;br /&gt;      } else {&lt;br /&gt;      }&lt;br /&gt;      i++;&lt;br /&gt;    }&lt;br /&gt;    llsd_scanner_free(scan);&lt;br /&gt;  }&lt;br /&gt;  printf("result = %i\n", res);&lt;br /&gt;  return 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3569666675299554168-712372158224200921?l=bnpcs.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bnpcs.blogspot.com/2009/03/llsd-scanning-with-ragel-made-parser.html</link><author>noreply@blogger.com (Andrew Yourtchenko)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3569666675299554168.post-1508912708444225065</guid><pubDate>Wed, 25 Feb 2009 22:08:00 +0000</pubDate><atom:updated>2009-02-26T00:45:37.173+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>wow</category><category domain='http://www.blogger.com/atom/ns#'>c</category><category domain='http://www.blogger.com/atom/ns#'>cpp</category><title>Preprocessor directives for ruby (not!:)</title><description>At first I thought to do some more link-whoring - as I found precisely the search terms that are in the title of this post to lead to this blog... But then I though I will limit the on-topic information on the matter:&lt;br /&gt;&lt;br /&gt;1) You don't need a preprocessor for Ruby&lt;br /&gt;2) If you think you do, read up on metaprogramming - &lt;a href="http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html"&gt;_Why's article&lt;/a&gt; will be a good start to spend a good time thinking. &lt;br /&gt;&lt;br /&gt;But, this lead me back to the CPP - the preprocessor. Of course, beyond the &lt;a href="http://www0.us.ioccc.org/1995/vanschnitz.c"&gt;Obfuscated C contest entries&lt;/a&gt; that are of parlor entertainment value only, there is some more to that.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://chaos-pp.cvs.sourceforge.net/chaos-pp/order-pp/example/bottles.c?revision=1.10&amp;view=markup"&gt;Take a look at this one.&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;Then get it for infinite fun:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;cvs -d:pserver:anonymous@chaos-pp.cvs.sourceforge.net:/cvsroot/chaos-pp login &lt;br /&gt;cvs -z3 -d:pserver:anonymous@chaos-pp.cvs.sourceforge.net:/cvsroot/chaos-pp co -P chaos-pp&lt;br /&gt;cvs -z3 -d:pserver:anonymous@chaos-pp.cvs.sourceforge.net:/cvsroot/chaos-pp co -P order-pp&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And then go check out and mess with the examples:&lt;br /&gt;&lt;br /&gt;the .c file looks like:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;.....&lt;br /&gt;int main(void) {&lt;br /&gt;   printf&lt;br /&gt;     ("The 500th Fibonacci number is "&lt;br /&gt;      ORDER_PP(8stringize(8to_lit(8fib(8nat(5,0,0)))))&lt;br /&gt;      ".\n");&lt;br /&gt;   return 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;//&gt;&lt;br /&gt;// Unless you are already convinced, you should check, by&lt;br /&gt;// preprocessing this example, that the actual parameter to&lt;br /&gt;// `printf' in the above code is just a single string that&lt;br /&gt;// contains the 500th Fibonacci number in base 10.&lt;br /&gt;//&lt;br /&gt;// If you know the order of growth of Fibonacci numbers, you&lt;br /&gt;// probably realized that the result isn't exactly small. &lt;br /&gt;.....&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now, let's try it (stderr forwarded to the null for brevity, as it seems to spit some errors):&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;:~/tmp/order-pp/example$ cpp -I../inc fibonacci.c 2&gt;/dev/null | tail&lt;br /&gt;  return fib_iter(n, 0, 1);&lt;br /&gt;}&lt;br /&gt;# 63 "fibonacci.c"&lt;br /&gt;int main(void) {&lt;br /&gt;   printf&lt;br /&gt;     ("The 500th Fibonacci number is "&lt;br /&gt;      "139423224561697880139724382870407283950070256587697307264108962948325571622863290691557658876222521294125"&lt;br /&gt;      ".\n");&lt;br /&gt;   return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now, let's look at another example - average.c&lt;br /&gt;&lt;br /&gt;you define the macro AVERAGE as:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#define AVERAGE(...)                                    \&lt;br /&gt;((ORDER_PP(8seq_for_each_with_delimiter                 \&lt;br /&gt;           (8put,                                       \&lt;br /&gt;            8emit(8quote(+)),                           \&lt;br /&gt;            8tuple_to_seq(8quote((__VA_ARGS__)))))) /   \&lt;br /&gt; ORDER_PP(8to_lit(8tuple_size(8quote((__VA_ARGS__))))))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;and use it in your C code like:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;int main(void) {&lt;br /&gt;  printf(AVERAGE(3, 1, 4, 1, 5, 9, 2, 6, 5) == 4&lt;br /&gt;         ? "OK.\n"&lt;br /&gt;         : "ERROR!\n");&lt;br /&gt;&lt;br /&gt;  return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The code post-cpp looks like:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;int main(void) {&lt;br /&gt;  printf(((3 + 1 + 4 + 1 + 5 + 9 + 2 + 6 + 5) / 9) == 4&lt;br /&gt;         ? "OK.\n"&lt;br /&gt;         : "ERROR!\n");&lt;br /&gt;&lt;br /&gt;  return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Of course, it's only simple things like this that are so nice looking... Any nontrivial definitions cause giant single-liners - the worst nightmare for the debuggers and maintainers - so I would personally torture anyone who used this in the production code.. :)&lt;br /&gt;&lt;br /&gt;Nonetheless - pretty impressive stuff.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3569666675299554168-1508912708444225065?l=bnpcs.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bnpcs.blogspot.com/2009/02/preprocessor-directives-for-ruby-not.html</link><author>noreply@blogger.com (Andrew Yourtchenko)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3569666675299554168.post-2652697843005431582</guid><pubDate>Tue, 24 Feb 2009 23:21:00 +0000</pubDate><atom:updated>2009-02-25T00:36:49.148+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>embedded</category><category domain='http://www.blogger.com/atom/ns#'>potion</category><category domain='http://www.blogger.com/atom/ns#'>lua</category><title>The FONC project &amp; potion</title><description>While messing around looking if anyone did anything with &lt;a href="http://github.com/why/potion/tree/master"&gt;potion language&lt;/a&gt;, &lt;a href="http://bnpcs.blogspot.com/2009/02/potion-for-x86.html"&gt;that I wrote about a few days ago&lt;/a&gt;, found this interesting link:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://wiki.ruby-lang.nl/amsterdamrbwiki/show/The+FONC+project"&gt;http://wiki.ruby-lang.nl/amsterdamrbwiki/show/The+FONC+project&lt;/a&gt; - The Fundamentals OF New Computing. Has some interesting reading on research in programming languages.&lt;br /&gt;&lt;br /&gt;Potion itself is rather fun, though of course my microbenchmark was a bit of an over-joyous :)&lt;br /&gt;&lt;br /&gt;Yeah, while it looks to be pretty damn fast, &lt;a href="http://luajit.org/"&gt;LuaJIT&lt;/a&gt; is only about 1.7 times slower. Nonetheless, I'll play with it more, it is an interesting thing to mess around with - at least the internals. Syntax I am not so sure...&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Foo = Object delegated&lt;br /&gt;Foo def("xx", (x): "foo\n".)&lt;br /&gt;&lt;br /&gt;Bar = Foo delegated&lt;br /&gt;Bar def("yy", (x): "123\n".)&lt;br /&gt;&lt;br /&gt;a = Foo allocate&lt;br /&gt;b = Bar allocate&lt;br /&gt;&lt;br /&gt;a xx print&lt;br /&gt;b xx print&lt;br /&gt;b yy print&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Running this with potion will give you three lines "foo", "foo", and "123" - the middle one being the method of "Bar", "inherited" from "Foo". Did not dig on how to glue multiple mixins - _why wrote that it's incomplete, I'll see maybe some other day.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3569666675299554168-2652697843005431582?l=bnpcs.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bnpcs.blogspot.com/2009/02/fonc-project-potion.html</link><author>noreply@blogger.com (Andrew Yourtchenko)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3569666675299554168.post-4585313117076615395</guid><pubDate>Sat, 21 Feb 2009 22:36:00 +0000</pubDate><atom:updated>2009-02-22T00:27:39.678+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>a</category><title>What the world is interested in...</title><description>The other day, while searching for a "how to" on something, I became amused with the autosuggestions I got after typing in the "how to" into the search input editor.&lt;br /&gt;&lt;br /&gt;Assuming the results there are sorted by the interest from the users (which is something pretty obvious to do), this is the apparent hit parade of the things &lt;br /&gt;that the people are wondering about:&lt;br /&gt;&lt;br /&gt;1. how to tie a tie&lt;br /&gt;&lt;br /&gt;Ha. I wonder whether this stems from the fact that the people don't really wear a tie every day, so this knowledge gets into the dark corners of the forgotten, or the science of tying the tie is as complicated as actually spelling it. I've last had to use this search maybe half a year ago when I in fact needed to wear the tie to some place. The caching is a good optimization here - tie the tie once, and keep it tied. Saves a lot of time.&lt;br /&gt;&lt;br /&gt;2. how to kiss&lt;br /&gt;&lt;br /&gt;Something is wrong. This one was supposed to land on the first position IMO - as the potential audience for the ties is at most is half as big as the potential audience for the kisses. So, I can conclude that the sets are actually very much intersecting and it's the same folks who don't know how to tie a tie. Others either already know it or are practicing it off-line. Indeed, practice is the key here. Instead of optimizing, just brute-force it. The process is fun.&lt;br /&gt;&lt;br /&gt;3. how to get pregnant&lt;br /&gt;&lt;br /&gt;Now the mystery of the bias for the previous one is probably starting to dissolve - that second half is actually not wasting the time on paying too much attention to the preamble, and is much more result driven. I'd think that here the practice is also a key. Also, there's something about the days of the month and such. But with sufficient practice the distribution is going to be across all the days of the month, so it should not be that important.&lt;br /&gt;&lt;br /&gt;4. how to make money&lt;br /&gt;&lt;br /&gt;assuming your looks are ok - after all, the tie is an important part of it! - indeed, money might be of use sometimes. I think it's a simple economics - find the area with most demand that is unsatisfied, and provide a supply there. Even better - create the demand out of thin air - that's how you make new markets. The most creative and spectacular that readily comes up, is the &lt;a href="http://www.milliondollarhomepage.com/"&gt;one million pixel page&lt;/a&gt;. In a nutshell - create 1000x1000 image, and start selling it in blocks of 10x10. Hundred bucks each. I am in awe. &lt;br /&gt;&lt;br /&gt;5. how to lose weight&lt;br /&gt;&lt;br /&gt;I won't comment much on this one - it's outside of my experience. Although, a full long weekend of dedicated nonstop gaming with not much food inbetween gets quite a few kilos off. I accidentally tried that once - the result was pretty funny (needless to say I was dead tired after that). But I think that's not something anyone should follow - talk to your doctor, or something. Eat lighter food, do sports, and such.&lt;br /&gt;&lt;br /&gt;6. how to draw&lt;br /&gt;&lt;br /&gt;I wonder if this is about drawing as in a form of art or it about making sure that no-one wins. My best advise - find an artist nearby who is willing to bear with you, and use the results from the (4) above to pay for the lessons. Practice makes miracles. But it aint going to be easy, if you want to get decent that is. &lt;br /&gt;My wife's an artist and she literally spent years doing that thing. (oh, if you wanna get lessons, maybe I can ask, drop me a note :)&lt;br /&gt;&lt;br /&gt;7. how to make a website&lt;br /&gt;&lt;br /&gt;Hire a professional. &lt;br /&gt;&lt;br /&gt;8. how to cook a turkey&lt;br /&gt;&lt;br /&gt;Ah, this is a much more appropriate one. Though, no opinion here - I'm in europe and prefer chicken anyway. Or beef, for that matter.&lt;br /&gt;&lt;br /&gt;9. how to write a resume&lt;br /&gt;&lt;br /&gt;I'd do it in a couple of steps: first achieve a bunch of great things. Then write them down. Though, it's not a quick process. But should surely work. &lt;br /&gt;&lt;br /&gt;10. how to lose friends and alienate people&lt;br /&gt;&lt;br /&gt;Oh, that's easy - just write something outright silly like I did in this post, and it might work. Or go watch &lt;a href="http://www.imdb.com/title/tt0455538/"&gt;the film&lt;/a&gt; and learn from there.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3569666675299554168-4585313117076615395?l=bnpcs.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bnpcs.blogspot.com/2009/02/what-world-is-interested-in.html</link><author>noreply@blogger.com (Andrew Yourtchenko)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3569666675299554168.post-5460190835496046686</guid><pubDate>Wed, 18 Feb 2009 00:40:00 +0000</pubDate><atom:updated>2009-02-18T01:48:44.886+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>javascript</category><title>Sketching network diagrams - entirely in javascript, in your browser!</title><description>This is a bit of shameless self-advertising - I figured that if I don't advertise a little bit, I never know if there are some people that might benefit of this thing.&lt;br /&gt;&lt;br /&gt;Basically, if you want to scratch a network with a couple of routers and a cloud, now you do not need to start visio, dia, or anything else for that matter: just go to &lt;a href="http://employees.org/~andin/network/"&gt;http://employees.org/~andin/network/&lt;/a&gt;, draw the network, and snap the picture from the screen. &lt;br /&gt;&lt;br /&gt;Of course, it's all web2.x enabled and jazz, so you can save the layout as JSON, and load it later. Even, in a demonstration of a blatant violation of the security, you can pull in the JSON from another domain.&lt;br /&gt;&lt;br /&gt;A little bit of history: as I use linux at work pretty much exclusively, I was always curious to have something simple to draw the diagrams. Dia is an excellent program, but I wanted something even simpler. &lt;br /&gt;&lt;br /&gt;And so when I saw the &lt;a href="http://draw2d.org/draw2d/"&gt;Draw2D&lt;/a&gt; library I thought "ah-ha!".&lt;br /&gt;&lt;br /&gt;The editor is not way too much more than a combination of the existing components - you can see the ingredients on its page.&lt;br /&gt;&lt;br /&gt;Well, enough of me talking, &lt;a href="http://employees.org/~andin/network/"&gt;go try it&lt;/a&gt; and let me know :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3569666675299554168-5460190835496046686?l=bnpcs.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bnpcs.blogspot.com/2009/02/sketching-network-diagrams-entirely-in.html</link><author>noreply@blogger.com (Andrew Yourtchenko)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3569666675299554168.post-2366980395770719962</guid><pubDate>Mon, 16 Feb 2009 20:48:00 +0000</pubDate><atom:updated>2009-02-16T22:20:14.998+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>potion embedded lua</category><title>Potion for x86</title><description>Looking around, I stumbled on something interesting. &lt;a href="http://github.com/why/potion/tree/master"&gt;Potion&lt;/a&gt;. &lt;br /&gt;The source has an example:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;fib = (n):&lt;br /&gt;  if (n &lt;= 1): 1. else: fib (n - 1) + fib (n - 2)..&lt;br /&gt;fib (40)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Interesting. Looks a bit like OCaml/Haskell. Sort of. &lt;br /&gt;A microbenchmark for calculating fibonacci number in a very inefficient way :-)&lt;br /&gt;Let's time it:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ time ./potion example/fib.pn &lt;br /&gt;real    0m17.924s&lt;br /&gt;user    0m17.909s&lt;br /&gt;sys     0m0.008s&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now I'll try the similar-looking lua code:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;function fib(n) &lt;br /&gt;  local ret = 1;&lt;br /&gt;  if (n &gt; 1) then&lt;br /&gt;    ret = fib(n-1) + fib(n-2)&lt;br /&gt;  end&lt;br /&gt;  return ret&lt;br /&gt;end&lt;br /&gt;fib(40)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Timing it:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ time lua fib.lua &lt;br /&gt;real    2m18.566s&lt;br /&gt;user    2m18.089s&lt;br /&gt;sys     0m0.048s&lt;br /&gt;$&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now, with all my non-love to microbenchmarks, this does look quite interesting.&lt;br /&gt;If this baby has zero-based arrays, I might get seduced :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3569666675299554168-2366980395770719962?l=bnpcs.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bnpcs.blogspot.com/2009/02/potion-for-x86.html</link><author>noreply@blogger.com (Andrew Yourtchenko)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3569666675299554168.post-3414255080566341161</guid><pubDate>Tue, 10 Feb 2009 20:39:00 +0000</pubDate><atom:updated>2009-02-10T21:42:56.662+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>prosody</category><category domain='http://www.blogger.com/atom/ns#'>lua</category><title>One-shot makefile to install lua, prosody, and associated libs...</title><description>I've a couple of systems that I do not want to touch the "system-wide" packages on, so I hacked the following makefile to do a one-shot install of prosody. Pretty darn ugly, but does its job. Maybe could be of use to someone...(NB: beware of horribly long lines that are wrapped by the display!)&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;INSTALL_DIR_NO_TRAILER=/tmp/prosody-test-inst&lt;br /&gt;INSTALL_DIR=$(INSTALL_DIR_NO_TRAILER)/&lt;br /&gt;INSTALL_DIR_ESCAPED=`(echo $(INSTALL_DIR) | sed -e 's/\\//\\\\\\//g')`&lt;br /&gt;LUA_TARGET=linux&lt;br /&gt;LUASEC_PLATFORM=linux&lt;br /&gt;# Lua version number&lt;br /&gt;# (according to Lua 5.1 definition:&lt;br /&gt;# first version digit * 100 + second version digit&lt;br /&gt;# e.g. Lua 5.0.2 =&gt; 500, Lua 5.1 =&gt; 501, Lua 5.1.1 =&gt; 501)&lt;br /&gt;#&lt;br /&gt;LUA_VERSION_NUM=501&lt;br /&gt;LUA_TGZ=lua-5.1.4.tar.gz&lt;br /&gt;PROSODY_TGZ=prosody-0.3.0.tar.gz&lt;br /&gt;LUAEXPAT_TGZ=luaexpat-1.1.tar.gz&lt;br /&gt;LUASEC_TGZ=luasec-0.3.tar.gz&lt;br /&gt;LUASOCKET_TGZ=luasocket-2.0.2.tar.gz&lt;br /&gt;&lt;br /&gt;all: tarballs tmpdir build&lt;br /&gt;&lt;br /&gt;tarballs: $(LUA_TGZ) $(PROSODY_TGZ) $(LUAEXPAT_TGZ) $(LUASEC_TGZ) $(LUASOCKET_TGZ)&lt;br /&gt;&lt;br /&gt;build: install-dir lua-build prosody-build luaexpat-build luasec-build luasocket-build&lt;br /&gt;&lt;br /&gt;install-dir:&lt;br /&gt;        install -d $(INSTALL_DIR)&lt;br /&gt;&lt;br /&gt;lua-build: $(LUA_TGZ) tmpdir&lt;br /&gt;        echo $(INSTALL_DIR_ESCAPED)&lt;br /&gt;        # unpack        &lt;br /&gt;        (cd tmp; tar xzvf ../$(LUA_TGZ))&lt;br /&gt;        # fix the path in luaconf.h&lt;br /&gt;        (cd tmp; REAL_ROOT=$(INSTALL_DIR_ESCAPED); EDIT_CMD="s#\(LUA_ROOT\s\"\)\/usr\/local\/\(\"\)#\1$$REAL_ROOT\2#g"; cd lua-*/src; sed -i.bak -e $$EDIT_CMD luaconf.h)&lt;br /&gt;        # fix the install path in Makefile&lt;br /&gt;        (cd tmp; REAL_ROOT=$(INSTALL_DIR_ESCAPED); EDIT_CMD="s#\(INSTALL_TOP=\s\)\/usr\/local#\1$$REAL_ROOT#g"; cd lua-*; sed -i.bak -e $$EDIT_CMD Makefile)&lt;br /&gt;        # build and install&lt;br /&gt;        (cd tmp; cd lua-*; make $(LUA_TARGET); make install)&lt;br /&gt;&lt;br /&gt;prosody-build: $(PROSODY_TGZ) tmpdir&lt;br /&gt;        (cd tmp; tar xzvf ../$(PROSODY_TGZ))&lt;br /&gt;        (cd tmp; cd prosody-*; ./configure --prefix=$(INSTALL_DIR_NO_TRAILER) --with-lua=$(INSTALL_DIR_NO_TRAILER) --with-lua-lib=$(INSTALL_DIR_NO_TRAILER)/lib ;)&lt;br /&gt;        (cd tmp; REAL_ROOT=$(INSTALL_DIR_ESCAPED); EDIT_CMD="s#\(LFLAGS=\)#\1-L$$REAL_ROOT\/lib\nLFLAGS+=#g"; cd prosody-*; sed -i.bak -e $$EDIT_CMD config.unix)&lt;br /&gt;        (cd tmp; cd prosody-*; make install)&lt;br /&gt;&lt;br /&gt;luaexpat-build: $(LUAEXPAT_TGZ) tmpdir&lt;br /&gt;        (cd tmp; tar xzvf ../$(LUAEXPAT_TGZ))&lt;br /&gt;        # patch the config&lt;br /&gt;        (cd tmp; REAL_ROOT=$(INSTALL_DIR_ESCAPED); EDIT_CMD1="s#\(LUA_LIBDIR=\s\)#\1$${REAL_ROOT}lib\/lua\/5.1\n\##g"; EDIT_CMD2="s#\(LUA_DIR=\s\)#\1$${REAL_ROOT}share\/lua\/5.1\n\##g";  EDIT_CMD3="s#\(LUA_INC=\s\)#\1$${REAL_ROOT}include\n\##g"; EDIT_CMD4="s#\(LUA_VERSION_NUM=\s\)#\1$(LUA_VERSION_NUM)\n\##g"; cd luaexpat-*; sed -i.bak -e $$EDIT_CMD1 -e $$EDIT_CMD2 -e $$EDIT_CMD3 -e $$EDIT_CMD4 config)&lt;br /&gt;        # compile&lt;br /&gt;        (cd tmp; cd luaexpat-*; make; make install)&lt;br /&gt;&lt;br /&gt;luasec-build: $(LUASEC_TGZ) tmpdir&lt;br /&gt;        (cd tmp; tar xzvf ../$(LUASEC_TGZ))&lt;br /&gt;        # patch the config&lt;br /&gt;        (cd tmp; REAL_ROOT=$(INSTALL_DIR_ESCAPED); EDIT_CMD1="s#\(^LUAPATH=\)#\1$${REAL_ROOT}share\/lua\/5.1\n\##g"; EDIT_CMD2="s#\(^CPATH=\)#\1$${REAL_ROOT}lib\/lua\/5.1\n\##g";  EDIT_CMD3="s#\(^LUAPATH=\)#INCDIR=-I$${REAL_ROOT}include\n\1#g"; cd luasec-*; sed -i.bak -e $$EDIT_CMD1 -e $$EDIT_CMD2 -e $$EDIT_CMD3 Makefile)&lt;br /&gt;        (cd tmp; cd luasec-*; make $(LUASEC_PLATFORM) &amp;&amp; make install)&lt;br /&gt;&lt;br /&gt;luasocket-build: $(LUASOCKET_TGZ) tmpdir&lt;br /&gt;        (cd tmp; tar xzvf ../$(LUASOCKET_TGZ))&lt;br /&gt;        # patch the config&lt;br /&gt;        (cd tmp; REAL_ROOT=$(INSTALL_DIR_ESCAPED); EDIT_CMD1="s#\(INSTALL_TOP_LIB=\)#\1$${REAL_ROOT}lib\/lua\/5.1\n\##g"; EDIT_CMD2="s#\(INSTALL_TOP_SHARE=\)#\1$${REAL_ROOT}share\/lua\/5.1\n\##g";  EDIT_CMD3="s#LUAINC=-Ilua#\nLUAINC=-I$${REAL_ROOT}include\n\##g"; cd luasocket-*; sed -i.bak -e $$EDIT_CMD1 -e $$EDIT_CMD2 -e $$EDIT_CMD3 config)&lt;br /&gt;        # compile&lt;br /&gt;        (cd tmp; cd luasocket-*; make &amp;&amp; make install)&lt;br /&gt;        $(PROSODY_TGZ):&lt;br /&gt;        wget -c http://prosody.im/downloads/source/$(PROSODY_TGZ)&lt;br /&gt;&lt;br /&gt;$(LUA_TGZ):&lt;br /&gt;        wget -c http://www.lua.org/ftp/$(LUA_TGZ)&lt;br /&gt;&lt;br /&gt;$(LUAEXPAT_TGZ):&lt;br /&gt;        wget -c http://luaforge.net/frs/download.php/2469/luaexpat-1.1.tar.gz&lt;br /&gt;&lt;br /&gt;$(LUASEC_TGZ):&lt;br /&gt;        wget -c http://luaforge.net/frs/download.php/3920/luasec-0.3.tar.gz&lt;br /&gt;&lt;br /&gt;$(LUASOCKET_TGZ):&lt;br /&gt;        wget -c http://luaforge.net/frs/download.php/2664/luasocket-2.0.2.tar.gz&lt;br /&gt;&lt;br /&gt;tmpdir:&lt;br /&gt;        install -d tmp&lt;br /&gt;        &lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3569666675299554168-3414255080566341161?l=bnpcs.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bnpcs.blogspot.com/2009/02/one-shot-makefile-to-install-lua.html</link><author>noreply@blogger.com (Andrew Yourtchenko)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3569666675299554168.post-2964543705858294361</guid><pubDate>Mon, 09 Feb 2009 21:15:00 +0000</pubDate><atom:updated>2009-02-10T13:33:05.877+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>fosdem</category><title>The FOSDEM'09 memories of a yellow T-shirt...</title><description>...or - "how we had a lot of fun and a little bit of pressure at FOSDEM 2009".&lt;br /&gt;&lt;br /&gt;I planned to attend Fosdem, but I was pretty delighted to hear that Jerome managed to get our employer Cisco to provide the wireless networking gear for the event, so jumped in to grab the opportunity to give back to the community, and meet the new friends.&lt;br /&gt;&lt;br /&gt;It was a lot of fun - thanks to Jerome, Peter, Seb, Antonio, and of course to Fosdem organizers, staff, and indeed the visitors - folks, you rock! :)&lt;br /&gt;&lt;br /&gt;We had about 60 access points scattered around the area, so the wireless controller proved to be a very handy beast (it reduced the number of entities to actually "manage" to 3).&lt;br /&gt;&lt;br /&gt;Of course, being first time and all, it was quite a few hiccups - ranging anywhere from cables to configs to users "helping" by misconfiguring their gear to do an Ad-Hoc network with the same SSID, and me being slow like a snail in the morning :)&lt;br /&gt;&lt;br /&gt;The hardest things for me were escaping from the office at 4:30pm on Friday, and waking up before 10am on Saturday.&lt;br /&gt;&lt;br /&gt;But hopefully we might repeat the experiment next year and try some improvements - the first on the wishlist being the faster-than-halfduplex-10mbps uplink to internet - if we manage to borrow the toys again :-)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Correction&lt;/b&gt;: "60" was the number of "unknown/rogue APs", we had only 37. &lt;br /&gt;Duh!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3569666675299554168-2964543705858294361?l=bnpcs.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bnpcs.blogspot.com/2009/02/fosdem09-memories-of-yellow-t-shirt.html</link><author>noreply@blogger.com (Andrew Yourtchenko)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3569666675299554168.post-6151244742343612533</guid><pubDate>Sun, 08 Feb 2009 22:52:00 +0000</pubDate><atom:updated>2009-02-09T00:19:23.776+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>psy</category><title>It's a small world after all...</title><description>When we were enjoying the last hours of warm spanish weather in Barcelona on 29th January after Networkers, a few of us went to Parc Guell. It was pretty much closed, so we had a beer in a cafe which was conveniently situated here to take the profit from the wave of the visitors. And then on the way back I heard a man playing medieval Lute. Inside the ancient column-rich area - so the acoustic qualities of the area were fantastic.&lt;br /&gt;&lt;br /&gt;Having devoted a nonzero portion of my life to the classical guitar, I can fully appreciate the richness of this instrument - and maybe given its specific non-mainstream nature, the only music I get a chance to hear with it has quite a quality. As we did not have the time to listen, I bought a CD right there. And today I finally got to slide it in... and it's pure joy. So, looking at the cover of the CD I find the name of the person, and punch it in the facebook - "Hey, maybe you do not remember me. You play great. How can I get more?". Amazing how simple it is. &lt;br /&gt;&lt;br /&gt;Possibly some 10 years from now we will be able to get connected with someone via even a less material token of information - maybe just by recalling their image from our memory. And the world might become a much happier place then.  &lt;br /&gt;&lt;br /&gt;Or not.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3569666675299554168-6151244742343612533?l=bnpcs.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bnpcs.blogspot.com/2009/02/its-small-world-after-all.html</link><author>noreply@blogger.com (Andrew Yourtchenko)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3569666675299554168.post-1565022397575044844</guid><pubDate>Fri, 06 Feb 2009 01:38:00 +0000</pubDate><atom:updated>2009-02-06T02:45:29.691+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>programming</category><title>Refactoring - when I don't want to do something else</title><description>&lt;a href="http://startuplessonslearned.blogspot.com/2009/01/refactoring-yourself-out-of-business.html"&gt;Refactoring&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;With my hobby code, I've caught myself thinking refactoring mostly when I realise that the next chunk of code I am going to write is going to be inherently ugly or large and boring. A very good recipe which I found against that is to put the thing on the shelf for a week or two, and let the brain work in the background - the power of the subconscious "coprocessor" is very well suited for that. Usually in this kind of time frame I'd have the "eureka" moment which unlocks the process and I happily hum along till the next "bore-block". &lt;br /&gt;&lt;br /&gt;Maybe that't the reason why I don't code for food.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3569666675299554168-1565022397575044844?l=bnpcs.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bnpcs.blogspot.com/2009/02/refactoring-when-i-dont-want-to-do.html</link><author>noreply@blogger.com (Andrew Yourtchenko)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3569666675299554168.post-7453349996526478862</guid><pubDate>Mon, 02 Feb 2009 23:36:00 +0000</pubDate><atom:updated>2009-02-03T00:37:11.206+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>sockets</category><category domain='http://www.blogger.com/atom/ns#'>ipv6</category><title>Writing IPv4+IPv6 apps</title><description>A nice link I've stubbled upon: &lt;a href="http://gsyc.escet.urjc.es/~eva/IPv6-web/ipv6.html"&gt;http://gsyc.escet.urjc.es/~eva/IPv6-web/ipv6.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3569666675299554168-7453349996526478862?l=bnpcs.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bnpcs.blogspot.com/2009/02/writing-ipv4ipv6-apps.html</link><author>noreply@blogger.com (Andrew Yourtchenko)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3569666675299554168.post-6933302540469216979</guid><pubDate>Sun, 01 Feb 2009 14:40:00 +0000</pubDate><atom:updated>2009-02-01T16:06:18.654+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>4to4</category><category domain='http://www.blogger.com/atom/ns#'>ipv6</category><title>Finally getting a bit more of IPv6...</title><description>While I was at Networkers, Eric has sent me a nice teaser - a &lt;a href="http://apps.facebook.com/ipvsixchallenge/"&gt;Facebook app to test the IPv6 connectivity&lt;/a&gt;. I've played with "getting IPv6" a while ago, but wanted to give it another try. Yesterday I spent a long while mucking with OpenVPN + a tunnel to my internet host that would connect to V6 via 6to4. Slow and painful - if running 6to4, I'd rather run it locally... Alas - the DSL box does not have enough memory to run a V6-enabled IOS.&lt;br /&gt;&lt;br /&gt;As a result, I've now split the single-head setup into dual-head, with one (older) router functioning as a modem + bridge, and the other one running the PPPoE client and doing all the cool IPv6 stuff.&lt;br /&gt;&lt;br /&gt;I'll write up in a bit more details on how I have it in the upcoming days (leave comment if I want it sooner!), meantime a menu of nice links:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="https://www.sixxs.net/wiki/Configuring_Windows_Vista"&gt;Vista tips from SixXS&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://tldp.org/HOWTO/Linux+IPv6-HOWTO/configuring-ipv6to4-tunnels.html"&gt;A classic Linux 6to4 howto&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://wiki.nil.com/IPv6_over_IPv4_tunneling"&gt;Nicely done 6to4 doc for IOS&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3569666675299554168-6933302540469216979?l=bnpcs.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bnpcs.blogspot.com/2009/02/finally-getting-bit-more-of-ipv6.html</link><author>noreply@blogger.com (Andrew Yourtchenko)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3569666675299554168.post-7845476225665512336</guid><pubDate>Sat, 31 Jan 2009 00:52:00 +0000</pubDate><atom:updated>2009-05-12T02:16:14.639+02:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>wintures</category><title>Troubleshooting lenovo's wireless with Vista: plot thickens</title><description>In the &lt;a href="http://bnpcs.blogspot.com/2009/01/how-i-shot-myself-in-foot-twice-during.html"&gt;previous post&lt;/a&gt;, I came to a conclusion that it was the wireless driver update which sent my wireless on a new vista laptop south. Today I finally got some time to debug it a bit further...&lt;br /&gt;&lt;br /&gt;..And it turns out the previous conclusions were, well... not entirely correct. Ubuntu livecd certainly has very little to it from Vista - yet I got only 400kbps performance - while on the wired connection I got 4Mbps. Though, the connectivity appeared smoother, but maybe it is the more tolerant Linux TCP stack. So, the conclusion is that it is OS-independent, and how I got "good" performance in the first place is a mystery. &lt;br /&gt;&lt;br /&gt;The access point I'm using was an almost 10 years old noname 802.11b. Given that all the neighbouring ones are 802.11g, I think mine is probably driving the neighbours' data rates down, so probably a good time to go and get something newer - and write how it looks after that.&lt;br /&gt;&lt;br /&gt;Update:&lt;br /&gt;&lt;br /&gt;Even though I did not try the G access point, this link might explain it - at least the symptoms match very well: http://ubuntuforums.org/archive/index.php/t-1032617.html&lt;br /&gt;Now, how in the world that happened for both Vista and Linux - I don't know :-)&lt;br /&gt;&lt;br /&gt;Indeed updating the driver from the linuxwireless seemed to alleviate the problem for linux at least.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3569666675299554168-7845476225665512336?l=bnpcs.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bnpcs.blogspot.com/2009/01/troubleshooting-lenovos-wireless-with.html</link><author>noreply@blogger.com (Andrew Yourtchenko)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-3569666675299554168.post-6790015871615940312</guid><pubDate>Wed, 21 Jan 2009 18:29:00 +0000</pubDate><atom:updated>2009-01-21T20:03:06.889+01:00</atom:updated><category domain='http://www.blogger.com/atom/ns#'>lua</category><title>Interfacing Lua with C and hacking Lua syntax</title><description>After my initial experiments, I played last weekend a bit more with the lua+c integration - and indeed it is quite nice and flexible. My fears about the 1-based array indexing so far turn out to be a bit oversized - the biggest problem this would bring is when porting something from a 0-based language, when writing a new code from scratch it is in fact pretty straightforward (and the "for i,v in ipairs(array) do" iterator helps to avoid thinking about indices altogether).&lt;br /&gt;&lt;br /&gt;What's especially cool is the freedom it allows - to code parts in the high-level language, and parts in low-level C, and intermix them as needed. &lt;br /&gt;&lt;br /&gt;As a result, over the past weekend I've ported some "hobby" XML-parsing HTTP code over form Ruby to Lua with very little effort.&lt;br /&gt;&lt;br /&gt;Joyed with such an ease, for the work (reproducing a setup involving the signaling of a couple dozen thousand IP phones) I've written in just over a day a little helper code, which includes Lua itself + convenient framework to abstract all of the socket-handling details into much more highlevel structures, something like:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;function server_read(sock, data)&lt;br /&gt;  print("Server received ", string.len(data), "bytes:", data)&lt;br /&gt;  send(sock, "I got your data!\n")&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;function server_closed(sock)&lt;br /&gt;  print("Client disconnected!")&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;function server_incoming_connect(parent, remotehost, remoteport, newindex)&lt;br /&gt;  local server_methods = {&lt;br /&gt;            read = server_read;&lt;br /&gt;            close = server_closed&lt;br /&gt;            }&lt;br /&gt;  return server_methods&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;function server_main(process, number)&lt;br /&gt;  tcp_listen("0.0.0.0", 12345, { connect = server_incoming_connect })&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So, all of the socket low-level code (poll cycle, checking where the data has arrived, etc.) is hidden inside the compiled C blob, with the higher-level logic easily adjustable. Quite yummy :-)&lt;br /&gt;&lt;br /&gt;Overall it looks like Lua is definitely there to stay in my toolbox, which now will mainly contain Lua, C, and Ruby (though the biggest major advantage of the latter for now is the richness of the libraries and the lack of parentheses).&lt;br /&gt;&lt;br /&gt;Speaking of parentheses, I experimented with getting rid of parens in Lua - alongside with more Ruby-esque "def" and "elsif" - but in the end decided to throw it into garbage - primarily because of the danger of the confusion in the brain because of somewhat-similar-yet-quite-different semantics of the resulting "language" vs. Ruby, as well of some of the inconsistencies that arised as a result, i.e.:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;foo bar baz&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;would be the same as foo(bar(baz)), and baz, to be called, would need explicit parens. As well - a single-handed statement "baz" on the line would cause a syntax error. These all are pretty easily fixable (though then I'd need to have a way to specify that I want a function itself, not its call), but would break a lot of backward compatibility with Lua, which I wanted to have - hence not worth it.&lt;br /&gt;I'll better live with "elseif". :-) But the entertainment value of this experiment was certainly worth it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3569666675299554168-6790015871615940312?l=bnpcs.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://bnpcs.blogspot.com/2009/01/interfacing-lua-with-c-and-hacking-lua.html</link><author>noreply@blogger.com (Andrew Yourtchenko)</author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></item></channel></rss>