1
0
mirror of git://projects.qi-hardware.com/ben-wpan.git synced 2024-11-27 03:31:52 +02:00
ben-wpan/prod/doc/hmac.pl

271 lines
5.8 KiB
Perl
Executable File

#!/usr/bin/perl
#
# hmac.pl - Simple macro pre-processor for HTML
#
# Written 2001, 2011 by Werner Almesberger
# Copyright 2001 EPFL DSC-ICA, Network Robots
# Copyright 2001, 2011 Werner Almesberger
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
#------------------------------------------------------------------------------
#
# hmac processes macro definitions of the following type:
#
# <MACRO NAME=name param[=default] ...> ... </MACRO>
#
# The macro is invoked with <name param=value ...> or with
# <name param=value ...> ... </name>
#
# HTML tags corresponding to the parameters (e.g. <param>) are expanded in
# the macro body. Parameters for which no default value was given must be
# specified.
#
# In the block-style invocation, the content of the block is assigned to
# the parameter BODY. Block-style invocations cannot be nested.
#
# Macros and macro definitions are processed in the order in which they appear
# in the input file. Macro definitions inside macros are processed when the
# outer macro is expanded.
#
# Files can be included with the <INCLUDE FILE=name> tag. File inclusions
# are made as we go.
#
# hmac is not case-sensitive.
#
#------------------------------------------------------------------------------
#
# Marker
#
$BM = "\001";
$EM = "\002";
#
# Collect -Dmacro=value options
#
while ($ARGV[0] =~ /^-D([^=]+)=/) {
$mac{$1} = $';
shift(@ARGV);
}
#
# Complain about unrecognized options
#
if ($ARGV[0] =~ /^-/) {
print STDERR "usage: $0 [-Dmacro=value ...] file ...\n";
exit(1);
}
#
# Read input and put warning
#
$in = join("",<>);
$in =~ s/\n/\n\n<!-- MACHINE-GENERATED FILE, DO NOT EDIT ! -->\n\n/;
#
# Scan text for macros or includes
#
while (1) {
$first_macdef = &find_macdef($in);
$first_macro = &find_macro($in);
$first_include = &find_include($in);
last if $first_macdef == -1 && $first_macro == -1 && $first_include == -1;
if ($first_include != -1 &&
($first_include < $first_macro || $first_macro == -1) &&
($first_include < $first_macdef || $first_macdef == -1)) {
$in = &include_file($in);
}
else {
if (($first_macdef < $first_macro && $first_macdef != -1) ||
$first_macro == -1) {
$in = &define_macro($in);
}
else {
$in = &expand_macro($in);
}
}
}
print $in;
#
# Find includes, and macros and their definitions
#
sub find_include
{
local ($in) = @_;
return -1 unless $in =~ /<INCLUDE\s+file="[^"]*"/i;
return length($`)+length($&);
}
sub find_macdef
{
local ($in) = @_;
return -1 unless $in =~ /<MACRO\b/i;
return length $`;
}
sub find_macro
{
local ($in) = @_;
local ($first) = -1;
for $mac (keys %mac) {
if ($in =~ /<$mac\b/i) {
$first = length $` if $first == -1 || length $` < $first;
}
}
return $first;
}
#
# Include a file
#
sub include_file
{
local ($in) = @_;
local ($name,$f);
$in =~ /<INCLUDE\s+FILE=("([^"]*)"|\S+)\s*>\s*/i;
$name = defined $2 ? $2 : $1;
undef $f;
open(FILE,$name) || die "open $name: $!";
$f = $`.join("",<FILE>).$';
close FILE;
return $f;
}
#
# Extract first macro definition
#
sub define_macro
{
local ($in) = @_;
local ($a,$b,$c,$d);
local ($name, $need, $prm, %arg);
$in =~ s/<MACRO\b/$BM/gi;
$in =~ s|</MACRO>|$EM|gi;
if ($in =~ /$BM(("[^"]*"|[^>])*)>/is) {
($a,$b,$c) = ($`,$1,$');
$d = "";
$need = 1;
while ($need) {
$bm = index($c,$BM);
$em = index($c,$EM);
die "<MACRO> without </MACRO>" if $em == -1;
if ($bm < $em && $bm != -1) {
$d .= substr($c,0,$bm+1,"");
$need++;
}
else {
$d .= substr($c,0,$em+1,"");
$need--;
}
}
$c =~ s/^\s*//s;
$in = $a.$c;
chop($d); # remove last $EM
undef $name;
undef %arg;
$b =~ s/^\s*//;
while ($b =~ /^([a-z_][a-z0-9_]*)(=("([^"]*)"|\S+))?\s*/is) {
$b = $';
($prm = $1) =~ tr/a-z/A-Z/;
if ($prm eq "NAME") {
die "duplicate NAME" if defined $name;
die "NAME without value" unless defined $2;
($name = defined $4 ? $4 : $3) =~ tr/a-z/A-Z/;
next;
}
die "reserved parameter name BODY" if $prm eq "BODY";
die "duplicate parameter \"$prm\"" if exists $arg{$prm};
$arg{$prm} = defined $2 ? defined $4 ? $4 : $3 : undef;
}
die "syntax error" unless $b eq "";
die "NAME parameter is missing" unless defined $name;
$d =~ s/$BM/<MACRO/gi;
$d =~ s|$EM|</MACRO>|gi;
# $mac{$name} = $d;
$mac{$name} = &expand_macro_list($d, $name);
$args{$name} = { %arg };
}
else {
die "</MACRO> without <MACRO>" if $in =~ m|$EM|;
}
$in =~ s/$BM/<MACRO/gi;
$in =~ s|$EM|</MACRO>|gi;
return $in;
}
#
# Expand first macro
#
sub expand_macro_list
{
local ($in, @mac) = @_;
local ($a,$b,$c);
local ($mac, $done, $prm, %arg);
undef $a;
for $mac (@mac) {
if ($in =~ /<$mac\b(("[^"]*"|[^>])*)>/is) {
($a,$b,$c) = ($`,$1,$') if length $` < length $a || !defined $a;
}
next unless defined $a;
undef %arg;
%arg = %{ $args{$mac} };
if ($c =~ m|</$mac>|i) {
$arg{"BODY"} = $`;
$c = $';
}
else {
$arg{"BODY"} = undef;
}
$b =~ s/^\s*//;
while ($b =~ /^([a-z_][a-z0-9_]*)(=("([^"]*)"|\S+))\s*/is) {
$b = $';
($prm = $1) =~ tr/a-z/A-Z/;
die "unrecognized parameter \"$prm\"" unless exists $arg{$prm};
$arg{$prm} = defined $2 ? defined $4 ? $4 : $3 : undef;
}
$b = $mac{$mac};
while (1) {
$done = 1;
for (keys %arg) {
while ($b =~ /<$_>/i) {
$done = 0;
die "required parameter $_ is missing in macro $mac"
unless defined $arg{$_};
$b = $`.$arg{$_}.$';
}
}
last if $done;
}
return $a.$b.$c;
}
return $in;
}
sub expand_macro
{
local ($in) = @_;
return &expand_macro_list($in, keys %mac);
}