#!/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. @<symbol> (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
# \<end of line> 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]+)/<i>$1<\/i>/gs; # italicize all letters
$x =~ s/\^\{([^}]*)\}/<sup>$1<\/sup>/gs; # convert ^{x} to html
$x =~ s/_\{([^}]*)\}/<sub>$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 "<table border=0 cellspacing=5 cellpadding=5 cols=1 width=\"100%\" bgcolor=\#c0ffff><tr><td><font color=\"#0000ff\"><pre>$a</td></tr></table>";
}
# 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 .= "<a name=\"func_$1\">\n"
}
}
return "$b<pre><font color=\"#0000ff\">$func</font></pre><blockquote>$desc</blockquote>";
}
# handle @func commands
sub HandleFunc
{
my $func = $_[0];
my $a = $func;
$a =~ s/(\w+)\s*\(.*//;
$a = $1;
if ($a eq '') {
$a1 = '';
$a2 = '';
}
else {
$a1 = "<a class=\"func\" href=\"\#func_$a\">";
$a2 = "</a>";
}
return "$a1<tt>$func</tt>$a2";
}
# handle @constdef commands
sub HandleConstdef
{
my $const = $_[0];
my $desc = $_[1];
my $a = "<a name=\"const_$const\"><font color=\"#c00000\"><tt>$const</tt></font>";
return $a if $desc eq '';
return "\@constdef_tablestart() <tr valign=\"top\"><td>$a</td><td>$desc</td> </tr> \@constdef_tableend()";
}
# handle @const commands
sub HandleConst
{
return "<tt><a class=\"const\" href=\"\#const_$_[0]\">$_[0]</a></tt>"
}
# 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 "<a href=\"$link\">$text<\/a>";
}
sub main::Snarf1
{
$_ = $_[0];
# remove comments
s/^#.*$//gm;
# remove whitespace at the end of lines
s/[ \t]*$//gm;
# replace \<end of line> 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><p>\n/gs;
# no-argument commands
s/\@_/<br>\n/g; # forced line break
s/\@\*/<li>/g; # list item
# convert commands where the arguments do not contain formatted text
s/\@picture\{([^{]*?)\}/<img border=1 src=\"$1\">/gs;
s/\@date\{([^{]*?)\}/&TheDate($1)/ge;
s/\@arg\{([^{]*?)\}/<font color=\"#0000ff\"><tt>$1<\/tt><\/font>/gs;
s/\@header\{([^{]*?)\}/<tt>$1<\/tt>/gs;
s/\@func\{([^{]*?)\}/&HandleFunc($1)/gse;
s/\@const\{([^{]*?)\}/&HandleConst($1)/gse;
s/\@struct\{([^{]*?)\}/<tt>$1<\/tt>/gs;
s/\@class\{([^{]*?)\}/<tt>$1<\/tt>/gs;
s/\@member\{([^{]*?)\}/<tt>$1<\/tt>/gs;
s/\@var\{([^{]*?)\}/<tt>$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\{([^{]*?)\}/<i>$1<\/i>/gs;
$n += s/\@c\{([^{]*?)\}/<tt>$1<\/tt>/gs;
$n += s/\@b\{([^{]*?)\}/<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\{([^{]*?)\}/<ul>$1<\/ul>/gs;
$n += s/\@numlist\{([^{]*?)\}/<ol>$1<\/ol>/gs;
$n += s/\@indent\{([^{]*?)\}/<blockquote>$1<\/blockquote>/gs;
$n += s/\@center\{([^{]*?)\}/<center>$1<\/center>/gs;
}
# concatenate constant tables
$const_table = "<center><table border=1 cellspacing=0 cellpadding=6 ".
"bgcolor=\#ffffc0>";
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 <br><br>...<hr> to just <hr>
s/(<br>\s*)*<hr>/<hr>/gs;
# put code chunks back in verbatim
s/\@verbatim\((\d+)\)/$verbchunks[$1]/gse;
return $_;
}
1;
syntax highlighted by Code2HTML, v. 0.9.1