#! /usr/bin/env perl

#  Read a set of labels (one per line) from the "global.labels" file.
#  Then read the input lines and create links for the first occurrence
#  of each label in each Latex section encountered (the links use \htmlref
#  to refer to HTX labels elsewhere in the document). Omit links wherever
#  they are not appropriate.

#  Read the list of labels for which links should be generated (these may
#  contain Latex escape characters, as they must exactly match the text from
#  which the link will be generated).
   open( LABELS, 'global.labels' );
   @labels = <LABELS>;
   close( LABELS );

#  Sort the labels into descending order of length. This is to avoid problems
#  with labels which are abbreviations of other labels.
   @labels = sort { length( $b ) <=> length( $a ) } @labels;

#  Build a regexp that will match any one of the labels.
   $pattern = "";
   for $label ( @labels ) {

#  Remove newlines from each label.
       $label =~ s/\n//g;

#  Labels must be whole words unless they start/end without an alphanumeric.
       $label_q = quotemeta( $label );
       if ( $label =~ m/^\w/ ) { $label_q = "\\b" . $label_q };
       if ( $label =~ m/\w$/ ) { $label_q = $label_q . "\\b" };

#  Build the regexp.
       $pattern = !$pattern ? $label_q : $pattern . "|" . $label_q;
   }

#  Loop through the input data.
   $sdiy = 0;
   $inr = 0;
   $source_line = 10;
   $verbatim = 0;
   while ( <> ) {

#  Detect the start of each type of document section.
      ( $s ) = /^ *\\section\{/;         # Latex section
      ( $ss ) = /^ *\\subsection\{/;     # Latex subsection
      ( $sss ) = /^ *\\subsubsection\{/; # Latex subsubsection
      ( $sr ) = /^ *\\sstroutine\{/;     # SST routine description

#  We only consider sst diytopic sections to be of significance if they 
#  introduce a listing of attributes or Functions. This is so that these 
#  sections always contain links. SO if the previous line was a diytopic 
#  line, see if this line contains the single word "Attributes" or 
#  "Functions"
      if( $sdiy ) {
         ( $attrfun ) = /^ *(Attributes|Functions) *$/;
         $linkatfun = 0;               
         $sdiy = 0;
      } else {
         ( $sdiy ) = /^ *\\sstdiytopic\{/;  
      }

# Do not make links in the introductory text in an Attributes or
# Functions DIY section.
      if( $attrfun ) {
         if( /^ *\\sstitemlist\{/ ) { $linkatfun = 1 };
      } else {
         $linkatfun = 0;               
      }

#  Watch for the end of the list of attributes or functions.
      if( $attrfun ) {
         if( /^ *\} *$/ ) {
            $attrfun = 0;
            $linkatfun = 0;
         }
      }

#  Note if a new section has started.
      $sx = ( $s || $ss || $sss || $sr );
      if ( $sx ) {

#  Set a flag to indicate which type of section we are in.
         $ins = $inss = $insss = $inr = 0;
         if ( $s ) { $ins = 1 };
         if ( $ss ) { $inss = 1 };
         if ( $sss ) { $insss = 1 };
         if ( $sr ) { $inr = 1 };

#  Clear the count of source lines for this section.
         $source_line = 0;

#  Clear the array of flags indicating which labels have been used.
         undef %used;
      }

#  Note if we are in a Latex "verbatim" or "terminalv" environment.
      if ( /^ *\\begin\{(verbatim|terminalv)\} *$/ ) { $verbatim = 1 };

#  Count the source lines read from each section.
      $source_line++;

#  Obtain an array of all the labels matched in the current source line.
      @match = /$pattern/og;

#  Consider generating a link for each label matched.
      for $label ( @match ) {
         $label_q = quotemeta( $label );

#  In an SST routine description, extract the name of the routine from
#  the second source line and mark the label of that name "used". This
#  prevents links being made to this section from within itself.
         if ( $inr && $source_line == 2 ) {
             $used{ $label }++;
             $label_x = $_;
             $label_x =~ s/\W//g;
             #s/$/\\sstlabel{$label_x}/;
         }

#  If we are in a Functions or Attributes section, see if the match occurs
#  at the start of the line and is followed by a colon. If it is, it is the 
#  name of the main Function or Attribute being described and so should be 
#  linkified.
         $atfun = ( $linkatfun && ( /^ *$label_q:/ ) );

#  Is this a caption? Do not replace entries in first part of caption
# that appears in TOC LOF
         $iscap = /\\caption/;

#  Check if a link should be made. Omit links in "verbatim" environments,
#  in any line which starts a new section (because labels don't work properly
#  if they get into the table of contents), in the 4th line of an SST
#  routine description (because these also go into the TOC), or if the label
#  has already been used in this section. We always linkify any match if it 
#  is in a list of Function or Attribute descriptions, if it is at the start 
#  of the line  and is followed by a colon.
         if ( $atfun || ( !$verbatim &&
                          !$iscap &&
                          !$sx &&
                          !( $inr && ( $source_line == 4 ) ) &&
                          !$used{ $label } ) )  {

# Increment the number of usages of this label.
            $used{ $label }++;

#  Labels must be whole words unless they start/end without an alphanumeric.
            if ( $label =~ m/^\w/ ) { $label_q = "\\b" . $label_q };
            if ( $label =~ m/\w$/ ) { $label_q = $label_q . "\\b" };

#  Form a version of the label with non alphanumerics removed.
            $label_x = $label;
            #$label_x =~ s/\W//g;

#  Edit each instance of the label in the source line to insert an \htmlref.
            s/$label_q/\\htmlref{$label}{$label_x}/;
         }
      }

#  Detect the end of "verbatim" environments.
      if ( /^ *\\end\{(verbatim|terminalv)\} *$/ ) { $verbatim = 0 };

#  Output the modified line.
      print;
   }
