#!/usr/bin/perl -w # ######################################################################### # # # Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. # # All rights reserved. Email: russ@q12.org Web: www.q12.org # # # # This library is free software; you can redistribute it and/or # # modify it under the terms of EITHER: # # (1) The GNU Lesser General Public License as published by the Free # # Software Foundation; either version 2.1 of the License, or (at # # your option) any later version. The text of the GNU Lesser # # General Public License is included with this library in the # # file LICENSE.TXT. # # (2) The BSD-style license that is included with this library in # # the file LICENSE-BSD.TXT. # # # # This library 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 files # # LICENSE.TXT and LICENSE-BSD.TXT for more details. # # # ######################################################################### # this is a perl package which is part of the REALM documentation system. # it exports two subroutines "Snarf1" and "Snarf2". they are used to take a # block of text containing formatting codes and return the HTML formatted # equivalent. here is how you use them: # # * start with some text containing `snarf' formatting commands and possibly # some `external' formatting commands using the @cmd{...} syntax. # # $a = "@foo{some} @b{text} ..."; # # * run the text through Snarf1. # # $a = Snarf1 ($a); # # now $a contains HTML for the snarf formatting commands. some commands are # not converted, to enable a simple search and replace for the external # formatting commands without worrying about character conflicts. # # * tidy up the resulting HTML and finalize the snarf formatting. # # $a = Snarf2 ($a); # # To use this package, say "require ('snarf')". # # Formatting commands # ------------------- # # A blank line is treated as a paragraph break. # Commands have one of two forms: # 1. @ (commands with no arguments) # 2. @command{arguments or affected text} # Curly braces are like TeX, they remember the external state and restore it # on exit. Comments can be written with a `#' at the start of the line. # # Formatting commands: # # @[ ... @] bracket verbatim text, no substitutions made # @code{...} source code. internal whitespace preserved # @emph{...} add emphasis to text # @m{...} mathematical stuff (^ and _ work like TeX) # @c{...} code (in a fixed width `courier' font) # @c{...} bold # @list{unordered list} # @numlist{numbered list} # @link{URL}{anchortext} # @indent{text} # @center{...} # # Definitions # # @funcdef{function_name}{description} # @constdef{constant_name}{description} # # the description can be blank to just mention the name for the first time. # # consecutive definitions of the same type may be concatenated together # into a single table - for this to happen, you must not leave any blank # lines between the definitions. # # Reference things # @arg{...} argument of a function # @header{...} header file # @func{...} function # @const{...} constant symbol (enums, defines etc) # @struct{...} structure (no member functions) # @class{...} class (has member functions) # @member{...} member of a class or struct # @var{...} variable # # @date{format} current date # @picture{filename} Include the given picture # # No-argument commands # @* prefixes each item in a list # @_ explicit line break # # Single character commands # @@ @ # @{ { # @} } # `` '' quotes # \ continuation with the next line # # Junkyard # @end Prevents processing of any subsequent text # @? line break # @space a space - can be used at the end of the above # commands package snarf; # Add the high bit to all characters sub AddHi { my $a = $_[0]; my $i; for ($i=0; $i < length($a); $i++) { substr($a,$i,1) = chr(ord(substr($a,$i,1)) | 128) } return $a; } # subtract the high bit from all characters sub SubHi { my $a = $_[0]; my $i; for ($i=0; $i < length($a); $i++) { substr($a,$i,1) = chr(ord(substr($a,$i,1)) & 127) } return $a; } # Do mathematics conversions. The input should contain no {}'s sub ConvertMath { my $x = $_[0]; # For all &...; and <...> sequences, set the top bit so that italicization # of letters doesnt affect them. They are converted back later. $x =~ s/(&[A-Za-z0-9]+;)/&AddHi($1)/gse; $x =~ s/(<[A-Za-z0-9\/]+>)/&AddHi($1)/gse; $x =~ s/\^(.)/^\{$1\}/gs; # convert ^x to ^{x} $x =~ s/_(.)/_\{$1\}/gs; # convert _x to _{x} $x =~ s/([A-Za-z]+)/$1<\/i>/gs; # italicize all letters $x =~ s/\^\{([^}]*)\}/$1<\/sup>/gs; # convert ^{x} to html $x =~ s/_\{([^}]*)\}/$1<\/sub>/gs; # convert _{x} to html return &SubHi($x); } # Used to handle @[ / @] commands sub StoreVerbatim { my $a = $_[0]; $a =~ s/[<]/</g; $a =~ s/[>]/>/g; $verbchunks[$num_chunks++]=$a; # Use a special @verbatim(n) directive in place of the text. # Note that ()'s are used instead of {}'s becase otherwise it would # screw up the processing of {} commands below. return "\@verbatim(".($num_chunks-1).")\n"; } # handle @code commands sub HandleCode { my $a=$_[0]; $a =~ s/\n$//; # remove termating \n return "
$a
"; } # handle @funcdef commands sub HandleFuncdef { my $func=$_[0]; my $desc=$_[1]; # try to make anchor for pure function name my $a = $func; my $b = ''; while ($a =~ s/(\w+)\s*\(.*//) { if ($1 ne '') { $b .= "\n" } } return "$b
$func
$desc
"; } # handle @func commands sub HandleFunc { my $func = $_[0]; my $a = $func; $a =~ s/(\w+)\s*\(.*//; $a = $1; if ($a eq '') { $a1 = ''; $a2 = ''; } else { $a1 = "
"; $a2 = ""; } return "$a1$func$a2"; } # handle @constdef commands sub HandleConstdef { my $const = $_[0]; my $desc = $_[1]; my $a = "$const"; return $a if $desc eq ''; return "\@constdef_tablestart() $a$desc \@constdef_tableend()"; } # handle @const commands sub HandleConst { return "$_[0]" } # return the current date sub TheDate { my $format=$_[0]; # currently unused my @monthnames=('January','February','March','April','May','June','July', 'August','September','October','November','December'); my @daynames=('Sunday','Monday','Tuesday','Wednesday','Thursday', 'Friday','Saturday'); my @t = localtime (time); return "$daynames[$t[6]] $t[3] $monthnames[$t[4]], ".(1900+$t[5])." "; } # Process links sub DoLink { my $link = $_[0]; my $text = $_[1]; return "$text<\/a>"; } sub main::Snarf1 { $_ = $_[0]; # remove comments s/^#.*$//gm; # remove whitespace at the end of lines s/[ \t]*$//gm; # replace \ with line continuation s/\\\n//g; # handle @[ / @] pairs before anything else because the enclosed text may # contain special characters which we want to temporarily obscure @verbchunks=(); $num_chunks=0; s/\@\[(.*?)\@\]/StoreVerbatim($1)/gse; # replace < and > symbols (must do this before any html is inserted) s/[<]/</gs; s/[>]/>/gs; # replace @@,@{ and @} with commands for @,{ and }, they will be changed # back later s/\@\@/\@at{}/g; s/\@\{/\@openbrace{}/g; s/\@\}/\@closebrace{}/g; # turn blank lines into paragraph breaks s/\n[\n]+/<\/p>

\n/gs; # no-argument commands s/\@_/
\n/g; # forced line break s/\@\*/

  • /g; # list item # convert commands where the arguments do not contain formatted text s/\@picture\{([^{]*?)\}//gs; s/\@date\{([^{]*?)\}/&TheDate($1)/ge; s/\@arg\{([^{]*?)\}/$1<\/tt><\/font>/gs; s/\@header\{([^{]*?)\}/$1<\/tt>/gs; s/\@func\{([^{]*?)\}/&HandleFunc($1)/gse; s/\@const\{([^{]*?)\}/&HandleConst($1)/gse; s/\@struct\{([^{]*?)\}/$1<\/tt>/gs; s/\@class\{([^{]*?)\}/$1<\/tt>/gs; s/\@member\{([^{]*?)\}/$1<\/tt>/gs; s/\@var\{([^{]*?)\}/$1<\/tt>/gs; # convert commands where the arguments *can* contain formatted text. # convert command heirarchies until none left. $n=1; while($n > 0) { $n=0; # text format commands $n += s/\@emph\{([^{]*?)\}/$1<\/i>/gs; $n += s/\@c\{([^{]*?)\}/$1<\/tt>/gs; $n += s/\@b\{([^{]*?)\}/$1<\/b>/gs; $n += s/\@m\{([^{]*?)\}/ConvertMath($1)/gse; $n += s/\@code\{([^{]*?)\}/HandleCode($1)/gse; $n += s/\@funcdef\{([^{]*?)\}\{([^{]*?)\}/HandleFuncdef($1,$2)/gse; $n += s/\@constdef\{([^{]*?)\}\{([^{]*?)\}/HandleConstdef($1,$2)/gse; # other $n += s/\@link\{([^{]*?)\}\{([^{]*?)\}/&DoLink($1,$2)/e; $n += s/\@list\{([^{]*?)\}/
      $1<\/ul>/gs; $n += s/\@numlist\{([^{]*?)\}/
        $1<\/ol>/gs; $n += s/\@indent\{([^{]*?)\}/
        $1<\/blockquote>/gs; $n += s/\@center\{([^{]*?)\}/
        $1<\/center>/gs; } # concatenate constant tables $const_table = "
        "; s/\@constdef_tableend\(\)\s*\@constdef_tablestart\(\)//g; s/\@constdef_tablestart\(\)/$const_table/g; s/\@constdef_tableend\(\)/<\/table><\/center>/g; return $_; } # do some special character replacements sub main::Snarf2 { $_ = $_[0]; # do some special character replacements s/\@at\{\}/\@/g; s/\@openbrace\{\}/\{/g; s/\@closebrace\{\}/\}/g; # change

        ...
        to just
        s/(
        \s*)*
        /
        /gs; # put code chunks back in verbatim s/\@verbatim\((\d+)\)/$verbchunks[$1]/gse; return $_; } 1;