#!/usr/bin/perl # ***************************************************************************** # # $Id: abnfchk,v 1.26 1999/09/18 23:08:16 bfb Exp bfb $ # # Copyright (C) 1999, 2000, Inet Technologies, Inc. # # Written by: Brian Bidulock # # 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. # # This program 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 program; if not, write to the Free Software Foundation, Inc., # 675 Mass Ave, Cambridge, MA 02139, USA. # # ***************************************************************************** eval 'exec /usr/bin/perl -S $0 ${1+"$@"}' if $running_under_some_shell; $progname = $0; if ($progname=~/^(.+\/)*sbnfchk/ ) { $gabnf = 1; } if ($progname=~/^(.+\/)*abnfchk/ ) { $gabnf = 1; } if ($progname=~/^(.+\/)*abnf2asn/ ) { $gasn = 1; } if ($progname=~/^(.+\/)*abnf2html/ ) { $ghtml = 1; } if ($progname=~/^(.+\/)*abnf2bison/) { $gbison = 1; } if ($progname=~/^(.+\/)*abnf2flex/ ) { $gflex = 1; } $numbers = 0; $debug = 0; $trace = 0; $verbose = 0; $crossref = 0; $comments = 0; $warnings = 0; while ($ARGV[0] =~ /^-/) { $_ = shift; last if /^--/; if (/^-h/) { usage(); exit; } if (/^-n/) { $numbers = 1; next; } if (/^-d/) { $debug = 1; next; } if (/^-t/) { $trace = 1; next; } if (/^-v/) { $verbose = 1; next; } if (/^-x/) { $crossref = 1; next; } if (/^-c/) { $comments = 1; next; } if (/^-w/) { $warnings = 1; next; } if (/^-r/) { $warnrefs = 1; next; } if (/^-f(.*)/) { if ($1) { $infile = $1; } else { $infile = shift; } next; } if (/^-o(.*)/) { if ($1) { $outfile = $1; } else { $outfile = shift; } next; } usage(); die "I don't recognize this switch: $_\\n"; } if ($_=shift) { $infile = $_; } if ($_=shift) { $outfile = $_; } sub usage { print STDERR "Usage: $0 ".'[-dtvxcn] [ [-f] infile [ [-o] outfile ] ]'."\n\n"; print STDERR " -h - this help message\n"; print STDERR " -d - turn on debug mode\n"; print STDERR " -t - turn on trace mode (lots of info)\n"; print STDERR " -v - turn on verbose mode (lots of info)\n"; print STDERR " -x - report crossreferences in output\n" if($gabnf||$gasn); print STDERR " -n - number productions in output\n" if ($ghtml); print STDERR " -c - include ABNF comments in output\n" if ($ghtml); print STDERR " -w - include warnings for mismatched case\n" if ($ghtml); print STDERR " -r - include warnings for orphan references\n" if ($ghtml); print STDERR " [-f] infile - input file (default stdin)\n"; print STDERR " [-o] outfile - output file (default stdout)\n"; print STDERR "\n$0: "; print STDERR "Syntax checks and pretty-prints ABNF\n" if ($gabnf); print STDERR "Converts ABNF to ASN (no too well)\n" if ($gasn); print STDERR "Provides HTML of ABNF syntax\n" if ($ghtml); print STDERR "Provides BISON parser output for ABNF\n" if ($gbison); print STDERR "Provides FLEX analyzer output for ABNF\n" if ($gflex); } $\ = "\n"; # add new-line to print $* = 0; # do multiline matching #undef $/; # read in whole file if ($infile) { open(INFILEH,"<$infile") || die "can't open $infile for input"; $ifh = \*INFILEH; } else { $ifh = \*STDIN; } if ($outfile) { open(OUTFILEH,">$outfile") || die "can't open $outfile for output"; select OUTFILEH; } else { select STDOUT; } $rulemax = 0; # ======================================= package Abnf; use strict; # ======================================= sub new { my $type = shift; my $self = {}; bless $self, $type; main->getone($_[0],$type); $::depth++; my $ret = $self->read(@_); if ($ret) { main->gotone($_[0],$type); } $::depth--; return $ret; } sub read { my $self = shift; my $line = $_[0]; my $o; main->getlines($line); if ($o = RuleList->new($line)) { push @{$self->{rulelist}}, $o; $::error = ''; $::errdep = 0; main->getlines($line); while ($o = RuleList->new($line)) { push @{$self->{rulelist}}, $o; $::error = ''; $::errdep = 0; main->getlines($line); } unless ($::done) { print "SYNTAX ERROR (LINE $::lineno) NEAR: '$::error'"; return 0; } } $_[0] = $line; return $self; } sub abnf { my $self = shift; print ';@@ ABNFCHK $Revision: 1.26 $'; print ';@@ Copyright (C) 1999, 2000, Brian F. G. Bidulock'; print ';@@ '; print ''; my $file = $::infile; $file = "(standard input)" unless ($file); print ";@@ Input file: <$file>"; my $d = `date`; chomp $d; printf ';@@ Date: '.$d; my $s; foreach $s (@{$self->{rulelist}}) { $s->abnf(); } print ''; print ''; print ''; print ';@@ end of productions'; if ($::crossref) { print ";@@ *******************************"; my $e; my $i = 0; foreach $e (keys %::caserefs) { $i++; unless ($::casedefs{$e}) { print ";@@ UNDEFINED REFERENCE: $e"; } } print ";@@ THERE ARE $i REFERENCES."; $i = 0; foreach $e (keys %::casedefs) { $i++; if ($::casedefs{$e}>1) { print ";@@ DEFINITION $e DEFINED $::casedefs{$e} TIMES!"; } unless ($::caserefs{$e}) { print ";@@ UNREFERENCED DEFINITION: $e"; } } print ";@@ THERE ARE $i DEFINITIONS."; } print ''; print ''; } sub asn1 { my $self = shift; print '--@@ ABNF2ASN $Revision: 1.26 $'; print '--@@ Copyright (C), 1999 Brian F. G. Bidulock'; print '--@@ '; print ''; my $f = $::infile; $f = "(standard input)" unless ($f); print "--@@ Input file: <$f>"; my $s; foreach $s (@{$self->{rulelist}}) { $s->asn1(); } print ''; print ''; print '--@@ end of syntax description'; } sub html { my $self = shift; my $e; my $i; my $f = $::infile; print ''; print ''; printf 'ABNF Specification'; printf ' for <'.$f.'>' if ($f); print ''; print ''; print ''; printf '

HTML Version of ABNF'; printf ' for <'.$f.'>' if ($f); print '

'; if (open(HEADER,"<.html.header")) { my $line; my $d = `date`; chomp $d; my $r = '$Revision: 1.26 $'; while ($line=
) { chop $line; $line=~s/\%f/$f/; $line=~s/\%p/\U$::progname\E/; $line=~s/\%r/$r/; $line=~s/\%d/$d/; print $line; } } else { print '

This HTML version of ABNF is automatically generated using '; print 'the abnf2html $Revision: 1.26 $ tool provided by '; print 'Inet Technologies, Inc. '; print 'written by Brian '; print 'Bidulock.'; print 'The protocol syntax is presented in ABNF according to RFC 2234 '; print 'and RFC 822.'; print 'This version of ABNF is for informational purposes only. It '; print 'is intended as a tool to help read the ABNF. '; print 'Errors may have been introduced in translating to HTML.

'; print ''; if ($f) { print 'This ABNF browser was generated from file <'.$f.'>'; print ' on '.`date`.'.'; } print '

'; print '

This file consists of:'; print '

'; } print '

ABNF Specification

'; print '

The productions for the ABNF specification are provided below.'; print '

'; print ''; printf ''; printf '' if ($::numbers); print ''; my $s; foreach $s (@{$self->{rulelist}}) { $s->html(); } print '
ABNF Productions
No.Rule NameProduction or Comment
'; print '

Symbol Cross Reference List

'; printf '

Following is a cross-reference list for the ABNF. On the left '; printf 'are references to productions, on the right are links to the rules in '; print 'which those productions are referenced.'; print ''; print ''; print ''; if ($::warnrefs) { foreach $e (keys %::defs) { unless ($::refs{$e}) { $::reflist{$e} = 0; } } } foreach $e (sort keys %::reflist) { printf ''; printf ''; } print '

Symbol Cross-Reference Table
ReferenceProductions which Reference this Symbol
'; if ($::casedefs{lc $e}) { printf ''; if ($::defs{$e} or not $::warnings) { printf $e; } else { printf ''.$e.''; } printf ''; } else { if ($::warnrefs) { printf ''; printf ''.$e.' (undefined)'; printf ''; } else { printf ''.$e.''; } } print ''; if ($::reflist{$e}) { for ($i=0;$i<$::reflist{$e};$i++) { printf ', ' if ($i); printf ''; printf $::deflist{$e}[$i]; printf ''; } } else { if ($::caserefs{lc $e} and $::warnings) { printf '(No references!)'; } else { printf '(No references!)'; } } print '
'; print '

General Directions

'; print '

Rule-Names

'; print ''; print '

References

'; print ''; if (open(FOOTER,"<.html.footer")) { my $line; my $d = `date`; chomp $d; my $r = '$Revision: 1.26 $'; while ($line=