<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-15425972</id><updated>2011-07-07T16:11:33.137-07:00</updated><title type='text'>TJ Laurenzo's Weblog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://tjlaurenzo.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15425972/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://tjlaurenzo.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>TJ Laurenzo</name><uri>http://www.blogger.com/profile/05554189172407515232</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://laurenzo.org/blog_attach/IMAG0003.JPG'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>8</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-15425972.post-114928141698780783</id><published>2006-06-02T13:49:00.000-07:00</published><updated>2006-06-02T13:50:16.996-07:00</updated><title type='text'>Blog moved</title><content type='html'>This weblog has been moved.  Its new home is:&lt;br /&gt;&lt;a href="http://www.rcode.net/blog/tlaurenzo"&gt;http://www.rcode.net/blog/tlaurenzo&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15425972-114928141698780783?l=tjlaurenzo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tjlaurenzo.blogspot.com/feeds/114928141698780783/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15425972&amp;postID=114928141698780783' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15425972/posts/default/114928141698780783'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15425972/posts/default/114928141698780783'/><link rel='alternate' type='text/html' href='http://tjlaurenzo.blogspot.com/2006/06/blog-moved.html' title='Blog moved'/><author><name>TJ Laurenzo</name><uri>http://www.blogger.com/profile/05554189172407515232</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://laurenzo.org/blog_attach/IMAG0003.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15425972.post-114610431016797574</id><published>2006-04-26T19:17:00.000-07:00</published><updated>2006-05-13T13:14:05.303-07:00</updated><title type='text'>Setup Rails</title><content type='html'>I always seem to miss a step when installing Rails on Fedora.  Here are the steps:&lt;br /&gt;&lt;br /&gt;Setup Rails (all steps as root)&lt;br /&gt;-----------&lt;br /&gt;Install optional Ruby packages:&lt;br /&gt;   - ruby-rdoc&lt;br /&gt;   - ruby-ri&lt;br /&gt;&lt;br /&gt;Download and install Ruby Gems:&lt;br /&gt;   - wget http://rubyforge.org/frs/download.php/5207/rubygems-0.8.11.tgz&lt;br /&gt;   - Extract archive and change into directory&lt;br /&gt;   - ruby setup.rb&lt;br /&gt;&lt;br /&gt;Install Rails:&lt;br /&gt;   - gem install rails --include-dependencies&lt;br /&gt;&lt;br /&gt;Installing Postgres support:&lt;br /&gt;- yum install postgresql-devel&lt;br /&gt;- gem install postgres&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15425972-114610431016797574?l=tjlaurenzo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tjlaurenzo.blogspot.com/feeds/114610431016797574/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15425972&amp;postID=114610431016797574' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15425972/posts/default/114610431016797574'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15425972/posts/default/114610431016797574'/><link rel='alternate' type='text/html' href='http://tjlaurenzo.blogspot.com/2006/04/setup-rails.html' title='Setup Rails'/><author><name>TJ Laurenzo</name><uri>http://www.blogger.com/profile/05554189172407515232</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://laurenzo.org/blog_attach/IMAG0003.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15425972.post-114546044036869847</id><published>2006-04-19T08:14:00.000-07:00</published><updated>2006-04-19T08:27:20.413-07:00</updated><title type='text'>Firefox View Source Trick</title><content type='html'>I might be the last one on the planet to discover this one, but I doubt it, so I thought I'd share.&lt;br /&gt;&lt;br /&gt;I'm used to right-clicking on a page and selecting "View Page Source" from the context menu. This has some advantages over the same command in the View menu because it allows you to narrow down which frame you want to view.&lt;br /&gt;&lt;br /&gt;Last night, however, I accidentally selected some text and right clicked. I noticed that the familiar "View Page Source" menu item had changed to a "View Selection Source". It seems that if an straight-forward subset of the document is spanned by the selection, the resulting view source window will only display that portion. If, however, the selection spans disjoint elements in the tree, the whole document will be displayed with the relevant pieces hilighted.&lt;br /&gt;&lt;br /&gt;This in and of itself is really helpful for comprehending a complex HTML structure, but there is one more thing I noticed that is even better:&lt;br /&gt;&lt;br /&gt;The output of the View Selection Source command seems to be the HTML representation of the current structure of the document as opposed to the raw text obtained at page load time. Put another way, the changes made via JavaScript to the HTML DOM are displayed by View Selection Source.&lt;br /&gt;&lt;br /&gt;I know there is an extension that lets you view the live document structure but I've never installed it and this is an easy trick that seemingly produces the same result.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15425972-114546044036869847?l=tjlaurenzo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tjlaurenzo.blogspot.com/feeds/114546044036869847/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15425972&amp;postID=114546044036869847' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15425972/posts/default/114546044036869847'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15425972/posts/default/114546044036869847'/><link rel='alternate' type='text/html' href='http://tjlaurenzo.blogspot.com/2006/04/firefox-view-source-trick.html' title='Firefox View Source Trick'/><author><name>TJ Laurenzo</name><uri>http://www.blogger.com/profile/05554189172407515232</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://laurenzo.org/blog_attach/IMAG0003.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15425972.post-114264422854868323</id><published>2006-03-17T16:51:00.000-08:00</published><updated>2006-03-17T17:24:17.160-08:00</updated><title type='text'>Getting dev tools working with XULRunner</title><content type='html'>I've recently had a revived interest in Mozilla XUL. Last month I saw a blog about the new XULRunner tool, so I downloaded it a few days ago for a closer look. The first thing that became pretty obvious was that the normal suite of tools that I'm used to working with in Firefox/Mozilla don't really fit into XULRunner out of the box. These include things like the &lt;a href="http://ted.mielczarek.org/code/mozilla/extensiondev/"&gt;Extension Developer Extension&lt;/a&gt;, the &lt;a href="http://getahead.ltd.uk/ajax/venkman"&gt;Venkman JavaScript Debugger&lt;/a&gt;, and the DOM Inspector.&lt;span class="" style="display: block;" id="formatbar_CreateLink" title="Link" onmouseover="ButtonHoverOn(this);" onmouseout="ButtonHoverOff(this);" onmouseup="" onmousedown="CheckFormatting(event);FormatbarButton('richeditorframe', this, 8);ButtonMouseDown(this);"&gt;&lt;br /&gt;There are a few places that mention that it should be possible to get these things going, but I couldn't find any solid instructions on how to do so. I haven't gotten the DOM Inspector going yet, but see below for a method for getting the first two working in your XULRunner app.&lt;br /&gt;&lt;br /&gt;First of all, I did all of this work using a custom built XULRunner on Linux from the XULRunner 1.8.0.1 source drop. I have not tried this on the stock binaries but I think it should work. In any case, here are the configure options I used:&lt;br /&gt;&lt;/span&gt;  &lt;pre&gt;--enable-application=xulrunner&lt;br /&gt;--enable-extensions=default,venkman,inspector&lt;br /&gt;--enable-svg&lt;br /&gt;--enable-storage&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The Extension Developer Extension was pretty easy to hack into an XULRunner app. I just extracted the extensiondev.jar from the xpi and created an extensiondev.manifest that reflected what was in the install.js. I dropped both of these files into my app's chrome directory and was then able to specify the FireFox overlay on my main window (chrome://extensiondev/content/firefoxOverlay.xul). It worked after creating a menupopup with the id "menu_ToolsPopup", which follows the FireFox naming convention.&lt;br /&gt;&lt;br /&gt;Venkman was trickier. I tried the same approach, ending up with a venkman.manifest and venkman.jar in my chrome directory. I then tried to overlay Venkman onto my main window (chrome://venkman/content/venkman-overlay.xul). The first hurdle is that the function toOpenWindowByType does not exist in the default XULRunner overlays. I just reimplemented it with the following:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;function toOpenWindowByType(inType, uri)&lt;br /&gt;{&lt;br /&gt; window.open(uri, "_blank", "chrome,extrachrome,menubar,resizable,scrollbars,status,toolbar");&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Then the problem became that it just didn't work. I was using the venkman.jar that I extracted from the XULRunner build that I was using. I finally switched to the patched version of Venkman for Firefox 1.5 available from &lt;a href="http://getahead.ltd.uk/ajax/venkman"&gt;here&lt;/a&gt;. It worked like a charm. The main thing you have to do is uncheck the menu option Debug/Exclude Browser Files. Note that if you open more than one debugger window, the app crashes with a nasty segfault. My toOpenWindowByType stub should keep this from happening, but I haven't gotten to adding any logic for that.&lt;br /&gt;&lt;br /&gt;I packaged the glue for these things up into an xulrunnerdev.jar that also adds a menu item to open the JavaScript Console (in lieu of having to pass the -jsconsole command line). Here are the exact steps to get it working in your XULRunner app:&lt;br /&gt;&lt;ul&gt;   &lt;li&gt;Download the xulrunnerdev.zip file from below and extract it to your application chrome directory.&lt;/li&gt;   &lt;li&gt;Add a line to your application chrome.manifest for each of your application windows you would like to overlay with the tools. For example:&lt;/li&gt; &lt;/ul&gt;&lt;br /&gt;&lt;pre&gt;overlay chrome://testapp/content/startPage.xul chrome://xulrunnerdev/content/devOverlay.xul&lt;/pre&gt;&lt;br /&gt;&lt;ul&gt;   &lt;li&gt;Add an appropriate menupopup to the windows you want overlayed.  For example:&lt;/li&gt; &lt;/ul&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; &amp;lt;toolbox flex="1"&amp;gt;&lt;br /&gt;   &amp;lt;menubar&amp;gt;&lt;br /&gt;    &amp;lt;menu label="Dev Tools"&amp;gt;&lt;br /&gt;     &amp;lt;menupopup id="menu_ToolsPopup"&amp;gt;&lt;br /&gt;     &amp;lt;/menupopup&amp;gt;&lt;br /&gt;    &amp;lt;/menu&amp;gt;&lt;br /&gt;   &amp;lt;/menubar&amp;gt;&lt;br /&gt; &amp;lt;/toolbox&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I have included a test application that includes all of this stuff below as well. There are certainly multiple ways to get this stuff to work. Hopefully this work can hold us over until more official support of the dev tools is included in XULRunner.&lt;br /&gt;&lt;br /&gt;Downloads:&lt;br /&gt;&lt;ul&gt;   &lt;li&gt;&lt;a href="http://www.rcode.net/blogattach/2006-03-17/xulrunnerdev.zip"&gt;xulrunnerdev.zip&lt;/a&gt;&lt;/li&gt;   &lt;li&gt;&lt;a href="http://www.rcode.net/blogattach/2006-03-17/testapp.zip"&gt;testapp.zip&lt;/a&gt;&lt;span class="down" style="display: block;" id="formatbar_CreateLink" title="Link" onmouseover="ButtonHoverOn(this);" onmouseout="ButtonHoverOff(this);" onmouseup="" onmousedown="CheckFormatting(event);FormatbarButton('richeditorframe', this, 8);ButtonMouseDown(this);"&gt;&lt;/span&gt;&lt;/li&gt; &lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15425972-114264422854868323?l=tjlaurenzo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tjlaurenzo.blogspot.com/feeds/114264422854868323/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15425972&amp;postID=114264422854868323' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15425972/posts/default/114264422854868323'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15425972/posts/default/114264422854868323'/><link rel='alternate' type='text/html' href='http://tjlaurenzo.blogspot.com/2006/03/getting-dev-tools-working-with.html' title='Getting dev tools working with XULRunner'/><author><name>TJ Laurenzo</name><uri>http://www.blogger.com/profile/05554189172407515232</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://laurenzo.org/blog_attach/IMAG0003.JPG'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15425972.post-112878719759437042</id><published>2005-10-08T08:27:00.000-07:00</published><updated>2005-10-08T11:00:54.856-07:00</updated><title type='text'>Dumping the phone company</title><content type='html'>So, I did it... I finally made the total and final switch to Voice Over IP. I have been trying to find a palatable way to do this for many months as I watch my Qwest bill inch higher and higher. There were three things that converged this month that finally made me jump ship:&lt;br /&gt;&lt;ul&gt;   &lt;li&gt;My Qwest bill topped $120 for a single line of service, a featureless home DSL package, and a minimal amount of long distance. Several months ago when my bill was hovering around $105/month, I considered it offensive that I was paying the phone company this much money for such a basic level of service. I called them and worked with the rep for nearly a half hour to trim out the optional features from my plan. Somehow, though, with taxes and all, I still ended up paying $101/month. My goal of getting my payments to the phone company down to a two digit number seemed unattainable. Needless to say, a $120 bill just fueled my desire to break away.&lt;/li&gt;   &lt;li&gt;I signed up some time ago for this Qwest long distance package that has no monthly fee and charges 5 cents a minute, with a cap of $20/month. I know an increasing number of people are using their cell phones for long distance because the cell companies now treat LD as a local call for billing purposes. For myself, though, when I'm at home talking to friends or family long distance, I like having the clarity that only a wired connection can bring. I gnash my teeth at the 5 cent per minute tax here, but as I said, it is a preference of mine and at least it will top out at $20 and I can't get hit by a massive long distance bill... Or so I thought. On one hand, an examination of my bill this month reveals that Qwest now charges a monthly service fee for this plan. I don't know how long they have been doing it, but I do know that when I signed up, I questioned them very closely and got no indication that there was any promotional period or other such tactic being employed. In addition, while working at home a few times over the past month, I inadvertently returned a couple of phone calls to Canada (which is actually far closer distance-wise than most of the long distance calls I make). The calls totaled 33 minutes and accounted for a $13 charge on my bill (which was not subject to my $20/month cap). When questioned, the rep (who was very nice, btw) informed me that I could activate some XYZ international rate plan, which had a monthly fee, and would allow me to make these calls to Canada for a mere 10 cents per minute (which is still highway robbery). This situation outlines my basic problem with long distance companies (and cell phone companies too, but that is for another day): Why do I have to opt in through some obscure process (and usually pay a fee) in order to avoid getting scammed into irreversibly paying exorbitant prices for deviating outside of my normal habits and performing a normal act that I had no idea I was going to do ahead of time. And really, HOW SHOULD I KNOW that placing a call across some line on a map (I didn't even have to dial a country code) without informing the phone company first and paying them an additional protection fee qualified me to be the fully-legal victim of a billing scam. Imagine if the criminal system took this approach. What would you do if you were told: "I'm sorry that you had your identity stolen, but since you didn't sign up on the &lt;span style="font-style: italic;"&gt;National Anti-Identity Theft Registry&lt;/span&gt; before-hand and pay the required monthly dues, there is really nothing we can do." Anyway, the extra $13 charge certainly didn't break the bank. It just reminded me why I dislike the phone company so much (and long distance companies especially). If all of the long distance companies in this country went bankrupt tomorrow (or at least their consumer long distance divisions), the world would be a slightly better place.&lt;/li&gt;&lt;li&gt;Ok. I said there were three things, and the first two were rants. This one is simple: I opened an email advertisement for a local broadband company (with whom I had inquired about service in the past) that outlined the basics of a new VOIP plan that they are rolling out. For a number of reasons which I'll explain below, this is different than "traditional" residential VOIP. The price was pretty compelling, too.&lt;/li&gt;  &lt;/ul&gt;&lt;br /&gt;Earlier this year I was responsible for overseeing the rollout of a new phone system to a small company with a couple of satellite offices. We went with Cisco's line of VOIP equipment and tied it all together with leased lines that had QoS running over them and a pair of ISDN PRI's to interface with the telco. This experience taught me a couple of things about VOIP:&lt;br /&gt;&lt;ul&gt;   &lt;li&gt;VOIP is viable.  It can produce very clear calls on par with good analog links.&lt;/li&gt;   &lt;li&gt;If QoS is not running on the network (especially the WAN links), or if it is not configured properly, things fall apart pretty quickly.&lt;/li&gt; &lt;/ul&gt;Bolstered by this success and wanting to add a second line of service to my home, I chose to go with one of the consumer internet VOIP providers. My experience was less than encouraging. Most of the time it sounded like I was on a poor quality cell phone. Also, whenever I would upload or download anything of substance while on the phone, it would break up. I knew that these experiences were a combination of using a low-bitrate codec and the inherent problems with sending real-time voice traffic over a link without any kind of QoS. It seemed to be a no-win scenario. Changing to a full-bitrate codec increased the sound quality but the added bandwidth requirements made it more likely for my internet activity to interfere with the phone call. Some tweaking made the situation better, but it was still bad in my opinion.&lt;br /&gt;&lt;br /&gt;When I saw the advertisement for the local Denver company &lt;a href="http://www.sbbone.com/"&gt;SBBOne&lt;/a&gt;, I jumped on it pretty quickly. They offer a full-stack VOIP/internet solution, becoming the ISP for your DSL link and riding the VOIP traffic wholly over their network. This allows them to provide end-to-end Quality of Service guarantees, which means that the VOIP traffic can always get the real-time priority that it needs. As added bonuses, they also do the following:&lt;br /&gt;&lt;ul&gt;   &lt;li&gt;Don't charge long distance for the lower 48 states.&lt;/li&gt;   &lt;li&gt;Charge international rates that are competitive (2 cents/minute to Canada for example)&lt;/li&gt;   &lt;li&gt;Wire the voice service back through your existing house wiring, which allows you to plug a normal phone into any existing phone jack without even thinking about the VOIP router.&lt;/li&gt;   &lt;li&gt;Provide the full calling features that we have come to expect from VOIP providers (and which will usually cost you in excess of $30/months to get from the phone company) such as 3-way calling, caller id, call waiting, voicemail to email options, web access, forwarding and more.&lt;/li&gt;   &lt;li&gt;Local number portability: You get to keep your phone number.&lt;/li&gt;   &lt;li&gt;They are a reseller for Qwest DSL which means that they deal with Qwest for the physical link so I don't have to.&lt;/li&gt;   &lt;li&gt;911 support&lt;/li&gt;   &lt;li&gt;Static, public IP&lt;br /&gt;&lt;/li&gt; &lt;/ul&gt; The cost for all of this is $65/month and includes equipment rental. I added another line of service for an extra $20/month, bringing the cost to $85/month. I have to say that the results are impressive. The sound quality is perfect, even when using both phone lines and the internet heavily, and as-advertised, all of the existing phones and fax machine in my house "just work".&lt;br /&gt;&lt;br /&gt;The price-tag for this may seem high for those of you using normal Internet based VOIP services. For these services you are probably paying $20-25/month. You have to remember that the SBBOne price tag includes DSL access. If I were to get a standalone DSL line from Qwest, the base cost would start at about $35 and increase to $40/month if I rented equipment from them.&lt;br /&gt;&lt;br /&gt;Doing the math, you see that rolling your own stand-alone VOIP service from someone like Vonage or Broadvoice will cost you the same as going with the SBBOne solution. And with SBBOne, you get the local number portability (and caller id displays actually show your name instead of "VONAGE HOLDINGS"), service on your normal house lines and the ability to make and receive crystal clear calls.&lt;br /&gt;&lt;br /&gt;This bundled approach really is the next generation in residential VOIP service. I would expect to see this type of arrangement popping up everywhere in the coming months. I know that &lt;a href="http://www.speakeasy.net/home/voip/"&gt;Speakeasy&lt;/a&gt; is providing something similar, but their price for the same service offering (1.5M/768k DSL + Phone service) appears to be about $45/month more than what I am paying SBBOne (not to mention the inevitable contracts when you deal with Speakeasy). At this rate, you are probably not seeing a price-break when compared with traditional DSL + wired service, but it is available nationwide. I have also heard that Qwest is gearing up to provide a similar service. I really don't think that I would ever really &lt;span style="font-style: italic;"&gt;choose&lt;/span&gt; to opt in to a Qwest offering. The price would have to pretty compelling. As it is, I have just found a viable and cheap way to &lt;span style="font-style: italic;"&gt;opt-out&lt;/span&gt; of Qwest services.  I don't anticipate going back anytime soon.&lt;br /&gt;&lt;br /&gt;It really is too bad. Qwest was a good company before they realized their dream of becoming a local phone provider by buying USWest. Then they got locked up into the 50 years of lock-step tradition that is the little bells. Why they would pay to get into that position is beyond me. Of course, being in the heart of the old USWest territory that Qwest now serves probably renders my vision a bit myopic. After all, &lt;span style="font-style: italic;"&gt;everyone&lt;/span&gt; hates their local telephone company.  Their other lines of business outside of this territory are probably still ok.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15425972-112878719759437042?l=tjlaurenzo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tjlaurenzo.blogspot.com/feeds/112878719759437042/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15425972&amp;postID=112878719759437042' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15425972/posts/default/112878719759437042'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15425972/posts/default/112878719759437042'/><link rel='alternate' type='text/html' href='http://tjlaurenzo.blogspot.com/2005/10/dumping-phone-company.html' title='Dumping the phone company'/><author><name>TJ Laurenzo</name><uri>http://www.blogger.com/profile/05554189172407515232</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://laurenzo.org/blog_attach/IMAG0003.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15425972.post-112803318207555249</id><published>2005-09-29T15:08:00.000-07:00</published><updated>2005-09-29T15:33:02.083-07:00</updated><title type='text'>Gas mileage</title><content type='html'>With soaring gas prices, I set out on an experiment over the last month to see how much better gas mileage I could get by simply changing my driving patterns.  For some background, I drive a Ford F150 extended cab pickup truck.  I'm really not part of the SUV craze that seems to have swept the nation.  I like my truck because it lets me do things that I couldn't do otherwise (and trust my I have tried) such as buying building supplies, clearing out yard trash or getting landscaping equipment from point a to point b.  The four wheel drive and high clearance has also been invaluable in more than a couple blizzards.&lt;br /&gt;&lt;br /&gt;What I don't like is the gas mileage.  The truck has a 25 gallon tank and generally gets just under 14.5 miles per gallon if I do a fair amount of highway driving.  At today's prices, this really hurts the wallet, to say nothing about contributing to the global oil problem. &lt;br /&gt;&lt;br /&gt;So, on the last tank of gas, I went totally against my nature and changed all of my driving habits to be just about as conservative as I could manage.  I accelerated slowly from every stop, coasted as much as possible, and kept my speed under 60 mph on the highway (which is a big deal -- the speed limit on the highway I have to drive to get anywhere is 75).  The first thing I noticed was just how little the big V8 had to work in order to maintain a 55 mph cruising speed on the highway.  With any downhill grade at all, I wouldn't even have to push the accelerator.  Most of the time, I applied just about as little pressure as I could manage.  I have to say as well, that it really didn't add a lot of time to my travels and I just felt so much more tranquil as a result of the slower speeds and easy acceleration.  In addition to all of this, September is a beautiful month in Colorado and I kept the air conditioner off.&lt;br /&gt;&lt;br /&gt;Well, even before filling up the tank in order to check the math, I knew something was different.  Under normal circumstances, my gas light comes on somewhere between 280 and 320 miles.  This time, though, at 350 miles, I still had about a quarter of a tank of gas.  It turns out that the gas light didn't come on until 412 miles and I didn't fill up until 450.  A calculation showed that I had used fuel at a rate of 19.3 mpg.  This may not seem like good gas mileage to people driving cars, but it represents something like a 34% improvement over what I have gotten historically.  I was able to go 1/3 further on a tank of gas just by slowing down, not running the AC, and not taking off from every stop light like I'm in a race.&lt;br /&gt;&lt;br /&gt;My wife was not able to duplicate my successes in her car.  I suspect that larger vehicles with big engines and poor aerodynamics have the most to gain from this regime.  Still, I was not expecting anything like a 34% improvement.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15425972-112803318207555249?l=tjlaurenzo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tjlaurenzo.blogspot.com/feeds/112803318207555249/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15425972&amp;postID=112803318207555249' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15425972/posts/default/112803318207555249'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15425972/posts/default/112803318207555249'/><link rel='alternate' type='text/html' href='http://tjlaurenzo.blogspot.com/2005/09/gas-mileage.html' title='Gas mileage'/><author><name>TJ Laurenzo</name><uri>http://www.blogger.com/profile/05554189172407515232</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://laurenzo.org/blog_attach/IMAG0003.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15425972.post-112449558475720622</id><published>2005-08-19T16:19:00.000-07:00</published><updated>2005-08-19T17:34:38.216-07:00</updated><title type='text'>Building libgcj.dll for MinGW with GCC 4.1</title><content type='html'>Here's some notes from my experience building libgcj.dll for MinGW using the GCC 4.1 (May 15, 2005 snapshot). This required a good deal of effort for me to figure out since quite a few things have diverged since the last reported sighting I could find of a working libgcj.dll.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Note that this entire process was done using a cross compiler hosted on Linux.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;First, it should be noted that I upgraded libtool prior to building the DLL. When I get some time, I'll rebuild it with pristine sources and make sure it works without this step. The basic process to upgrading libtool is:&lt;br /&gt;&lt;ul&gt;   &lt;li&gt;Copy libtool.m4 from a newer libtool distro to the root gcc source directory&lt;/li&gt;   &lt;li&gt;Run autoconf (version 2.59) followed by automake (version 1.9.3) in the subdirectories that will be built. Do not regenerate the config on the root directory unless if you make special arrangements to regenerate it with autoconf version 2.13.&lt;/li&gt;   &lt;li&gt;In the libjava target, you will manually have to patch the generated libtool after it gets created. You will need to change the "compiler_c_o" property in the GCJ section to "yes". This is line 7278 of the version of libtool I used. Not doing this will cause problems when the Makefile tries to compile resources. There has got to be a better way to make this work, but I am not terribly familiar with libtool and didn't look into it.&lt;/li&gt; &lt;/ul&gt; My primary motivation for upgrading libtool was to see if it would just automagically generate the dll for me. Sadly, this didn't work but I think it tried. With that being the case, it is probably ok to skip the libtool upgrade altogether.&lt;br /&gt;&lt;br /&gt;I also ran into a problem with the sequence of the build. During the first pass build, the gnu-java-beans.lo file is generated prior to the most of its classfiles being compiled. Because of this, it only contains a handful of classes, which causes a lot of undefined references when building the dll later. I think this is a general problem that just doesn't manifest very often because the java.beans.* API is very rarely used in practice. A work-around is simple enough. After you build it once, just delete the generated gnu-java-beans.lo and rerun make. Since all of the class files are present the output file will be created as expected. You should see that the backing .o file(s) are much larger the second time around.&lt;br /&gt;&lt;br /&gt;The next step is to create the actual dll. You should be aware that this is an extremely memory intensive operation. The memory usage of ld tops off at about 630MB on my machine. If you don't have at least this much physical memory available to ld, your machine could thrash for hours.&lt;br /&gt;&lt;br /&gt;I used the following script to create the dll:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/bin/sh&lt;br /&gt;LIBGCJ_A=libgcj-static.a&lt;br /&gt;&lt;br /&gt;mkdir libgcjobjs&lt;br /&gt;cd libgcjobjs&lt;br /&gt;ar x ../$LIBGCJ_A&lt;br /&gt;cd ..&lt;br /&gt;&lt;br /&gt;find libgcjobjs -name '*.o' &gt; libgcjobjs.list&lt;br /&gt;&lt;br /&gt;i686-pc-mingw32-ld --shared -Bdynamic -e _DllMainCRTStartup@12  -o libgcj.dll --out-implib libgcj.a /.1/home/tlaurenzo/gcc_cross/bin/../lib/gcc/i686-pc-mingw32/4.1.0/../../../../i686-pc-mingw32/lib/dllcrt2.o -L~/gcc_native/i686-pc-mingw32/lib -L/.1/home/tlaurenzo/gcc_cross/bin/../lib/gcc/i686-pc-mingw32/4.1.0 -L/.1/home/tlaurenzo/gcc_cross/bin/../lib/gcc -L/home/tlaurenzo/gcc_cross/lib/gcc/i686-pc-mingw32/4.1.0 -L/.1/home/tlaurenzo/gcc_cross/bin/../lib/gcc/i686-pc-mingw32/4.1.0/../../../../i686-pc-mingw32/lib -L/home/tlaurenzo/gcc_cross/lib/gcc/i686-pc-mingw32/4.1.0/../../../../i686-pc-mingw32/lib --export-all-symbols --enable-runtime-pseudo-reloc --allow-multiple-definition `cat libgcjobjs.list` -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt -lm -lgdi32 -lws2_32 -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt -luser32 -lkernel32 -ladvapi32 -lshell32 -lmingw32 -lgcc -lmoldname -lmingwex -lmsvcrt&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;(This script is just for demonstration purposes.  You will obviously need to update all of the paths appropriately)&lt;br /&gt;&lt;br /&gt;To build programs that link to the dll, you will need to use some extra switches:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;i686-pc-mingw32-gcj --main=Test -L. -o test.exe -Wl,--enable-runtime-pseudo-reloc Test.java&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If trying to duplicate this work, note that I am not working on pristine sources.  In particular the changes described in the java@gcc.gnu.org mailing list thread entitled "Linker name conflicts due to optimization in gjavah" are critical for this to work.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15425972-112449558475720622?l=tjlaurenzo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tjlaurenzo.blogspot.com/feeds/112449558475720622/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15425972&amp;postID=112449558475720622' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15425972/posts/default/112449558475720622'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15425972/posts/default/112449558475720622'/><link rel='alternate' type='text/html' href='http://tjlaurenzo.blogspot.com/2005/08/building-libgcjdll-for-mingw-with-gcc.html' title='Building libgcj.dll for MinGW with GCC 4.1'/><author><name>TJ Laurenzo</name><uri>http://www.blogger.com/profile/05554189172407515232</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://laurenzo.org/blog_attach/IMAG0003.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-15425972.post-112413533899263066</id><published>2005-08-15T12:28:00.000-07:00</published><updated>2005-09-29T16:18:33.443-07:00</updated><title type='text'>Adventures with Java 5 and GCJ</title><content type='html'>A few days ago I set out to do something that had seemingly never been tried, yet the process seemed straight-forward enough and I anticipated few problems (famous last words, I know). You see, I am working on this client-server systems management application which requires a small agent to be installed on a number of client machines (Windows, Linux, MacOS, etc). The server side is written with Java 5. I entertained some thoughts of writing the agent in C++, but my C++ is a little rusty and I haven't had much experience in managing a full-blown C/C++ cross-platform initiative... besides, I like working in Java. So, throwing caution to the wind, I set out to see if a natively compiled version of my Java agent would be possible and acceptable (I don't want to contend with a huge JRE install or the memory footprint associated with it). Just to make life more interesting, my development environment is Windows XP.&lt;br /&gt;&lt;br /&gt;So, here is the basic process I intended to follow:&lt;br /&gt;&lt;ol&gt;   &lt;li&gt;Install Mingw/Msys (I already use Cygwin heavily but want to be closer to the Win32 api and not have dependencies on cygwin1.dll)&lt;/li&gt;   &lt;li&gt;Use &lt;a href="http://retroweaver.sourceforge.net/"&gt;RetroWeaver&lt;/a&gt; to convert my Java 5 class files to Java 1.4 compatible equivilents.&lt;/li&gt;   &lt;li&gt;Use the RetroWeaver reference verifier to find references to classes/methods which are new to Java 5.&lt;/li&gt;   &lt;li&gt;Create a compatibility layer to call through to new features of Java 5 (note that from the outset I had been trying to avoid most new APIs so this step wasn't so bad. Most of the stuff I found was as simple as using Arrays.toString(...) in test classes)&lt;/li&gt;   &lt;li&gt;Use GCJ to compile my classes and dependencies natively.&lt;/li&gt; &lt;/ol&gt;Well, I hit my first snag with RetroWeaver. While I was able to convert the class files, the reference verifier was buggy and difficult to invoke from ant. Poking around on the SourceForge site, I found a number of patches to fix the things I was having problems with. Unfortunately, the author hasn't released an updated version of RetroWeaver in over 6 months and many of these patches conflict with each other or do not note properly what version of the source code the diff was generated against. Also, for some reason that was probably my own brain-damage, I was having a particularly bad time getting patch to actually do its thing. So, if anyone is looking for a version of RetroWeaver that has what I consider to be the right set of patches applied, you can get it &lt;a href="http://www.laurenzo.org/blog_attach/retroweaver.zip"&gt;here&lt;/a&gt;. This version seems to have a "mostly working" reference verifier, and the Ant task has been updated to make it easy to invoke, like so (assumes that the directory ${common.dir}/retroweaver contains all of the jars found in the RetroWeaver distribution. also assumes that retroverf.dir contains a copy of all class files, retrort.file points to a JRE 1.4 rt.jar file and std.classpath and depend.classpath are valid path constructs that contain all the needed dependencies for your classes):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;taskdef name="retroweaver" classname="com.rc.retroweaver.ant.RetroWeaverTask"&amp;gt;&lt;br /&gt;&amp;lt;classpath&amp;gt;&lt;br /&gt;  &amp;lt;fileset dir="${common.dir}/retroweaver"&amp;gt;&lt;br /&gt;     &amp;lt;include name="*.jar"/&amp;gt;&lt;br /&gt;  &amp;lt;/fileset&amp;gt;&lt;br /&gt;&amp;lt;/classpath&amp;gt;&lt;br /&gt;&amp;lt;/taskdef&amp;gt;&lt;br /&gt;&amp;lt;retroweaver srcDir="${retroverf.dir}"&lt;br /&gt;verify="true"&amp;gt;&lt;br /&gt;&amp;lt;classpath&amp;gt;&lt;br /&gt;  &amp;lt;pathelement location="${retrort.file}"/&amp;gt;&lt;br /&gt;  &amp;lt;path refid="std.classpath"/&amp;gt;&lt;br /&gt;  &amp;lt;path refid="depend.classpath"/&amp;gt;&lt;br /&gt;  &amp;lt;pathelement location="${retroverf.dir}"/&amp;gt;&lt;br /&gt;&amp;lt;/classpath&amp;gt;&lt;br /&gt;&amp;lt;/retroweaver&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Having spent far to long attempting to get RetroWeaver to do everything I wanted it to, I naively thought that GCJ would just work and life would be good. I couldn't have been more mistaken! When I tried to compile my main jar file, I got an obscure error from the assembler complaining about duplicate symbols. I was on my way down the rabbit hole now! I recognized the duplicate symbol name as the mangled form of a method on one of my classes. I looked it up and saw that the method in question was an implementation of a method from an implemented generic interface. Looking at the byte-code revealed that the class had two methods with the same signature and differing return types. I vaguely recalled some discussion about covariant return types and bridge methods in Java 5 and the problem started to become a little less murky. The error spit out by the assembler included a mangled name that did not have the return type encoded in it, and that was apparently causing the name collision.&lt;br /&gt;&lt;br /&gt;Doing some googling and sifting through the GCC bug database revealed that this bug is officially listed as bug #9861 and it has been open since 2003 (apparently the original bug was noticed while using one of the old prototype generics compilers). There was some comment that a new ABI was expected to fix this problem, but a look at recent snapshots of GCC revealed no fix yet. Well, it started to look like my original idea had hit a dead-end.&lt;br /&gt;&lt;br /&gt;For some reason, though, I didn't stop there. I downloaded the May 15, 2005 GCC 4.1 snapshot and started hacking. Now, the last time I actually tried to build GCC was back in 1998 on a Slackware Linux box. I don't remember much except searing pain and an eventual partial success. To be fair, the GCC build has gotten a lot easier since then... at least if you are using Linux. If you are trying to build GCC on Windows using mingw, just stop. I eventually settled for the procedure outlined by Ranjit Mathew on his &lt;a href="http://ranjitmathew.hostingzero.com/phartz/gcj/index.html"&gt;website&lt;/a&gt; for first building a cross-compiler on Linux, then using it to build a native compiler for Windows/Mingw. He includes some scripts that work really well for this purpose. Of course, there is a reason why you can't find pre-built binaries for any GCC &gt;= 4.0 on Windows/Mingw. There are two compilation problems that keep the suite from being built on mingw. The patches for these two problems are included in the main patch below. I'll get them to the GCC team eventually, after making sure that the fix already isn't in CVS head.&lt;br /&gt;&lt;br /&gt;So I set my old Linux box to building the GCC compilers and went camping for the weekend. I just picked up the results today and started looking for actually how to fix the original problem. It seemed to me that the goal should be to modify the mangling routines so that they include the mangled return type in the name passed to the assmebler. For GCJ, this is actually really easy to comprehend and implement... just a one-liner change. The problem is, however, that with this change, the C++ and Java ABI's no longer match up. This may not seem like a problem at first until you consider that all of the native parts of libjava are written in C++ using CNI, which requires the mangled names of methods match up on the C++ and Java sides of the house. It took me quite a bit longer to paw through the C++ compiler to figure out what to do. It would seem that including the return type in the mangled function name is already done for function templates (I think... I didn't trace this down all the way), so the fix involved just adding another condition in which to include the return type. So, if the function is a method of a class and if the class is a Java class (descended from java::lang::Object), I do the same thing as is done for that special template case. There are some macros in G++ that make this a one-liner change as well... it's just a much scarier change for the uninitiated because the G++ compiler is really complicated!&lt;br /&gt;&lt;br /&gt;In conclusion, I think it is a Good Thing to have a working path for moving from Java 5 source code to native binaries and I hope that this article can help make that a reality (at least in the interim, since the "official" support for Java 5 in GCJ seems to be a way off). I also think it is really important to have an up-to-date GCJ compiler for Windows and am going to pursue making actual builds available. For now, though, the patch will have to be enough for anyone interested in duplicating my work. &lt;a href="http://www.laurenzo.org/blog_attach/patches/mingw-java5-gcc-4.1-20050515.patch"&gt;Here&lt;/a&gt; it is. I haven't finished the clean build of the compiler and test suite yet, but have visually inspected and verified the results of this patch and it seems to be ok. YMMV. Since this is a breaking ABI change, I wouldn't anticpate seeing it anytime soon in the official GCJ releases.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;UPDATE 8/17/05:&lt;br /&gt;&lt;/span&gt;&lt;font&gt;It turns out that there was one additional thing that complicated the process of changing the mangling scheme. This was causing unsatisfied link errors when calling, either directly or indirectly, a number of static methods on the Math class. Since this was clearly a problem with the Java side of things, I breathed a sigh of relief (for not having to delve back into the C++ compiler). I did an objdump on the Math.o file and looked at the disassembly for the round(float) method, because it called the Math.floor(float) method which was one of the unresolved symbols. I was surprised to find that even though the Java code for round(float) calls floor, this call was nowhere to be found in the disassembly. At this point I realized that the compiler must have some mechanism for inlining some operations. So I did a grep for "floor" in the gcc/java directory and found the following:&lt;br /&gt;   &lt;span style="font-size:85%;"&gt; &lt;span style="font-family:courier new;"&gt;builtins.c:               double_ftype_double, "_ZN4java4lang4Math5floorEd");&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;There was my unresolved symbol without the return type mangled into the name. There are 13 of these in the builtins.c file. Updating them with the proper signature makes everything work correctly.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;File List:&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;ul&gt;&lt;font&gt;   &lt;li&gt;&lt;a href="http://laurenzo.org/blog_attach/retroweaver.zip"&gt;retroweaver.zip&lt;/a&gt; - 8/15/2005&lt;/li&gt;   &lt;li&gt;&lt;a href="http://laurenzo.org/blog_attach/patches/mingw-java5-gcc-4.1-20050515.patch"&gt;mingw-java5-gcc-4.1-20050515.patch&lt;/a&gt; - 8/17/2005 - Combined patch against the 05/15/2005 GCC 4.1 snapshot to enable name mangling and mingw support.&lt;/li&gt; &lt;/span&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/15425972-112413533899263066?l=tjlaurenzo.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://tjlaurenzo.blogspot.com/feeds/112413533899263066/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=15425972&amp;postID=112413533899263066' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/15425972/posts/default/112413533899263066'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/15425972/posts/default/112413533899263066'/><link rel='alternate' type='text/html' href='http://tjlaurenzo.blogspot.com/2005/08/adventures-with-java-5-and-gcj.html' title='Adventures with Java 5 and GCJ'/><author><name>TJ Laurenzo</name><uri>http://www.blogger.com/profile/05554189172407515232</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='26' height='32' src='http://laurenzo.org/blog_attach/IMAG0003.JPG'/></author><thr:total>4</thr:total></entry></feed>
