#!/bin/sh
#
# generate_examples [command_options]
#
# Regenerage all the images from the code blocks in the index.html
#
# command_options...
#    -v  verbose
#    -d  verbose and debug extra processing
#    -s  Start skipping blocks from start, EXIT block is done anyway
#
# <CODE EXECUTE [example_options] >
#     command args output_image
# </CODE>
#
# CODE BLOCK flags...
#    EXECUTE         Only work with code bloacks containing this option
#
#    OUT=file.img    Save standard output into this text or image file
#    ERR=file.txt    Save the error channel into this text file
#    ERR2OUT         (These text files can be set to /dev/null to ignore)
#
#    SCRIPT          Treat all the lines as a single shell script!
#    ASSERT          As SCRIPT, no image is expected, output ignored.
#    RANDOM          Image is Random - restore the original unless forced
#    REPLACE         Image is Random - always replace it with new one
#
#    IMAGE=image     The SCRIPT will produce at least this image.
#    NOIMAGE         No image will be created, ignore result (but not errors)
#                    Some commands (like SCRIPT/ASSERT) set this automatically
#
#    HDRI            use HDRI version of ImageMagick
#
#    NO_PNG2JPG      Do not convert PNG output to JPG (DISABLED)
#    NO_TXT2GIF      Do not convert generated text files to GIF format
#    TXT2GIF         Do convert 'TXT' image output to GIF format
#
#    VERBOSE         Always print the parsed command before executing
#    NOWARN          Do not warn that the image is already present
#
#    SKIP=boolean    Skip code blocks until otherwise (values are 0 or 1)
#    EXIT            Abort when this code block has finished (SKIP ignored)
#
# On top of this the command line may be prefixed with
#    #               This line is a shell comment (visible but not executed)
#    <r>             Image generated is random - restore original image
#    <c>             Command is a psuedo-comment, do not execute
#    <n>             Command generates no image (execute only)
#    <z>             Does nothing, execute as normal (spacing only)
# Note that these tags are NOT part of the HTML specification, and some
# browsers may not ignore them. For example using "<.>" is left visible in the
# latest firefox browser as being code punctuation.  "<!>" isn't visible but
# using a letter "<z>" appears to be the safest course.
#
# The FORCE or -f flags will force images marked 'random' to be regenerated.
#
# Anthony Thyssen  <A.Thyssen@grffith.edu.au>

# Source settings common to all examples
[ -f ./generate_options     ] && . ./generate_options
[ -f ../generate_options    ] && . ../generate_options
[ -f ../../generate_options ] && . ../../generate_options

# Generate the ImageMagick version image
[ -f ./generate_version     ] && ./generate_version
[ -f ../generate_version    ] && ../generate_version
[ -f ../../generate_version ] && ../../generate_version

# Link the "PNG with transparnecy on IE" style sheet and JAVA
for file in ../png_ie ../../png_ie; do
  [ -h "$link.css" ] && continue
  [ ! -f "$link.css" ] && continue
  [ ! -r "$link.css" ] && continue
  rm $link.*
  ln -s $link.* .
done

if [ "$TEST" ]; then
  # set up the test environment to run IM commands direct from the build area.
  # This does not work with HDRI marked examples
  DIR='/home/anthony/store/'.$TEST

  export MAGICK_CODER_MODULE_PATH="$DIR/coders"
  export MAGICK_CONFIGURE_PATH="$DIR/config"
  export MAGICK_FILTER_MODULE_PATH="$DIR/filters"

  export PATH="$DIR/utilities:${PATH}"
  #export LD_LIBRARY_PATH="$DIR/magick/.libs:$DIR/wand/.libs:$LD_LIBRARY_PATH"
fi

# Make option.cgi a local link  (hard link)
# if [ ! -r "option_link.cgi" ]; then
#   rm -f option_link.cgi
#   [ -r "../option_link.cgi"    ] && ln ../option_link.cgi .
#   [ -r "../../option_link.cgi" ] && ln ../../option_link.cgi .
# fi

# Execute IM commands from "CODE EXECUTE" blocks in the index.html files
perl -0777ne '
  $skip = ("'$SKIP'" eq "true");   # immediately SKIP until otherwise changed?

  for ( /<(CODE EXECUTE\b[^>]*)>(.*?)<\/CODE>/isg ) { # search for code blocks
    if ( s/^CODE EXECUTE\s*//i ) {
      $flags = $_;  # the flags and options for this CODE block
      next;
    }
    $verbose = ( "'"$VERBOSE"'" || $flags =~ /\bVERBOSE\b/i );

    # EXIT handling
    exit if $exit;      # Abort now!  Last block was an EXIT code block
    if ( $flags =~ /\bEXIT\b/ ) { # exit after this code block is finished
      $exit=1; $skip=0;    # always run the EXIT block - do not SKIP
    }

    # SKIP handling
    $skip=$1   if $flags =~ /\bSKIP=(\S*)/i;  # turn skip code blocks on/off
    next if $skip;   # skip code blocks if SKIP is set

    if ( $output = ( $flags =~ /\bOUT=(\S*)/i )[0] ) {
      print STDERR "WARNING: STDOUT file \"$output\" already present!",
            " -- appending\n"     if -e $output && $output ne "/dev/null";
    }
    if ( $error = ( $flags =~ /\bERR=(\S*)/i )[0] ) {
      print STDERR "WARNING: STDERR file \"$error\" already present!",
            " -- appending\n"     if -e $error && $error ne "/dev/null";
    }
    if ( $flags =~ /\b(SCRIPT|ASSERT)\b/ ) {
      @lines = ( $_ );              # treat block is a single shell script
    }
    else {
      @lines = split /(?<!\\)\n/;   # do each command one at a time (HACK)
               # WARNING: this could leave \ within command quotes!
    }
    for ( @lines ) {   # for each line (command)
      if ( $flags !~ /\b(SCRIPT|ASSERT)\b/ ) {
        s/\s+$//;         # clear end space
        s/^\s*\n//;       # clear start space
        next if /^\s*?#/; # ignore comment lines
        next if /^$/;     # ignore blank line
      }
      s/&lt;/</g;      # convert HTML to plain TEXT
      s/&gt;/>/g;
      s/&#45;/-/g;     # for double hyphenation "--gnu-option"
                       # which is illegal in html comments
      s/&amp;/&/g;

      # Get the command being executed (first word in command line)
      $command = $_;
      $command = $&     if $flags =~ /\b(SCRIPT|ASSERT)\b/;
      $command =~ s/^\s+//;
      $command =~ s/\s.*$//s;

      next if $command eq "#";     # command is a shell comment, ignore
      next if $command eq "<c>";   # command is a psuedo-comment, ignore

      # Get the file name of the image generated (last word in command line)
      ( $image = $_ ) =~ s/^.*\s//s;

      $noimage=0;  # assume we have an image

      $image =~ s/.html$/.png/;      # HTML pages generate PNG image instead
      $image =~ s/\.gif$/.anim/i      if $command eq "gif2anim";
      $image =~ s/\.anim$/_anim.gif/i if $command eq "anim2gif";
      $image =~ s/_plot$/_plot.gif/i  if $command eq "im_histogram";
      $image =~ s/$/.gif/i            if $command eq "txt2gif";

      $noimage++             if $flags =~ /\b(SCRIPT|ASSERT|NOIMAGE)\b/;
      $noimage++             if $command eq "rm";
      $noimage++             if $command eq "<n>";
      $noimage=0,$image=$1   if $flags =~ /\bIMAGE=([^\\\s>]+)/;

      # handle "randomized image" flag - restore the backup image
      if ( $command eq "<r>" || $flags =~ /\bRANDOM\b/ ) {
        if ( -f "_$image" && ! $ENV{FORCE} ) {
          printf "Generating %-32s using RESTORE\n", "\"$image\"";
          rename( "_$image", "$image" );
          next;
        }
      }
      if ( $command =~ /<.>/ ) {
        s/^<.>\s*//;    # remove special marker, and re-extract the command
        $command = $_;
        $command = $&     if $flags =~ /\b(SCRIPT|ASSERT)\b/;
        $command =~ s/^\s+//;
        $command =~ s/\s.*$//s;
      }

      # Append standard error to a file...
      $_ = "( $_ ) 2>> $error"   if $error;

      # Save the standard output of the command to a text file?
      $_ = "( $_ ) >> $output"   if $output;
      $_ = "$_ 2>&1"             if $output && $flags =~ /\bERR2OUT\b/i;

      $noimage++  if $image eq "/dev/null";             # null image requested
      $noimage++  if $image =~ /^(txt|info|null):-?$/;  # direct text ouput
      $image = "/dev/null"   if $noimage;

      printf "Generating %-32s using %s...\n",
             $image ne "/dev/null" ? "\"$image\""
                         : $output ? "\"$output\""
                          : $error ? "\"$error\""
                                   : "\"$image\"",   $command;
      print "$_\n"    if $verbose;


      if ( !$noimage && -f $image && $flags !~ /\bNOWARN\b/ ) {
        print STDERR "WARNING: Image \"$image\" already present!",
                            " -- proceeding\n";
      }
      #s/\\\n\s+/ /g;   # remove the line continuation seperators

      # Output format modifications
      s/\s(\S+)$/ '"$jpg_opt"' $1/s     if $image =~ /\.jpg$/;
      s/\s(\S+)$/  '"$png_format"'$1/s  if $image =~ /\.png$/;

      if ( $flags =~ /\bHDRI\b/ ) {
        $_ = `grep '^export' $ENV{HOME}/bin/local/hdri` .  $_;
      }

      # Execute the IM command in bash
      system( "/bin/bash", "-c", $_ );

      # Check if command was interupted
      if ($? == -1) {
        warn "ERROR: $command failed to execute: $!\n";
      }
      elsif ($? & 127) {
        die "INTERUPT: $command terminated with signal ". ($? & 127). "\n";
      }

      # post processing
      # Output a warning if images not created!
      if ( ! $noimage ) {
        if ( ( my $images = $image ) =~ s/%\d*d/[0-9]*/ ) {
          if ( (glob($images)) > 0 ) {
            print STDERR "WARNING: Multi-Image \"$image\" was not created\n";
          }
        }
        elsif ( $image =~ s/^(gif|histogram)://i && ! -f $image ) {
          print STDERR "WARNING: Image \"$image\" was not created\n";
        }
        elsif ( ! -f $image ) {
          print STDERR "WARNING: Image \"$image\" was not created\n";
        }
      }
      if ( -f $image && $flags =~ /\bREPLACE\b/ ) {
        # new randomized image was created, remove the backup image
        unlink( "_$image") if  -f "_$image";
      }

      # # Compress gifs using gifsicle?
      # if ( "'"$gifsicle"'" && -f $image && $image =~ /\.gif$/ ) {
      #   print "  Optimizing GIF format of \"$image\"...\n";
      #   system "gifsicle -O -b \"$image\"";
      # }

      # # Generate JPG verson of PNG images containing transparency?
      # # This is because microsoft IE does not handle PNG semi-transparency
      # if ( $flags !~ /\bNO_PNG2JPG\b/i &&
      #                 ( my $jpeg = $image ) =~ s/.png$/.jpg/ ) {
      #   print "  Converting \"$image\" to \"$jpeg\" ...\n";
      #   system "'"$DEBUG"' convert \"$image\" ".
      #          "  -background '"'$page_bg_color'"' ".
      #          "  -flatten  '"'$jpg_opt'"' \"$jpeg\" ";
      # }

      if (  ( $image =~ /\.(txt|anim)$/i && $flags !~ /\bNO_TXT2GIF\b/i )
         || ( $flags =~ /\bTXT2GIF\b/i && $flags !~ /\bOUT=/i ) ) {
        # Convert a text image output into an GIF image of that text
        #  Includes images of the form TXT, MVG, ANIM, NetPBM.
        if ( -s "$image" ) {
          printf "Generating %-32s using %s...\n", "\"$image.gif\"", "txt2gif";
          system( "txt2gif", $image );
        } else {
          print "  Resulting \U$1\E contains no output (making junk image)\n"
              unless $flags =~ /\bNOWARN\b/i;
          system "convert null: \"$image.gif\"";
        }
        if ( -f "$image.gif" && $flags =~ /\bREPLACE\b/ ) {
          # new randomized image was created, remove the backup image
          unlink( "_$image.gif") if  -f "_$image.gif";
        }
      }
    } # For each line found in a single CODE block


    # Handle text output for a whole CODE block of commands.
    if ( $flags !~ /\bNO_TXT2GIF\b/i ) {

      # Convert STDOUT text to GIF image of that text.
      $image = $output;
      if ( length($image) &&
           ( $image =~ /\.(txt|mvg|anim)$/ || $flags =~ /\bTXT2GIF\b/i ) ) {
        if ( -s "$image" ) {
          printf "Generating %-32s using %s...\n", "\"$image.gif\"", "txt2gif";
          if ( $flags =~ /\bREPLACE\b/ ) {
            unlink( "_$image") if -f "_$image";
          }
          system( "txt2gif", $image );
          if ( -f "$image.gif" && $flags =~ /\bREPLACE\b/ ) {
            unlink( "_$image.gif") if  -f "_$image.gif";
          }
        } else {
          print "  Text Image \U$1\E contains no output (making junk image)\n"
                if $flags !~ /\bNOWARN\b/i;
          system "convert null: \"$image.gif\"";
        }
      }

      # Convert STDERR to GIF image.
      $image = $error;
      if ( length($image) &&
           ( $image =~ /\.(txt|mvg|anim)$/ || $flags =~ /\bTXT2GIF\b/i ) ) {
        if ( -s "$image" ) {
          printf "Generating %-32s using %s...\n", "\"$image.gif\"", "txt2gif";
          if ( $flags =~ /\bREPLACE\b/ ) {
            unlink( "_$image") if -f "_$image";
          }
          system( "txt2gif", $image );
          if ( -f "$image.gif" && $flags =~ /\bREPLACE\b/ ) {
            unlink( "_$image.gif") if  -f "_$image.gif";
          }
        } else {
          print "  Text Image \U$1\E contains no output (making junk image)\n"
                if $flags !~ /\bNOWARN\b/i;
          system "convert null: \"$image.gif\"";
        }
      }

    } # text output

  }' index.html

