# Various utility functions, including template substitution.
#
# Copyright (C) 1999 Ian Jackson <ijackson@chiark.greenend.org.uk>
#
# This 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,
# or (at your option) any later version.
#
# This is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with this file; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

open RAND,"/dev/urandom" or die $!;

sub process_file ($) {
    local ($filename) = @_;
    
    open X, "$filename" or die "$filename: $!";
    @x= <X>;
    close X or die $!;

    $x[$#x] eq "\@\@\@eof:\@\@\@\n" or die $!;
    $#x--;

    $cl= 0;
    $out= '';
    $level= -1;
    process(1);
}

sub randnybs ($) {
    my ($nybbles) = @_;
    my ($v, $r, $bytes);
    $bytes= $nybbles/2;
    read(RAND,$v,$bytes) == $bytes or die $!;
    $r= scalar unpack("H$nybbles",$v);
print DEBUG "randnybs($nybbles) -> $r\n";
    return $r;
}

sub out ($) {
    $out.= $_[0]."\n";
}

sub process ($) {
    my ($doing) = @_;
    my ($bcl);
    $level++;
    for (;;) {
	return if $cl > $#x;
	$_= $x[$cl++];
	s/\n$//; s/\s*$//;
#	out("<!-- $level $doing $_ -->");
	last if m/^\@\@\@end\w+\:\@\@\@$/;

	if (m/^\@\@\@(if|ifnot):([0-9a-z_|]+)\@\@\@$/) {
	    $q=$1; $v=$2;
	    $do= 0;
	    if ($doing) {
		map { $do=1 if getvar($_); } split(/\|/,$v);
		$do= !$do if $q eq 'ifnot';
#		out("<!-- $level $doing $do $q $v $_ -->");
	    }
	    process($doing && $do);
	} elsif (m/^\@\@\@foreach\:(area|db)\@\@\@$/) {
	    if ($doing) {
		$bcl= $cl;
		for (&{"foreach_start_$1"};
		     &{"foreach_cond_$1"};
		     &{"foreach_incr_$1"}) {
		    &{"foreach_setvars_$1"};
		    process($doing);
		    $cl= $bcl;
		}
	    }
	    process(0);
	} elsif (m/^\@\@\@comment\:(\s.*)?$/) {
	} elsif (m/\S/) {
	    s/^\@\@\@$//;
	    if ($doing) {
		s/\@\@\@(\w+)\@\@\@/ getvar("$1") /ge;
	        out($_);
	    } else {
		s/\@\@\@\w+\@\@\@//g;
	    }		
	    die "$filename:$cl:unknown $_\n" if m/\@\@\@/;
	}
    }
    $level--;
}

sub getvar ($) {
    my ($vn) = @_;
    defined $$vn or die "$filename:$cl:undefined $vn\n$out";
    return $$vn;
}

%saniarray= ('<','lt', '>','gt', '&','amp', '"','quot');
sub html_sani {
    local ($in) = @_;
    local ($out);
    while ($in =~ m/[<>&"]/) {
        $out.= $`. '&'. $saniarray{$&}. ';';
        $in=$';
    }
    $out.= $in;
    $out;
}

1;
