]> git.ipfire.org Git - thirdparty/squid.git/blame - scripts/www/build-cfg-help.pl
Bootstrapped
[thirdparty/squid.git] / scripts / www / build-cfg-help.pl
CommitLineData
c05220db 1#!/usr/bin/perl -w
2
3use strict;
4use IO::File;
5use Getopt::Long;
6
7# This mess is designed to parse the squid config template file
8# cf.data.pre and generate a set of HTML pages to use as documentation.
9#
10# Adrian Chadd <adrian@squid-cache.org>
11#
12# $Id: build-cfg-help.pl,v 1.1 2007/05/18 00:43:28 hno Exp $
13
14#
15# The template file is reasonably simple to parse. There's a number of
16# directives which delineate sections but there's no section delineation.
17# A section will "look" somewhat like this, most of the time:
18# NAME: <name>
19# IFDEF: <the ifdef bit>
20# TYPE: <the config type>
21# DEFAULT: <the default value>
22# LOC: <location in the Config struct>
23# DOC_START
24# documentation goes here
25# NOCOMMENT_START
26# stuff which goes verbatim into the config file goes here
27# NOCOMMENT_END
28# DOC_END
29#
30# Now, we can't assume its going to be nicely nested, so I'll say that
31# sections are delineated by NAME: lines, and then stuff is marked up
32# appropriately.
33#
34# Then we have to fake paragraph markups as well for the documentation.
35# We can at least use <PRE> type markups for the NOCOMMENT_START/_END stuff.
36
37#
38# Configuration sections are actually broken up by COMMENT_START/COMMENT_END
39# bits, which we can use in the top-level index page. Nifty!
40#
41
42# XXX NAME: can actually have multiple entries on it; we should generate
43# XXX a configuration index entry for each, linking back to the one entry.
44# XXX I'll probably just choose the first entry in the list.
45
46#
47# This code is ugly, but meh. We'll keep reading, line by line, and appending
48# lines into 'state' variables until the next NAME comes up. We'll then
49# shuffle everything off to a function to generate the page.
50
51
52my ($state) = "";
53my (%option);
54my (%all_names);
55my ($comment);
56
57my $version = "2.HEAD";
58my $verbose = '';
59my $path = "/tmp";
60my $format = "splithtml";
61my $pagetemplate;
62
63my ($index) = new IO::File;
64
65my $top = $0;
66$top =~ s%[^/]*$%%;
67
68GetOptions(
69 'verbose' => \$verbose, 'v' => \$verbose,
70 'out=s' => \$path,
71 'version=s' => \$version,
72 'format=s' => \$format
73 );
74
75if ($format eq "splithtml") {
76 $pagetemplate = "template.html";
77} elsif ($format eq "singlehtml") {
78 $pagetemplate = "template_single.html";
79}
80
81# XXX should implement this!
82sub uriescape($)
83{
84 my ($line) = @_;
85 return $line;
86}
87
88sub filename($)
89{
90 my ($name) = @_;
91 return $path . "/" . $name . ".html";
92}
93
94sub htmlescape($)
95{
96 my ($line) = @_;
97 return "" if !defined $line;
98 $line =~ s/([^\w\s])/sprintf ("&#%d;", ord ($1))/ge;
99 return $line;
100}
101
102sub section_link($)
103{
104 return uriescape($_[0]).".html" if $format eq "splithtml";
105 return "#".$_[0] if $format eq "singlehtml";
106}
107
108sub toc_link($)
109{
110 return "index.html#toc_".uriescape($_[0]) if $format eq "splithtml";
111 return "#toc_".uriescape($_[0]) if $format eq "singlehtml";
112}
113
114sub alpha_link($)
115{
116 return "index_all.html#toc_".uriescape($_[0]);
117}
118
119#
120# Yes, we could just read the template file in once..!
121#
122sub generate_page($$)
123{
124 my ($template, $data) = @_;
125 my $fh;
126 my $fh_open = 0;
127 # XXX should make sure the config option is a valid unix filename!
128 if ($format eq "splithtml") {
129 my ($fn) = filename($data->{'name'});
130 $fh = new IO::File;
131 $fh->open($fn, "w") || die "Couldn't open $fn: $!\n";
132 $fh_open = 1;
133 } else {
134 $fh = $index;
135 }
136
137
138 my ($th) = new IO::File;
139 $th->open($template, "r") || die "Couldn't open $template: $!\n";
140
141 # add in the local variables
142 $data->{"title"} = $data->{"name"};
143 $data->{"ldoc"} = $data->{"doc"};
144 $data->{"toc_link"} = toc_link($data->{"name"});
145 $data->{"alpha_link"} = alpha_link($data->{"name"});
146 if (exists $data->{"aliases"}) {
147 $data->{"aliaslist"} = join(", ", @{$data->{"aliases"}});
148 }
149 # XXX can't do this and then HTML escape..
150 # $data->{"ldoc"} =~ s/\n\n/<\/p>\n<p>\n/;
151 # XXX and the end-of-line formatting to turn single \n's into <BR>\n's.
152
153 while (<$th>) {
154 # Do variable substitution
155 s/%(.*?)%/htmlescape($data->{$1})/ge;
156 print $fh $_;
157 }
158 close $th;
159 undef $th;
160
161 if ($fh_open) {
162 close $fh;
163 undef $fh;
164 }
165}
166
167$index->open(filename("index"), "w") || die "Couldn't open ".filename("index").": $!\n" if ($format eq "splithtml");
168$index->open($path, "w") || die "Couldn't open ".filename("index").": $!\n" if ($format eq "singlehtml");
169print $index <<EOF
170<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
171<html xmlns="http://www.w3.org/1999/xhtml">
172<head>
173<meta http-equiv="content-type" content="text/html; charset=utf-8" />
174 <title>Squid $version configuration file</title>
175 <meta name="keywords" content="squid squid.conf config configure" />
176 <meta name="description" content="Squid $version" />
177</head>
178<body>
179EOF
180;
181
182
183my ($name, $data);
184my (@chained);
185
186my $in_options = 0;
187sub start_option($)
188{
189 my ($name) = @_;
190 if (!$in_options) {
191 print $index "<ul>\n";
192 $in_options = 1;
193 }
194 print $index ' <li><a href="' . htmlescape(section_link($name)) . '" name="toc_' . htmlescape($name) . '">' . htmlescape($name) . "</a></li>\n";
195}
196sub end_options()
197{
198 return if !$in_options;
199 print $index "</ul>\n";
200 $in_options = 0;
201}
202while (<>) {
203 chomp;
204 last if (/^EOF$/);
205 if ($_ =~ /^NAME: (.*)$/) {
206 my (@aliases) = split(/ /, $1);
207 $data = {};
208 $data->{'version'} = $version;
209 foreach (@aliases) {
210 $all_names{$_} = $data;
211 }
212
213 $name = shift @aliases;
214
215 $option{$name} = $data;
216 $data->{'name'} = $name;
217 $data->{'aliases'} = \@aliases;
218
219 start_option($name);
220 print "DEBUG: new option: $name\n" if $verbose;
221 } elsif ($_ =~ /^COMMENT: (.*)$/) {
222 $data->{"comment"} = $1;
223 } elsif ($_ =~ /^TYPE: (.*)$/) {
224 $data->{"type"} = $1;
225 } elsif ($_ =~ /^DEFAULT: (.*)$/) {
226 if ($1 eq "none") {
227 $data->{"default"} = "$1";
228 } else {
229 $data->{"default"} = "$name $1";
230 }
231 } elsif ($_ =~ /^LOC:(.*)$/) {
232 $data->{"loc"} = $1;
233 $data->{"loc"} =~ s/^[\s\t]*//;
234 } elsif ($_ =~ /^DOC_START$/) {
235 $state = "doc";
236 } elsif ($_ =~ /^DOC_END$/) {
237 $state = "";
238 my $othername;
239 foreach $othername (@chained) {
240 $option{$othername}{'doc'} = $data->{'doc'};
241 }
242 undef @chained;
243 } elsif ($_ =~ /^DOC_NONE$/) {
244 push(@chained, $name);
245 } elsif ($_ =~ /^NOCOMMENT_START$/) {
246 $state = "nocomment";
247 } elsif ($_ =~ /^DEFAULT_IF_NONE: (.*)$/) {
248 $data->{"default_if_none"} = $1;
249 } elsif ($_ =~ /^NOCOMMENT_END$/) {
250 $state = "";
251 } elsif ($_ =~ /^IFDEF: (.*)$/) {
252 $data->{"ifdef"} = $1;
253 } elsif ($_ =~ /^#/ && $state eq "doc") {
254 $data->{"config"} .= $_ . "\n";
255 } elsif ($state eq "nocomment") {
256 $data->{"config"} .= $_ . "\n";
257 } elsif ($state eq "doc") {
258 $data->{"doc"} .= $_ . "\n";
259 } elsif ($_ =~ /^COMMENT_START$/) {
260 end_options;
261 $state = "comment";
262 $comment = "";
263 } elsif ($_ =~ /^COMMENT_END$/) {
264 print $index "<pre>\n";
265 print $index $comment;
266 print $index "</pre>\n";
267 } elsif ($state eq "comment") {
268 $comment .= $_ . "\n";
269 } elsif (/^#/) {
270 next;
271 } elsif ($_ ne "") {
272 print "NOTICE: unknown line '$_'\n";
273 }
274}
275end_options;
276print $index "</ul>\n";
277print $index "<p><a href=\"index_all.html\">Alphabetic index</a></p>\n" if $format eq "splithtml";
278print $index "<p><a href=\"#index\">Alphabetic index</a></p>\n" if $format eq "singlehtml";
279print $index "<hr />\n" if $format eq "singlehtml";
280
281# and now, build the option pages
282my (@names) = keys %option;
283foreach $name (@names) {
284 generate_page("${top}${pagetemplate}", $option{$name});
285}
286
287# and now, the alpabetic index file!
288my $fh;
289my $fh_open = 0;
290
291if ($format eq "splithtml") {
292 $fh = new IO::File;
293 my ($indexname) = filename("index_all");
294 $fh->open($indexname, "w") || die "Couldn't open $indexname for writing: $!\n";
295 $fh_open = 1;
296 print $fh <<EOF
297<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
298<html xmlns="http://www.w3.org/1999/xhtml">
299<head>
300<meta http-equiv="content-type" content="text/html; charset=utf-8" />
301 <title>Squid $version configuration file</title>
302 <meta name="keywords" content="squid squid.conf config configure" />
303 <meta name="description" content="Squid $version" />
304</head>
305<body>
306 <div id="header">
307 <div id="logo">
308 <h1><a href="http://www.squid-cache.org/"><span>Squid-</span>Cache.org</a></h1>
309 <h2>Optimising Web Delivery</h2>
310 </div>
311 </div>
312
313 <p>| <a href="index.html">Table of contents</a> |</p>
314
315 <h1>Alphabetic index of all options</h1>
316EOF
317;
318} elsif ($format eq "singlehtml") {
319 $fh = $index;
320 print $fh "<h2><a name=\"index\">Alphabetic index of all options</a></h2>\n";
321}
322
323print $fh "<ul>\n";
324
325foreach $name (sort keys %all_names) {
326 my ($data) = $all_names{$name};
327 print $fh ' <li><a href="' . uriescape($data->{'name'}) . '.html" name="toc_' . htmlescape($name) . '">' . htmlescape($name) . "</a></li>\n";
328}
329
330print $fh "</ul>\n";
331if ($fh_open) {
332print $fh <<EOF
333 <p>| <a href="index.html">Table of contents</a> |</p>
334 </body>
335</html>
336EOF
337;
338$fh->close;
339}
340undef $fh;
341
342print $index <<EOF
343 </body>
344</html>
345EOF
346;
347$index->close;
348undef $index;