Root/prod/doc/hmac.pl

1#!/usr/bin/perl
2#
3# hmac.pl - Simple macro pre-processor for HTML
4#
5# Written 2001, 2011 by Werner Almesberger
6# Copyright 2001 EPFL DSC-ICA, Network Robots
7# Copyright 2001, 2011 Werner Almesberger
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 2 of the License, or
12# (at your option) any later version.
13#
14
15#------------------------------------------------------------------------------
16#
17# hmac processes macro definitions of the following type:
18#
19# <MACRO NAME=name param[=default] ...> ... </MACRO>
20#
21# The macro is invoked with <name param=value ...> or with
22# <name param=value ...> ... </name>
23#
24# HTML tags corresponding to the parameters (e.g. <param>) are expanded in
25# the macro body. Parameters for which no default value was given must be
26# specified.
27#
28# In the block-style invocation, the content of the block is assigned to
29# the parameter BODY. Block-style invocations cannot be nested.
30#
31# Macros and macro definitions are processed in the order in which they appear
32# in the input file. Macro definitions inside macros are processed when the
33# outer macro is expanded.
34#
35# Files can be included with the <INCLUDE FILE=name> tag. File inclusions
36# are made as we go.
37#
38# hmac is not case-sensitive.
39#
40#------------------------------------------------------------------------------
41
42#
43# Marker
44#
45$BM = "\001";
46$EM = "\002";
47
48#
49# Collect -Dmacro=value options
50#
51while ($ARGV[0] =~ /^-D([^=]+)=/) {
52    $mac{$1} = $';
53    shift(@ARGV);
54}
55
56#
57# Complain about unrecognized options
58#
59if ($ARGV[0] =~ /^-/) {
60    print STDERR "usage: $0 [-Dmacro=value ...] file ...\n";
61    exit(1);
62}
63
64#
65# Read input and put warning
66#
67$in = join("",<>);
68$in =~ s/\n/\n\n<!-- MACHINE-GENERATED FILE, DO NOT EDIT ! -->\n\n/;
69
70#
71# Scan text for macros or includes
72#
73while (1) {
74    $first_macdef = &find_macdef($in);
75    $first_macro = &find_macro($in);
76    $first_include = &find_include($in);
77    last if $first_macdef == -1 && $first_macro == -1 && $first_include == -1;
78    if ($first_include != -1 &&
79      ($first_include < $first_macro || $first_macro == -1) &&
80      ($first_include < $first_macdef || $first_macdef == -1)) {
81    $in = &include_file($in);
82    }
83    else {
84    if (($first_macdef < $first_macro && $first_macdef != -1) ||
85      $first_macro == -1) {
86        $in = &define_macro($in);
87    }
88    else {
89        $in = &expand_macro($in);
90    }
91    }
92}
93print $in;
94
95
96#
97# Find includes, and macros and their definitions
98#
99
100sub find_include
101{
102    local ($in) = @_;
103    return -1 unless $in =~ /<INCLUDE\s+file="[^"]*"/i;
104    return length($`)+length($&);
105}
106
107
108sub find_macdef
109{
110    local ($in) = @_;
111    return -1 unless $in =~ /<MACRO\b/i;
112    return length $`;
113}
114
115
116sub find_macro
117{
118    local ($in) = @_;
119    local ($first) = -1;
120
121    for $mac (keys %mac) {
122    if ($in =~ /<$mac\b/i) {
123        $first = length $` if $first == -1 || length $` < $first;
124    }
125    }
126    return $first;
127}
128
129
130#
131# Include a file
132#
133
134sub include_file
135{
136    local ($in) = @_;
137    local ($name,$f);
138
139    $in =~ /<INCLUDE\s+FILE=("([^"]*)"|\S+)\s*>\s*/i;
140    $name = defined $2 ? $2 : $1;
141    undef $f;
142    open(FILE,$name) || die "open $name: $!";
143    $f = $`.join("",<FILE>).$';
144    close FILE;
145    return $f;
146}
147
148
149#
150# Extract first macro definition
151#
152
153sub define_macro
154{
155    local ($in) = @_;
156    local ($a,$b,$c,$d);
157    local ($name, $need, $prm, %arg);
158
159    $in =~ s/<MACRO\b/$BM/gi;
160    $in =~ s|</MACRO>|$EM|gi;
161    if ($in =~ /$BM(("[^"]*"|[^>])*)>/is) {
162    ($a,$b,$c) = ($`,$1,$');
163    $d = "";
164    $need = 1;
165        while ($need) {
166        $bm = index($c,$BM);
167        $em = index($c,$EM);
168        die "<MACRO> without </MACRO>" if $em == -1;
169        if ($bm < $em && $bm != -1) {
170        $d .= substr($c,0,$bm+1,"");
171        $need++;
172        }
173        else {
174        $d .= substr($c,0,$em+1,"");
175        $need--;
176        }
177    }
178    $c =~ s/^\s*//s;
179    $in = $a.$c;
180    chop($d); # remove last $EM
181    undef $name;
182    undef %arg;
183    $b =~ s/^\s*//;
184    while ($b =~ /^([a-z_][a-z0-9_]*)(=("([^"]*)"|\S+))?\s*/is) {
185        $b = $';
186        ($prm = $1) =~ tr/a-z/A-Z/;
187        if ($prm eq "NAME") {
188        die "duplicate NAME" if defined $name;
189        die "NAME without value" unless defined $2;
190        ($name = defined $4 ? $4 : $3) =~ tr/a-z/A-Z/;
191        next;
192        }
193        die "reserved parameter name BODY" if $prm eq "BODY";
194        die "duplicate parameter \"$prm\"" if exists $arg{$prm};
195        $arg{$prm} = defined $2 ? defined $4 ? $4 : $3 : undef;
196    }
197    die "syntax error" unless $b eq "";
198    die "NAME parameter is missing" unless defined $name;
199    $d =~ s/$BM/<MACRO/gi;
200    $d =~ s|$EM|</MACRO>|gi;
201# $mac{$name} = $d;
202    $mac{$name} = &expand_macro_list($d, $name);
203    $args{$name} = { %arg };
204    }
205    else {
206    die "</MACRO> without <MACRO>" if $in =~ m|$EM|;
207    }
208    $in =~ s/$BM/<MACRO/gi;
209    $in =~ s|$EM|</MACRO>|gi;
210    return $in;
211}
212
213
214#
215# Expand first macro
216#
217
218sub expand_macro_list
219{
220    local ($in, @mac) = @_;
221    local ($a,$b,$c);
222    local ($mac, $done, $prm, %arg);
223
224    undef $a;
225    for $mac (@mac) {
226    if ($in =~ /<$mac\b(("[^"]*"|[^>])*)>/is) {
227        ($a,$b,$c) = ($`,$1,$') if length $` < length $a || !defined $a;
228    }
229    next unless defined $a;
230    undef %arg;
231    %arg = %{ $args{$mac} };
232    if ($c =~ m|</$mac>|i) {
233        $arg{"BODY"} = $`;
234        $c = $';
235    }
236    else {
237        $arg{"BODY"} = undef;
238    }
239    $b =~ s/^\s*//;
240    while ($b =~ /^([a-z_][a-z0-9_]*)(=("([^"]*)"|\S+))\s*/is) {
241        $b = $';
242        ($prm = $1) =~ tr/a-z/A-Z/;
243        die "unrecognized parameter \"$prm\"" unless exists $arg{$prm};
244        $arg{$prm} = defined $2 ? defined $4 ? $4 : $3 : undef;
245    }
246    $b = $mac{$mac};
247    while (1) {
248        $done = 1;
249        for (keys %arg) {
250        while ($b =~ /<$_>/i) {
251            $done = 0;
252            die "required parameter $_ is missing in macro $mac"
253              unless defined $arg{$_};
254            $b = $`.$arg{$_}.$';
255        }
256        }
257        last if $done;
258    }
259    return $a.$b.$c;
260    }
261    return $in;
262}
263
264
265sub expand_macro
266{
267    local ($in) = @_;
268
269    return &expand_macro_list($in, keys %mac);
270}
271

Archive Download this file



interactive