Csh2Perl Coding Style

Perl's slogan "There's more than one way to do it." summarises quite nicely the power and flexibility of the language. When porting the Radiance Csh scripts, there are no hard rules and coding styles that you absolutely must follow. At the same time, the Perl scripts that will be written to replace some of the old Csh scripts found in Radiance will end up in the Radiance code repository, and it is therefore important to ensure that they can be read and modified by people who do not have a black belt in Perl code obscurity.

Below are some first thougths that I think might help us speak a common dialect of the Perl language. Very recently, NREL have begun to invest serious man power into OpenStudio, a framework for thermal and lighting building simulations that relies on EnergyPlus and Radiance. Part of their efforts is to ensure that Radiance compiles and runs smoothly on the MS Windows platform that until now has not been officially supported. While most of the important binaries seem to work fine, it is the plethora of Radiance shell scripts that are almost impossible to port over to Windows. With only minor modifications, Perl scripts can be coded to run as happily under Windows as they do under LINUX or MacOS. Here's how.

Pragmas

I have made it a habit to always use the strict and warnings pragmas in my scripts. This checks for unsafe programming constructs and generates warnings for possible typos and other mistakes.

use strict;
use warnings;

Path Separators

Although the path separator under Windows is a backslash '\', not a forward slash '/', the Perl interpretor under Windows seems to cope admirably with UNIX-style forward slashes and even a mix of the two. It appears there is no need to use the File::Spec module which is meant to perform file path manipulations in a platform independent way. Just construct your paths with UNIX-style forward slashes.

File Names

Please ensure that the new Perl script accepts file names with spaces in them by enclosing the relavant variable names in double inverted commas like so:

system qq[ ies2rad -p $td -o lumi "$ARGV[0]" ];

Temporary Files

I have found the File::Temp module to be both convenient, and to provide a cross-platform solution:

use File::Temp qw/ tempdir /;
...
my $td = tempdir( CLEANUP => 1 );

For the auto-cleanup to work under Windows, it is essential that you explicitly close all open file handles of files that are created in the temp directory:

open( FH, ">$td/kung-fu.cal" );
print FH <<EndOfHere;
...
EndOfHere
close FH;

Floating-point Arithmetic

Shell scripting is notoriously clunky when it comes to non-integer arithmetic. The obvious solution to this was to use Radiance's rcalc or ev commands. Below is an example from the old falsecolor.csh:

set scale=`ev "$mult/179*10^$LogLmax"`

With Perl, there is no need to spawn a system command to do fp calculations since floating point arithmetic is supported out-of-the-box:

$scale = $mult / 179 * 10**$LogLmax;

Running System Commands

Here is a nice overview. You probably don't want to use exec, so the only choice is between system() and backticks. Use the latter if you want to capture STDOUT of the command.

Many of the Radiance scripts use lots of calls to rcalc. The expressions are wrapped in single quotes in the Csh scripts. Windows doesn't like that and insists on double quoted. Luckily, LINUX and MacOS are happy with this, too.

To avoid having to escape the single or double quotes, it is best to use Perl's quote operators q// or qq//. The former is equivalent to enclosing the string with single ticks, which means that no variable interpolation takes place. qq//, on the other hand does allow variable interpolation. It is the equivalent to using double quotes. In the code snippet below, both $pc0args and $pal would be replaced with the values held in those variables. Brackets were chosen to enclose the string because the default forward slash occurs within the string.

$cmd = qq[pcomb $pc0args -e "v=x/256" -e "ro=clip(${pal}_red(v));..."];

Platform Sniffing

To test whether the platform that we're running on is Windows, you can do something like this:

my $windoz = ($^O eq "MSWin32" or $^O eq "MSWin64");
if ($windoz) {
   ...
} else {
   ...
}

However, this should not be necessary in most cases. The only reason for such platform sniffing might be if the script calls a (binary) command that doesn't exist under Windows, such as ximage or x11meta.

If, for instance, a certain script calls ximage at the end to display an image, it might be a good idea to ensure that the bulk of the script runs under Windows and UNIX, then wrap the final call to ximage into a construct like this:

if ($windoz) {
   die("$0 is currently not supported under Windows.");
} else {
   system "ximage $td/nice.hdr";
}

Style

I have found perltidy to be very helpful in creating a consisten look. It's very easy to run:

$ perltidy -ce <falsecolor0.pl >falsecolor.pl

The '-ce' option is for 'cuddled-else'. There are tons of other options which have reasonably default settings. Indentation, for instance, defaults to four spaces.