2009-04-23

Skeeter Davis -- The End Of The World

2008-07-22

Don't worship keystrokes!

Code is not a log for a plethora of not-so-valuable trials (pardon me, worthless to what it's meant to accomplish) ...ONLY the the working one should be there. It's not a time capsule for trials neither can it be a scratch pad. Try else where. Code should only reflect one's state of mind when reached the working solution not the compilation of twisted fused bloated trials nor the log for a set of keystrokes.
Have courage... DEL(
7F) is meant for some thing... Clean your code, Value your time and most valuably mine!

2008-07-16

Jimbo and the Jetset

Oh, Jimbo my childhood favorite!

2008-07-04

Coding Horor: طنوش طنوش طنوش

Refactoring an existing code you are usually fighting bugs resultant from such coding attitude , Listen how Mounir puts it.
Lyrics:
طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش. طنوش قال لك طناش.... و متعصلجلناش... طنوش قال لك طناش... و متعصلجلناش . تعملى فيها عنتر ده شئ ميخصناش..... بس البعيد هيتعب و هتبقى حالته أصعب, بس البعيد هيتعب و هتبقى حالته أصعب, خليك من حزب أشعب, طنش تاكل بلاش. تنح أفاك و فأم و أزرع وشك أوالح, متحطش المصالح ما بين خاصم و صالح. ده مفيش خصومه دايمة تفضل عالوش عايمة ولا القيامة قايمة الا في لحظة طناش. طنوش طنوش طنوش طنوش طنوش طنوش. غفير و خالته داية لو مسكوه عصاية و لبسوه عباية و حطوه عالمراية... غفير و خالته داية لو مسكوه عصاية و لبسوه عباية و حطوه عالمراية....هيشوف أتخن أمير ملعون أبو الفقير, هيشوف أتخن أمير ملعون أبو الفقير....و تسأله عن أصوله... و تسأله عن أصوله....يقول مشفتهاش.............
طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش طنوش

2008-06-26

كعبول

childhood memories

2008-05-25

Maria Callas -- Habanera (1962)

OpenDNS... How far can specialization go?

Two days now with OpenDNS, it's impressively fast and reliable. Now i won't be wondering why www.vmware.com or www.google.com isn't available sometimes. Shame on ISPs. It's funny, by having lousy DNS servers they are simply opening business for others. When I was first aware of dyndns and no-ip I was amazed how are they making money out of this (not charging for what any ISP do charge for). I know premium services do exist...yet to have my m\c uniquely referenceable costs extra money and they don't charge me for it.
I believe in specialization. Yet, to build your system as a stack of extremely (individually) reliable services is not reliable. it's an additive contribution to the overall risk and a costly involvement.
I wonder what entrepreneurs will come up with...NEW TTL Value setter?! HTTP DELETE responder?!

2008-05-22

No more Linkdsl DNS

That's it. I won't be using link's corrupted DNS servers any more. OpenDNS (208.67.222.222 and 208.67.220.220) is worth trying. Hope it is kept as good.

2007-12-27

Package of the Day: chere

This package adds context menu entry that allows having cygwin prompt of your favorite shell at the selected directory in windows explorer.

2007-10-10

Alexandria to host Wikimania 2008!

Alexandria to host Wikimania 2008! WOW!
thanks to the bidding team and their continual efforts throughout the last two years. See you there!

2007-10-06

BetterWorld

new semester... Looking for nice books and don't mind them being used... give it a try...a search plugin for Firefox now exists too :-)

2007-10-02

Adorable fonts on your linux box

While Mahmoud was showing me how he is debugging the plan9 kernel, The eye catching sharpness and beauty of fonts on his linux m/c charmed me. Having suffered a lot from fonts on Linux without actually seeking a solution, I promptly asked him. He told me about libfreetype and how they use a very decent font rendering algorithm. I gave it a look, it turned out that they reverse engineered reserved bytecode in the TTF format which apple used for there beautiful font rendering. FreeType developers knowing that the algorithm is patented they disabled it by default, yet it can be enabled by a flag at compile time ...luckily the major Linux distros enable it. The issue was to find proprietary fonts... you will need webcore font package but it doesn't have the whole thing, you need to search for some fonts in your safari for windows installation and in windows fonts itself.
tldp has a tutor on the issue here .

2006-07-29

Blogger Categories

Change log:
  • 2006-07-29 | V0.1b | Initial release
  • 2006-08-13 | V0.11b | fix -> Category tag escaped for long/image/video posts
  • 2006-08-14 | aware of blogger beta relaunch :-)
  • 2006-08-18 | V0.111b | fix->more robust fix for escaped tags (the last fix failed against malformed xml.

This is a clean (hopefully), self-contained, client side solution to
Blogger Categories To View its' features check this Demo as my blog isn't fat enough to exploit categorization :( .

(This post was written prior to Blogger beta relaunch which amongst it's features "labeling posts" ..pretty much "categories" , though i'll continue to maintain this script )


to Add Categories to your blog follow:
Users Guide:
  1. When Composing the post switch to "Edit Html" and the following
    <category cats="category1, category2, ...., categoryN"></category>
    Tip: to make this in an automated fashion add it to the "Post Template" form "Settings- > Formatting"
  2. Apply the following to the "Template"
    • Insert between section <head></head>

      <script type="text/javascript" >
      /* Prototype JavaScript framework, version 1.4.0_pre10_ajax
      * (c) 2005 Sam Stephenson <sam@conio.net>
      *
      * This is a downcut version for AJAX by Alexander Kirk http://alexander.kirk.at/
      *
      * Prototype is freely distributable under the terms of an MIT-style license.
      *
      * For details, see the Prototype web site: http://prototype.conio.net/
      *
      /*--------------------------------------------------------------------------*/
      var Prototype = {
      Version: '1.4.0_pre10_ajax',

      emptyFunction: function() {},
      K: function(x) {return x}
      }

      var Class = {
      create: function() {
      return function() {
      this.initialize.apply(this, arguments);
      }
      }
      }

      var Abstract = new Object();

      Object.extend = function(destination, source) {
      for (property in source) {
      destination[property] = source[property];
      }
      return destination;
      }

      Object.inspect = function(object) {
      try {
      if (object == undefined) return 'undefined';
      if (object == null) return 'null';
      return object.inspect ? object.inspect() : object.toString();
      } catch (e) {
      if (e instanceof RangeError) return '...';
      throw e;
      }
      }

      Function.prototype.bind = function(object) {
      var __method = this;
      return function() {
      return __method.apply(object, arguments);
      }
      }

      Function.prototype.bindAsEventListener = function(object) {
      var __method = this;
      return function(event) {
      return __method.call(object, event || window.event);
      }
      }

      Object.extend(Number.prototype, {
      toColorPart: function() {
      var digits = this.toString(16);
      if (this < 16) return '0' + digits;
      return digits;
      },

      succ: function() {
      return this + 1;
      },

      times: function(iterator) {
      $R(0, this, true).each(iterator);
      return this;
      }
      });

      var Try = {
      these: function() {
      var returnValue;

      for (var i = 0; i < arguments.length; i++) {
      var lambda = arguments[i];
      try {
      returnValue = lambda();
      break;
      } catch (e) {}
      }

      return returnValue;
      }
      }

      /*--------------------------------------------------------------------------*/

      var PeriodicalExecuter = Class.create();
      PeriodicalExecuter.prototype = {
      initialize: function(callback, frequency) {
      this.callback = callback;
      this.frequency = frequency;
      this.currentlyExecuting = false;

      this.registerCallback();
      },

      registerCallback: function() {
      setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
      },

      onTimerEvent: function() {
      if (!this.currentlyExecuting) {
      try {
      this.currentlyExecuting = true;
      this.callback();
      } finally {
      this.currentlyExecuting = false;
      }
      }
      }
      }

      /*--------------------------------------------------------------------------*/

      function $() {
      var elements = new Array();

      for (var i = 0; i < arguments.length; i++) {
      var element = arguments[i];
      if (typeof element == 'string')
      element = document.getElementById(element);

      if (arguments.length == 1)
      return element;

      elements.push(element);
      }

      return elements;
      }

      var Ajax = {
      getTransport: function() {
      return Try.these(
      function() {return new ActiveXObject('Msxml2.XMLHTTP')},
      function() {return new ActiveXObject('Microsoft.XMLHTTP')},
      function() {return new XMLHttpRequest()}
      ) || false;
      }
      }

      Ajax.Base = function() {};
      Ajax.Base.prototype = {
      setOptions: function(options) {
      this.options = {
      method: 'post',
      asynchronous: true,
      parameters: ''
      }
      Object.extend(this.options, options || {});
      },

      responseIsSuccess: function() {
      return this.transport.status == undefined
      || this.transport.status == 0
      || (this.transport.status >= 200 && this.transport.status < 300);
      },

      responseIsFailure: function() {
      return !this.responseIsSuccess();
      }
      }

      Ajax.Request = Class.create();
      Ajax.Request.Events =
      ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];

      Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
      initialize: function(url, options) {
      this.transport = Ajax.getTransport();
      this.setOptions(options);
      this.request(url);
      },

      request: function(url) {
      var parameters = this.options.parameters || '';
      if (parameters.length > 0) parameters += '&_=';

      try {
      if (this.options.method == 'get')
      url += '?' + parameters;

      this.transport.open(this.options.method, url,
      this.options.asynchronous);

      if (this.options.asynchronous) {
      this.transport.onreadystatechange = this.onStateChange.bind(this);
      setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
      }

      this.setRequestHeaders();

      var body = this.options.postBody ? this.options.postBody : parameters;
      this.transport.send(this.options.method == 'post' ? body : null);

      } catch (e) {
      }
      },

      setRequestHeaders: function() {
      var requestHeaders =
      ['X-Requested-With', 'XMLHttpRequest',
      'X-Prototype-Version', Prototype.Version];

      if (this.options.method == 'post') {
      requestHeaders.push('Content-type',
      'application/x-www-form-urlencoded');

      /* Force "Connection: close" for Mozilla browsers to work around
      * a bug where XMLHttpReqeuest sends an incorrect Content-length
      * header. See Mozilla Bugzilla #246651.
      */
      if (this.transport.overrideMimeType)
      requestHeaders.push('Connection', 'close');
      }

      if (this.options.requestHeaders)
      requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);

      for (var i = 0; i < requestHeaders.length; i += 2)
      this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
      },

      onStateChange: function() {
      var readyState = this.transport.readyState;
      if (readyState != 1)
      this.respondToReadyState(this.transport.readyState);
      },

      evalJSON: function() {
      try {
      var json = this.transport.getResponseHeader('X-JSON'), object;
      object = eval(json);
      return object;
      } catch (e) {
      }
      },

      respondToReadyState: function(readyState) {
      var event = Ajax.Request.Events[readyState];
      var transport = this.transport, json = this.evalJSON();

      if (event == 'Complete')
      (this.options['on' + this.transport.status]
      || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
      || Prototype.emptyFunction)(transport, json);

      (this.options['on' + event] || Prototype.emptyFunction)(transport, json);

      /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
      if (event == 'Complete')
      this.transport.onreadystatechange = Prototype.emptyFunction;
      }
      });

      Ajax.Updater = Class.create();
      Ajax.Updater.ScriptFragment = '(?:<script.*?>)((\n|.)*?)(?:<\/script>)';

      Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
      initialize: function(container, url, options) {
      this.containers = {
      success: container.success ? $(container.success) : $(container),
      failure: container.failure ? $(container.failure) :
      (container.success ? null : $(container))
      }

      this.transport = Ajax.getTransport();
      this.setOptions(options);

      var onComplete = this.options.onComplete || Prototype.emptyFunction;
      this.options.onComplete = (function(transport, object) {
      this.updateContent();
      onComplete(transport, object);
      }).bind(this);

      this.request(url);
      },

      updateContent: function() {
      var receiver = this.responseIsSuccess() ?
      this.containers.success : this.containers.failure;

      var match = new RegExp(Ajax.Updater.ScriptFragment, 'img');
      var response = this.transport.responseText.replace(match, '');
      var scripts = this.transport.responseText.match(match);

      if (receiver) {
      if (this.options.insertion) {
      new this.options.insertion(receiver, response);
      } else {
      receiver.innerHTML = response;
      }
      }

      if (this.responseIsSuccess()) {
      if (this.onComplete)
      setTimeout(this.onComplete.bind(this), 10);
      }

      if (this.options.evalScripts && scripts) {
      match = new RegExp(Ajax.Updater.ScriptFragment, 'im');
      setTimeout((function() {
      for (var i = 0; i < scripts.length; i++)
      eval(scripts[i].match(match)[1]);
      }).bind(this), 10);
      }
      }
      });

      Ajax.PeriodicalUpdater = Class.create();
      Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
      initialize: function(container, url, options) {
      this.setOptions(options);
      this.onComplete = this.options.onComplete;

      this.frequency = (this.options.frequency || 2);
      this.decay = 1;

      this.updater = {};
      this.container = container;
      this.url = url;

      this.start();
      },

      start: function() {
      this.options.onComplete = this.updateComplete.bind(this);
      this.onTimerEvent();
      },

      stop: function() {
      this.updater.onComplete = undefined;
      clearTimeout(this.timer);
      (this.onComplete || Ajax.emptyFunction).apply(this, arguments);
      },

      updateComplete: function(request) {
      if (this.options.decay) {
      this.decay = (request.responseText == this.lastText ?
      this.decay * this.options.decay : 1);

      this.lastText = request.responseText;
      }
      this.timer = setTimeout(this.onTimerEvent.bind(this),
      this.decay * this.frequency * 1000);
      },

      onTimerEvent: function() {
      this.updater = new Ajax.Updater(this.container, this.url, this.options);
      }
      });

      </script>

    • Change <body> to <body onload="getAtom(event)">

    • Add a placeholder for the category list in the menu sidebar (or wherever)

      <h2 class="sidebar-title">Categories <font color="red" style="font-size:large" ><sup>BETA</sup > </font></h2> <img id="waiting" src="http://photos.blogger.com/img/icon_inprogress.gif"/> <ul id="catList"></ul>



    • Insert before </body>

      <script type="text/javascript" >
      /**
      *Blogger Categories
      *@author Eslam Ahmed Al-Morshdy (e_morshdy At acm Dot org
      *@license GPL
      */

      log = function(msg){
      document.getElementById('out').value +=msg;
      };

      thenode=null;
      lastcat=null;
      theparent=null;

      function handle_onmouseover(event)
      {
      var element = (window.event!=undefined)? window.event.srcElement: event.target;
      var parent= element.parentNode;
      if(parent.tagName != "LI"){ return;};
      if( parent.getElementsByTagName("A").length == 0 ){ return;};
      var cat = parent.getElementsByTagName("A")[0]["theCategory"];
      if(lastcat==cat){return;};

      if(thenode != null)
      {

      thetitle['style']['fontWeight'] = 'normal';
      thetitle['style']['fontSize']= 'small';
      thenode['style']['display']='none';
      };
      lastcat=cat;
      thetitle=parent.getElementsByTagName("A")[0];/*category title*/;
      thetitle['style']['fontWeight']='bolder';
      thetitle['style']['fontSize']='large';
      thenode = parent.childNodes[2];/*the list*/;
      thenode["style"]["display"]='list-item';
      };

      function handle_onmouseout(event)
      {
      var element = (window.event!=undefined)? window.event.srcElement: event.target;
      if(element.tagName!="DIV"){return;};
      if(thenode != null)
      {
      thetitle['style']['fontWeight'] = 'normal';
      thetitle['style']['fontSize']= 'small';
      thenode['style']['display']='none';
      thenode=null;
      thetitle=null;
      lastcat=null;
      };
      };

      var e;
      function showResponse(event)
      {
      if (event)
      e=event;
      /*Parsing the Atom*/;

      if(!e || !e.responseXML)
      {
      reportError();
      return;
      };
      response = e;
      root=e.responseXML.documentElement

      /*log(responseText);*/

      root.getElementsByTagName("content")

      var entries = root.getElementsByTagName("entry");
      categories = {};
      categories['all']=[];
      categories['other']=[];
      if(entries==null)
      {
      return;
      }
      else
      { for(var entryCount = 0; entryCount < entries.length ; entryCount++)
      {
      //log("Starting entry :"+entryCount);
      var contents = entries[entryCount].getElementsByTagName("content");
      if( (null == contents )||(contents.length == 0 ))
      {
      reportError();
      return;
      }

      if( contents[0].getAttribute("mode") == null )
      {
      var category = entries[entryCount].getElementsByTagName("category");
      if(( null==category )||( category.length ==0))
      {
      cats="";
      }
      else
      {
      var cats = category[0].getAttribute("cats");
      };

      }else
      {
      var text ;
      if(contents[0].textContent){text = contents[0].textContent}
      else if(contents[0].text){text = contents[0].text}
      else{reportError();return;}

      var start= text.indexOf("<category");
      var end= text.indexOf("</category>");
      var cats = text.slice(start,end);
      start = cats.indexOf("cats");;
      end = cats.indexOf("\">");
      cats = cats.slice(start+6,end)
      }


      cats = cats.toLowerCase();
      cats = cats.split(",");

      //log(cats+'\n');

      if(cats.length==0 || cats[0]=="")
      {
      //log("OTHER")
      link = entries[entryCount].getElementsByTagName("link");
      for(var x = 0 ; x < link.length ; x++ )
      if(link[x].getAttribute("rel") == "alternate" )
      {
      link=link[x];
      var found=true;
      break;
      };
      if(!found){
      continue;
      };
      var title = link.getAttribute("title") ;
      var link = link.getAttribute("href") ;/*destructive*/;
      categories['other'][categories['other'].length]={'link':link,'title':title};
      categories['all'][categories['all'].length]={'link':link,'title':title};
      }
      else
      {
      link = entries[entryCount].getElementsByTagName("link");
      for(var x = 0 ; x < link.length ; x++ )
      {
      if(link[x].getAttribute("rel") == "alternate" )
      {
      link=link[x];
      break;
      };
      };
      var title = link.getAttribute("title") ;
      var link = link.getAttribute("href") ;/*destructive*/;

      for(var x = 0 ; x < cats.length ; x++)
      {
      if(categories[cats[x]] == undefined)
      {
      categories[cats[x]]=new Array();
      };
      var indx = categories[cats[x]].length;
      categories[ cats[x] ][ indx ]={'link':link,'title':title};
      categories['all'][categories['all'].length]={'link':link,'title':title};
      };
      };

      };
      };

      for(var x =0 ; x < categories['all'].length ; x++)
      {
      for(var y =x+1 ; y < categories['all'].length ; y++)
      {
      if(categories['all'][x]['link'] == categories['all'][y]['link'])
      {
      categories['all'].splice(y,1);
      y--;
      };
      };
      };

      /*Building UI elements*/;
      computedLinks={};
      computedCategories={};
      for(var x in categories)
      {
      var item = document.createElement("li");
      var subitem = document.createElement("A");
      var subitem2 = document.createElement("FONT");
      var text = document.createTextNode(x);
      var text2= document.createTextNode('('+categories[x].length+')');

      if(subitem.attachEvent)
      {
      subitem.attachEvent('onclick',handle_onmouseover);
      }
      else
      {
      subitem.setAttribute('onclick',"handle_onmouseover(event)");
      };

      subitem2['color']="orange";
      subitem['style']['cursor']="pointer";
      subitem.theCategory=x;
      subitem2.appendChild(text2);
      subitem.appendChild(text);
      item.appendChild(subitem);
      item.appendChild(subitem2);
      computedCategories[x]=item;
      computedLinks[x]= document.createElement("ul");
      computedLinks[x]['style']['display']="none";

      for(var y = 0 ; y < categories[x].length;y++ )
      {
      var link = document.createElement("a");
      link["href"]=categories[x][y]['link'];
      var text = document.createTextNode(categories[x][y]['title'] );
      link.appendChild(text);
      var listItem = document.createElement("li");
      listItem['style']['fontWeight']="normal";
      listItem['style']['fontSize'] = 'small';
      listItem.appendChild(link);
      computedLinks[x].appendChild(listItem);
      };
      computedCategories[x].appendChild(computedLinks[x]);
      };
      /*clear waiting spin*/;
      document.getElementById("waiting")['style']['display']='none';

      /*Appending categories to the catlistt*/;
      var tempList = document.getElementById("catList");

      /*First remove empty categories mistakes*/
      if(computedCategories[''] != undefined)
      {
      delete computedCategories[''];
      };

      /*Second append in the list*/
      for(var x in computedCategories )
      {
      tempList.appendChild(computedCategories[x]);
      };

      /*Registering Collapse to the sidebar*/;
      var tempSidebar= document.getElementById("sidebar");
      if(tempSidebar.attachEvent)
      {
      tempSidebar.attachEvent("onmouseout",handle_onmouseout) ;
      }
      else
      {
      tempSidebar.setAttribute("onmouseout","handle_onmouseout(event)");
      };



      };

      function getAtom()
      {
      var temp = window.document.location.toString();

      var url = temp.substr(0, 7 + temp.substr( 7 , temp.length ).indexOf('/') ) + "/atom.xml";

      reportError=function()
      {
      document.getElementById("waiting")['style']['display']='none';
      var theitem = document.createElement("li");
      var subitem = document.createElement("FONT");
      var text= document.createTextNode("\n\n\nfailed request for:\n "+url+"\n\n propably you are in preview of blog template");
      subitem['color']="red";
      subitem.appendChild(text);
      theitem.appendChild(subitem);
      document.getElementById("catList").appendChild(theitem);

      };

      var pars = '';
      try
      {
      var myAjax = new Ajax.Request(url,
      {method:'get',
      parameters:pars,
      asynchronous:true,
      onFailure:reportError,
      onSuccess:showResponse});
      }
      catch (e)
      {
      reportError();
      };
      };

      doEval = function(event)
      {
      alert('how') ;
      eval( document.getElementById('in').value );
      };

      </script>

  1. You are done feel free to comment anyfeedback is most welcome

Developer Notes:

  • Blogger supported categories from a while!! yes it did when it introduced syndication (don't know when)?! lets' see what we have
    1. can edit the blog template ( Injecting handy JavaScript )
    2. can edit posts in Html, and even defining a template for it
    3. have syndication that doesn't alter your posts or escape it and that is available at the same domain
    4. No thanks ..... but Thanks!! that's enough for introducing categorization

    • The accompanying script parses the corresponding atom syndication of your blog searching for the <category> tag in each <entry> This is totally self contained solution to categorizing blogger
      • no third party to which you hand the view of your content
      • no redirection to a foreign page (social-book marking blogger-search)
      • no server abuse
        • each page impression acts as if some one reading ur atom syndication
        • Blog template + the script ~32kb could be stripped to ~24kb
      • no expected localization problems
      • totally client side processing.
      • Asynchronous no blocking (AJAX-Based).
      • posts count
      • not that painful (but thanks to them i was forced to do it)
        Behave!
      • works out of the box yet is highly configurable
      • handle old posts: viewable from all and other tags no need to re-publish them
      • free as in Willy ;-)
  • Issues
    • Categories aren’t available in preview of a modified template?
      • Categories rely on parsing the Atom feed available relative to your blog at

http://name.blogspot.com /atom.xml

but the domain from which the preview is fetched is a sessioned access to

http://www.blogger.com/blog-preview.g

and xmlHTTPrequest couldn't (and shouldn't) be issued for pages that doesn't share same domain.

    • Why not use RSS instead of Atom for the parsing issue?
      • Atom preserves < > of the embedded tag unlike rss that escapes it.
        • not necessarily long/image/video posts do get escaped :-( but this fix did the trick
          • no, the parser requires a well formed xml which isn't gauranteed I had to search for tags in the textual representation of the <content> tag.

    • Script size: a stripped down version of prototype by Alexander Kirk was used.

    • A Downside: The embedded tag <category> </category> breaks the conformance of the post to HTML but luckily it's gracefully ignored by rendering browsers and (Firefox, IE and safari ) feed-readers.

    • Feedback: Feature requests, comments, error reports, uncaught exceptions :(, are most welcome.



2006-07-08

Excessive Macros

Recently I've been working on a project that made an excessive use of Macros. Such usage is usually discouraged. Yet it was a must -or at least it seemed so-. We needed a component to be highly configurable in order to be able to exploit different implementation techniques or even more, different programming paradigms, we also needed that at minimum maintenance cost . To be clearer "function or procedure" was considered a high level abstraction that might be under investigation !!.
The implementation language was C++ as a multi paradigm language. The component was deeply studied and it's operations were extensively annotated. It was decomposed into fine grained operations, the core logic of each was attached to a macro, with which we play, reorder or discard depending on the technique or paradigm under investigation.

Macros
Debugging macros is poorly supported in the output of most C/C++ compilers -or at least ones that came to my notice -cl6,7,7.1 gcc4.01-, which is inherent from the nature of macros being repeatedly defined or redefined across a single source file or even across the project, added to that the possibility of containing other macros which adds recursion to it's forementioned nature. So debuggers have no clue about which definition to attach to the encountered macro. gdb for example the only macro support it provides is to expand -just expand- the encountered macro with no digging into it.

We made use of a level of indirection in the compilation process as follows from the following steps
  1. Editing and coding is done in a file excluded from build with only includes of macros to be expanded and no std includes added to avoid their lengthy expansion.
  2. The file is preprocessed into another files with macros expanded.
  3. Each macro is expanded into single line the matter what how lengthy it is, so to make it readable we made use of a sed script to format it (probably we should have used gnu indent)
  4. The other includes are added to the formatted file
  5. The final file is the one that is included in the build and marked as read only to prevent editing.
  6. Encountered bugs are fixed in the original file not the expanded one (a down side of the indirection)


eclipse
Eclipse provide nice integration/wrapping to GNU tool chain. Adding the pre mentioned indirection in automated fashion to a CDT managed C++ project is described in the following steps

  1. Write the following to a shell script gen.sh and put it in the src root directory
    ## Announcing it to the console
    echo Generating the Interpreter

    ## Stepping up to the src root directory to
    cd ..

    ## Removing the old file
    rm ExecutionEng.cpp

    ## Preprocessing
    gcc -E -P -CC -ointerpreter-1.cpp interpreter.cpp

    ## formatting: replacing each ; by ;\n
    ## ps: you can use gnu indent instead
    sed -e 's/;/;\n/g' interpreter-1.cpp > interpreter-2.cpp

    ## Adding other includes to the final output
    echo \#include\"ejvm.h\" > ExecutionEng.cpp
    echo \#include\"log.h\" >> ExecutionEng.cpp
    cat interpreter-2.cpp >> ExecutionEng.cpp

    ## Attributing the generated file as Read Only
    chmod u=+r ExecutionEng.cpp

    ## Removing intermediate files
    rm interpreter-1.cpp interpreter-2.cpp

  2. Add the script as a prebuild operation in the project build process


  3. To enforce the generation use Build all or Clean from project menu

2006-06-12

Google Adsense

I hate adds (even smooth textual ones). I couldn't imagine myself clicking on one ( unless it says "hay come earn a Ph.D at Stanford and join Knuth's Tree and tailed with "PS: we will forget all about bad marks u got for non-cs subjects" ).

Yet I find my HCI lecturer saying "it's bad yet a must" very execusing for the "468x115" banner up here !!! . A bit of inconsistency hah.. U hate ads and in the same time provide them to others .

Well.. this special banner is very funny. Entities there aren't adds or "direct ones" at least , they are categories that google adsense indexer(not Bot?) found most relevant to the contents of this blog. So a level of indirection is introduced here. allowing more decent persuasive non eye-hurting way to advertise

if u r willing to be exposed to adds of category X1 X2 X3 that is found so relevant to the web page u r currently browsing
then do click on any!!!

then the inconsistency is the misleading "Ads by Google" it should've been "Categories by Google" or "Tags by Google " !!!

2006-06-11

eJVM

eJVM is to be launched in 3 weeks' time inshaa Allah.