I think what is needed in this case a macro, not a subroutine...
Macros are not part of perl per se, but can be implemented via source
filters. It shouldn't be too hard to write a filter like that.
Thank you, Peter. Indeed I do want a preprocessor macro, but I was
not aware that perl's preprocessor macros were called filters
(perlfilter).
But it happens that Damian Conway already wrote one which might do what
the OP wants: Smart::Comments.
Well, I want something which will log to the same file as Log::StdLog
does, so I wrote my own. It's got some rough edges and a kludge or
two, but it works and does not use any of the black magic. Here it
is. Thanks again for the help...
package LogVar ;
use Filter::Util::Call;
sub import {
my ($type) = @_;
my ($ref) = [];
filter_add(bless $ref);
}
sub filter {
my ($self) = @_;
my ($status);
if (($status = filter_read()) > 0) {
# Substitute for the one-argument version, LogVar(varName)
s /LogVar[\s]*\([\s]*(\$|\@|\%)([\w]+)[\s]*\)/doLogVar($2,
$1$2, info)/ ;
# Substitute for the two-argument version, LogVar(varName,
level),
# when the level is 'warn'.
# The 'warn' has to be treated specially because 'warn' is
# also a predefined function in perl and really weird things
# happen if I don't do this
s /LogVar[\s]*\([\s]*(\$|\@|\%)([\w]+),[\s]*warn[\s]*\)/
doLogVarWarn($2, $1$2)/ ;
# Substitute for the two-argument version, LogVar(varName,
level)
# for other levels
s /LogVar[\s]*\([\s]*(\$|\@|\%)([\w]+),[\s]*([\w]+)[\s]*\)/
doLogVar($2, $1$2, $3)/ ;
# Now, heres the tricky part. I need to define the functions
# doLogVar, doLogVarWarn (and makeDefined, which they call).
# For some reasons which I don't understand,
# (1) If I simply define sub doLogVar in this module, it is
# "not found" when it runs from the host program file.
# (2) If I change the calls to "LogVar::doLogVar", then it
runs,
# but nothing gets logged
# So, my workaround for these two problems is to add the
placeholder
# use logVarFunctions
# to the main program file and then replace it with the
function
# definitions using the following s///, except s''' is used
to
# avoid variable interpolations.
# This also has the advantage of using the same Log::StdLog
# initialization and thus the same level that is used in the
main
# program file.
s 'use[\s]*LogVarFunctions[\s]*;'
sub makeDefined {
my $var_ref = shift ;
if (!defined($$var_ref)) {
$$var_ref = "<undefined>" ;
}
}
sub doLogVar {
my $varName = shift ;
my $varValue = shift ;
my $level = shift ;
makeDefined(\$varValue) ;
my $msg = sprintf ("%24s: %s\n", $varName, $varValue) ;
print {*STDLOG} $level => $msg ;
}
sub doLogVarWarn {
my $varName = shift ;
my $varValue = shift ;
makeDefined(\$varValue) ;
my $msg = sprintf ("%24s: %s\n", $varName, $varValue) ;
print {*STDLOG} \'warn\' => $msg ;
}
'
}
$status;
}
1;
__END__
=head1 NAME
LogVar - Logs variable name and value using Log::StdLog
=head1 SYNOPSIS
# Your program file must be using Log::StdLog and
# have initialized it with a level.
# Both of these are necessary
use LogVar ;
use LogVarFunctions ;
my $myVar = 5 ;
# Log to Log::StdLog at default level 'info'
LogVar($myVar) ;
# Log to Log::StdLog at some other level
LogVar($myVar, trace) ;
LogVar($myVar, debug) ;
# ...
LogVar($myVar, none) ;
=head1 DESCRIPTION
This module provides a perl filter (see perlfilter), which is a
preprocessor.
It provides the macro LogVar() which extracts the variable name from
the
first argument and logs the variable name and value to the file
designated
in Log::StdLog, producing lines that are nicely aligned like this:
$myVar: 5
$name: Jerry
$weight: 150.3