<?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:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0' version='2.0'><channel><atom:id>tag:blogger.com,1999:blog-23323574</atom:id><lastBuildDate>Mon, 16 Apr 2012 01:25:47 +0000</lastBuildDate><title>Meditation, The Art of Exploitation</title><description>Thinking? At last I have discovered it--thought; this alone is inseparable from me. I am, I exist--that is certain. But for how long? For as long as I am thinking. For it could be, that were I totally to cease from thinking, I should totally cease to exist....I am, then, in the strict sense only a thing that thinks.</description><link>http://meditation-art.blogspot.com/</link><managingEditor>noreply@blogger.com (Fei Liu)</managingEditor><generator>Blogger</generator><openSearch:totalResults>109</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-23323574.post-3338644812301936352</guid><pubDate>Mon, 07 Jul 2008 01:22:00 +0000</pubDate><atom:updated>2008-07-06T20:48:06.645-05:00</atom:updated><title>Windows Win32 APIs: changes from win95/98/2000 to XP</title><description>I needed to code a simple http downloader, a dialog based win32 application. This application provides a simple UI to allow user to put in an URL and click a button to start downloading. Initially I also want to provide a RichEdit text area to log transactions and messages for debugging/diagnosis purpose. &lt;br /&gt;&lt;br /&gt;I used to program win32 applications on windows 2000 platform with visual c++ 6.0, using a CmnHdr.H dialog template. This header file has some convenience macros to easily define win32 message handlers. The first problem I encountered is on Windows XP, this header file no longer works well. It can still be made to work after some modifications but the template needs adjustment. It made more sense to throw away to header file and template and just code the dialog box directly using this example code:&lt;br /&gt;&lt;source&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#define STRICT&lt;br /&gt;#define WIN32_LEAN_AND_MEAN&lt;br /&gt;#include &lt;windows.h&gt;&lt;br /&gt;#include "resource.h"&lt;br /&gt;&lt;br /&gt;BOOL CALLBACK DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {&lt;br /&gt; switch (message) {&lt;br /&gt;  case WM_INITDIALOG:&lt;br /&gt;   return (TRUE);&lt;br /&gt;  case WM_COMMAND:&lt;br /&gt;   switch (wParam) {&lt;br /&gt;    case IDOK:&lt;br /&gt;    case IDCANCEL:&lt;br /&gt;     EndDialog(hDlg, TRUE);&lt;br /&gt;     return (TRUE);&lt;br /&gt;     }&lt;br /&gt;   break;&lt;br /&gt; }&lt;br /&gt;return (FALSE);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {&lt;br /&gt; int ReturnValue;&lt;br /&gt;        ReturnValue = DialogBoxParam(NULL, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DialogProc, NULL);&lt;br /&gt;        return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/source&gt;&lt;br /&gt;&lt;br /&gt;The 2nd problem really puzzled me. My dialogbox won't show up no matter what. DialogBox returned -1 but GetLastError returned 0. Debugging into the win32 library code quickly showed me that there is something intricately wrong and -1 is returned from win32 internals. After spending many hours to resolve this issue, I finally found the solution from the win32.programmer.ui newsgroups. The answer is an win32 API called InitCommonControlsEx. On WinXP, one must call this API to use standard controls, otherwise the syptom is exactly as I described, the dialogbox won't show up (for some people, the dialog box would show up but without controls). &lt;br /&gt;&lt;br /&gt;References:&lt;br /&gt;1. http://simplesamples.info/Windows/DlgHello.php&lt;br /&gt;2. http://msdn.microsoft.com/en-us/library/bb775697(VS.85).aspx&lt;div class="blogger-post-footer"&gt;Meditation, The Art of Exploitation&lt;/div&gt;</description><link>http://meditation-art.blogspot.com/2008/07/windows-win32-apis-changes-from.html</link><author>noreply@blogger.com (Fei Liu)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-23323574.post-3179610800253325820</guid><pubDate>Wed, 14 May 2008 21:43:00 +0000</pubDate><atom:updated>2008-05-14T17:10:58.080-05:00</atom:updated><title>C++: static initialization order fiasco and mixed language programming</title><description>As c++ faq-lite puts it, 'static initialization order fiasco' is "a subtle way to crash your program" (1). The C++ run time system exhibits a phenomenon, static objects in the global scope can initialize in arbitrary order between different builds. In other words, if there are two static objects in the global scope called A and B in a program, in one build with a compiler on a platform, A could initialize before B but on another platform with another compiler in a different build, B could initialize before A. This could happen even on a single platform with a single compiler but different build options (e.g. optimization levels)&lt;br /&gt;&lt;br /&gt;The similarity of compiler dependency is striking between this problem and the RVO problem in the previous entry. And *similarly* any failure is a indication of coding defect by the programmer. A hypothetical scenario with the 'static initialization order fiasco' is such:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;sourcecode&gt;&lt;br /&gt;&lt;br /&gt;A.hpp&lt;br /&gt;struct A{&lt;br /&gt;   static bool initialized;&lt;br /&gt;   A() : initialized(true) {}&lt;br /&gt;};&lt;br /&gt;A.cpp&lt;br /&gt;bool A::initialized;&lt;br /&gt;&lt;br /&gt;B.hpp&lt;br /&gt;struct B{&lt;br /&gt;   B(){&lt;br /&gt;       if(A::initialized) x = 1;&lt;br /&gt;       else x = 0;&lt;br /&gt;   }&lt;br /&gt;   static int x;&lt;br /&gt;};&lt;br /&gt;int B:x;&lt;br /&gt;&lt;br /&gt;C.cpp&lt;br /&gt;void foo(){&lt;br /&gt;    int fiasco = B:x;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/sourcecode&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;What should be the value of fiasco inside foo when the program runs? It could be either 0 or 1. Thus the program exhibits unreliable behavior.&lt;br /&gt;&lt;br /&gt;Ok, now we know what's 'static initialization order fiasco', what does it have to do with mixed language programming? In mixed language programming, specifically between C++ and something else, let's say G, if G's run time system is dominate and starting user code is written in G (compiled and linked with G compiler/linker), G should refrain from calling any C++ code that may reference static objects (e.g. void foo()). Take a look at this bug.&lt;br /&gt;&lt;br /&gt;Process received signal 11 (SIGSEGV)&lt;br /&gt;__CPR123____ls__tm__30_Q2_3std20char_traits__tm__2_c__3stdFRQ2_3std25basic_ostre/opt/ctl/CC/5.5.0.9/include/ostream+???    (???) at ostream&lt;br /&gt;                c_strings_+0x00F0 (0x1004AF0) at A.C:48&lt;br /&gt;               stringtest_+0x0874 (0x1022374) at B.F90:77 &lt;br /&gt;&lt;br /&gt;Here is A.C:48&lt;br /&gt;      cout &lt;&lt; "\n\n-- entering c_strings" &lt;&lt; endl;&lt;br /&gt;&lt;br /&gt;http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12&lt;div class="blogger-post-footer"&gt;Meditation, The Art of Exploitation&lt;/div&gt;</description><link>http://meditation-art.blogspot.com/2008/05/c-static-initialization-order-fiasco.html</link><author>noreply@blogger.com (Fei Liu)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-23323574.post-5723171138975673719</guid><pubDate>Tue, 13 May 2008 20:19:00 +0000</pubDate><atom:updated>2008-05-13T16:59:43.933-05:00</atom:updated><title>C++: return value optimization (RVO) and reference class member</title><description>Recently I was experimenting with expression templates (1,2), I was making good progress with my toy code until suddenly I started getting correct answer from optimized build (-O2) and segmentation faults from debug build (-O0). With judicious object creation/destruction tracer code, it's clear to me return value optimization (3,4) or RVO is playing a trick here. This is troublesome as the program behavior depends on unreliable optimization from a compiler. When RVO optimization is not available, the program produces wrong result. This syndrome typically means there is a problem in the source code that binds variables (reference or pointer type) to temporary stack object and later references it while the temporary stack object has gone out of scope and become invalid. &lt;br /&gt;&lt;br /&gt;The source code will make the problem clearer and easier to explain:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;sourcecode&gt;&lt;br /&gt;#include &lt; iostream&gt;&lt;br /&gt;using namespace std;&lt;br /&gt;&lt;br /&gt;template &lt; typename E&gt;&lt;br /&gt;struct expr {&lt;br /&gt;    double eval() const {&lt;br /&gt;        return e.eval();&lt;br /&gt;    };&lt;br /&gt;    double eval() {&lt;br /&gt;        return e.eval();&lt;br /&gt;    };&lt;br /&gt;&lt;br /&gt;    expr(const E &amp; e) : e(e) {}&lt;br /&gt;    E e;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;class Literal {&lt;br /&gt;public:&lt;br /&gt;   Literal(double v) : val_(v) {}&lt;br /&gt;   double eval() const { return val_; }&lt;br /&gt;private:&lt;br /&gt;   const double val_;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;class Variable {&lt;br /&gt;public:&lt;br /&gt;   Variable(double&amp; v) : val_(v) { cout &lt;&lt; &amp;val_ &lt;&lt; " default initialized " &lt;&lt; id++ &lt;&lt; endl;}&lt;br /&gt;   Variable(const Variable &amp; v) : val_(*&amp;(v.val_)) { cout &lt;&lt; &amp;val_ &lt;&lt; " copy initialized " &lt;&lt; this &lt;&lt; ' ' &lt;&lt; *(double *)this &lt;&lt; ' ' &lt;&lt; id++ &lt;&lt; endl; }&lt;br /&gt;   ~Variable() { cout &lt;&lt; &amp;val_ &lt;&lt; " destroyed" &lt;&lt; endl; }&lt;br /&gt;   double eval() const { cout &lt;&lt; &amp;val_ &lt;&lt; " eval " &lt;&lt; this &lt;&lt; ' ' &lt;&lt; &amp;(this-&gt;val_) &lt;&lt; endl; return val_; }&lt;br /&gt;private:&lt;br /&gt;   double&amp; val_;&lt;br /&gt;   static int id;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;int Variable::id = 0;&lt;br /&gt;&lt;br /&gt;// Abstraction of a binary expression&lt;br /&gt;template &lt; typename expr1, typename expr2, typename binop&gt;&lt;br /&gt;struct BinaryExpr {&lt;br /&gt;    double eval() const {&lt;br /&gt;        return binop::eval(_expr1.eval(), _expr2.eval());&lt;br /&gt;    }&lt;br /&gt;    BinaryExpr(const expr1 &amp; e1, const expr2 &amp; e2)&lt;br /&gt;     : _expr1(e1),_expr2(e2) {}&lt;br /&gt;    BinaryExpr(const BinaryExpr &amp; be) : _expr1(be._expr1), _expr2(be._expr2) { cout &lt;&lt; "BE copy initiailized" &lt;&lt; endl; }&lt;br /&gt;private:&lt;br /&gt;    const expr1 &amp; _expr1; &lt;br /&gt;    // Cannot use reference here (const expr1 &amp;) because _expr1 may refer to a temporary stack object and becomes invalid when the bound object went ou&lt;br /&gt;t of scope later&lt;br /&gt;    const expr2 &amp; _expr2;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;// Abstraction of semantic plus operation '+'&lt;br /&gt;struct plusOp {&lt;br /&gt;    static double eval (const double &amp; d1, const double &amp; d2) {&lt;br /&gt;        return d1 + d2;&lt;br /&gt;    }&lt;br /&gt;};&lt;br /&gt;// Expression Traits class, convert primitive type to Literal type&lt;br /&gt;template &lt; typename T&gt;&lt;br /&gt;struct ExprTraits&lt;br /&gt;{&lt;br /&gt;    typedef T type;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;template &lt;&gt;&lt;br /&gt;struct ExprTraits&lt; int&gt;&lt;br /&gt;{&lt;br /&gt;    typedef Literal type;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;template &lt;&gt;&lt;br /&gt;struct ExprTraits&lt; double&gt;&lt;br /&gt;{&lt;br /&gt;    typedef Literal type;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;// This is the critical piece in building expression template&lt;br /&gt;// An overloaded operator builds an expression that can be evaluated later.&lt;br /&gt;template &lt; typename expr1, typename expr2&gt;&lt;br /&gt;expr&lt; BinaryExpr&lt; typename ExprTraits&lt; expr1&gt;::type, typename ExprTraits&lt; expr2&gt;::type, plusOp&gt; &gt;&lt;br /&gt;operator + (const expr1 &amp; e1, const expr2 &amp; e2){&lt;br /&gt;    typedef BinaryExpr&lt; typename ExprTraits&lt; expr1&gt;::type, typename ExprTraits&lt; expr2&gt;::type, plusOp&gt; ExprT;&lt;br /&gt;    return expr&lt; ExprT&gt;(ExprT(typename ExprTraits&lt; expr1&gt;::type(e1), typename ExprTraits&lt; expr2&gt;::type(e2)));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;template &lt; typename E&gt;&lt;br /&gt;double eval(expr&lt; E&gt; e){&lt;br /&gt;    return e.eval();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int main(){&lt;br /&gt;&lt;br /&gt;    double x = 10;&lt;br /&gt;    Variable v(x);&lt;br /&gt;    Literal l(3);&lt;br /&gt;    cout &lt;&lt; &amp;x &lt;&lt; ' ' &lt;&lt; x &lt;&lt; endl;&lt;br /&gt;&lt;br /&gt;    // evaluate expressions&lt;br /&gt;    cout &lt;&lt; sizeof(v) &lt;&lt; ' ' &lt;&lt; eval(v + 10.0) &lt;&lt; endl;&lt;br /&gt;}&lt;br /&gt;&lt;/sourcecode&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The problem as indicated in the source code comment, is with the member variables _expr1, _expr2 of BinaryExpr. BinaryExpr can be constructed from 2 participating expressions (e1, e2). When _expr1 is declared as const expr1 &amp;, it binds to the first argument e1. This is the problem, when RVO is not available, it's conceivable (as shown in this example) that BinaryExpr's constructor can be invoked with temporary stack objects as arguments. When it happens, _expr1 is bound to a stack local object and later on causes erratic program behavior when referenced as the stack local object went out of scope. To fix this, a deep copy (more precisely until nothing is bound to temporary objects that can go out of scope independently) is required.&lt;br /&gt;&lt;br /&gt;Careful readers may raise the question why in Variable, there is a 'double &amp; val_'. Will this be a problem? Yes and No. Yes, in general, it holds true that a reference or a pointer type variable (regardless if it's a class member variable or not) when bound to a temporary stack local variable should never *dereference* that object later when the object goes out of scope. No, in this toy program, all 'double &amp; val_' in all Variable instances are carefully referenced to '10.0' in the expression in main function and '10.0' only goes out of scope when eval() finishes and therefore the code is safe from the dreaded 'dereferencing dead (out of scope) object' problem.&lt;br /&gt;&lt;br /&gt;References:&lt;br /&gt;1. http://www.ddj.com/cpp/184401627&lt;br /&gt;2. http://ubiety.uwaterloo.ca/~tveldhui/papers/Expression-Templates/exprtmpl.html&lt;br /&gt;3. http://www.cs.cmu.edu/~gilpin/c++/performance.html&lt;br /&gt;4. http://msdn.microsoft.com/en-us/library/ms364057(VS.80).aspx#nrvo_cpp05_topic4&lt;div class="blogger-post-footer"&gt;Meditation, The Art of Exploitation&lt;/div&gt;</description><link>http://meditation-art.blogspot.com/2008/05/c-return-value-optimization-rvo-and.html</link><author>noreply@blogger.com (Fei Liu)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-23323574.post-6533252548629307611</guid><pubDate>Mon, 07 Apr 2008 16:57:00 +0000</pubDate><atom:updated>2008-05-13T15:18:46.187-05:00</atom:updated><title>FPGA: LCD display from RS232 interface</title><description>After more than a month's of studying of verilog and fpga design, I am proud to present the result of my first mini-project. Controlling Spartan3A LCD display with RS232 serial interface from a host computer. The setup is very simple:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;minicom (linux host) &lt;------&gt; RS232 (J27) &lt;-------&gt; LCD (DISP1)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I used the 2 serial interface modules from fpga4fun.com (async_receiver and async_transmitter). I implemented the main serial to lcd control module and the lcd display module. The lcd display module implementation is especially gratifying after it was completed. I learnt a great deal about finite state machine implementation in verilog and how sequential/combinatorial logic work together. Here is the state machine of the lcd controller (drawn using qfsm):&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_Z8d_fzejWt4/R_pU3-3Wx9I/AAAAAAAAC54/dyiJqhYWimg/s1600-h/lcd_controller_fsm.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_Z8d_fzejWt4/R_pU3-3Wx9I/AAAAAAAAC54/dyiJqhYWimg/s320/lcd_controller_fsm.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5186551241615263698" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;As you can see, state 2,3,4,5 (I didn't use one-hot encoding) all require that certain signal lines driven at a certain value for a certain amount of time (or number of clks). To achieve such kind of effect, one need to combine a FSM with a counter. The technical details of the requirements can be found in Spartan3A revion D's user's guide (ug334.pdf) in the LCD section.&lt;br /&gt;&lt;br /&gt;The implementation of the lcd controller follows:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;sourcecode&gt;&lt;br /&gt;module lcd_controller (clk, rst_n, data_ready, rx_data, lcd_rs, lcd_rw, lcd_e, lcd_4, lcd_5, lcd_6, lcd_7);&lt;br /&gt;&lt;br /&gt;parameter k = 18;&lt;br /&gt;// in register_input mode, the input doesn't have to stay valid&lt;br /&gt;// while the character is being transmitted&lt;br /&gt;parameter register_input = 1;&lt;br /&gt;parameter clr = 8'h0A;&lt;br /&gt;&lt;br /&gt;input                   clk;        // synthesis attribute PERIOD clk "50 MHz"&lt;br /&gt;input                   rst_n;&lt;br /&gt;input                   data_ready;&lt;br /&gt;input   [7:0]           rx_data;&lt;br /&gt;output                  lcd_rs;&lt;br /&gt;output                  lcd_rw;&lt;br /&gt;output                  lcd_e;&lt;br /&gt;output                  lcd_7;&lt;br /&gt;output                  lcd_6;&lt;br /&gt;output                  lcd_5;&lt;br /&gt;output                  lcd_4;&lt;br /&gt;&lt;br /&gt;reg lcd_e, lcd_rs, lcd_rw, lcd_7, lcd_6, lcd_5, lcd_4;&lt;br /&gt;&lt;br /&gt;reg     [k+8:0]         count;&lt;br /&gt;reg     [6:0]           lcd_code;&lt;br /&gt;reg     [2:0]           state;&lt;br /&gt;reg     [2:0]           next_state;&lt;br /&gt;&lt;br /&gt;wire lcd_ready = (state==1);&lt;br /&gt;&lt;br /&gt;// store rx_data locally&lt;br /&gt;reg     [7:0]           lcd_dataReg;&lt;br /&gt;always @(posedge clk) if(data_ready &amp; lcd_ready) lcd_dataReg &lt;= rx_data;&lt;br /&gt;wire    [7:0]           lcd_dataD = register_input ? lcd_dataReg : rx_data;&lt;br /&gt;&lt;br /&gt;// continuous assignment by default of wire type, clr key clears display&lt;br /&gt;wire clear = (rx_data == clr)? 1:0;&lt;br /&gt;//assign {lcd_e,lcd_rs,lcd_rw,lcd_7,lcd_6,lcd_5,lcd_4} = lcd_code;&lt;br /&gt;&lt;br /&gt;// sequential logic&lt;br /&gt;always @ (posedge clk or negedge rst_n)&lt;br /&gt;begin&lt;br /&gt;    if(~rst_n)&lt;br /&gt;    begin&lt;br /&gt;        state &lt;= 0;&lt;br /&gt;        next_state &lt;= 0;&lt;br /&gt;        count &lt;= 0;&lt;br /&gt;        lcd_code[6:0] &lt;= 0;&lt;br /&gt;    end&lt;br /&gt;    else&lt;br /&gt;        state &lt;= next_state;&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;always @ (posedge clk)&lt;br /&gt;begin&lt;br /&gt;    case (state)&lt;br /&gt;        3'b000: count &lt;= count + 1;&lt;br /&gt;        3'b001: count &lt;= 0;&lt;br /&gt;        3'b010: count &lt;= (count[4]? 0 : count + 1);&lt;br /&gt;        3'b011: count &lt;= (count[5]? 0 : count + 1);&lt;br /&gt;        3'b100: count &lt;= (count[4]? 0 : count + 1);&lt;br /&gt;        3'b101: count &lt;= (count[10]? 0 : count + 1);&lt;br /&gt;        3'b110: count &lt;= count + 1;&lt;br /&gt;    endcase&lt;br /&gt;    {lcd_e,lcd_rs,lcd_rw,lcd_7,lcd_6,lcd_5,lcd_4} &lt;= lcd_code;&lt;br /&gt;    if(state == 0 || state == 6) lcd_e &lt;= ^count[k+1:k];&lt;br /&gt;end // sequential logic&lt;br /&gt;&lt;br /&gt;// combinatorial logic&lt;br /&gt;always @ (state or count or data_ready or clear) begin&lt;br /&gt;    case(state)&lt;br /&gt;        3'b000:&lt;br /&gt;        begin&lt;br /&gt;            if(count[k+5:k+2] == 12)&lt;br /&gt;                next_state = 3'b1;         // idle_data/1&lt;br /&gt;            else&lt;br /&gt;                next_state = 0;&lt;br /&gt;        end&lt;br /&gt;        3'b001:&lt;br /&gt;        begin&lt;br /&gt;            if(data_ready) begin&lt;br /&gt;                if(clear)&lt;br /&gt;                    next_state = 3'b110;   // clear/6&lt;br /&gt;                else&lt;br /&gt;                    next_state = 3'b10;    // disp_hn/2&lt;br /&gt;            end&lt;br /&gt;            else&lt;br /&gt;                next_state = 3'b1;         // idle_data/1&lt;br /&gt;        end&lt;br /&gt;        3'b010:&lt;br /&gt;        begin&lt;br /&gt;            if(count[4])&lt;br /&gt;                next_state = 3'b11;        // idle_high/3&lt;br /&gt;            else&lt;br /&gt;                next_state = 3'b10;        // disp_hn/3&lt;br /&gt;        end&lt;br /&gt;        3'b011:&lt;br /&gt;        begin&lt;br /&gt;            if(count[5])&lt;br /&gt;                next_state = 3'b100;       // disp_ln/4&lt;br /&gt;            else&lt;br /&gt;                next_state = 3'b11;        // idle_high/3&lt;br /&gt;        end&lt;br /&gt;        3'b100:&lt;br /&gt;        begin&lt;br /&gt;            if(count[4])&lt;br /&gt;                next_state = 3'b101;       // wait/5&lt;br /&gt;            else&lt;br /&gt;                next_state = 3'b100;       // disp_ln/4&lt;br /&gt;        end&lt;br /&gt;        3'b101:&lt;br /&gt;        begin&lt;br /&gt;            if(count[10])&lt;br /&gt;                next_state = 3'b1;         // idle_data/1&lt;br /&gt;            else&lt;br /&gt;                next_state = 3'b101;       // wait/5&lt;br /&gt;        end&lt;br /&gt;        3'b110:&lt;br /&gt;        begin&lt;br /&gt;            if(count[k+3:k+2] == 2)&lt;br /&gt;                next_state = 3'h1;         // idle_data/1&lt;br /&gt;            else&lt;br /&gt;                next_state = 3'h6;         // clear/6&lt;br /&gt;        end&lt;br /&gt;    endcase&lt;br /&gt;end // combinatorial logic&lt;br /&gt;&lt;br /&gt;// output logic&lt;br /&gt;always @(state or count or lcd_dataD) begin&lt;br /&gt;    lcd_code &lt;= 7'h00;&lt;br /&gt;    case(state)&lt;br /&gt;        3'b000:&lt;br /&gt;        begin&lt;br /&gt;            case (count[k+5:k+2])&lt;br /&gt;                0: lcd_code &lt;= 7'h43;        // power-on initialization&lt;br /&gt;                1: lcd_code &lt;= 7'h43;&lt;br /&gt;                2: lcd_code &lt;= 7'h43;&lt;br /&gt;                3: lcd_code &lt;= 7'h42;&lt;br /&gt;                4: lcd_code &lt;= 7'h42;        // function set&lt;br /&gt;                5: lcd_code &lt;= 7'h48;&lt;br /&gt;                6: lcd_code &lt;= 7'h40;        // entry mode set&lt;br /&gt;                7: lcd_code &lt;= 7'h46;&lt;br /&gt;                8: lcd_code &lt;= 7'h40;        // display on/off control&lt;br /&gt;                9: lcd_code &lt;= 7'h4C;&lt;br /&gt;              10: lcd_code &lt;= 7'h40;         // display clear&lt;br /&gt;              11: lcd_code &lt;= 7'h41;&lt;br /&gt;            endcase&lt;br /&gt;        end&lt;br /&gt;        3'b001:&lt;br /&gt;            lcd_code &lt;= 7'h00;&lt;br /&gt;        3'b010:&lt;br /&gt;            lcd_code &lt;= {3'b110, lcd_dataD[7:4]};&lt;br /&gt;        3'b011:&lt;br /&gt;            lcd_code &lt;= 7'b0110000;&lt;br /&gt;        3'b100:&lt;br /&gt;            lcd_code &lt;= {3'b110, lcd_dataD[3:0]};&lt;br /&gt;        3'b101:&lt;br /&gt;            lcd_code &lt;= 7'b0110000;&lt;br /&gt;        3'b110:&lt;br /&gt;        begin&lt;br /&gt;            case(count[k+2])&lt;br /&gt;                  0: lcd_code &lt;= 7'h40;      // display clear&lt;br /&gt;                  1: lcd_code &lt;= 7'h41;&lt;br /&gt;            endcase&lt;br /&gt;        end&lt;br /&gt;    endcase&lt;br /&gt;end // output logic&lt;br /&gt;&lt;br /&gt;endmodule&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/sourcecode&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;Meditation, The Art of Exploitation&lt;/div&gt;</description><link>http://meditation-art.blogspot.com/2008/04/fpga-lcd-display-from-rs232-interface.html</link><author>noreply@blogger.com (Fei Liu)</author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_Z8d_fzejWt4/R_pU3-3Wx9I/AAAAAAAAC54/dyiJqhYWimg/s72-c/lcd_controller_fsm.png' height='72' width='72'/></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-23323574.post-5808897253564809963</guid><pubDate>Tue, 01 Apr 2008 14:22:00 +0000</pubDate><atom:updated>2008-04-01T10:29:51.474-05:00</atom:updated><title>Linux Networking 3: network bridge and bump in the wire</title><description>A Linux network bridge can be understood as a bump in the wire on steroid. In the physical world, a bridge is used to connect multiple landmass together. This notion is used in a similar meaning in networking. A Linux network bridge is virtual and it connects different 'Ethernet' network segments together, albeit transparently to the Ethernet packets going through it.&lt;br /&gt;&lt;br /&gt;Ever wondered what the 'Bridged' networking means in VMWare? It's exactly the kind of network setup allowed by Linux network bridge (practically handled by bridge-utils). Except that VMWare has its own implementation of a virtual network bridge that connects the guest virtual network and the host network together, thus allowing the guest OS virtual network direct access to the external (relative to the host) network.&lt;br /&gt;&lt;br /&gt;Because bridge works at Layer 2 for Ethernet packets, a bridge can often be considered functionally equivalent to a switch, albeit a virtual software solution. The simplest bridge acts as a bump in the wire, connecting different network segments just like a switch. However, bridge has the following distinctive advantages:&lt;br /&gt;&lt;br /&gt;1) A bridge can act as a network interface and assume a binding IP address, allowing network access to the Linux host.&lt;br /&gt;&lt;br /&gt;2) Network packets going through a bridge can be manipulated by iptables, thus allowing greater control such as mangling and filtering not present in switch and bump in the wire.&lt;br /&gt;&lt;br /&gt;Because a virtual bridge only examines Ethernet header (layer 2), it's transparent to IP protocols . This has some implications:&lt;br /&gt;&lt;br /&gt;1) It's important to take care of ARP tables that translate Ethernet address to IP address, no arp poisoning or other monkey business. The Linux host must forward arp packets properly.&lt;br /&gt;&lt;br /&gt;2) It's important to avoid routing loops (cyclic routes through bridges), often requiring turning Spanning Tree Protocol (STP) in network bridges.&lt;br /&gt;&lt;br /&gt;A bridge is most useful in the following scenarios:&lt;br /&gt;&lt;br /&gt;1) Network transparency and redundancy is required for internal network users. Redundant virtual network bridges can be set up (use STP if necessary) to allow non-interrupted network traffic flow.&lt;br /&gt;&lt;br /&gt;2) Administrator needs better packet filtering control over packets striding over network segments.&lt;br /&gt;&lt;br /&gt;3) Simply replacing a hardware switch or act as a bump in the wire (connecting two hosts on same network for example)&lt;br /&gt;&lt;br /&gt;References:&lt;br /&gt;1) http://www.linux-foundation.org/en/Net:Bridge&lt;br /&gt;2) http://www.vmweekly.com/articles/networking_in_vmware/1/&lt;div class="blogger-post-footer"&gt;Meditation, The Art of Exploitation&lt;/div&gt;</description><link>http://meditation-art.blogspot.com/2008/04/linux-networking-3-network-bridge-and.html</link><author>noreply@blogger.com (Fei Liu)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-23323574.post-6642038323570639762</guid><pubDate>Mon, 10 Mar 2008 23:18:00 +0000</pubDate><atom:updated>2008-04-08T15:00:45.842-05:00</atom:updated><title>Linux Networking 2: a router with port forwarding</title><description>Make simple things simple, complex things possible. Linux router is an example of this motto. A linux box with 2 NICs (network interface card) can function as a router with 2 simple commands from default configuration, and a 3rd command enables port forwarding to a specific port on a specific host. We'll cover a lot of theory of linux routing and firewalling in this article because subsequent article in this mini-serie are built based on the knowledge present here and will focus on more practical use.&lt;br /&gt;&lt;br /&gt;First of all, let's understand the requirement of a router or its definition. A router routes network packets between two network segments. It needs to do source NAT or destination NAT on a network packet. NAT stands for network address translation and is a layer 3 (IP) functionality. What this means is that an outgoing network packet through the router will have its source IP address modified to the external IP of the router (sometimes referred to as WAN IP). A related incoming network packet or port forwarded network packet will have its destination IP address modified, known as destination NAT.&lt;br /&gt;&lt;br /&gt;On 2.4+ Linux, NAT is done by iptables nat table during prerouting or postrouting. SNAT of an outgoing packet is performed during postrouting in nat just before it leaves the box. Linux kernel routing table knows that a packet destined to external IP address should go through the PREROUTING-&gt;FORWARD-&gt;POSTROUTING chain. Similarly, DNAT is performed during prerouting in nat just after it enters the box, typically going through PREROUTING-&gt;FORWARD-&gt;POSTROUTING chain. DNAT is done automatically for related or established packets (e.g. consequence of an outgoing SNAT SYN packet that establishes a network connection). DNAT is also done explicitly for packets that meet predefined port forwarding rules (an incoming SYN packet). It's strongly recommended the table traverse graph studied and understood.&lt;br /&gt;&lt;br /&gt;By default, kernel disables forward chain. That is when a packet coming in on a NI (network interface) has a different destination IP address than the address bound to that NI will be dropped. To allow linux kernel to make routing decision on such kind of packets, the forward chain must be enabled. Next to ensure the kernel can properly route such kind of packets, DNAT must be performed such that when the packet is inspected by the kernel, upon consulting the kernel routing table, the packet can be forwarded to the correct destination NI.&lt;br /&gt;&lt;br /&gt;An example will make this clear, given the following defintion&lt;br /&gt;&lt;br /&gt;eth0_ip="192.168.0.1"&lt;br /&gt;eth0_nw="192.168.0.1/24"&lt;br /&gt;eth0_gw="192.168.0.150"&lt;br /&gt;eth1_ip="192.168.1.1"&lt;br /&gt;eth1_nw="192.168.1.1/24"&lt;br /&gt;eth1_gw="192.168.1.150"&lt;br /&gt;pfw_serv_ip="192.168.1.3"&lt;br /&gt;&lt;br /&gt;kernel routing table can be displayed by "ip route" or "route -n", "ip route" shows more information and sometimes shows information not available through "route -n".&lt;br /&gt;&lt;br /&gt;In this hypothetical case, let's suppose:&lt;br /&gt;$eth0_nw route to eth0 via $eth0_nw_gw&lt;br /&gt;$eth1_nw route to eth1 via $eth1_nw_gw&lt;br /&gt;default route to eth0 via $eth0_nw_gw&lt;br /&gt;&lt;br /&gt;This is equivalent in English, packets destined to $eth0_nw will be routed to interface eth0, ditto for $eth1_nw and eth1. And if a packet whose destination is not in either $eth0_nw or  $eth1_nw, it should be routed to interface eth0.&lt;br /&gt;&lt;br /&gt;Now that we have established the routing table and have the forward chain enabled (echo 1 &gt; /proc/net/ipv4/ip_forward), let's see what happens when a packet originated from $pfw_server_ip with its destination ip set to kernel.org comes in from eth1. First the packet is seen on the wire and by the card, the kernel takes the packet and put it on the network stack. Before routing decision is made for this particular packet, there are 2 state machine states it will go through: the mangle table and nat table in PREROUTING chain. Two common actions will be taken by the kernel&lt;br /&gt;&lt;br /&gt;1. The incoming packet has SYN flag set and is the first packet for an outgoing connection (similarly for UDP packet, the connection tracking is based on the 5-tuple: src ip, src port, dst ip, dst port, and protocol). The kernel consults the mangle table and nat table for PREROUTING chain and make appropriate changes to the packet. It's not recommended to do any filtering (ACCEPT, DROP, REJECT etc) with mangle/nat tables in PREROUTING chain. Suppose a DNAT rule exists to change the destination address of this packet in nat table, this packet will be redirected to a different server IP address. Thus it's extremely easy to construct a layer 3 proxy with Linux, some times referred to as port forwarding. &lt;br /&gt;&lt;br /&gt;The mangle table has rules to modify the packet in other packet header fields different than the IP address. By marking the packet, mangle table can be used to select routing decisions for this packet based 'ip route/rule' kernel tables. For example, the mangle table rule can be used to create a tunnel, a bridge of 2 NIs. mangle table marks a packet and then the kernel routing table routes the packet based on its marking. We'll cover this in a later article in this serie.&lt;br /&gt;&lt;br /&gt;2. The incoming packet does not have SYN flag set and the kernel connection tracking module determines it's part of an established connection. In this case, the rules that applied to the SYN packet of this 5-tuple connection are automatically applied to this packet as well.&lt;br /&gt;&lt;br /&gt;At this point the packet leaves the PREROUTING chain, based on the kernel routing table, a routing decision will be made where this packet will be delivered to, typically one of the following decisions is made:&lt;br /&gt;&lt;br /&gt;1. the destination ip address is one of local host addresses, in this case, the packet is delivered to the internal/local ip address and NI the address is bound to. Next the packet is scheduled to go through the INPUT/OUTPUT chain and the filter table. The filter table is the default table for the INPUT/OUTPUT chain, provided through iptables syntactical sugar. This is an often overlooked fact and causes most confusion to iptables beginners. It'd have been better that '-t filter' be made explicit on command line at the cost of increased verbosity.&lt;br /&gt;&lt;br /&gt;It's possible a local process on the local host will consume the incoming packet after the INPUT chain and the story of the packet ends here. &lt;br /&gt;&lt;br /&gt;2. the destination ip address is an external address, a routing table entry is available to calculate its destination network interface on the host, the packet is scheduled to go through the FORWARD chain next.&lt;br /&gt;&lt;br /&gt;3. the destination ip address is an external address but none of the routing table entry yields a destination network interface on the host, this packet will be dropped. This packet is said to be undeliverable.&lt;br /&gt;&lt;br /&gt;After the packet has gone through either the INPUT/OUTPUT or the FORWARD chain, another routing decision is made whether the packet is 'undeliverable' or can be sent out through POSTROUTING chain. Here is place to do either SNAT or MASQUERADE on the outgoing packets before it goes on the wire. The difference between SNAT or MASQUERADE is that MASQUERADE allows dynamic destination address calculation and is typically used when the outgoing NIC has its address obtained from a DHCP server. SNAT rule binds a static IP address to the nat table rule. If you are not sure you should use SNAT or MASQUERADE, use MASQUERADE just to be safe.&lt;br /&gt;&lt;br /&gt;After the packet is mangled or SNATed/MASQUERADEd in POSTROUTING chain, it leaves the local host and is sent on the wire.&lt;br /&gt; &lt;br /&gt;References:&lt;br /&gt;1. http://iptables-tutorial.frozentux.net/images/tables_traverse.jpg&lt;br /&gt;2. http://iptables-tutorial.frozentux.net/iptables-tutorial.html&lt;div class="blogger-post-footer"&gt;Meditation, The Art of Exploitation&lt;/div&gt;</description><link>http://meditation-art.blogspot.com/2008/03/linux-networking-2-router-with-port.html</link><author>noreply@blogger.com (Fei Liu)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-23323574.post-5333939401232249230</guid><pubDate>Sat, 08 Mar 2008 21:20:00 +0000</pubDate><atom:updated>2008-03-08T16:58:56.183-05:00</atom:updated><title>Linux Networking 1: server work load balancing with multiple NICs</title><description>We'll cover some advanced use of linux networking capabilities in this mini series (including load balancings, 2 nic with same IP--bonding, bridge, and router). We'll begin with load balancing of server workload. Although this discussion does not cover subjects such as routing, packet manipulation (through iptables), it illustrates from an application level, how to use a linux box with multiple NICs to do useful things. A linux box with multiple NICs will be a common theme of this mini series.&lt;br /&gt;&lt;br /&gt;The concept of server work load balancing is to allow a linux box to use multiple NIC to service network traffic. A simple setup is to have a single external IP exposed to clients. Behind the external IP are multiple NICs that can form a dispatch table based on traffic and workload behind each NIC. &lt;br /&gt;&lt;br /&gt;Let's use 2 NIC load balancing to illustrate the idea:&lt;br /&gt;&lt;br /&gt;ext_nic(ip)-----load-balancer-demon-----NIC0-----SERVER0&lt;br /&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;+----NIC1-----SERVER1&lt;br /&gt;&lt;br /&gt;Whenever a client request comes in, the load-balancer-demon queries the SERVER behind a NIC to figure out which NIC the traffic/request should be forwarded to depending on the current workload on each server.&lt;br /&gt;&lt;br /&gt;Thus the load-balancer-demon is a user space application that proxies client requests.&lt;div class="blogger-post-footer"&gt;Meditation, The Art of Exploitation&lt;/div&gt;</description><link>http://meditation-art.blogspot.com/2008/03/linux-networking-1-server-work-load.html</link><author>noreply@blogger.com (Fei Liu)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-23323574.post-5928048355000621130</guid><pubDate>Sat, 08 Mar 2008 20:22:00 +0000</pubDate><atom:updated>2008-05-13T15:16:56.895-05:00</atom:updated><title>FPGA: Initial impression of Xilinx-3A starter board and fpga</title><description>I've recently started to learn FPGA architecture and Verilog hardware programming. It feels like the old DOS days when we could program interrupts and use 'outp' to signal hardware ports directly. In fact, the module port and pin assignment reminds me of the same pattern of hardware programming. The board has a builtin clock (oscillator) and with behavioral modelling, programer can program the hardware behavior. With DOS, I remember interrupt 8 was the XT8086 oscillator(timer) interrupt and the interrupt service code was executed at a fixed frequency. DOS allows programmer to reprogram the interrupt service code to emulate multitasking system.&lt;br /&gt;&lt;br /&gt;FPGA is a powerful and flexible platform that supports many IO ports and levels of programming models (switch-level, gate-level, dataflow-level, and behavioral-level). Behavioral level programming is reminiscent of C programming except that Verilog provides concurrent and non-blocking (asynchronous) programming paradigms with native language contructs. For example, the always, initial procedual blocks are concurrent and the code sequence in these blocks are executed concurrently on fpga hardware. Verilog also provides delayed assignment, a nice variation of synchronous assignment. Nonblocking procedual assignment allows programer to describe asynchronous assignment behavior.&lt;br /&gt;&lt;br /&gt;Programmable digital circuit is an interesting idea and hopefully I will have some interesting stuff to report later with the semi-expensive fpga development board.&lt;div class="blogger-post-footer"&gt;Meditation, The Art of Exploitation&lt;/div&gt;</description><link>http://meditation-art.blogspot.com/2008/03/initial-expression-of-xilinx-3astarter.html</link><author>noreply@blogger.com (Fei Liu)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-23323574.post-9178531968717996443</guid><pubDate>Fri, 29 Feb 2008 01:37:00 +0000</pubDate><atom:updated>2008-02-28T20:53:17.155-05:00</atom:updated><title>modprobe returns Invalid kernel module Format</title><description>I just experienced this problem recently on my new gentoo installation. I wanted to use my USB wireless card (netgear ma111), this requires a custom build of linux-wlan-ng that provides prism2 kernel module (this is now part of official kernel since 2.6.24). &lt;br /&gt;&lt;br /&gt;So I downloaded the latest (0.2.8) version of linux-wlan-ng and went through the configure/make chore. Everything worked fine (on newer kernel, one has to change socket-&gt;mac to socket-&gt;mac_header) and I got the modules compiled. But when I tried to insert the modules into kernel space, modprobe tells me the newly built kernel modules have 'Invalid Format' and cannot be used. &lt;br /&gt;&lt;br /&gt;This is rather interesting. After much research, the problem was found to be a mismatch of running kernel config and the config file found as /usr/src/linux/.config. It appears the 2.6 kernel has a tightened requirement of how a kernel module must be built to be used with a live running kernel.&lt;br /&gt;&lt;br /&gt;Two things I learned helped me to diagnose the problem:&lt;br /&gt;1. 2.6 kernel allows a copy of running kernel config accessible as /proc/config.gz. This is now a kernel configuration option. Make sure you turn it on if you build 2.6 kernel from source, this can be a life/time-saver.&lt;br /&gt;&lt;br /&gt;2. modinfo. Running this command on a kernel module file shows detailed information of the kernel module, in particular the versionmagic string shows options used to build the kernel module. The options in this magic string must match between this module and running kernel for the module to be useful. Mismatch here will produce the mysterious 'Invalid Format' error I initially stumbled upon.&lt;br /&gt;&lt;br /&gt;With these knowledge, it's simple to fix the problem:&lt;br /&gt;1. emerge the correct kernel source (yum, aptitude, smart, etc...on other distro)&lt;br /&gt;2. cp /proc/config.gz to /usr/src/linux and decompress it; rename config to .config&lt;br /&gt;3. in /usr/src/linux, make (don't have to be complete, make sure include/linux/version.h is produced)&lt;br /&gt;4. re-configure/make linux-wlan-ng&lt;br /&gt;5. make sure modinfo of newly built kernel module agree with existing modules of the live kernel&lt;br /&gt;6. modprobe/modins prism2 module (should work perfectly now)&lt;div class="blogger-post-footer"&gt;Meditation, The Art of Exploitation&lt;/div&gt;</description><link>http://meditation-art.blogspot.com/2008/02/modprobe-returns-invalid-kernel-module.html</link><author>noreply@blogger.com (Fei Liu)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-23323574.post-5780310315593912827</guid><pubDate>Tue, 19 Feb 2008 22:45:00 +0000</pubDate><atom:updated>2008-03-08T15:54:30.400-05:00</atom:updated><title>Bayes probability model</title><description>Bayes probability model is an important probability model to predict prior stage probabilities of a multi-stage probability model. Typically it's applied to a 2 stage probability model where the 2nd stage is dependent on the events in the first stage.&lt;br /&gt;&lt;br /&gt;Unlike 2 part probability model where events in either part are independent of events in the other part, 2 stage probability model is more complicated because 2nd stage probability is dependent on the 1st stage probability, where conditional probability applies. Bayes probability model quantifies the relationship between probabilities of different events happening in the model. It can be used to compute the 1st stage probability given the conditional probability of 2nd stage events.&lt;br /&gt;&lt;br /&gt;A simple dependent probability for event E and F is: P(E and F) = P(E) P(F|E) (the multiplication law), it says the probability that both E and F happen is the product of E happens and the conditional probability of F happens given that E happens. It often is written as P(F|E) = P(E and F)/P(E).&lt;br /&gt;&lt;br /&gt;The symmetry in the formulation can be explored: P(E and F) = P(F) P(E|F) = P(E) P(F|E). Thus, &lt;br /&gt;given P(E) = P(F) P(E|F)/P(F|E). Given conditional probabilities of P(E|F), P(F|E), and P(F), one can compute P(E).&lt;br /&gt;&lt;br /&gt;Let E and F represent simple event Ei and Fji (Fj happens given that Ei happens) in event sets, P(Ei and Fj) = pE_i * pF_j_i where P(Ei) = pE_i and P(Fj|Ei) = pF_j_i, therefore the chance Fj happens in a 2 stage experiment is sigma(P(Ei and Fj), i = 0..I) = sigma(pE_i * pF_j_i, i = 0..I)&lt;br /&gt;&lt;br /&gt;Thus we can rewrote the symmetry formula as P(Fj) P(Eij|Fj) = P(Ei) P(Fji|Ei). This illustrates that given 2nd stage probability P(Fj), we can reliably compute first stage conditional probability P(Eij|Fj) by rewrite it again as:&lt;br /&gt;&lt;br /&gt;P(Eij|Fj) = P(Ei) P(Fji|Ei)/P(Fj) = P(Ei) P(Fji|Ei) / [sigma(P(Ei) * P(Fji), i = 0..I)]&lt;div class="blogger-post-footer"&gt;Meditation, The Art of Exploitation&lt;/div&gt;</description><link>http://meditation-art.blogspot.com/2008/02/bayes-probability-model.html</link><author>noreply@blogger.com (Fei Liu)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-23323574.post-7021480121816434977</guid><pubDate>Tue, 19 Feb 2008 22:43:00 +0000</pubDate><atom:updated>2008-02-19T17:45:38.281-05:00</atom:updated><title>Suse 10.2, how to load a kernel module during system boot automatically</title><description>Different linux distros have different ways of loading kernel module during system boot. The way it works in Suse Linux is by adding module name into MODULES_LOADED_ON_BOOT in /etc/sysconfig/kernel. This configuration file is read by /etc/init.d/boot.loadmodules and specified modules will be loaded on demand.&lt;div class="blogger-post-footer"&gt;Meditation, The Art of Exploitation&lt;/div&gt;</description><link>http://meditation-art.blogspot.com/2008/02/suse-102-how-to-load-module-during.html</link><author>noreply@blogger.com (Fei Liu)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-23323574.post-1315322766974369445</guid><pubDate>Tue, 19 Feb 2008 03:33:00 +0000</pubDate><atom:updated>2008-02-18T23:13:46.327-05:00</atom:updated><title>makefile, dependencies, and single target multiple rules</title><description>To work with a large software system, a reliable and fast build system is one of the most important pieces. Without a reliable and fast build system, development can ground to a halt. Imagine if it takes 10-15 minutes to build a new version of the software when there were one or two changes. Unfortunately this happens more often than one might have expected. GNU make provides a framework to construct a build system through makefiles. Most of us use it on a daily basis. &lt;br /&gt;&lt;br /&gt;There is one important and interesting feature of makefile often overlooked, automatic dependency generation and inclusion. This feature is enabled by the fact that gmake allows a single target having multiple dependences but only one rule can have associated action. (Rules, dependencies, it's like lex/yacc, isn't it?)&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;sourcecode&gt;&lt;br /&gt;objects = foo.o bar.o&lt;br /&gt;foo.o : defs.h&lt;br /&gt;bar.o : defs.h test.h&lt;br /&gt;$(objects) : config.h&lt;br /&gt;&lt;/sourcecode&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In this quoted example, foo.o depends on both defs.h and config.h. &lt;br /&gt;&lt;br /&gt;Thus automatic dependency is typically done like this:&lt;br /&gt;&lt;br /&gt;foo.o: f1.c f2.h&lt;br /&gt;  gcc -c f1.c&lt;br /&gt;dep:&lt;br /&gt;  gcc -E -M -MF dep/foo.d -c f1.c&lt;br /&gt;-include dep/foo.d&lt;br /&gt;&lt;br /&gt;in this example, a dependency file dep/foo.d is generated and included in the makefile. Initially the include file does not exist and an error will be reported without '-' before include. '-' suppresses error reporting in gmake commands. The first time gmake runs through this makefile with 'make dep', it will generate the dependency file and compile f1.c. Alternatively, one can force the dependency generation as in the following example with 'make' (if all is the first rule in this makefile) but since its effect is not immediately available in compiling foo.o it's generally considered a bad practice. It forces generation of dependencies files every time during 'make all' (this can be somewhat alleviated by using make or shell conditionals). Unless a user of the makefile has a good reason to do so, avoid it:&lt;br /&gt;&lt;br /&gt;all: dep foo.o&lt;br /&gt;foo.o: f1.c f2.h&lt;br /&gt;  gcc -c f1.c&lt;br /&gt;dep:&lt;br /&gt;  gcc -E -M -MF dep/foo.d -c f1.c&lt;br /&gt;-include dep/foo.d&lt;br /&gt;&lt;br /&gt;The various flags used in this example taken from gcc manual:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;       -E  Stop after the preprocessing stage; do not run the compiler proper.&lt;br /&gt;           The output is in the form of preprocessed source code, which is&lt;br /&gt;           sent to the standard output.&lt;br /&gt;&lt;br /&gt;           Input files which don't require preprocessing are ignored.&lt;br /&gt;&lt;br /&gt;       -M  Instead of outputting the result of preprocessing, output a rule&lt;br /&gt;           suitable for make describing the dependencies of the main source&lt;br /&gt;           file.  The preprocessor outputs one make rule containing the object&lt;br /&gt;           file name for that source file, a colon, and the names of all the&lt;br /&gt;           included files, including those coming from -include or -imacros&lt;br /&gt;           command line options.&lt;br /&gt;&lt;br /&gt;           Unless specified explicitly (with -MT or -MQ), the object file name&lt;br /&gt;           consists of the basename of the source file with any suffix&lt;br /&gt;           replaced with object file suffix.  If there are many included files&lt;br /&gt;           then the rule is split into several lines using \-newline.  The&lt;br /&gt;           rule has no commands.&lt;br /&gt;&lt;br /&gt;           This option does not suppress the preprocessor's debug output, such&lt;br /&gt;           as -dM.  To avoid mixing such debug output with the dependency&lt;br /&gt;           rules you should explicitly specify the dependency output file with&lt;br /&gt;           -MF, or use an environment variable like DEPENDENCIES_OUTPUT.&lt;br /&gt;           Debug output will still be sent to the regular output stream as&lt;br /&gt;           normal.&lt;br /&gt;&lt;br /&gt;           Passing -M to the driver implies -E, and suppresses warnings with&lt;br /&gt;           an implicit -w.&lt;br /&gt;&lt;br /&gt;       -MF file&lt;br /&gt;           When used with -M or -MM, specifies a file to write the dependen-&lt;br /&gt;           cies to.  If no -MF switch is given the preprocessor sends the&lt;br /&gt;           rules to the same place it would have sent preprocessed output.&lt;br /&gt;&lt;br /&gt;           When used with the driver options -MD or -MMD, -MF overrides the&lt;br /&gt;           default dependency output file.&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;-M implies -E, but for illustration '-E' is explicitly specified in this example. This will speed up the make process before first gcc command will stop right after preprocessing is done.&lt;br /&gt;&lt;br /&gt;The second time make command is issued, the dependencies files are all available and will participate dependency check on its target. This is why with old software build systems, we often see instructions such as do 'make dep' first, then do 'make' (e.g the pre-2.4 linux kernel build system). The first step generates all the dependencies and the second step does the actual compilation. Of course, we can take out '-E' and '-M' and use '-MD' instead which will produce dependency and object files in a single step. The following is taken from autoconf/make output using 'Makefile' generated from 'configure' command:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;/bin/sh ../libtool --tag=CXX   --mode=compile g++ -DHAVE_CONFIG_H  -I../include -I../include -I/usr/include    -g -O2 -Werror -MT binarystring.lo -MD -MP -MF .deps/binarystring.Tpo -c -o binarystring.lo binarystring.cxx&lt;br /&gt;&lt;br /&gt;g++ -DHAVE_CONFIG_H -I../include -I../include -I/usr/include -g -O2 -Werror -MT binarystring.lo -MD -MP -MF .deps/binarystring.Tpo -c binarystring.cxx -o binarystring.o&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The dependency file foo.d will always depend on the source file foo.c from which it's generated. So whenever we update foo.c and issue 'make', a new dependency file will be generated. Viola, we remember now we were required to do 'make dep' and 'make' with this kind of makefile system.&lt;br /&gt;&lt;br /&gt;References:&lt;br /&gt;1. man gcc&lt;br /&gt;2. http://www.gnu.org/software/make/manual/make.html#Multiple-Rules&lt;br /&gt;3. http://www.gsp.com/cgi-bin/man.cgi?section=1&amp;topic=mkdep&lt;br /&gt;4. http://www.linuxdriver.net/make3/make3-CHP-8-SECT-3.html&lt;div class="blogger-post-footer"&gt;Meditation, The Art of Exploitation&lt;/div&gt;</description><link>http://meditation-art.blogspot.com/2008/02/makefile-dependencies-and-single-target.html</link><author>noreply@blogger.com (Fei Liu)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-23323574.post-220129334572239822</guid><pubDate>Thu, 14 Feb 2008 02:45:00 +0000</pubDate><atom:updated>2008-03-14T10:27:00.089-05:00</atom:updated><title>Compilers Part 7, theoretical considerations of the parsing process</title><description>There are a few key concepts and data structures commonly utilized in a parser: the abstract syntax tree (AST)/parse tree/syntax tree, type and value stacks, action execution.&lt;br /&gt;&lt;br /&gt;It's not initially obvious, but a parser is essentially a stack machine operating on an abstract syntax tree with post-order action execution. The AST graph (constructed by observing predefined hierarchical shift/reduce rules embedded in grammars during parsing) is traversed in a breath-first order and the action associated with each node executed post-order. Incidentally, a stack is a perfect data structure when breath-first traversing a graph, another candidate is deque. A deque allows stack operations at its either end and thus a stack can be considered a half-closed (usually head closed) deque. By definition stack operates on a first in first out (FIFO) order while deque allows either FIFO or first in last out (FILO).&lt;br /&gt;&lt;br /&gt;A parse tree construction process explains why it's mandatory that predefined grammars assisted with associativity and precedence order rules cannot have any unresolved syntactical ambiguity or such that only one parse tree can be constructed according to the grammatical rules as in the case of a GLR parser. A syntactical ambiguity translates into an undefined parse tree and does not constitute a regular grammar (in fact a relaxed form of regular grammar because LR parsers allows the production rule expressed as TERMINAL NONTERMINAL) that's commonly implemented in most computer programming language.&lt;br /&gt;&lt;br /&gt;The parsing process becomes alive once it's understood, 1) AST or parse tree is constructed based on the hierarchical (defined by hierarchical structure and shift/reduce rules) grammars; 2) the parse tree is then traversed breath-first and terminals/non-terminals(products) evaluated post order; 3) result of evaluation is pushed back into the traverse stack, equivalent to tree leaf folding upward (try to visualize the content of an internal vertex replaced by the result of evaluation its children vertexes according to user defined actions).&lt;br /&gt;&lt;br /&gt;Interestingly hierarchical (which implies a tree) grammars can also be used generatively to produce strings of arbitrary length that conforms to production rules. Although the generation process can produce any string, a parser effectively defines the generation process bound by input to produce one and only one syntax tree. This is thus a deterministic finite state machine when considering only the start state (empty syntax tree) and end state (a syntax tree generated based on a predefined input). Not to be confused with the state transition process within a GLR parser during parsing, a GLR parser can be a nondeterministic finite state machine.&lt;br /&gt;&lt;br /&gt;References&lt;br /&gt;1. http://en.wikipedia.org/wiki/Formal_grammar&lt;div class="blogger-post-footer"&gt;Meditation, The Art of Exploitation&lt;/div&gt;</description><link>http://meditation-art.blogspot.com/2008/02/compilers-part-7-theoretical.html</link><author>noreply@blogger.com (Fei Liu)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-23323574.post-315690842109442487</guid><pubDate>Wed, 13 Feb 2008 17:40:00 +0000</pubDate><atom:updated>2008-02-13T12:59:56.105-05:00</atom:updated><title>Flavors of Linux, the Gentoo distro</title><description>If you have a computer with 3G harddrive and 128M memory. What do you do if you want to install a linux distro on it? This kind of computer configuration is probably considered archaic and unusable. Even the main stream linux distros are having trouble with it, including Fedora core, Opensuse, Ubunto. Here comes Gentoo for the rescue. &lt;br /&gt;&lt;br /&gt;The gentoo quick installation guide shows the user the full control on how the system can be built. With a network connection established, the system can be built from a remote shell by executing a bunch of command line commands! This convenience is invaluable, considering that you don't have to sit next to a noisy box and stare at its screen. The base system uses only about 1G harddrive space with most of the useful development tools installed. &lt;br /&gt;&lt;br /&gt;The gentoo 'emerge' system provides decent package management features that most other small linux distros don't have. Therefore you pretty much get the best of both worlds (the all-in-one big desktop distro and down-to-the-earth barebone small distro). The only drawback is emerge usually needs to compile a package from source, the '-k' flag rarely works. :( But fortunately for what it's good for, you shouldn't have to emerge big apps all the time. &lt;br /&gt;&lt;br /&gt;One of the headaches of using gentoo is what I call 'dead patch' problem. Sometimes, the ebuild info came with a distro or portage does not get updated to reflect patch changes and you end up with dead patch files that are no longer available from gentoo distfiles sources. In this kind of rare situations, one has to create new ebuild files and update the package ebuild database. The steps are:&lt;br /&gt;&lt;br /&gt;1. after emerge failure, figure out a live patch file and note the difference between dead patch number and live patch number&lt;br /&gt;2. cd /usr/portage/category/package-name/&lt;br /&gt;3. cp deadpatch.ebuild livepatch.ebuild, make necessary changes in livepatch.ebuild, as of 2007.1 distro, it is no longer necessary to modify the newly created livepatch.ebuild as the ebuild system automatically deduct the patch number from the ebuild file name.&lt;br /&gt;4. issue command: ebuild livepatch.ebuild digest This will update the ebuild database&lt;br /&gt;5. redo emerge and repeat the process if there is remaining errors related to bad ebuild info&lt;br /&gt;&lt;br /&gt;References:&lt;br /&gt;1. http://www.gentoo.org/doc/en/gentoo-x86-quickinstall.xml&lt;br /&gt;2. http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?part=1&amp;chap=10&lt;div class="blogger-post-footer"&gt;Meditation, The Art of Exploitation&lt;/div&gt;</description><link>http://meditation-art.blogspot.com/2008/02/flavors-of-linux-gentoo-distro.html</link><author>noreply@blogger.com (Fei Liu)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-23323574.post-5106293356480603582</guid><pubDate>Mon, 11 Feb 2008 15:30:00 +0000</pubDate><atom:updated>2008-02-11T14:13:11.525-05:00</atom:updated><title>Compilers Part 6, DSEL interpreter in a tcp/ip server</title><description>We are finally ready to port our interpreter into a tcp/ip server. DSEL stands for domain specific embedded language. In our project, we created a simple sql like scripting language to directly manipulate data stored in memory. &lt;br /&gt;&lt;br /&gt;There are a few technicalities apart from lexer/parser to successfully build a tcp/ip server. We use the TCP_server implementation from STLplus library, this implementation provides us a non-blocking poll based tcp server implementation. Combined with forking or boost thread, it can be easily adapted in a multiplexing tcp/ip server. &lt;br /&gt;&lt;br /&gt;We introduce a new output string stream as our global (or per thread if necessary) output buffer because we no longer have yyout (stdout) to display result from interpreter. The result of interpreting user input is put into the output string stream and sent back to client. We simply rename the 'main' method in the bison grammar file to 'parse' and invoke it from a serverlet thread as the server processing function, it simply calls 'yyparse' to parse client input. Before the server calls parse, it calls set_yybuffer(TCP_connection &amp; conn) to set up flex in memory string buffer using techniques discussed in the previous entry on compiler construction. &lt;br /&gt;&lt;br /&gt;In set_yybuffer, we send the server output to client and accepts client input and creates a flex string buffer from it. Every time client input is exhausted, yywrap is called and current flex buffer is released and set_yybuffer is called again to read input from client. Because we use poll based non-blocking tcp IO provided by STLplus, we don't have to worry much about synchronizing between client and server. The library provides convenient interface to operate IO based on the socket status.&lt;br /&gt;&lt;br /&gt;As usual, the complete listing including its makefile is posted here:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;sourcecode&gt;&lt;br /&gt;#ifndef MAP_H&lt;br /&gt;#define MAP_H&lt;br /&gt;#include &lt; string&gt;&lt;br /&gt;#include &lt; iostream&gt;&lt;br /&gt;#include &lt; sstream&gt;&lt;br /&gt;#include &lt; iomanip&gt;&lt;br /&gt;#include &lt; map&gt;&lt;br /&gt;&lt;br /&gt;#include &lt; boost/lambda/lambda.hpp&gt;&lt;br /&gt;typedef std::map&lt; std::string, std::string&gt; map_t;&lt;br /&gt;&lt;br /&gt;#include "tcp.hpp"&lt;br /&gt;extern int set_yybuffer(TCP_connection &amp; );&lt;br /&gt;extern int parse();&lt;br /&gt;// a value type that describe the value of a symbol table entry&lt;br /&gt;// Essentially the symbol table entry data structure&lt;br /&gt;struct value{&lt;br /&gt;    unsigned char type; // the first letter of corresponding union type&lt;br /&gt;    union {&lt;br /&gt;        int ival;&lt;br /&gt;        float fval;&lt;br /&gt;        double dval;&lt;br /&gt;        char * sval;&lt;br /&gt;        map_t * mval;&lt;br /&gt;    } ivalue;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;// The symbol table data structure&lt;br /&gt;// Symbol table entry is keyed by the symbol string value&lt;br /&gt;typedef std::map&lt; std::string, value&gt; symtab_t;&lt;br /&gt;&lt;br /&gt;extern symtab_t symtab;&lt;br /&gt;extern std::ostringstream os;&lt;br /&gt;extern int yyerror(char *);&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;%{&lt;br /&gt;#include "map.tab.h"&lt;br /&gt;#include "map.h"&lt;br /&gt;&lt;br /&gt;extern "C"{&lt;br /&gt;#include &lt; unistd.h&gt;&lt;br /&gt;#include &lt; fcntl.h&gt;&lt;br /&gt;#include &lt; time.h&gt;&lt;br /&gt;#include &lt; string.h&gt;&lt;br /&gt;}&lt;br /&gt;TCP_connection conn_yy;&lt;br /&gt;std::string data;&lt;br /&gt;std::ostringstream os;&lt;br /&gt;&lt;br /&gt;bool report_err;&lt;br /&gt;int lineno;&lt;br /&gt;int tokenpos;&lt;br /&gt;%}&lt;br /&gt;D   [0-9]&lt;br /&gt;N   {D}+&lt;br /&gt;L   [a-zA-Z]&lt;br /&gt;A   [a-zA-Z0-9]&lt;br /&gt;ID  ({L}{A}*)&lt;br /&gt;&lt;br /&gt;%option yylineno&lt;br /&gt;%%&lt;br /&gt;&lt;br /&gt;select      { tokenpos += yyleng; return SELECT; }&lt;br /&gt;insert      { tokenpos += yyleng; return INSERT; }&lt;br /&gt;into        { tokenpos += yyleng; return INTO; }&lt;br /&gt;from        { tokenpos += yyleng; return FROM; }&lt;br /&gt;create      { tokenpos += yyleng; return CREATE; }&lt;br /&gt;table       { tokenpos += yyleng; return TABLE; }&lt;br /&gt;list        { tokenpos += yyleng; return LIST; }&lt;br /&gt;where       { tokenpos += yyleng; return WHERE; }&lt;br /&gt;key         { tokenpos += yyleng; return KEY; }&lt;br /&gt;value       { tokenpos += yyleng; return VALUE; }&lt;br /&gt;quit        { tokenpos += yyleng; return QUIT; }&lt;br /&gt;&lt;br /&gt;${ID}       { tokenpos += yyleng; yylval.text = strdup(yytext+1); return OBJECT; }&lt;br /&gt;{ID}        { tokenpos += yyleng; yylval.text = strdup(yytext); return TEXT; }&lt;br /&gt;[ \t]       { tokenpos += yyleng; /* ignore white space */ }&lt;br /&gt;.           { tokenpos += yyleng; return yytext[0]; }&lt;br /&gt;\n          { return '\n'; }&lt;br /&gt;&lt;br /&gt;%%&lt;br /&gt;&lt;br /&gt;int yyerror(char * s){&lt;br /&gt;    extern int yylineno;&lt;br /&gt;    os &lt;&lt; yylineno &lt;&lt; " : " &lt;&lt; s &lt;&lt; " at \n" &lt;&lt; data;&lt;br /&gt;    for(int i = 0; i &lt; tokenpos; i ++) os &lt;&lt; ' ';&lt;br /&gt;    os &lt;&lt; "^\n";&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;YY_BUFFER_STATE cur_buffer;&lt;br /&gt;&lt;br /&gt;int set_yybuffer(TCP_connection &amp; conn){&lt;br /&gt;    conn_yy = conn;&lt;br /&gt;    tokenpos = 0;&lt;br /&gt;    int ntry = 0; // time out after 120 seconds&lt;br /&gt;&lt;br /&gt;    while(!conn.send_ready(100000)) ;&lt;br /&gt;    std::string send_data = os.str();&lt;br /&gt;    std::cout &lt;&lt; "send to client: " &lt;&lt; send_data;&lt;br /&gt;    if(!conn.send(send_data)) return 1;&lt;br /&gt;    os.str("");&lt;br /&gt;&lt;br /&gt;    while(!conn.receive_ready(100000) &amp;&amp; ntry ++ &lt; 1200) ;&lt;br /&gt;    data = "";&lt;br /&gt;    if(ntry &gt;= 1200 || !conn.receive(data)) return 1;&lt;br /&gt;    os &lt;&lt; data;&lt;br /&gt;&lt;br /&gt;    std::cout &lt;&lt; "analyze: " &lt;&lt; data;&lt;br /&gt;    cur_buffer = yy_scan_string(data.c_str());&lt;br /&gt;&lt;br /&gt;    return 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int yywrap(){&lt;br /&gt;    yy_delete_buffer(cur_buffer);&lt;br /&gt;    return set_yybuffer(conn_yy);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;%{&lt;br /&gt;extern "C"{&lt;br /&gt;#include &lt; stdio.h&gt;&lt;br /&gt;#define YYDEBUG 1&lt;br /&gt;}&lt;br /&gt;extern int yyerror(char *);&lt;br /&gt;extern int yylex();&lt;br /&gt;&lt;br /&gt;#include "map.h"&lt;br /&gt;&lt;br /&gt;symtab_t symtab;&lt;br /&gt;bool where_by_key = false;&lt;br /&gt;bool where_by_value = false;&lt;br /&gt;std::string tablename;&lt;br /&gt;std::string where;&lt;br /&gt;%}&lt;br /&gt;&lt;br /&gt;%union{&lt;br /&gt;    char * text;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;%token &lt;text&gt; INSERT SELECT INTO TEXT OBJECT FROM CREATE TABLE LIST&lt;br /&gt;%token &lt;text&gt; WHERE KEY VALUE&lt;br /&gt;%token &lt;text&gt; QUIT&lt;br /&gt;%%&lt;br /&gt;&lt;br /&gt;statements: statements statement&lt;br /&gt;    | statement&lt;br /&gt;    ;&lt;br /&gt;statement: insert_stmt opt_semicolon '\n'&lt;br /&gt;    | select_stmt opt_semicolon '\n'&lt;br /&gt;    | create_stmt opt_semicolon '\n'&lt;br /&gt;    | assign_stmt opt_semicolon '\n'&lt;br /&gt;    | list_stmt opt_semicolon '\n'&lt;br /&gt;    | QUIT opt_semicolon '\n'&lt;br /&gt;    | '\n'&lt;br /&gt;    | error '\n' { yyclearin; yyerrok; }&lt;br /&gt;    ;&lt;br /&gt;opt_semicolon:&lt;br /&gt;    | ';'&lt;br /&gt;    ;&lt;br /&gt;assign_stmt:&lt;br /&gt;    OBJECT '=' TEXT&lt;br /&gt;            {&lt;br /&gt;                // string variable assignment&lt;br /&gt;                symtab_t::iterator it = symtab.find($1);&lt;br /&gt;                if(it != symtab.end() &amp;&amp; it-&gt;second.type == 's') // Symbol found and type is correct&lt;br /&gt;                    it-&gt;second.ivalue.sval = $3;&lt;br /&gt;                else{  // New symbol, add to symbol table&lt;br /&gt;                    value v;&lt;br /&gt;                    v.ivalue.sval = $3;&lt;br /&gt;                    v.type = 's';&lt;br /&gt;                    symtab[$1] = v;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;    ;&lt;br /&gt;create_stmt:&lt;br /&gt;    CREATE TABLE OBJECT&lt;br /&gt;            {&lt;br /&gt;                // Create a new dictionary&lt;br /&gt;                std::string symbol = $3;&lt;br /&gt;                symtab_t::iterator it = symtab.find(symbol);&lt;br /&gt;                if(it != symtab.end() &amp;&amp; it-&gt;second.type == 'm'){ // Symbol found and type is correct&lt;br /&gt;                    os &lt;&lt; "symbol: " &lt;&lt; symbol &lt;&lt; " already exists\n";&lt;br /&gt;                }else{ // New symbol, create new map(table), add to symbol table&lt;br /&gt;                    value v;&lt;br /&gt;                    v.ivalue.mval = new(map_t);&lt;br /&gt;                    v.type = 'm';&lt;br /&gt;                    symtab[symbol] = v;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;    ;&lt;br /&gt;insert_stmt:&lt;br /&gt;    INSERT INTO OBJECT '(' TEXT ',' TEXT ')'&lt;br /&gt;            {&lt;br /&gt;                // insert key, value pair into an existing dictionary&lt;br /&gt;                symtab_t::const_iterator it = symtab.find($3);&lt;br /&gt;                if(it != symtab.end() &amp;&amp; it-&gt;second.type == 'm'){ // Symbol found and type is correct&lt;br /&gt;                    (*(it-&gt;second.ivalue.mval))[std::string($5)] = std::string($7);&lt;br /&gt;                }else&lt;br /&gt;                    os &lt;&lt; "unknown symbol: " &lt;&lt; $3 &lt;&lt; " create first\n";&lt;br /&gt;            }&lt;br /&gt;    ;&lt;br /&gt;select_stmt: simple_select_stmt&lt;br /&gt;            {&lt;br /&gt;                // go through all key, value pair of a dictionary&lt;br /&gt;                symtab_t::const_iterator it = symtab.find(tablename);&lt;br /&gt;                if(it != symtab.end() &amp;&amp; it-&gt;second.type == 'm'){&lt;br /&gt;                    map_t::const_iterator mit = it-&gt;second.ivalue.mval-&gt;begin();&lt;br /&gt;                    for(; mit != it-&gt;second.ivalue.mval-&gt;end(); ++ mit)&lt;br /&gt;                        os &lt;&lt; "key = " &lt;&lt; mit-&gt;first &lt;&lt; ' '&lt;br /&gt;                            &lt;&lt; "value = " &lt;&lt; mit-&gt;second &lt;&lt; '\n';&lt;br /&gt;                }else&lt;br /&gt;                    os &lt;&lt; "invalid object\n";&lt;br /&gt;&lt;br /&gt;            }&lt;br /&gt;    | simple_select_stmt opt_where_stmt&lt;br /&gt;            {&lt;br /&gt;                // go through all key, value pair of a dictionary&lt;br /&gt;                // based on where criteria, search by key or value&lt;br /&gt;                symtab_t::const_iterator it = symtab.find(tablename);&lt;br /&gt;                if(it != symtab.end() &amp;&amp; it-&gt;second.type == 'm'){&lt;br /&gt;                    map_t::const_iterator mit = it-&gt;second.ivalue.mval-&gt;begin();&lt;br /&gt;                    for(; mit != it-&gt;second.ivalue.mval-&gt;end(); ++ mit)&lt;br /&gt;                        if( (where_by_key &amp;&amp; mit-&gt;first == where) ||&lt;br /&gt;                            (where_by_value &amp;&amp; mit-&gt;second == where) ||&lt;br /&gt;                            (!where_by_key &amp;&amp; !where_by_value) )&lt;br /&gt;                            os &lt;&lt; "key = " &lt;&lt; mit-&gt;first &lt;&lt; ' '&lt;br /&gt;                                &lt;&lt; "value = " &lt;&lt; mit-&gt;second &lt;&lt; '\n';&lt;br /&gt;                }else&lt;br /&gt;                    os &lt;&lt; "invalid object\n";&lt;br /&gt;&lt;br /&gt;                where_by_key = where_by_value = false;&lt;br /&gt;&lt;br /&gt;            }&lt;br /&gt;    ;&lt;br /&gt;simple_select_stmt:&lt;br /&gt;    SELECT '*' FROM OBJECT  { tablename = $4; }&lt;br /&gt;    ;&lt;br /&gt;opt_where_stmt: WHERE KEY '=' TEXT { where_by_key = true; where = $4; }&lt;br /&gt;    | WHERE VALUE '=' TEXT         { where_by_value = true; where = $4; }&lt;br /&gt;    ;&lt;br /&gt;list_stmt:&lt;br /&gt;    LIST&lt;br /&gt;            {&lt;br /&gt;                // Dump the entire symbol table&lt;br /&gt;                // For dictionaries, dump all key, value pairs as well&lt;br /&gt;                //&lt;br /&gt;                // Iterate through the symbol table&lt;br /&gt;                symtab_t::const_iterator it = symtab.begin();&lt;br /&gt;                for(; it != symtab.end(); ++it){&lt;br /&gt;                    os &lt;&lt; "symbol: " &lt;&lt; it-&gt;first &lt;&lt; ' ' &lt;&lt; it-&gt;second.type &lt;&lt; '\n';&lt;br /&gt;                    switch(it-&gt;second.type){&lt;br /&gt;                        case 's':    os &lt;&lt; "value = " &lt;&lt; it-&gt;second.ivalue.sval &lt;&lt; '\n';&lt;br /&gt;                                break;&lt;br /&gt;                        case 'm':    {&lt;br /&gt;                                // iterate through the dictionary&lt;br /&gt;                                map_t::const_iterator mit = it-&gt;second.ivalue.mval-&gt;begin();&lt;br /&gt;                                for(; mit != it-&gt;second.ivalue.mval-&gt;end(); ++ mit)&lt;br /&gt;                                    os &lt;&lt; "key = " &lt;&lt; mit-&gt;first &lt;&lt; ' '&lt;br /&gt;                                        &lt;&lt; "value = " &lt;&lt; mit-&gt;second &lt;&lt; '\n';&lt;br /&gt;                                }&lt;br /&gt;                                break;&lt;br /&gt;                        default:&lt;br /&gt;                                os &lt;&lt; "Unknown data type\n";&lt;br /&gt;                                break;&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;    ;&lt;br /&gt;%%&lt;br /&gt;&lt;br /&gt;int parse(){&lt;br /&gt;    extern int yydebug;&lt;br /&gt;    yydebug = 0;&lt;br /&gt;    yyparse();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;#include &lt; vector&gt;&lt;br /&gt;#include &lt; iostream&gt;&lt;br /&gt;#include &lt; algorithm&gt;&lt;br /&gt;#include &lt; functional&gt;&lt;br /&gt;&lt;br /&gt;#include "map.h"&lt;br /&gt;&lt;br /&gt;#include "tcp.hpp"&lt;br /&gt;#include "fileio.hpp"&lt;br /&gt;#include "debug.hpp"&lt;br /&gt;using namespace std;&lt;br /&gt;&lt;br /&gt;int main (int argc, char* argv[])&lt;br /&gt;{&lt;br /&gt;    DEBUG_TRACE;&lt;br /&gt;    if (argc != 2)&lt;br /&gt;        ferr &lt;&lt; "usage: " &lt;&lt; argv[0] &lt;&lt; " &lt;port&gt;" &lt;&lt; endl;&lt;br /&gt;    else&lt;br /&gt;    {&lt;br /&gt;        // create a client connection&lt;br /&gt;        // the address is specified by command argument 1 and the port&lt;br /&gt;        // specified by argument 2. Use a timeout of 10s.&lt;br /&gt;        TCP_server main_server((unsigned short)atoi(argv[1]), 5);&lt;br /&gt;        // test to see if the connection completed OK within the timeout&lt;br /&gt;        if (!main_server.initialised())&lt;br /&gt;        {&lt;br /&gt;            ferr &lt;&lt; "server failed to initialise" &lt;&lt; endl;&lt;br /&gt;            return -1;&lt;br /&gt;        }&lt;br /&gt;        if (main_server.error())&lt;br /&gt;        {&lt;br /&gt;            ferr &lt;&lt; "server initialisation failed with error " &lt;&lt; main_server.error() &lt;&lt; endl;&lt;br /&gt;            return -1;&lt;br /&gt;        }&lt;br /&gt;        while(!main_server.connection_ready(1000000)) ;&lt;br /&gt;        TCP_connection server = main_server.connection();&lt;br /&gt;&lt;br /&gt;        std::cout &lt;&lt; "Got a new connection.\n";&lt;br /&gt;        if(!set_yybuffer(server))&lt;br /&gt;            parse();&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/sourcecode&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;A few notes, the program misses stringent memory manage, there are memory leaks associated with strdup usage (fix is simple, add free in grammar action code); server does not finalize without proper QUIT action code; turn the server into a multiplexing server and add proper synchronization on shared objects. These are important for a real world application but they are not the focus of our project. &lt;br /&gt;&lt;br /&gt;We have successfully create a DSEL interpreter living inside a tcp/ip server utlizing powerful C++ STL library. This is a good starting point to implement more robust and useful server side DSEL interpreters.&lt;div class="blogger-post-footer"&gt;Meditation, The Art of Exploitation&lt;/div&gt;</description><link>http://meditation-art.blogspot.com/2008/02/compilers-part-6-edsl-interpreter-in.html</link><author>noreply@blogger.com (Fei Liu)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-23323574.post-8270881611636827537</guid><pubDate>Sat, 09 Feb 2008 01:17:00 +0000</pubDate><atom:updated>2008-02-08T20:18:20.034-05:00</atom:updated><title>Bash Programming Cheat Sheet (Repost)</title><description>Help File Library: Bash Programming Cheat Sheet&lt;br /&gt;&lt;br /&gt;Written By: ph34r&lt;br /&gt;&lt;br /&gt;A quick cheat sheet for programmers who want to do shell scripting. This is not intended to teach programming, etc. but it is intended for a someone who knows one programming language to begin learning about bash scripting.&lt;br /&gt;&lt;br /&gt;Basics&lt;br /&gt;&lt;br /&gt;All bash scripts must tell the o/s what to use as the interpreter. The first line of any script should be:&lt;br /&gt;#!/bin/bash&lt;br /&gt;&lt;br /&gt;You must make bash scripts executable.&lt;br /&gt;chmod +x filename&lt;br /&gt;&lt;br /&gt;Variables&lt;br /&gt;&lt;br /&gt;Create a variable - just assign value. Variables are non-datatyped (a variable can hold strings, numbers, etc. with out being defined as such).&lt;br /&gt;varname=value&lt;br /&gt;&lt;br /&gt;Access a variable by putting $ on the front of the name&lt;br /&gt;echo $varname&lt;br /&gt;&lt;br /&gt;Values passed in from the command line as arguments are accessed as $# where #= the index of the variable in the array of values being passed in. This array is base 1 not base 0.&lt;br /&gt;command var1 var2 var3 .... varX&lt;br /&gt;$1 contains whatever var1 was, $2 contains whatever var2 was, etc.&lt;br /&gt;&lt;br /&gt;Built in variables:&lt;br /&gt;&lt;br /&gt;Variable  Use&lt;br /&gt;$1-$N  Stores the arguments (variables) that were passed to the shell program from the command line.&lt;br /&gt;$?  Stores the exit value of the last command that was executed.&lt;br /&gt;$0  Stores the first word of the entered command (the name of the shell program).&lt;br /&gt;$*  Stores all the arguments that were entered on the command line ($1 $2 ...).&lt;br /&gt;"$@"  Stores all the arguments that were entered on the command line, individually quoted ("$1" "$2" ...).&lt;br /&gt;&lt;br /&gt;Quote Marks&lt;br /&gt;Regular double quotes ("like these") make the shell ignore whitespace and count it all as one argument being passed or string to use. Special characters inside are still noticed/obeyed.&lt;br /&gt;&lt;br /&gt;Single quotes 'like this' make the interpreting shell ignore all special characters in whatever string is being passed.&lt;br /&gt;&lt;br /&gt;The back single quote marks (`command`) perform a different function. They are used when you want to use the results of a command in another command. For example, if you wanted to set the value of the variable contents equal to the list of files in the current directory, you would type the following command: contents=`ls`, the results of the ls program are put in the variable contents.&lt;br /&gt;&lt;br /&gt;Logic and comparisons&lt;br /&gt;A command called test is used to evaluate conditional expressions, such as a if-then statement that checks the entrance/exit criteria for a loop.&lt;br /&gt;&lt;br /&gt;test expression&lt;br /&gt;Or&lt;br /&gt;[ expression ]&lt;br /&gt;&lt;br /&gt;Numeric Comparisons&lt;br /&gt;int1 -eq int2     Returns True if int1 is equal to int2.&lt;br /&gt;int1 -ge int2     Returns True if int1 is greater than or equal to int2.&lt;br /&gt;int1 -gt int2     Returns True if int1 is greater than int2.&lt;br /&gt;int1 -le int2     Returns True if int1 is less than or equal to int2&lt;br /&gt;int1 -lt int2     Returns True if int1 is less than int2&lt;br /&gt;int1 -ne int2     Returns True if int1 is not equal to int2&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;String Comparisons&lt;br /&gt;str1 = str2     Returns True if str1 is identical to str2.&lt;br /&gt;str1 != str2     Returns True if str1 is not identical to str2.&lt;br /&gt;str     Returns True if str is not null.&lt;br /&gt;-n str     Returns True if the length of str is greater than zero.&lt;br /&gt;-z str     Returns True if the length of str is equal to zero. (zero is different than null)&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;File Comparisons&lt;br /&gt;-d filename     Returns True if file, filename is a directory.&lt;br /&gt;-f filename     Returns True if file, filename is an ordinary file.&lt;br /&gt;-r filename     Returns True if file, filename can be read by the process.&lt;br /&gt;-s filename     Returns True if file, filename has a nonzero length.&lt;br /&gt;-w filename     Returns True if file, filename can be written by the process.&lt;br /&gt;-x filename     Returns True if file, filename is executable.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Expression Comparisons&lt;br /&gt;!expression     Returns true if expression is not true&lt;br /&gt;expr1 -a expr2     Returns True if expr1 and expr2 are true. ( &amp;&amp; , and )&lt;br /&gt;expr1 -o expr2     Returns True if expr1 or expr2 is true. ( ||, or )&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Logic Con't.&lt;br /&gt;&lt;br /&gt;If...then&lt;br /&gt;&lt;br /&gt;if [ expression ]&lt;br /&gt;        then&lt;br /&gt;                commands&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;If..then...else&lt;br /&gt;&lt;br /&gt;if [ expression ]&lt;br /&gt;        then&lt;br /&gt;                commands&lt;br /&gt;        else&lt;br /&gt;                commands&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;If..then...else If...else&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;if [ expression ]&lt;br /&gt;        then&lt;br /&gt;                commands&lt;br /&gt;elif [ expression2 ]&lt;br /&gt;        then&lt;br /&gt;                commands&lt;br /&gt;else&lt;br /&gt;                commands&lt;br /&gt;fi&lt;br /&gt;&lt;br /&gt;Case select&lt;br /&gt;&lt;br /&gt;case string1 in&lt;br /&gt;        str1)&lt;br /&gt;                commands;;&lt;br /&gt;        str2)&lt;br /&gt;                commands;;&lt;br /&gt;        *)&lt;br /&gt;                commands;;&lt;br /&gt;esac&lt;br /&gt;&lt;br /&gt;string1 is compared to str1 and str2. If one of these strings matches string1, the commands up until the double semicolon (; ;) are executed. If neither str1 nor str2 matches string1, the commands associated with the asterisk are executed. This is the default case condition because the asterisk matches all strings.&lt;br /&gt;&lt;br /&gt;Iteration (Loops)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;for var1 in list&lt;br /&gt;do&lt;br /&gt;        commands&lt;br /&gt;done&lt;br /&gt;&lt;br /&gt;This executes once for each item in the list. This list can be a variable that contains several words separated by spaces (such as output from ls or cat), or it can be a list of values that is typed directly into the statement. Each time through the loop, the variable var1 is assigned the current item in the list, until the last one is reached.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;while [ expression ]&lt;br /&gt;do&lt;br /&gt;        commands&lt;br /&gt;done&lt;br /&gt;&lt;br /&gt;until [ expression ]&lt;br /&gt;do&lt;br /&gt;        commands&lt;br /&gt;done&lt;br /&gt;&lt;br /&gt;Functions&lt;br /&gt;&lt;br /&gt;Create a function:&lt;br /&gt;&lt;br /&gt;fname(){&lt;br /&gt;        commands&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Call it by using the following syntax: fname&lt;br /&gt;&lt;br /&gt;Or, create a function that accepts arguments:&lt;br /&gt;&lt;br /&gt;fname2 (arg1,arg2...argN){&lt;br /&gt;        commands&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;And call it with: fname2 arg1 arg2 ... argN&lt;div class="blogger-post-footer"&gt;Meditation, The Art of Exploitation&lt;/div&gt;</description><link>http://meditation-art.blogspot.com/2008/02/bash-programming-cheat-sheet-repost.html</link><author>noreply@blogger.com (Fei Liu)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-23323574.post-1565701908194371002</guid><pubDate>Thu, 07 Feb 2008 19:10:00 +0000</pubDate><atom:updated>2008-02-07T14:50:28.065-05:00</atom:updated><title>Compilers Part 5, working with in memory data buffers</title><description>In the previous entries, we were able to set up the spec for the scripting language. To port the interpreter into a tcp/ip server, the first task is to allow the lexer to work with in memory data buffers instead of stdin and stdout. The reason is simple, user input will come from a network client and there are subtle differences between a network socket and stdin. &lt;br /&gt;&lt;br /&gt;Fortunately, flex provides several interface to set up in memory data buffer as token input. The following lex source code demonstrates how to use the relevant interface:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;sourcecode&gt;&lt;br /&gt;%{&lt;br /&gt;extern "C"{&lt;br /&gt;#include &lt; sys/stat.h&gt;&lt;br /&gt;#include &lt; fcntl.h&gt;&lt;br /&gt;#include &lt; string.h&gt;&lt;br /&gt;}&lt;br /&gt;#include &lt; iostream&gt;&lt;br /&gt;#include &lt; sstream&gt;&lt;br /&gt;#include &lt; fstream&gt;&lt;br /&gt;#include &lt; string&gt;&lt;br /&gt;#include &lt; vector&gt;&lt;br /&gt;#include &lt; algorithm&gt;&lt;br /&gt;using namespace std;&lt;br /&gt;&lt;br /&gt;unsigned int line = 0;&lt;br /&gt;std::vector&lt; std::string&gt; text;&lt;br /&gt;&lt;br /&gt;%}&lt;br /&gt;&lt;br /&gt;extern int yywrap();&lt;br /&gt;%%&lt;br /&gt;&lt;br /&gt;\/\/.*$    { cout &lt;&lt; "comment: " &lt;&lt; yytext; }&lt;br /&gt;.|\n        ;&lt;br /&gt;%%&lt;br /&gt;&lt;br /&gt;YY_BUFFER_STATE cur_buffer;&lt;br /&gt;int main(int argc, char * argv[]){&lt;br /&gt;&lt;br /&gt;    cout &lt;&lt; argv[1] &lt;&lt; '\n';&lt;br /&gt;    ifstream ifs(argv[1]);&lt;br /&gt;&lt;br /&gt;    char buf[256];&lt;br /&gt;    int len;&lt;br /&gt;    while(ifs.good()){&lt;br /&gt;        memset(buf, 0, 256);&lt;br /&gt;        ifs.getline(buf, 254);&lt;br /&gt;        len = strlen(buf);&lt;br /&gt;        buf[len] = '\n';&lt;br /&gt;        text.push_back(buf);&lt;br /&gt;        cout &lt;&lt; buf;&lt;br /&gt;    }&lt;br /&gt;    cout &lt;&lt; "\nlines read: " &lt;&lt; text.size() &lt;&lt; '\n';&lt;br /&gt;&lt;br /&gt;    cur_buffer = yy_scan_string(text[line].c_str());&lt;br /&gt;    extern int yylex();&lt;br /&gt;    yylex();&lt;br /&gt;&lt;br /&gt;    return 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;int yywrap(){&lt;br /&gt;&lt;br /&gt;    yy_delete_buffer(cur_buffer);&lt;br /&gt;    if(line+1 &gt; text.size()) return 1;&lt;br /&gt;    cur_buffer = yy_scan_string(text[line].c_str());&lt;br /&gt;    line ++;&lt;br /&gt;    return 0;&lt;br /&gt;}&lt;br /&gt;&lt;/sourcecode&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;yywrap gets called by yylex whenever a input buffer is exhausted, if yywrap returns 1, yylex will return; Therefore, it's a common technique to set up another available data buffer and return 0 to allow yylex continue processing as done in this example.&lt;br /&gt;&lt;br /&gt;References:&lt;br /&gt;1. http://flex.sourceforge.net/manual/Multiple-Input-Buffers.html#Multiple-Input-Buffers&lt;div class="blogger-post-footer"&gt;Meditation, The Art of Exploitation&lt;/div&gt;</description><link>http://meditation-art.blogspot.com/2008/02/compilers-part-4-working-with-in-memory.html</link><author>noreply@blogger.com (Fei Liu)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-23323574.post-8546943533114731967</guid><pubDate>Fri, 01 Feb 2008 16:51:00 +0000</pubDate><atom:updated>2008-02-01T12:56:14.229-05:00</atom:updated><title>Compilers Part 4, Symbol tables</title><description>Continue from last entry, we will add a symbol table to our little sql parser that interacts with in memory dictionaries. We have chosen to support dictionaries of the type std:map&lt; std::string, std::string&gt; because coupled with serialization/deserialization techniques, a dictionary is fit to describe a hierarchical organization of data objects. Theoretically, all things can be represented by strings in a Turing machine. We may cover automatic type deduction and more generic (in terms of coding convenience) solution in future entries on symbol tables. &lt;br /&gt;&lt;br /&gt;The reason a map is used instead of using a plain std::set is coding convenience. For std::set&lt;dictionary_type&gt; we have to supply user defined ordering functions to work with properly. Since we know that symbol table entries are always keyed by symbol name, a straight forward std::string key type works well. Our symbol table itself is a std::map type with key_type std::string and value_type value. struct value is user defined in map.h that contains a union ivalue type in which we hold multiple types our scripting language supports. One of the ivalue type is the dictionary type std::map&lt;std::string, std::string&gt;, typdef map_t. Our mini sql language revolves around manipulating this type of data structure.&lt;br /&gt;&lt;br /&gt;We will also make significant enhancement to the syntax of our little scripting language, allowing greater freedom in dictionary creation, object manipulation. Let's first see a transcript of the interpreter in action:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;./map&lt;br /&gt;create table $sss;&lt;br /&gt;list&lt;br /&gt;symbol: sss m&lt;br /&gt;insert into $sss (abc, efg)&lt;br /&gt;list&lt;br /&gt;symbol: sss m&lt;br /&gt;key = abc value = efg&lt;br /&gt;insret into $sss( ddd, hik)&lt;br /&gt;4 : syntax error at&lt;br /&gt;insret into $sss( ddd, hik)&lt;br /&gt;      ^&lt;br /&gt;insert into $sss (ddd, hik)&lt;br /&gt;Enter another command&lt;br /&gt;list&lt;br /&gt;symbol: sss m&lt;br /&gt;key = abc value = efg&lt;br /&gt;key = ddd value = hik&lt;br /&gt;select * from $sss;&lt;br /&gt;key = abc value = efg&lt;br /&gt;key = ddd value = hik&lt;br /&gt;select * from $sss where key = ddd&lt;br /&gt;key = ddd value = hik&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We have added more reserved keywords, more grammars to enhance the scripting language. Here is the complete code listing:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;sourcecode&gt;&lt;br /&gt;#ifndef MAP_H&lt;br /&gt;#define MAP_H&lt;br /&gt;#include &lt; string&gt;&lt;br /&gt;#include &lt; iostream&gt;&lt;br /&gt;#include &lt; map&gt;&lt;br /&gt;&lt;br /&gt;#include &lt; boost/lambda/lambda.hpp&gt;&lt;br /&gt;typedef std::map&lt; std::string, std::string&gt; map_t;&lt;br /&gt;&lt;br /&gt;// a value type that describe the value of a symbol table entry&lt;br /&gt;// Essentially the symbol table entry data structure&lt;br /&gt;struct value{&lt;br /&gt;    unsigned char type; // the first letter of corresponding union type&lt;br /&gt;    union {&lt;br /&gt;        int ival;&lt;br /&gt;        float fval;&lt;br /&gt;        double dval;&lt;br /&gt;        char * sval;&lt;br /&gt;        map_t * mval;&lt;br /&gt;    } ivalue;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;// The symbol table data structure&lt;br /&gt;// Symbol table entry is keyed by the symbol string value&lt;br /&gt;typedef std::map&lt; std::string, value&gt; symtab_t;&lt;br /&gt;&lt;br /&gt;extern int yyerror(char *);&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;%{&lt;br /&gt;#include "map.tab.h"&lt;br /&gt;#include "map.h"&lt;br /&gt;&lt;br /&gt;extern symtab_t symtab;&lt;br /&gt;std::string line;&lt;br /&gt;bool report_err;&lt;br /&gt;int lineno;&lt;br /&gt;int tokenpos;&lt;br /&gt;%}&lt;br /&gt;D   [0-9]&lt;br /&gt;N   {D}+&lt;br /&gt;L   [a-zA-Z]&lt;br /&gt;A   [a-zA-Z0-9]&lt;br /&gt;ID  ({L}{A}*)&lt;br /&gt;%%&lt;br /&gt;&lt;br /&gt;select      { tokenpos += yyleng; return SELECT; }&lt;br /&gt;insert      { tokenpos += yyleng; return INSERT; }&lt;br /&gt;into        { tokenpos += yyleng; return INTO; }&lt;br /&gt;from        { tokenpos += yyleng; return FROM; }&lt;br /&gt;create      { tokenpos += yyleng; return CREATE; }&lt;br /&gt;table       { tokenpos += yyleng; return TABLE; }&lt;br /&gt;list        { tokenpos += yyleng; return LIST; }&lt;br /&gt;where       { tokenpos += yyleng; return WHERE; }&lt;br /&gt;key         { tokenpos += yyleng; return KEY; }&lt;br /&gt;value       { tokenpos += yyleng; return VALUE; }&lt;br /&gt;&lt;br /&gt;${ID}       { tokenpos += yyleng; yylval.text = strdup(yytext+1); return OBJECT; }&lt;br /&gt;{ID}        { tokenpos += yyleng; yylval.text = strdup(yytext); return TEXT; }&lt;br /&gt;[ \t]       { tokenpos += yyleng; /* ignore white space */ }&lt;br /&gt;.           { tokenpos += yyleng; return yytext[0]; }&lt;br /&gt;\n.*        { report_err = true; tokenpos = 0; line = yytext+1; yyless(1); lineno++; return '\n'; }&lt;br /&gt;&lt;br /&gt;%%&lt;br /&gt;&lt;br /&gt;int yyerror(char * s){&lt;br /&gt;    if(report_err){&lt;br /&gt;        std::cout &lt;&lt; lineno &lt;&lt; " : " &lt;&lt; s &lt;&lt; " at \n" &lt;&lt; line &lt;&lt; '\n';&lt;br /&gt;        printf("%*s\n", 1+tokenpos, "^");&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;%{&lt;br /&gt;extern "C"{&lt;br /&gt;#include &lt; stdio.h&gt;&lt;br /&gt;#define YYDEBUG 1&lt;br /&gt;}&lt;br /&gt;extern int yyerror(char *);&lt;br /&gt;extern int yylex();&lt;br /&gt;&lt;br /&gt;#include "map.h"&lt;br /&gt;&lt;br /&gt;symtab_t symtab;&lt;br /&gt;bool where_by_key = false;&lt;br /&gt;bool where_by_value = false;&lt;br /&gt;std::string tablename;&lt;br /&gt;std::string where;&lt;br /&gt;%}&lt;br /&gt;&lt;br /&gt;%union{&lt;br /&gt;    char * text;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;%token &lt; text&gt; INSERT SELECT INTO TEXT OBJECT FROM CREATE TABLE LIST&lt;br /&gt;%token &lt; text&gt; WHERE KEY VALUE&lt;br /&gt;%%&lt;br /&gt;&lt;br /&gt;statements: statements statement&lt;br /&gt;    | statement&lt;br /&gt;    ;&lt;br /&gt;statement: insert_stmt opt_semicolon '\n'&lt;br /&gt;    | select_stmt opt_semicolon '\n'&lt;br /&gt;    | create_stmt opt_semicolon '\n'&lt;br /&gt;    | assign_stmt opt_semicolon '\n'&lt;br /&gt;    | list_stmt opt_semicolon '\n'&lt;br /&gt;    | '\n'&lt;br /&gt;    | error '\n' { yyclearin; yyerrok; std::cout &lt;&lt; "Enter another command\n"; }&lt;br /&gt;    ;&lt;br /&gt;opt_semicolon:&lt;br /&gt;    | ';'&lt;br /&gt;    ;&lt;br /&gt;assign_stmt:&lt;br /&gt;    OBJECT '=' TEXT&lt;br /&gt;            {&lt;br /&gt;                // string variable assignment&lt;br /&gt;                symtab_t::iterator it = symtab.find($1);&lt;br /&gt;                if(it != symtab.end() &amp;&amp; it-&gt;second.type == 's') // Symbol found and type is correct&lt;br /&gt;                    it-&gt;second.ivalue.sval = $3;&lt;br /&gt;                else{  // New symbol, add to symbol table&lt;br /&gt;                    value v;&lt;br /&gt;                    v.ivalue.sval = $3;&lt;br /&gt;                    v.type = 's';&lt;br /&gt;                    symtab[$1] = v;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;    ;&lt;br /&gt;create_stmt:&lt;br /&gt;    CREATE TABLE OBJECT&lt;br /&gt;            {&lt;br /&gt;                // Create a new dictionary&lt;br /&gt;                std::string symbol = $3;&lt;br /&gt;                symtab_t::iterator it = symtab.find(symbol);&lt;br /&gt;                if(it != symtab.end() &amp;&amp; it-&gt;second.type == 'm'){ // Symbol found and type is correct&lt;br /&gt;                    std::cerr &lt;&lt; "symbol: " &lt;&lt; symbol &lt;&lt; " already exists\n";&lt;br /&gt;                }else{ // New symbol, create new map(table), add to symbol table&lt;br /&gt;                    value v;&lt;br /&gt;                    v.ivalue.mval = new(map_t);&lt;br /&gt;                    v.type = 'm';&lt;br /&gt;                    symtab[symbol] = v;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;    ;&lt;br /&gt;insert_stmt:&lt;br /&gt;    INSERT INTO OBJECT '(' TEXT ',' TEXT ')'&lt;br /&gt;            {&lt;br /&gt;                // insert key, value pair into an existing dictionary&lt;br /&gt;                symtab_t::const_iterator it = symtab.find($3);&lt;br /&gt;                if(it != symtab.end() &amp;&amp; it-&gt;second.type == 'm'){ // Symbol found and type is correct&lt;br /&gt;                    (*(it-&gt;second.ivalue.mval))[std::string($5)] = std::string($7);&lt;br /&gt;                }else&lt;br /&gt;                    std::cerr &lt;&lt; "unknown symbol: " &lt;&lt; $3 &lt;&lt; " create first\n";&lt;br /&gt;            }&lt;br /&gt;    ;&lt;br /&gt;select_stmt: simple_select_stmt&lt;br /&gt;            {&lt;br /&gt;                // go through all key, value pair of a dictionary&lt;br /&gt;                symtab_t::const_iterator it = symtab.find(tablename);&lt;br /&gt;                if(it != symtab.end() &amp;&amp; it-&gt;second.type == 'm'){&lt;br /&gt;                    map_t::const_iterator mit = it-&gt;second.ivalue.mval-&gt;begin();&lt;br /&gt;                    for(; mit != it-&gt;second.ivalue.mval-&gt;end(); ++ mit)&lt;br /&gt;                        std::cout &lt;&lt; "key = " &lt;&lt; mit-&gt;first &lt;&lt; ' '&lt;br /&gt;                            &lt;&lt; "value = " &lt;&lt; mit-&gt;second &lt;&lt; '\n';&lt;br /&gt;                }else&lt;br /&gt;                    std::cerr &lt;&lt; "invalid object\n";&lt;br /&gt;&lt;br /&gt;            }&lt;br /&gt;    | simple_select_stmt opt_where_stmt&lt;br /&gt;            {&lt;br /&gt;                // go through all key, value pair of a dictionary&lt;br /&gt;                // based on where criteria, search by key or value&lt;br /&gt;                symtab_t::const_iterator it = symtab.find(tablename);&lt;br /&gt;                if(it != symtab.end() &amp;&amp; it-&gt;second.type == 'm'){&lt;br /&gt;                    map_t::const_iterator mit = it-&gt;second.ivalue.mval-&gt;begin();&lt;br /&gt;                    for(; mit != it-&gt;second.ivalue.mval-&gt;end(); ++ mit)&lt;br /&gt;                        if( (where_by_key &amp;&amp; mit-&gt;first == where) ||&lt;br /&gt;                            (where_by_value &amp;&amp; mit-&gt;second == where) ||&lt;br /&gt;                            (!where_by_key &amp;&amp; !where_by_value) )&lt;br /&gt;                            std::cout &lt;&lt; "key = " &lt;&lt; mit-&gt;first &lt;&lt; ' '&lt;br /&gt;                                &lt;&lt; "value = " &lt;&lt; mit-&gt;second &lt;&lt; '\n';&lt;br /&gt;                }else&lt;br /&gt;                    std::cerr &lt;&lt; "invalid object\n";&lt;br /&gt;&lt;br /&gt;                where_by_key = where_by_value = false;&lt;br /&gt;&lt;br /&gt;            }&lt;br /&gt;    ;&lt;br /&gt;simple_select_stmt:&lt;br /&gt;    SELECT '*' FROM OBJECT  { tablename = $4; }&lt;br /&gt;    ;&lt;br /&gt;opt_where_stmt: WHERE KEY '=' TEXT { where_by_key = true; where = $4; }&lt;br /&gt;    | WHERE VALUE '=' TEXT         { where_by_value = true; where = $4; }&lt;br /&gt;    ;&lt;br /&gt;list_stmt:&lt;br /&gt;    LIST&lt;br /&gt;            {&lt;br /&gt;                // Dump the entire symbol table&lt;br /&gt;                // For dictionaries, dump all key, value pairs as well&lt;br /&gt;                //&lt;br /&gt;                // Iterate through the symbol table&lt;br /&gt;                symtab_t::const_iterator it = symtab.begin();&lt;br /&gt;                for(; it != symtab.end(); ++it){&lt;br /&gt;                    std::cout &lt;&lt; "symbol: " &lt;&lt; it-&gt;first &lt;&lt; ' ' &lt;&lt; it-&gt;second.type &lt;&lt; '\n';&lt;br /&gt;                    switch(it-&gt;second.type){&lt;br /&gt;                        case 's':    std::cout &lt;&lt; "value = " &lt;&lt; it-&gt;second.ivalue.sval &lt;&lt; '\n';&lt;br /&gt;                                break;&lt;br /&gt;                        case 'm':    {&lt;br /&gt;                                // iterate through the dictionary&lt;br /&gt;                                map_t::const_iterator mit = it-&gt;second.ivalue.mval-&gt;begin();&lt;br /&gt;                                for(; mit != it-&gt;second.ivalue.mval-&gt;end(); ++ mit)&lt;br /&gt;                                    std::cout &lt;&lt; "key = " &lt;&lt; mit-&gt;first &lt;&lt; ' '&lt;br /&gt;                                        &lt;&lt; "value = " &lt;&lt; mit-&gt;second &lt;&lt; '\n';&lt;br /&gt;                                }&lt;br /&gt;                                break;&lt;br /&gt;                        default:&lt;br /&gt;                                std::cerr &lt;&lt; "Unknown data type\n";&lt;br /&gt;                                break;&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;    ;&lt;br /&gt;%%&lt;br /&gt;&lt;br /&gt;int main(){&lt;br /&gt;    extern int yydebug;&lt;br /&gt;    yydebug = 0;&lt;br /&gt;    yyparse();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/sourcecode&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We do not provide symlookup kind of functions because it's fairly straightforward to find symtable entry with our symtab_t data structure and the returned iterator is of immediate use in the action code. The complex object chaining action code may seem a little taunting at first but they are just regular C++ STL ways of getting/setting std::map data. We also let STL to handle all the memory issues, computing efficiency (std::map is typically implemented as a red-black tree, a kind of balanced binary search tree with very decent insertion, search, deletion speed O(lgN)), APIs. This is primarily why we would like to get lex and yacc to work with C++.&lt;br /&gt;&lt;br /&gt;Perhaps most telling is the 'list' command covered by list_stmt grammar, whose action code performs a complete dump of the entire symbol table. We first iterate the symbol table data structure, upon seeing a map_t type, we also iterate all key, value pairs of this symbol. This code illustrate the data structures we use to contain data.&lt;div class="blogger-post-footer"&gt;Meditation, The Art of Exploitation&lt;/div&gt;</description><link>http://meditation-art.blogspot.com/2008/02/compilers-part-4-symbol-tables.html</link><author>noreply@blogger.com (Fei Liu)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-23323574.post-7177779713890649273</guid><pubDate>Thu, 31 Jan 2008 17:27:00 +0000</pubDate><atom:updated>2008-02-01T11:47:40.260-05:00</atom:updated><title>Compilers Part 3, lex &amp; yacc debugging and error recovery</title><description>So far we deliberately didn't talk much about the basics of Lex and Yacc because they are better covered in books and online documents (check the reference section of this entry). In our last entry we focused on how to use C++ code in Lex&amp;Yacc generated parsers and lexers. In this entry, we will talk about debugging lex &amp; yacc and show simple error recovery techniques. These topics are important because as we develop a compiler (or to develop any software), debugging becomes a necessary repeated task if not most frequently. We collect the tips here hidden in corners of various documents.&lt;br /&gt;&lt;br /&gt;To help with debugging, start with compile&lt;br /&gt;&lt;br /&gt;1) add -d to lex&lt;br /&gt;2) add --debug to yacc (add -t to bison)&lt;br /&gt;&lt;br /&gt;In yacc source code, in the definition section, add the following code:&lt;br /&gt;&lt;br /&gt;extern "C"{&lt;br /&gt;#include &lt;stdio.h&gt;&lt;br /&gt;#define YYDEBUG 1&lt;br /&gt;}&lt;br /&gt;    extern int yydebug;&lt;br /&gt;    yydebug = 1;&lt;br /&gt;&lt;br /&gt;These additions will allow verbose debugging messages displayed in both lex and yacc to learn how tokens are matched and states transitioned.&lt;br /&gt;&lt;br /&gt;For error recovery:&lt;br /&gt;The Lex &amp; Yacc book has a dedicated chapter on error recovery. The basic idea is that we need a user defined yyerror function to report error and a hint where the error occured. In the grammar file, we provide action for error state that allows the parser to recover from syntax error in user input. &lt;br /&gt;&lt;br /&gt;To demonstrate the debugging techniques and error recovery techniques, a complete lex&amp;yacc specifications are provided. In this example, we would like to provide an interface to allow client modify and display a c++ std::map object. The syntax will be similar to sql. We are going to build a small in memory dictionary (database) that lives in a tcp/ip server that provides a minimal terminal interface to allow data manipulation. We start with simple insert/select commands to demonstrate various techniques that will be used in building this application. We will cover alternative input, symbol table, and tcp/ip client/server in the succeeding entries.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;sourcecode&gt;&lt;br /&gt;#ifndef MAP_H&lt;br /&gt;#define MAP_H&lt;br /&gt;#include &lt; string&gt;&lt;br /&gt;#include &lt; iostream&gt;&lt;br /&gt;#include &lt; map&gt;&lt;br /&gt;&lt;br /&gt;#include &lt; boost/lambda/lambda.hpp&gt;&lt;br /&gt;typedef std::map&lt;std::string, std::string&gt; map_t;&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;%{&lt;br /&gt;#include "map.tab.h"&lt;br /&gt;#include "map.h"&lt;br /&gt;&lt;br /&gt;extern map_t symtab;&lt;br /&gt;int lineno;&lt;br /&gt;std::string line;&lt;br /&gt;int tokenpos;&lt;br /&gt;bool report_err;&lt;br /&gt;%}&lt;br /&gt;D   [0-9]&lt;br /&gt;N   {D}+&lt;br /&gt;L   [a-zA-Z]&lt;br /&gt;A   [a-zA-Z0-9]&lt;br /&gt;ID  ({L}{A}*)&lt;br /&gt;%%&lt;br /&gt;&lt;br /&gt;select              { tokenpos += yyleng; return SELECT; }&lt;br /&gt;insert              { tokenpos += yyleng; return INSERT; }&lt;br /&gt;into                { tokenpos += yyleng; return INTO; }&lt;br /&gt;from                { tokenpos += yyleng; return FROM; }&lt;br /&gt;\${ID}              { tokenpos += yyleng; return OBJECT; }&lt;br /&gt;{ID}                { tokenpos += yyleng;&lt;br /&gt;                        symtab[std::string(yytext)] = std::string(yytext);&lt;br /&gt;                        std::cout &lt;&lt; symtab[yytext] &lt;&lt; '\n';&lt;br /&gt;                        yylval.text=strdup(yytext);&lt;br /&gt;                        return TEXT;&lt;br /&gt;                    }&lt;br /&gt;[ \t]               { tokenpos += yyleng; /* ignore white space */ }&lt;br /&gt;.                   { tokenpos += yyleng; return yytext[0]; }&lt;br /&gt;\n.*                { report_err = true; tokenpos = 0; line = yytext+1; yyless(1); lineno++; return '\n'; }&lt;br /&gt;&lt;br /&gt;%%&lt;br /&gt;&lt;br /&gt;void yyerror(char * s){&lt;br /&gt;    if(report_err){&lt;br /&gt;        std::cout &lt;&lt; lineno &lt;&lt; " : " &lt;&lt; s &lt;&lt; " at \n" &lt;&lt; line &lt;&lt; '\n';&lt;br /&gt;        printf("%*s\n", 1+tokenpos, "^");&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;%{&lt;br /&gt;extern "C"{&lt;br /&gt;#include &lt; stdio.h&gt;&lt;br /&gt;#define YYDEBUG 1&lt;br /&gt;}&lt;br /&gt;extern int yyerror(char *);&lt;br /&gt;extern int yylex();&lt;br /&gt;&lt;br /&gt;#include "map.h"&lt;br /&gt;&lt;br /&gt;map_t object;&lt;br /&gt;map_t symtab;&lt;br /&gt;%}&lt;br /&gt;&lt;br /&gt;%union{&lt;br /&gt;    char * text;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;%token &lt;text&gt; INSERT SELECT INTO TEXT OBJECT FROM&lt;br /&gt;%%&lt;br /&gt;&lt;br /&gt;statements: statements statement&lt;br /&gt;    | statement&lt;br /&gt;    ;&lt;br /&gt;statement: insert_stmt '\n'&lt;br /&gt;    | select_stmt '\n'&lt;br /&gt;    | '\n'&lt;br /&gt;    | error '\n' { yyclearin; yyerrok; std::cout &lt;&lt; "Enter another command\n"; }&lt;br /&gt;    ;&lt;br /&gt;insert_stmt:&lt;br /&gt;    INSERT INTO OBJECT '&lt;' TEXT ',' TEXT '&gt;'  {&lt;br /&gt;                object[std::string($5)] = std::string($7);&lt;br /&gt;                }&lt;br /&gt;    ;&lt;br /&gt;select_stmt:&lt;br /&gt;    SELECT '*' FROM OBJECT  {&lt;br /&gt;        std::cout &lt;&lt; "SELECT\n";&lt;br /&gt;        map_t::const_iterator it = object.begin();&lt;br /&gt;        for(; it != object.end(); ++it)&lt;br /&gt;            std::cout &lt;&lt; it-&gt;first &lt;&lt; ' ' &lt;&lt; it-&gt;second &lt;&lt; '\n';&lt;br /&gt;        it = symtab.begin();&lt;br /&gt;        for(; it != symtab.end(); ++it)&lt;br /&gt;            std::cout &lt;&lt; "symbol: " &lt;&lt; it-&gt;first &lt;&lt; ' ' &lt;&lt; it-&gt;second &lt;&lt; '\n';&lt;br /&gt;    }&lt;br /&gt;%%&lt;br /&gt;&lt;br /&gt;int main(){&lt;br /&gt;    extern int yydebug;&lt;br /&gt;    yydebug = 1;&lt;br /&gt;    yyparse();&lt;br /&gt;}&lt;br /&gt;&lt;/sourcecode&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We will use the same makefile provided in last entry. 'make map' will build the binary 'map'. Try&lt;br /&gt;./map and input 'insert into $mm &lt;abc,def&gt;' and 'insert int $ss &lt;a,b&gt;', we get the following output and diagnosis from our parser. There is a caveat with the error reporting, if the first line the user entered has syntax error, it won't be able to report it because the first line's text is not saved (it can be altered to save the text of every line but I haven't found a good way to do it).&lt;br /&gt;&lt;br /&gt;Starting parse&lt;br /&gt;Entering state 0&lt;br /&gt;Reading a token: --(end of buffer or a NUL)&lt;br /&gt;insert into $mm &lt;abc,def&gt;&lt;br /&gt;--accepting rule at line 19 ("insert")&lt;br /&gt;Next token is token INSERT ()&lt;br /&gt;Shifting token INSERT ()&lt;br /&gt;Entering state 2&lt;br /&gt;Reading a token: --accepting rule at line 29 (" ")&lt;br /&gt;--accepting rule at line 20 ("into")&lt;br /&gt;Next token is token INTO ()&lt;br /&gt;Shifting token INTO ()&lt;br /&gt;Entering state 10&lt;br /&gt;Reading a token: --accepting rule at line 29 (" ")&lt;br /&gt;--accepting rule at line 22 ("$mm")&lt;br /&gt;Next token is token OBJECT ()&lt;br /&gt;Shifting token OBJECT ()&lt;br /&gt;Entering state 16&lt;br /&gt;Reading a token: --accepting rule at line 29 (" ")&lt;br /&gt;--accepting rule at line 30 ("&lt;")&lt;br /&gt;Next token is token '&lt;' ()&lt;br /&gt;Shifting token '&lt;' ()&lt;br /&gt;Entering state 18&lt;br /&gt;Reading a token: --accepting rule at line 23 ("abc")&lt;br /&gt;abc&lt;br /&gt;Next token is token TEXT ()&lt;br /&gt;Shifting token TEXT ()&lt;br /&gt;Entering state 20&lt;br /&gt;Reading a token: --accepting rule at line 30 (",")&lt;br /&gt;Next token is token ',' ()&lt;br /&gt;Shifting token ',' ()&lt;br /&gt;Entering state 21&lt;br /&gt;Reading a token: --accepting rule at line 23 ("def")&lt;br /&gt;def&lt;br /&gt;Next token is token TEXT ()&lt;br /&gt;Shifting token TEXT ()&lt;br /&gt;Entering state 22&lt;br /&gt;Reading a token: --accepting rule at line 30 ("&gt;")&lt;br /&gt;Next token is token '&gt;' ()&lt;br /&gt;Shifting token '&gt;' ()&lt;br /&gt;Entering state 23&lt;br /&gt;Reducing stack by rule 7 (line 31):&lt;br /&gt;   $1 = token INSERT ()&lt;br /&gt;   $2 = token INTO ()&lt;br /&gt;   $3 = token OBJECT ()&lt;br /&gt;   $4 = token '&lt;' ()&lt;br /&gt;   $5 = token TEXT ()&lt;br /&gt;   $6 = token ',' ()&lt;br /&gt;   $7 = token TEXT ()&lt;br /&gt;   $8 = token '&gt;' ()&lt;br /&gt;-&gt; $$ = nterm insert_stmt ()&lt;br /&gt;Stack now 0&lt;br /&gt;Entering state 7&lt;br /&gt;Reading a token: --(end of buffer or a NUL)&lt;br /&gt;&lt;br /&gt;Entering state 5&lt;br /&gt;Reading a token: --(end of buffer or a NUL)&lt;br /&gt;insert int $ss &lt;a,b&gt;&lt;br /&gt;--accepting rule at line 31 ("&lt;br /&gt;insert int $ss &lt;a,b&gt;")&lt;br /&gt;Next token is token '\n' ()&lt;br /&gt;Shifting token '\n' ()&lt;br /&gt;Entering state 4&lt;br /&gt;Reducing stack by rule 5 (line 27):&lt;br /&gt;   $1 = token '\n' ()&lt;br /&gt;-&gt; $$ = nterm statement ()&lt;br /&gt;Stack now 0 5&lt;br /&gt;Entering state 13&lt;br /&gt;Reducing stack by rule 1 (line 22):&lt;br /&gt;   $1 = nterm statements ()&lt;br /&gt;   $2 = nterm statement ()&lt;br /&gt;-&gt; $$ = nterm statements ()&lt;br /&gt;Stack now 0&lt;br /&gt;Entering state 5&lt;br /&gt;Reading a token: --accepting rule at line 19 ("insert")&lt;br /&gt;Next token is token INSERT ()&lt;br /&gt;Shifting token INSERT ()&lt;br /&gt;Entering state 2&lt;br /&gt;Reading a token: --accepting rule at line 29 (" ")&lt;br /&gt;--accepting rule at line 23 ("int")&lt;br /&gt;int&lt;br /&gt;Next token is token TEXT ()&lt;br /&gt;2 : syntax error at&lt;br /&gt;insert int $ss &lt;a,b&gt;                 &lt;------------ Nice diagnosis from the parser&lt;br /&gt;          ^&lt;br /&gt;Error: popping token INSERT ()&lt;br /&gt;Stack now 0 5&lt;br /&gt;Shifting token error ()&lt;br /&gt;Entering state 1&lt;br /&gt;Next token is token TEXT ()&lt;br /&gt;Error: discarding token TEXT ()&lt;br /&gt;Error: popping token error ()&lt;br /&gt;Stack now 0 5&lt;br /&gt;Shifting token error ()&lt;br /&gt;Entering state 1&lt;br /&gt;Reading a token: --accepting rule at line 29 (" ")&lt;br /&gt;--accepting rule at line 22 ("$ss")&lt;br /&gt;Next token is token OBJECT ()&lt;br /&gt;Error: discarding token OBJECT ()&lt;br /&gt;Error: popping token error ()&lt;br /&gt;Stack now 0 5&lt;br /&gt;Shifting token error ()&lt;br /&gt;Entering state 1&lt;br /&gt;Reading a token: --accepting rule at line 29 (" ")&lt;br /&gt;--accepting rule at line 30 ("&lt;")&lt;br /&gt;Next token is token '&lt;' ()&lt;br /&gt;Error: discarding token '&lt;' ()&lt;br /&gt;Error: popping token error ()&lt;br /&gt;Stack now 0 5&lt;br /&gt;Shifting token error ()&lt;br /&gt;Entering state 1&lt;br /&gt;Reading a token: --accepting rule at line 23 ("a")&lt;br /&gt;a&lt;br /&gt;Next token is token TEXT ()&lt;br /&gt;Error: discarding token TEXT ()&lt;br /&gt;Error: popping token error ()&lt;br /&gt;Stack now 0 5&lt;br /&gt;Shifting token error ()&lt;br /&gt;Entering state 1&lt;br /&gt;Reading a token: --accepting rule at line 30 (",")&lt;br /&gt;Next token is token ',' ()&lt;br /&gt;Error: discarding token ',' ()&lt;br /&gt;Error: popping token error ()&lt;br /&gt;Stack now 0 5&lt;br /&gt;Shifting token error ()&lt;br /&gt;Entering state 1&lt;br /&gt;Reading a token: --accepting rule at line 23 ("b")&lt;br /&gt;b&lt;br /&gt;Next token is token TEXT ()&lt;br /&gt;Error: discarding token TEXT ()&lt;br /&gt;Error: popping token error ()&lt;br /&gt;Stack now 0 5&lt;br /&gt;Shifting token error ()&lt;br /&gt;Entering state 1&lt;br /&gt;Reading a token: --accepting rule at line 30 ("&gt;")&lt;br /&gt;Next token is token '&gt;' ()&lt;br /&gt;Error: discarding token '&gt;' ()&lt;br /&gt;Error: popping token error ()&lt;br /&gt;Stack now 0 5&lt;br /&gt;Shifting token error ()&lt;br /&gt;Entering state 1&lt;br /&gt;Reading a token: --(end of buffer or a NUL)&lt;br /&gt;&lt;br /&gt;References:&lt;br /&gt;1. Lex &amp; Yacc John R. Levine, Tony Mason, Doug Brown ISBN: 1565920007&lt;br /&gt;2. http://dinosaur.compilertools.net/yacc/index.html&lt;div class="blogger-post-footer"&gt;Meditation, The Art of Exploitation&lt;/div&gt;</description><link>http://meditation-art.blogspot.com/2008/01/compilers-part-3-lex-yacc-debugging-and.html</link><author>noreply@blogger.com (Fei Liu)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-23323574.post-6130623262903132791</guid><pubDate>Tue, 29 Jan 2008 14:55:00 +0000</pubDate><atom:updated>2008-01-31T12:27:23.894-05:00</atom:updated><title>Compilers Part 2, lex &amp; yacc with C++, types of external linkage</title><description>Lex and Yacc were traditionally used with C, more importantly lots of default functions provided by the lex/yacc (or flex/bison) library all have C linkage, meaning their function names are not mangled, notably yyparse, yywrap, yyerror.&lt;br /&gt;&lt;br /&gt;yyparse generated by yacc internally calls yylex generated by lex. Therefore it's important that both yyparse and yylex use same linkage, either C or C++. linkage is determined in the definition section.&lt;br /&gt;&lt;br /&gt;For example in this yacc definition of grammar.y:&lt;br /&gt;%{&lt;br /&gt;extern "C"{&lt;br /&gt;extern int yyerror(char *);&lt;br /&gt;}&lt;br /&gt;extern int yylex(void);&lt;br /&gt;%}&lt;br /&gt;&lt;br /&gt;yyerror has C linkage, this parser uses the default yyerror implementation provided by the yacc library (-ly). yylex has the linkage the compiler used to compile the generated source code, in the case (gcc -c y.tab.c) the result yylex will have a C linkage, evidenced by (nm y.tab.o|grep yylex) 'U yylex'&lt;br /&gt;&lt;br /&gt;On the other hand, if g++ is used to compile (g++ -c -x c++ y.tab.c), the result yylex symbol in the grammar object file will have C++ linkage, its name will be mangled as shown by 'nm': 'U _Z5yylexv'. In both cases, 'U' means undefined symbol because it has external linkage and will be provided by another compilation unit. The mangled name can be inspected by 'nm -C y.tab.o|grep lex' which yields 'U yylex()'&lt;br /&gt;&lt;br /&gt;Ok, enough introduction of library, external linkage and nm tricks. The point is when using lex&amp;yacc with C++, it's very important to pay attention to function names and declare proper linkage.&lt;br /&gt;&lt;br /&gt;If we intend to use C++ to compile/link our grammar.y example with a grammar.l lex file, the lex file needs to have the following definition:&lt;br /&gt;%{&lt;br /&gt;extern "C"{&lt;br /&gt;//extern int yylex(void);&lt;br /&gt;}&lt;br /&gt;#include "y.tab.h"&lt;br /&gt;%}&lt;br /&gt;&lt;br /&gt;Note that yylex is specifically commented out to make it clear that it will use the compiler default linkage (C for gcc or C++ for g++).&lt;br /&gt;&lt;br /&gt;Here is a makefile that can be used to compile lex/yacc with C++ code embedded directly.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;sourcecode&gt;&lt;br /&gt;LEX=flex&lt;br /&gt;YACC=bison&lt;br /&gt;CXX=g++&lt;br /&gt;CXXFLAGS=-g -O0&lt;br /&gt;%: %.l %.y&lt;br /&gt;    $(LEX) -t $@.l &gt; $@.c&lt;br /&gt;    if [[ -e $@.y ]] ; then \&lt;br /&gt;        $(YACC) -d --verbose --debug $@.y; \&lt;br /&gt;        $(CXX) $(CXXFLAGS) -c -x c++ $@.tab.c; \&lt;br /&gt;        $(CXX) $(CXXFLAGS) -c -x c++ $@.c; \&lt;br /&gt;        $(CXX) $@.o $@.tab.o -o $@ -ly -lfl -lm ; \&lt;br /&gt;    else \&lt;br /&gt;        $(CXX) $(CXXFLAGS) -o $@ $@.c -lfl -lm ; \&lt;br /&gt;    fi&lt;br /&gt;    @if [[ -e y.tab.c ]] ; then rm $@.tab.c ; fi&lt;br /&gt;    @if [[ -e y.tab.h ]] ; then rm $@.tab.h ; fi&lt;br /&gt;    #@-rm $@.c&lt;br /&gt;clean:&lt;br /&gt;    rm *.o&lt;br /&gt;&lt;/sourcecode&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you examine the lex generated source code, you will see something like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;sourcecode&gt;&lt;br /&gt;/* Default declaration of generated scanner - a define so the user can&lt;br /&gt; * easily add parameters.&lt;br /&gt; */&lt;br /&gt;#ifndef YY_DECL&lt;br /&gt;#define YY_DECL_IS_OURS 1&lt;br /&gt;&lt;br /&gt;extern int yylex (void);&lt;br /&gt;&lt;br /&gt;#define YY_DECL int yylex (void)&lt;br /&gt;#endif /* !YY_DECL */&lt;br /&gt;/** The main scanner function which does all the work.&lt;br /&gt; */&lt;br /&gt;YY_DECL&lt;br /&gt;{&lt;br /&gt;&lt;/sourcecode&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The extra 'extern' storage specifier for int yylex() is redundant and confusing. According to C and C++ linkage rule, an 'extern' function with a visible definition in the same file will result in external linkage. Since yylex is later defined in the lex generated source code, yylex has external linkage and internal definition (lacking a better term). In the following example, test has external linkage and internal definition; test1 has external linkage and external definition; test2 causes compilation failure. In this nm output, 'T' means the test has internal definition and its definition is in the text section of the object file; 'U' means test1 is undefined (external definition, defined in another translation/compilation unit/object file).&lt;br /&gt;&lt;br /&gt;00000000 T test&lt;br /&gt;         U test1&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;sourcecode&gt;&lt;br /&gt;#include &lt; errno.h&gt;&lt;br /&gt;extern int errno;&lt;br /&gt;&lt;br /&gt;int errno;&lt;br /&gt;&lt;br /&gt;extern int test();&lt;br /&gt;extern int test1();&lt;br /&gt;extern int test2();&lt;br /&gt;&lt;br /&gt;int test(){&lt;br /&gt;    test1();&lt;br /&gt;    test();&lt;br /&gt;    errno = 10;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;static int test2(){&lt;br /&gt;    test();&lt;br /&gt;}&lt;br /&gt;&lt;/sourcecode&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;References:&lt;br /&gt;1. http://publications.gbdirect.co.uk/c_book/chapter4/linkage.html&lt;br /&gt;2. http://publications.gbdirect.co.uk/c_book/chapter8/declarations_and_definitions.html&lt;div class="blogger-post-footer"&gt;Meditation, The Art of Exploitation&lt;/div&gt;</description><link>http://meditation-art.blogspot.com/2008/01/lex-yacc-with-c-types-of-external.html</link><author>noreply@blogger.com (Fei Liu)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-23323574.post-9099743261322830280</guid><pubDate>Tue, 22 Jan 2008 15:14:00 +0000</pubDate><atom:updated>2008-01-31T12:26:50.611-05:00</atom:updated><title>Compilers Part 1, top-down vs. bottom-up and why nested C style comment is disallowed</title><description>Yacc allows BNF syntax such as this (note definition section is omitted for illustration purpose):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;sourcecode&gt;&lt;br /&gt;program:&lt;br /&gt;      program statement '\n'&lt;br /&gt;    | &lt;br /&gt;    ;&lt;br /&gt;&lt;br /&gt;statement:&lt;br /&gt;      expression&lt;br /&gt;    | VARIABLE '=' expression&lt;br /&gt;    ;&lt;br /&gt;&lt;br /&gt;expression:&lt;br /&gt;      INTEGER&lt;br /&gt;    | VARIABLE&lt;br /&gt;    | expression '+' expression&lt;br /&gt;    | expression '-' expression&lt;br /&gt;    | expression '*' expression&lt;br /&gt;    | expression '/' expression&lt;br /&gt;    | '(' expression ')'&lt;br /&gt;    ;&lt;br /&gt;&lt;br /&gt;&lt;/sourcecode&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;A program is a collection of statements and has a left recursion in its grammar. Now this would have been a problem for a top-down (predicative) or recursive descent or LL (left to right and left most derivation) parser due to the fact that left recursive grammar causes indefinite parsing of input string. Yacc has no problem with such kind of grammar because Yacc is a bottom-up or shift-reduce or LR (left to right and producing right most derivation) parser. In fact left recursive grammar produces better parser with Yacc due to less number of stack entries used during shift-reduce. &lt;br /&gt;&lt;br /&gt;Often hand crafted lexers and parsers take LL(k) approach, that is LL with k # of characters look ahead. As the LL parser reads a input string, it generates a syntax tree started from nothing (root). It's done more often simply because it's easier to write a LL(k) parser.&lt;br /&gt;&lt;br /&gt;LR or shift-reduce parser often has an easier time parsing because a LR parser is an automaton suitable for parsing string patterns efficiently (Refer to the finite automaton regex pattern matching algorithm in Introduction to Algorithm). Often course it's possible and done to hand craft LR parsers.&lt;br /&gt;&lt;br /&gt;In improved form LALR (look ahead left to right right most derivation production) parser such as Yacc, stacks are used to support shift-reduce and reduce-reduce operations. Yacc takes a default action when there is a conflict. For shift-reduce conflicts, yacc will shift. For reduce-reduce conflicts, it will use the first rule in the listing. It also issues a warning message whenever a conflict exists.&lt;br /&gt;&lt;br /&gt;A common problem is parsing of a c comment /* this is a comment *****/,  such syntax can be expressed as:&lt;br /&gt;&lt;br /&gt;comment.l&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;sourcecode&gt;&lt;br /&gt;%%&lt;br /&gt;"/*"        {&lt;br /&gt;            register int c;&lt;br /&gt;&lt;br /&gt;            for ( ; ; )&lt;br /&gt;                {&lt;br /&gt;                while ( (c = input()) != '*' &amp;&amp;&lt;br /&gt;                        c != EOF )&lt;br /&gt;                    ;    /* eat up text of comment */&lt;br /&gt;&lt;br /&gt;                if ( c == '*' )&lt;br /&gt;                    {&lt;br /&gt;                    while ( (c = input()) == '*' )&lt;br /&gt;                        ;&lt;br /&gt;                    if ( c == '/' )&lt;br /&gt;                        break;    /* found the end */&lt;br /&gt;                    }&lt;br /&gt;&lt;br /&gt;                if ( c == EOF )&lt;br /&gt;                    {&lt;br /&gt;                    error( "EOF in comment" );&lt;br /&gt;                    break;&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;%%&lt;br /&gt;&lt;/sourcecode&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In this example, the lexer simply skips the comment, also note that nested comments are not allowed. This lexer code is prevalent in most C compiler implementation and is the reason why nested comment is still not allowed in C regardless the advance of parsing technology.&lt;br /&gt;&lt;br /&gt;Do use lex/yacc to implement scanner/parsers instead of handcrafting them.&lt;br /&gt;&lt;br /&gt;On using lex/yacc with C++:&lt;br /&gt;"To summarize: don't bother to compile your Lexer in C++, keep it in C. Make your Parser in C++ and explain your compiler that some functions are C functions with extern "C" statements."&lt;br /&gt;&lt;p&gt;&lt;br /&gt;References&lt;br /&gt;1. http://www.lysator.liu.se/c/ANSI-C-grammar-l.html&lt;br /&gt;2. http://www.garshol.priv.no/download/text/bnf.html&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;Meditation, The Art of Exploitation&lt;/div&gt;</description><link>http://meditation-art.blogspot.com/2008/01/parsers-top-down-vs-bottom-up.html</link><author>noreply@blogger.com (Fei Liu)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-23323574.post-2216029525509522989</guid><pubDate>Fri, 18 Jan 2008 15:42:00 +0000</pubDate><atom:updated>2008-01-22T14:44:47.657-05:00</atom:updated><title>Notes on Linux signal in the context of process and thread</title><description>Handing Linux signals correctly is difficult, for a few reasons 1) Linux signal descends from the archaic Unix SysV signal system, it still supports the signal/pause calls etc that are susceptible to race conditions and all kinds of haphazard ways of bad signal handling practice; 2) The POSIX standard is intentionally cloudy on a couple of signal related issues, e.g. fields in siginfo_t; 3) Linux signal does not always follow the POSIX standard; 4) There are still lots of code using the SysV signal mechanism, that should be migrated to the better POSIX system. &lt;br /&gt;&lt;br /&gt;Linux Programming by Example has an excellent chapter on Linux signal handling. The picture is not complete because Linux thread increases the complexity of signal handling. The following code tries to demonstrate a few important points of Linux signal handling in the context Linux threads:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;sourcecode&gt;&lt;br /&gt;/*&lt;br /&gt;1. there is no per thread signal mask or signal handler, these concepts only&lt;br /&gt;applies to a process&lt;br /&gt;&lt;br /&gt;2. raise and kill work differently with pthreads&lt;br /&gt;&lt;br /&gt;3. synchronous signal raised by a thread goes to that thread itself *only* not the process group&lt;br /&gt;&lt;br /&gt;*/&lt;br /&gt;#include &lt; iostream&gt;&lt;br /&gt;using namespace std;&lt;br /&gt;&lt;br /&gt;#include &lt; boost/thread/thread.hpp&gt;&lt;br /&gt;&lt;br /&gt;extern "C"{&lt;br /&gt;#include &lt; signal.h&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;volatile sig_atomic_t interrupted = 0;&lt;br /&gt;int standby_thr_pid = (long int)syscall(224);&lt;br /&gt;&lt;br /&gt;//#define SI_USER     0       /* sent by kill, sigsend, raise */&lt;br /&gt;//#define SI_KERNEL   0x80        /* sent by the kernel from somewhere */&lt;br /&gt;//#define SI_QUEUE    -1      /* sent by sigqueue */&lt;br /&gt;//#define SI_TIMER __SI_CODE(__SI_TIMER,-2) /* sent by timer expiration */&lt;br /&gt;//#define SI_MESGQ __SI_CODE(__SI_MESGQ,-3) /* sent by real time mesq state change */&lt;br /&gt;//#define SI_ASYNCIO  -4      /* sent by AIO completion */&lt;br /&gt;//#define SI_SIGIO    -5      /* sent by queued SIGIO */&lt;br /&gt;//#define SI_TKILL    -6      /* sent by tkill system call */&lt;br /&gt;//#define SI_DETHREAD -7      /* sent by execve() killing subsidiary threads */&lt;br /&gt;&lt;br /&gt;// pid = 0 uid = 0 -&gt; process itself&lt;br /&gt;// else pid &gt; 0 uid &gt; 0 -&gt; external process sent signal&lt;br /&gt;// si_code = 128 (0x80) sent by kernel, e.g. interactive terminal ctl+c&lt;br /&gt;// si_code = -6         sent by tkill&lt;br /&gt;// si_code = 0          sent by kill/killpg/raise call&lt;br /&gt;// there is no per thread signal handler, signal handler is installed&lt;br /&gt;// process wise always&lt;br /&gt;void ctlc(int sig, siginfo_t * info, void * context){&lt;br /&gt;    interrupted = 1;&lt;br /&gt;    int pid = (long int)syscall(224);&lt;br /&gt;    cout &lt;&lt; pid &lt;&lt; " received: " &lt;&lt;&lt;br /&gt;    sig &lt;&lt; ' ' &lt;&lt; info-&gt;si_code &lt;&lt; ' ' &lt;&lt; info-&gt;si_pid &lt;&lt; ' ' &lt;&lt; info-&gt;si_uid &lt;&lt; '\n';&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// raise SIGINT in a separate thread&lt;br /&gt;void sig_sender(void){&lt;br /&gt;    cout &lt;&lt; "sig sender " &lt;&lt; (long int)syscall(224) &lt;&lt; '\n';&lt;br /&gt;    sleep(3);&lt;br /&gt;    raise(SIGINT);          // raise = kill(getpid(), sig) in process, signal sent to sender itself only&lt;br /&gt;    sleep(1);&lt;br /&gt;    kill(standby_thr_pid, SIGINT); // signal only sent to the standby thread process/thread&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void sig_receiver(void){&lt;br /&gt;    //sigset_t set, old_set;&lt;br /&gt;&lt;br /&gt;    //sigaddset(&amp;set, SIGINT);&lt;br /&gt;    //sigprocmask(SIG_BLOCK, &amp;set, &amp;old_set);&lt;br /&gt;&lt;br /&gt;    cout &lt;&lt; "sig installer: " &lt;&lt; (long int)syscall(224) &lt;&lt; '\n';&lt;br /&gt;    struct sigaction act, old_act;&lt;br /&gt;    sigaddset(&amp;(act.sa_mask), SIGINT);&lt;br /&gt;    sigaddset(&amp;(act.sa_mask), SIGSEGV);&lt;br /&gt;    act.sa_flags = SA_SIGINFO;&lt;br /&gt;    act.sa_sigaction = ctlc;&lt;br /&gt;&lt;br /&gt;    sigaction(SIGINT, &amp;act, &amp;old_act);&lt;br /&gt;    sigaction(SIGSEGV, &amp;act, &amp;old_act);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;void standby(void){&lt;br /&gt;    standby_thr_pid = (long int)syscall(224);&lt;br /&gt;    cout &lt;&lt; "sig standby " &lt;&lt; standby_thr_pid &lt;&lt; '\n';&lt;br /&gt;    sleep(5);&lt;br /&gt;}&lt;br /&gt;// one thread acts as sender, the other receiver&lt;br /&gt;int main(){&lt;br /&gt;    boost::thread trs(sig_sender);&lt;br /&gt;    boost::thread trr(sig_receiver);&lt;br /&gt;    boost::thread trsb(standby);&lt;br /&gt;    while(true){&lt;br /&gt;        sleep(1);&lt;br /&gt;        if(interrupted){&lt;br /&gt;            cout &lt;&lt; "interrupt handler invoked\n";&lt;br /&gt;            interrupted = 0;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/sourcecode&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;Meditation, The Art of Exploitation&lt;/div&gt;</description><link>http://meditation-art.blogspot.com/2008/01/notes-of-linux-signal-in-context-of.html</link><author>noreply@blogger.com (Fei Liu)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-23323574.post-4827538419023226987</guid><pubDate>Thu, 10 Jan 2008 18:34:00 +0000</pubDate><atom:updated>2008-01-10T13:42:00.979-05:00</atom:updated><title>Annoying issue with Linux sound</title><description>To this day, linux sound device cannot be shared by multiple sound players. Typially /dev/dsp is locked by a single process and no other process can access it and output any sound. This is quite annoying because sometimes it's difficult to figure out what process has the lock on /dev/dsp. lsof does not do anything. &lt;br /&gt;&lt;br /&gt;If you insist to reuse the sound device, you have to restart the sound service. This is /etc/init.d/alsasound on Suse Linux. Restarting the sound service will cause termination of locking process (through SIGIO or SIGPIPE I imagine) and release the sound device. After which (in gnome) add back the volume control applet to the application tray in lower right corner.&lt;div class="blogger-post-footer"&gt;Meditation, The Art of Exploitation&lt;/div&gt;</description><link>http://meditation-art.blogspot.com/2008/01/annoying-issue-with-linux-sound.html</link><author>noreply@blogger.com (Fei Liu)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-23323574.post-1003629164950998729</guid><pubDate>Thu, 03 Jan 2008 18:51:00 +0000</pubDate><atom:updated>2008-01-03T13:52:03.845-05:00</atom:updated><title>Graph algorithms, data structures, pattern, and algorithm correctness</title><description>&lt;div class="blogger-post-footer"&gt;Meditation, The Art of Exploitation&lt;/div&gt;</description><link>http://meditation-art.blogspot.com/2008/01/graph-algorithms-data-structures.html</link><author>noreply@blogger.com (Fei Liu)</author></item><item><guid isPermaLink='false'>tag:blogger.com,1999:blog-23323574.post-7460970890354305102</guid><pubDate>Thu, 03 Jan 2008 17:16:00 +0000</pubDate><atom:updated>2008-01-25T20:26:40.636-05:00</atom:updated><title>GNU tool chain</title><description>I have been quite busy with several projects for the last month (hence the lack of blog activity) and in the process, I've learnt a few tricks about makefile, vim/cscope, and man page.&lt;br /&gt;&lt;br /&gt;Given a large project on GNU/linux, it's often necessary to first cross reference the code, getting a higher level overview of the data structures, generate man pages of essential APIs and data types. &lt;br /&gt;&lt;br /&gt;The following tools are my favorite&lt;br /&gt;&lt;br /&gt;1. umbrello, for creating high level UML diagrams of essential data structures and APIs&lt;br /&gt;2. cscope, ctags to generate cross reference, sometimes I also use lxr for c/c++ projects&lt;br /&gt;3. creating man pages, this generally involves a few shell scripts and perl scripts to convert html document to man page.&lt;br /&gt;4. use small test programs to understand the existing framework's APIs and design structure.&lt;br /&gt;&lt;br /&gt;During the process, I found it's essential to have a basic knowledge of the following GNU toolchain to make a developer's life easier:&lt;br /&gt;&lt;br /&gt;1. bash scripting. Writing bash script is like writing assembly, succinct, efficient, and to the point. One additional trick is the bash built in 'help' command to look up information on bash builtin commands, e.g. 'help for'&lt;br /&gt;&lt;br /&gt;2. vim or emacs. After 13 years of vim, there are still new things to be learnt, this is a keybind macro I devised recently to lookup C++ stl API/data structures directly from SGI website inside vim (look at the html source code directly to see how this macro is done, there is no direct way to expose it through blogspot):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;:vmap &lt;C-k&gt; :&lt;C-U&gt;!links -dump http://www.sgi.com/tech/stl/&lt;C-R&gt;=expand('&lt;cword&gt;')&lt;CR&gt;.html\|vim -R -&lt;CR&gt;&lt;CR&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Enter visual mode (v), highly your keyword, and push Ctrl+k, this will take you to another vim session with the page downloaded and formatted. Isn't it neat?&lt;br /&gt;&lt;br /&gt;3. makefile. It's naive to think of makefile/make as only a compile/link tool. It's more than that. Ever notice its similarity with the EBNF form in terms of structure? Yes it's actually an automaton, a complete turing machine. It can be literally used to perform any task C/C++/Perl etc can do. Its EBNF structure provides a powerful and intuitive hierarchical approach to resolve difficult problems. &lt;br /&gt;&lt;br /&gt;4. The old and good man page. Use 'shift+k' inside vim on a keyword (non visual mode) to get its man page, this is default installed in vim. Typically MANPATH is the search path for man pages. I have not found a good way to break up long lines in man pages. COLUMNWIDTH etc does not seem to affect man page generation from a text file with troff.&lt;br /&gt;&lt;br /&gt;References:&lt;br /&gt;1. http://www.hsrl.rutgers.edu/ug/shell_help.html&lt;br /&gt;2. http://vim.wikia.com/wiki/Mapping_keys_in_Vim_-_Tutorial_(Part_1)#Visual_mode_maps&lt;br /&gt;3. http://www.osdev.org/wiki/Makefile&lt;br /&gt;4. Bash Cookbook solutions and examples for bash users&lt;br /&gt;5. Hacking vim a cookbook to get the most out of the latest vim editor&lt;br /&gt;6. http://www.gnu.org/software/make/manual/make.html (unfortunately there is not a single book available to systematically introduce gnu make to general public. The manual remains the sole source of comprehensive explanation of gnu make)&lt;div class="blogger-post-footer"&gt;Meditation, The Art of Exploitation&lt;/div&gt;</description><link>http://meditation-art.blogspot.com/2008/01/gnu-tool-chain.html</link><author>noreply@blogger.com (Fei Liu)</author></item></channel></rss>