blob: 34fd207593d5b1c8da77b7bcbe68bde7baa9c796 (
plain) (
tree)
|
|
#!/usr/bin/perl
# This script translates a simple definition-based grammar
# to either C, sh, Javascript, or in (in = identity grammar, i.e.
# same grammar as input).
#
# Input grammar:
# (1) comments having ';' or '#' as the first char in the line
# (2) a blank line
# (3) !include "file"
# (4) !define foo bar
# (5) !define foo "bar"
#
# Environmental variables can be used to override a setting.
# The special value "null" causes the variable to be undefined.
# If an environmental value is bracketed, i.e [abc], the brackets
# will be converted to double quotes prior to output.
sub comment {
my ($cmt) = @_;
print "//$cmt\n" if ($mode =~ /^(c|js|h)$/);
print "#$cmt\n" if ($mode =~ /^(sh|nsi|in)$/);
}
sub define {
my ($name, $value) = @_;
if ($mode eq "sh") {
$value="true" if !$value;
print "[ -z \"\$$name\" ] && export $name=$value\n";
print "[ \"\$$name\" = \"$nulltag\" ] && unset $name\n";
} else {
if ($ENV{$name}) {
$value = $ENV{$name};
$value = "\"$1\"" if ($value =~ /\[(.*)\]$/);
}
if ($value ne $nulltag) {
print "#define $name $value\n" if ($mode =~ /^(c|h)$/);
print "!define $name $value\n" if ($mode =~ /^(nsi|in)$/);
print "var $name=$value;\n" if ($mode eq "js");
} else {
print "//#undef $name\n" if ($mode =~ /^(c|h)$/);
print "#!undef $name\n" if ($mode eq "nsi");
print ";!undef $name\n" if ($mode eq "in");
print "//undef $name\n" if ($mode eq "js");
}
}
}
sub include_file {
local $_;
$include_file_level++;
die "!include file nesting too deep" if ($include_file_level > $max_inc_depth);
my ($parm) = @_;
my $fn = "$incdir/$parm";
local *IN;
open(IN, "< $fn") or die "cannot open $fn";
while (<IN>) {
chomp;
if (/^\s*$/) {
print "\n";
} elsif (/^[#;](.*)$/) {
comment ($1);
} elsif (/^!define\s+(\w+)(?:\s+(.*?))?\s*$/) {
define ($1, $2);
} elsif (/^!include\s+"(.+)"$/) {
include_file ($1);
} else {
die "can't parse this line: $_\n";
}
}
$include_file_level--;
}
die "usage: trans <c|h|sh|js|nsi|in> [-I<dir>] [files ...]" if (@ARGV < 1);
($mode) = shift(@ARGV);
die "mode must be one of c, h, sh, js, nsi, or in" if !($mode =~ /^(c|h|sh|js|nsi|in)$/);
$nulltag = "null";
$max_inc_depth = 10;
$include_file_level = 0;
$incdir = ".";
comment(" This file was automatically generated by trans.pl");
while ($arg=shift(@ARGV)) {
if ($arg =~ /^-/) {
if ($arg =~ /^-I(.*)$/) {
$incdir = $1;
} else {
die "unrecognized option: $arg";
}
} else {
print "\n";
include_file ($arg);
}
}
|