#!/usr/bin/perl
# +-======-+ 
#  Copyright (c) 2003-2007 United States Government as represented by 
#  the Admistrator of the National Aeronautics and Space Administration.  
#  All Rights Reserved.
#  
#  THIS OPEN  SOURCE  AGREEMENT  ("AGREEMENT") DEFINES  THE  RIGHTS  OF USE,
#  REPRODUCTION,  DISTRIBUTION,  MODIFICATION AND REDISTRIBUTION OF CERTAIN 
#  COMPUTER SOFTWARE ORIGINALLY RELEASED BY THE UNITED STATES GOVERNMENT AS 
#  REPRESENTED BY THE GOVERNMENT AGENCY LISTED BELOW ("GOVERNMENT AGENCY").  
#  THE UNITED STATES GOVERNMENT, AS REPRESENTED BY GOVERNMENT AGENCY, IS AN 
#  INTENDED  THIRD-PARTY  BENEFICIARY  OF  ALL  SUBSEQUENT DISTRIBUTIONS OR 
#  REDISTRIBUTIONS  OF THE  SUBJECT  SOFTWARE.  ANYONE WHO USES, REPRODUCES, 
#  DISTRIBUTES, MODIFIES  OR REDISTRIBUTES THE SUBJECT SOFTWARE, AS DEFINED 
#  HEREIN, OR ANY PART THEREOF,  IS,  BY THAT ACTION, ACCEPTING IN FULL THE 
#  RESPONSIBILITIES AND OBLIGATIONS CONTAINED IN THIS AGREEMENT.
#  
#  Government Agency: National Aeronautics and Space Administration
#  Government Agency Original Software Designation: GSC-15354-1
#  Government Agency Original Software Title:  GEOS-5 GCM Modeling Software
#  User Registration Requested.  Please Visit http://opensource.gsfc.nasa.gov
#  Government Agency Point of Contact for Original Software:  
#  			Dale Hithon, SRA Assistant, (301) 286-2691
#  
# +-======-+ 
#
#  $Id: protex,v 1.7.12.9 2013-05-01 21:00:05 rtodling Exp $
#
#BOP
#
# !ROUTINE: ProTeX v. 2.00 - Translates DAO Prologues to LaTeX
#
# !INTERFACE:
#         protex [-hbgACFS] ] [+-nlsxf] [src_file(s)]
#
# !DESCRIPTION:
#         Perl filter to produce a \LaTeX compatible document 
#         from a DAO Fortran source code with standard Pro\TeX 
#         prologues. If source files are not specified it
#         reads from stdin; output is always to stdout.
#
# \noindent
# {\bf Command Line Switches:} \vspace{0.2cm}
#
# \begin{center}
# \begin{tabular}{|c|l|} \hline \hline
#   -h   & Help mode: list command line options   \\ \hline
#   -b   & Bare mode, meaning no preamble, etc.  \\ \hline
#   -i   & internal mode: omit prologues marked !BOPI  \\ \hline
#   -g   & Use GEOS style.
#   +/-n & New Page for each subsection (wastes paper) \\ \hline
#   +/-l & Listing mode, default is prologues only \\ \hline
#   +/-s & Shut-up mode, i.e., ignore any code from BOC to EOC \\ \hline
#   +/-x & No LaTeX mode, i.e., put !DESCRIPTION: in verbatim mode \\ \hline
#   +/-f & No source file info \\ \hline
#   -A   & Ada code \\ \hline
#   -C   & C++ code \\ \hline
#   -F   & F90 code (default) \\ \hline
#   -S   & Shell script \\ \hline \hline
# \end{tabular}
# \end{center}
#
# The options can appear in any order.  The options, -h and -b, affect
# the input from all files listed on command-line input.  Each of the
# remaining options affects only the input from the files listed after
# the option and prior to any overriding option.  The plus sign
# turns off the option.  For example, the command-line input,
# \bv
#      protex -bnS File1 -F File2.f +n File3.f
# \ev
# will cause the option, {\tt -n} to affect the input from the files,
# {\tt File} and {\tt File2.f}, but not from {\tt File3.f}.  The
# {\tt -S} option is implemented for {\tt File1} but is overridden by
# the {\tt -F} for files {\tt File2.f} and {\tt File3.f}.
#
#
# !SEE ALSO:
#         For a more detailed description of ProTeX functionality,
#         DAO Prologue and other conventions, consult:
#
#           Sawyer, W., and A. da Silva, 1997: ProTeX: A Sample
#           Fortran 90 Source Code Documentation System.
#           DAO Office Note 97-11
#         
#
# !REVISION HISTORY:
#
#  20Dec1995  da Silva  First experimental version
#  10Nov1996  da Silva  First internal release (v1.01)
#  28Jun1997  da Silva  Modified so that !DESCRIPTION can appear after
#             !INTERFACE, and !INPUT PARAMETERS etc. changed to italics.
#  02Jul1997  Sawyer    Added shut-up mode
#  20Oct1997  Sawyer    Added support for shell scripts
#  11Mar1998  Sawyer    Added: file name, date in header, C, script support
#  05Aug1998  Sawyer    Fixed LPChang-bug-support-for-files-with-underscores
#  10Oct1998  da Silva  Introduced -f option for removing source file info
#                       from subsection, etc.  Added help (WS).
#  06Dec1999  C. Redder Added LaTeX command "\label{sec:prologues}" just 
#                       after the beginning of the proglogue section.
#  13Dec1999  C. Redder Increased flexbility in command-line
#                       interface.  The options can appear in any
#                       order which will allow the user to implement
#                       options for select files.
#  01Feb1999  C. Redder Added \usepackage commands to preamble of latex
#                       document to include the packages amsmath, epsfig
#                       and hangcaption.
#  10May2000  C. Redder Revised LaTeX command "\label{sec:prologues}"
#                       to "\label{app:ProLogues}"
#  10/10/2002 da Silva  Introduced ARGUMENTS keyword, touch ups.
#
#  15Jan2003  R. Staufer
#                       Modified table of contents to print only section
#                       headers - no descriptions
#
#  25Feb2003  R. Staufer
#                       Added BOPI/EOPI and -i (internal) switch to provide
#                       the option of omitting prologue information from
#                       output files.
#
#  30Jul2012  P. Chakraborty
#                       1. Added BOS/EOS to list states (from spec calls)
#                          as a table instead of makebox'es which do not play
#                          well with latex2html
#                       2. Modified EOR/BOR: please see description below
#                       3. Section heading 'CODE' is not bold anymore
#                       4. Added indexing of subroutines/functions (!IROUTINE:)
#                       5. Added !IDESCRIPTION: (same as !DESCRIPTION:, except
#                          that the word 'DESCRIPTION' does not appear on top
#  08Apr2013  R. Todling  Add graphicx to packages used
#
#EOP

# !BOS/!EOS
# To document the spec calls for Import/Export/Internal states, these calls
# need to be enclosed between !BOS and !EOS. Also the spec call should look like
# call MAPL_AddExportSpec(gc,                                                  &
#                         SHORT_NAME = 'KE',                                   &
# 			  LONG_NAME  = 'vertically_integrated_kinetic_energy', &
# 			  UNITS      = 'J m-2',                                &
# 			  DIMS       = MAPL_DimsHorzOnly,                      &
# 			  VLOCATION  = MAPL_VLocationNone,                     &
# 			  RC         = STATUS)
# Multiple arguments (e.g. UNITS and DIMS) in one line would lead to errors.
# The state variables are listed in a table, instead of makebox-es which do not
# play nice with latex2html.
#
# !BOR/EOR
# The resource items are listed in a table instead of makebox-es which do not
# play nice with latex2html.
# To document the resources fully, the call to MAPL_GetResource(...) needs to
# be enclosed between !BOR and !EOR. For complete documentation, protex needs
# two lines: the first comment line starting with the keyword !RESOURCE_ITEM:
# followed by the actual call to MAPL_GetResource(...) (in that order). e.g.
#
# !BOR
# !RESOURCE_ITEM: K :: Value of isothermal temperature on coldstart
# call MAPL_GetResource ( MAPL, T0, 'T0:', default=300., RC=STATUS )
# !EOR
#
# From the !RESOURCE_ITEM line, protex reads the unit (K) and the description
# (Value of isothermal temperature on coldstart). From the call line, protex
# reads the name (label) and its default value. The call line should NOT be
# continued to the next line(s).



#----------------------------------------------------------------------------

# Keep this if you don't know what it does...
# -------------------------------------------
$[ = 1;                 # set array base to 1
$, = ' ';               # set output field separator
$\ = "\n";              # set output record separator

# Set valid options lists
# -----------------------

$GlobOptions = 'hbgM';   # Global options (i.e for all files)
$LangOptions = 'ACFS';   # Options for setting programming languages
$SwOptions   = 'flinsx'; # Options that can change for each input 
#   file
$RegOptions  = "$GlobOptions$LangOptions";
# Scan for global options until first first
#   file is processed.

# Scan for global options
# -----------------------
$NFiles = 0;
Arg:
foreach $arg (@ARGV) {
  $option = &CheckOpts ( $arg, $RegOptions, $SwOptions ) + 1;
  if ( $option ) {
    $rc = &GetOpts    ( $arg, $GlobOptions );
    next Arg; }
  else { $NFiles++;
       }
}

# If all input arguments are options, then assume the
# filename, "-", for the standard input
# --------------------------------------------------
if ( $NFiles == 0 ) { push (@ARGV, "-"); }

# Implement help option
# ---------------------
if ( $opt_h ) {
  &print_help();
  exit();
}

# Optional Prologue Keywords
# --------------------------
@keys = ( "!INTERFACE:",
	  "!USES:",
	  "!PUBLIC TYPES:",
	  "!PRIVATE TYPES:",
	  "!PUBLIC MEMBER FUNCTIONS:",
	  "!PRIVATE MEMBER FUNCTIONS:",
	  "!METHOD OVERLOADING:",
	  "!PUBLIC DATA MEMBERS:",
	  "!PARAMETERS:",
	  "!ARGUMENTS:",
	  "!IMPORT STATE:",
	  "!EXPORT STATE:",
	  "!INTERNAL STATE:",
	  "!DEFINED PARAMETERS:",
	  "!INPUT PARAMETERS:",
	  "!INPUT/OUTPUT PARAMETERS:",
	  "!OUTPUT PARAMETERS:",
	  "!RETURN VALUE:",
	  "!REVISION HISTORY:",
	  "!BUGS:",
	  "!SEE ALSO:",
	  "!SYSTEM ROUTINES:",
	  "!FILES USED:",
	  "!REMARKS:",
	  "!TO DO:",
	  "!CALLING SEQUENCE:",
	  "!AUTHOR:",
	  "!CALLED FROM:",
	  "!LOCAL VARIABLES:" );

# Initialize these for clarity
# ----------------------------
$intro = 0;             # doing introduction?
$prologue = 0;          # doing prologue?
$first = 1;             # first prologue?
$source = 0;            # source code mode?
$verb = 0;              # verbatim mode?
$tpage = 0;             # title page?
$begdoc = 0;            # has \begin{document} been written?
$inspec = 0;            # are we processing state specs
$initem = 0;            # are we processing state specs item
$resource = 0;          # are we processing resources
$inresource = 0;        # are we in a resource item
$do_code = 0;           # produce a code section in MAPL; Stubbed for now.

# Initial LaTeX stuff
# -------------------
&print_notice();
&print_preamble();      # \documentclass, text dimensions, etc.
&print_macros();        # short-hand LaTeX macros

# Main loop -- for each command-line argument
# -------------------------------------------
ARG:
foreach $arg (@ARGV) {
  #    Scan for non-global command-line options
  #    ----------------------------------------
  $option = &CheckOpts ( $arg, $RegOptions, $SwOptions, "quiet" ) + 1;
  if ( $option ) {
    &GetOpts  ( $arg, $SwOptions   );
    &SetOpt   ( $arg, $LangOptions );
    next ARG;
  }

  $is_mapl = $opt_g || $opt_M;

  #    Determine the type of code, set corresponding search strings
  #    ------------------------------------------------------------
  #    if ( $opt_F ) {            # FORTRAN
  $comment_string = '!';  # -------
  $boi_string = '!BOI';
  $eoi_string = '!EOI';
  $bop_string = '!BOP';
  $eop_string = '!EOP';
  $bopi_string = '!BOPI';
  $eopi_string = '!EOPI';
  $boc_string = '!BOC';
  $eoc_string = '!EOC';
  $boe_string = '!BOE';
  $eoe_string = '!EOE';
  $bor_string = '!BOR';
  $eor_string = '!EOR';
  $bos_string = '!BOS';  # begin state (import/export/internal)
  $eos_string = '!EOS';  # end state
  #}

  if ( $opt_A ) {            # ADA
    $comment_string = '--'; # ---
    $boi_string = '--BOI';
    $eoi_string = '--EOI';
    $bop_string = '--BOP';
    $eop_string = '--EOP';
    $bopi_string = '--BOPI';
    $eopi_string = '--EOPI';
    $boc_string = '--BOC';
    $eoc_string = '--EOC';
    $boe_string = '--BOE';
    $eoe_string = '--EOE';
  }

  if ( $opt_C ) {
    $comment_string = '//'; # C 
    $boi_string = '//BOI';  # -
    $eoi_string = '//EOI';
    $bop_string = '//BOP';
    $eop_string = '//EOP';
    $bopi_string = '//BOPI';
    $eopi_string = '//EOPI';
    $boc_string = '//BOC';
    $eoc_string = '//EOC';
    $boe_string = '//BOE';
    $eoe_string = '//EOE';
  }

  if ( $opt_S ) {            # Script
    $comment_string = '#';  # ------
    $boi_string = '#BOI';
    $eoi_string = '#EOI';
    $bop_string = '#BOP';
    $eop_string = '#EOP';
    $bopi_string = '#BOPI'; 
    $eopi_string = '#EOPI';
    $boc_string = '#BOC';
    $eoc_string = '#EOC';
    $boe_string = '#BOE';
    $eoe_string = '#EOE';
  }

  #    Set file name parameters
  #    ------------------------
  $InputFile           = $arg;
  @all_path_components = split( /\//, $InputFile     );
  $FileBaseName        = pop  ( @all_path_components );
  $FileBaseName        =~ s/_/\\_/g;
  if ( $InputFile eq "-" ) {$FileBaseName = "Standard Input";}

  #    Set date
  #    --------
  $Date                = `date`;

  #    Open current file
  #    -----------------
  open ( InputFile, "$InputFile" )
    or print STDERR "Unable to open $InputFile: $!";

  #    Print page header
  #    -----------------
  if($is_mapl) {
    $shname =  " ";
    $lnname =  " ";
    $units  =  " ";
    $dims   =  " ";
    $child  =  " ";
    $locs   =  " "; 
  }
  else {
    printf "\n\\markboth{Left}{Source File: %s,  Date: %s}\n\n",
      $FileBaseName,    $Date;
  }

 LINE:
  #    Inner loop --- for processing each line of the input file
  #    ---------------------------------------------------------
  while ( <InputFile> ) {
    chop;     # strip record separator

    # add a space around '=', needed for parsing addspec calls
    s/=/\ =\ /g;

    next LINE if /^\#/;  # skip CPP directives 

    #       !PARAMETERS: really mean !ARGUMENTS:
    #       ------------------------------------
    #        s/!PARAMETERS:/!ARGUMENTS:/g;

    # begin pc
    # if($in_resource) {
    #   @Fld = split(',', $_, 9999);
    # } else {
    #   @Fld = split(' ', $_, 9999);
    # }
    # end pc

    # if($initem){
    #   @Fld = split(',', $_, 9999);
    # } else {
    #   @Fld = split(' ', $_, 9999);
    # }

    @Fld = split(' ', $_, 9999);
    # end pc

    #       Straight quote
    #       --------------
    if ( ($Fld[1] eq '!QUOTE:') || ($is_mapl && ($Fld[1] eq '!MQUOTE:'))) {
      for ($i = 2; $i <= $#Fld; $i++) {
	printf '%s ', $Fld[$i];
      }
      print " ";
      next LINE;
    }


    if ($Fld[1] eq $bor_string) {
      print "\\emph{RESOURCES:}\\\\";
      print "\\newline";

      print "\\texttt{";
      print "\\begin{longtable}{p{1in} | p{3in} p{1in} p{0.5in}}";
      print "\\hline";
      print "{\\sf \\sf Name} & {Description} & {\\sf \\sf Units} & {\\sf \\sf Default}\\\\";
      print "\\hline\\\\";
      print "\\endhead";

      $resource=1;
      next LINE;
    }

    if ($Fld[1] eq $eor_string) {
      if($resource){
	print "\\end{longtable}";
	print "}"; # closes \texttt{
	$resource=0;
      }
      next LINE;
    }

    if ($Fld[1] eq $bos_string) {
      print "\\emph{STATES:}\\\\";
      print "\\newline";
      print "The following is a list of \\texttt{Import}, \\texttt{Export} and";
      print "\\texttt{Internal} states (second column specifies the type):";
      print "\\texttt{";
      print "\\begin{longtable}{p{1in} | p{0.2in} p{0.8in} p{0.3in} p{0.6in} p{2.4in}}";
      print "\\hline";
      print "{\\sf \\sf Short Name} & {\\sf \\sf Type} & {\\sf \\sf Units} & {\\sf \\sf Dims} & {\\sf \\sf Vert Loc} & {\\sf \\sf Long name}\\\\";
      print "\\hline\\\\";
      print "\\endhead";

      $inspec=1;
      $initem=0;
      next LINE;
    }

    if ($Fld[1] eq $eos_string) {
      if($inspec){
	&beg_item();
	print "\\end{longtable}";
	print "}"; # closes \texttt{
	$inspec=0;
      }
      next LINE;
    }

    #       Handle optional Title Page and Introduction
    #       -------------------------------------------
    if ($Fld[1] eq $boi_string) {
      print ' ';
      $intro = 1;
      next LINE;
    }

    if ($Fld[2] eq '!TITLE:') {
      if ( $intro ) {
	shift @Fld;
	shift @Fld;
	@title = @Fld;
	$tpage = 1;
	next LINE;
      }
    }

    if ($Fld[2] eq '!AUTHORS:') {
      if ( $intro ) {
	shift @Fld;
	shift @Fld;
	@author = @Fld;
	$tpage = 1;
              next LINE;
      }
    }

    if ($Fld[2] eq '!AFFILIATION:') {
      if ( $intro ) {
	shift @Fld;
	shift @Fld;
	@affiliation = @Fld;
	$tpage = 1;
	next LINE;
      }
    }

    if ($Fld[2] eq '!DATE:') {
      if ( $intro ) {
	shift @Fld;
	shift @Fld;
	@date = @Fld;
	$tpage = 1;
	next LINE;
      }
    }

    if ($Fld[2] eq '!INTRODUCTION:') {
      if ( $intro ) {
	&do_beg();
	print ' ';
	print '%..............................................';
	shift @Fld;
              shift @Fld;
	if($is_mapl) {
	  print "\\part{\\Large @Fld}";}
	else{
	  print "\\section{@Fld}";
	}
	next LINE;
      }
    }


    #       End of introduction
    #       -------------------
    if ($Fld[1] eq $eoi_string) {
      print ' ';
      print '%/////////////////////////////////////////////////////////////';
      print "\\newpage";
      $intro = 0;
      next LINE;
    }

    #       Beginning of prologue
    #       ---------------------
    if ($Fld[1] eq $bop_string) {
      if ( $source ) { &do_eoc(); }
      print ' ';
      print '%/////////////////////////////////////////////////////////////'; 
      &do_beg();
      if ($first == 0 && $opt_n==0) {
	### print "\\newpage";
	print " ";
	print "\\mbox{}\\hrulefill\\ ";
	print " ";}
      else {
	unless($opt_b || $is_mapl) { 
	  print "\\section{Routine/Function Prologues} \\label{app:ProLogues}";
	}
      }

      $first = 0;
      $prologue = 1;
      $verb = 0;
      $source = 0;
      $resource = 0;
      $inspec = 0;
      $inresource = 0;
      &set_missing();   # no required keyword yet
      next LINE;
    }

    #	Beginning of internal prologue
    #	------------------------------
    if ($Fld[1] eq $bopi_string) {
      if ($opt_i) {$prologue = 0;}
      else {
	if ($source) { &do_eoc(); }
	print ' ';
	print '%/////////////////////////////////////////////////////////////';  
	&do_beg();
	if ($first ==0 && $opt_n==0) {
	  ### print "\\newpage";
	  print " ";
	  print "\\mbox{}\\hrulefill\\";
	  print " ";}
	else {
	  unless($opt_b || $is_mapl) { 
	    print "\\section{Routine/Function Prologues} \\label{app:ProLogues}";
	  }
	}
	$first = 0;
	$prologue = 1;
	$verb = 0;
	$source = 0;
	$resource = 0;
	$inspec = 0;
	$inresource = 0;
	&set_missing();    # no required keyword yet
	next LINE;
      }
    }

    #       A new subroutine/function
    #       -------------------------
    if ($Fld[2] eq '!ROUTINE:' ) { 
      if ($prologue) {
	shift @Fld;
	shift @Fld;
	$_ = join(' ', @Fld);
	$name_is = $_;
	s/_/\\_/g;                         # Replace "_" with "\_"
	if ( $opt_n && $not_first ) { printf "\\newpage\n"; }
	unless ($opt_f) {printf "\\subsubsection{%s (Source File: %s)}\n\n", $_, $FileBaseName;}
	else            {printf "\\subsubsection{%s }\n\n", $_;}
	$have_name = 1;
	$not_first = 1;
	next LINE;
      }
    }


    #       A new Module
    #       ------------
    if ($Fld[2] eq '!PROGRAM:' ) {
      if ($prologue) {
	shift @Fld;
	shift @Fld;
	$_ = join(' ', @Fld);
	$name_is = $_;
	s/_/\\_/g;                         # Replace "_" with "\_"
	if ( $opt_n && $not_first ) { printf "\\newpage\n"; }
	if($is_mapl) {
	  printf "\\section [%s] {Program  %s }\n\n", $_,$_;}
	else {
	  unless($opt_f) {printf "\\subsection{Fortran:  Main Program %s (Source File: %s)}\n\n", $_, $FileBaseName;}
	  else           {printf "\\subsection{Fortran:  Main Program %s }\n\n", $_;}
	} # endif

	$have_name = 1;
	$have_intf = 1;  # fake it, it does not need one.
	$not_first = 1;
	next LINE;
      }
    }


    #       A new Module
    #       ------------
    if ($Fld[2] eq '!MODULE:' ) { 
      if ($prologue) {
	shift @Fld;
	shift @Fld;
	$_ = join(' ', @Fld);
	$name_is = $_;
	s/_/\\_/g;                         # Replace "_" with "\_"
	if ( $opt_n && $not_first ) { printf "\\newpage\n"; }
	if($is_mapl) {printf "\\section [%s] {Module  %s }\n\n", $_,$_;}
	else {
	  unless($opt_f){
	    printf "\\subsection{Fortran:  Module Interface %s (Source File: %s)}\n\n", $_, $FileBaseName;
	  }
	  else{
	    printf "\\subsection{Fortran:  Module Interface %s }\n\n", $_;
	  }
	} # endif

	$have_name = 1;
	$have_intf = 1;  # fake it, it does not need one.
	$not_first = 1;
	next LINE;
      }
    }


    #       A new include file
    #       ------------------
    if ($Fld[2] eq '!INCLUDE:' ) { 
      if ($prologue) {
	shift @Fld;
	shift @Fld;
	$_ = join(' ', @Fld);
	$name_is = $_;
	s/_/\\_/g;                         # Replace "_" with "\_"
	if ( $opt_n && $not_first ) { printf "\\newpage\n"; }
	unless($opt_f) {printf "\\subsubsection{Include File %s (Source File: %s)}\n\n", $_, $FileBaseName;}
	else           {printf "\\subsubsection{Include File %s }\n\n", $_;}  
	$have_name = 1;
	$have_intf = 1;  # fake it, it does not need one.
	$not_first = 1;
	next LINE;
      }
    }


    #       A new INTERNAL subroutine/function
    #       ----------------------------------
    if ($Fld[2] eq '!IROUTINE:') {            # Internal routine
      if ($prologue) {
	shift @Fld;
	shift @Fld;
	$Generic_name = $Fld[0]; # For overloads: padded
	$generic_name = $Fld[0]; # For overloads: not padded
	$internal_name = $Fld[0];
	$_ = join(' ', @Fld);
	$name_is = $_;
	s/_/\\_/g;                        # Replace "_" with "\_"
	if ( $opt_n && $not_first ) {printf "\\newpage\n";}
	if($is_mapl) {
	  #ams		  @words = split "-", $_;
	  #ams		  printf "\\subsection [$words[1]] {$_}\n\n";
	  $Fld[0] =~ s/_/\\_/g;           # Replace "_" with "\_"
	  printf "\\subsection [$_] {$_\\index{$Fld[0]}}\n\n";
	}
	else {
	  ###		  @words = split " ", $_;
	  ###		  printf "\\subsubsection [$words[1]] {$_}\n\n";
	  $Fld[0] =~ s/_/\\_/g;           # Replace "_" with "\_"
	  printf "\\subsection [$_] {$_\\index{$Fld[0]}}\n\n";
	}
	$have_name = 1;
	next LINE;
      }
    }


    #       A new OVERLOADED subroutine/function
    #       -----------------------------------
    if ($Fld[2] eq '!IIROUTINE:') {            # Internal routine
      if ($prologue) {
	shift @Fld;
	shift @Fld;
	$internal_name = $Fld[0];
	$Generic_name = $generic_name; # padded copy
	for($i=length($generic_name); 
	    $i<length($internal_name);
	    $i++ ) { $Generic_name = $Generic_name . " "; }
	$_ = join(' ', @Fld);
	$name_is = $_;
	s/_/\\_/g;                        # Replace "_" with "\_"
	if ( $opt_n && $not_first ) {printf "\\newpage\n";}
	@words = split " ", $_;
	shift @words;
	shift @words;
	printf "\\subsubsection [@words] {@words}\n\n";
	$have_name = 1;
	next LINE;
      }
    }


    #       A new CONTAINED subroutine/function
    #       ----------------------------------
    if ($Fld[2] eq '!CROUTINE:') {            # Contained routine
      if ($prologue) {
	shift @Fld;
	shift @Fld;
	$_ = join(' ', @Fld);
	$name_is = $_;
	s/_/\\_/g;                        # Replace "_" with "\_"
	@words = split " ", $_;
	printf "\\subsubsection [$words[1]] {$_}\n\n";
	$have_name = 1;
	next LINE;
      }
    }


    #       A new CLASS
    #       ------------
    if ($Fld[2] eq '!CLASS:' ) { 
      if ($prologue) {
	shift @Fld;
	shift @Fld;
	$_ = join(' ', @Fld);
	$name_is = $_;
              s/_/\\_/g;                         # Replace "_" with "\_"
	if ( $opt_n && $not_first ) { printf "\\newpage\n"; }
	unless($opt_f) {printf "\\subsection{C++:  Class Interface %s (Source File: %s)}\n\n", $_, $FileBaseName;}
	else           {printf "\\subsection{C++:  Class Interface %s }\n\n", $_;}
	$have_name = 1;
	$have_intf = 1;  # fake it, it does not need one.
	$not_first = 1;
	next LINE;
      }
    }


    #       A new Method
    #       -------------------------
    if ($Fld[2] eq '!METHOD:' ) { 
      if ($prologue) {
	shift @Fld;
	shift @Fld;
	$_ = join(' ', @Fld);
	$name_is = $_;
	s/_/\\_/g;                         # Replace "_" with "\_"
	if ( $opt_n && $not_first ) { printf "\\newpage\n"; }
	unless ($opt_f){
	  printf "\\subsubsection{%s (Source File: %s)}\n\n", $_, $FileBaseName;
	}
	else{
	  printf "\\subsubsection{%s }\n\n", $_;
	}
	$have_name = 1;
	$not_first = 1;
	next LINE;
      }
    }


    #       A new function
    #       -------------------------
    if ($Fld[2] eq '!FUNCTION:' ) { 
      if ($prologue) {
	shift @Fld;
	shift @Fld;
	$_ = join(' ', @Fld);
	$name_is = $_;
	s/_/\\_/g;                         # Replace "_" with "\_"
	if ( $opt_n && $not_first ) { printf "\\newpage\n"; }
	unless ($opt_f) {
	  printf "\\subsubsection{%s (Source File: %s)}\n\n", $_, $FileBaseName;}
	else {printf "\\subsubsection{%s }\n\n", $_;}
	$have_name = 1;
	$not_first = 1;
	next LINE;
      }
    }


    #       Description: what follows will be regular LaTeX (no verbatim)
    #       -------------------------------------------------------------
    if (/!DESCRIPTION:/ || /!DESIGN ISSUES:/ ) {
      if ($prologue) {
	if ($verb) {
	  printf "\\end{verbatim}";
	  printf "\n{\\sf \\sf DESCRIPTION:\\ }\n\n"
	    if ( /!DESCRIPTION:/ ) ;
	  printf "\n{\\sf \\sf DESIGN ISSUES:\\ }\n\n"
	    if ( /!DESIGN/ ) ;
	  $verb = 0; }
	else {
	  printf "\n{\\sf \\sf DESCRIPTION:\\ }\n\n"
	    if ( /!DESCRIPTION:/ ) ;
	  printf "\n{\\sf \\sf DESIGN ISSUES:\\ }\n\n"
	    if ( /!DESIGN ISSUES:/ ) ;
	}
	if ($opt_x) {
	  printf "\\begin{verbatim} ";
	  $verb = 1;
	  $first_verb = 1; }
	else {
	  for ($i = 3; $i <= $#Fld; $i++) {
	    printf '%s ', $Fld[$i];
	  }
	}
	### print " ";
	$have_desc = 1;
	next LINE;
      }
    }

    #       !IDESCRIPTION: Same as !DESCRIPTION, except that the word
    #       'DESCRIPTION' does not appear on top
    #       ---------------------------------------------------------
    if (/!IDESCRIPTION:/) {
      if ($prologue) {
	if ($verb) {
	  printf "\\end{verbatim}";
	  $verb = 0;
	}
	if ($opt_x) {
	  printf "\\begin{verbatim} ";
	  $verb = 1;
	  $first_verb = 1; }
	else {
	  for ($i = 3; $i <= $#Fld; $i++) {
	    printf '%s ', $Fld[$i];
	  }
	}
	### print " ";
	$have_desc = 1;
	next LINE;
      }
    }

    #       Handle optional keywords (these will appear as verbatim)
    #       --------------------------------------------------------
    if ($prologue) {
    KEY:       foreach $key ( @keys ) {
	if ( /$key/ ) {
	  $doing_interface = 0;
	  if ($verb) {
	    printf "\\end{verbatim}";
	    $verb = 0;
	  }
	  $k = sprintf('%s', $key);
	  $ln = length($k);
	  $_ = $key;

	  if($is_mapl) {
	    if( /USES/ || /INPUT/ || /OUTPUT/ || /PARAMETERS/ ||
		/VALUE/|| /ARGUMENTS/ ) {
	      printf "{\\em %s}\n", substr($k, 2, $ln - 1); # italics
	    } else {
	      printf "{\\sf %s}\n", substr($k, 2, $ln - 1); # san serif
	    }
	  } else {
	    if( /USES/ || /INPUT/ || /OUTPUT/ || /PARAMETERS/ || 
		/VALUE/  || /ARGUMENTS/ ) {
	      printf "{\\em %s}\n", substr($k, 2, $ln - 1); # italics
	    } else {
	      printf "{\\sf %s}\n", substr($k, 2, $ln - 1); # san serif
	    }
	  }

	  printf "\\begin{verbatim} ";
	  $verb = 1;
	  $first_verb = 1;
	  if ( $key eq "!INTERFACE:" ) { 
	    $have_intf = 1; 
	    $doing_interface = 1;
	  }
	  if ( $key eq "!CALLING SEQUENCE:" ) { $have_intf = 1; }
	  if ( $key eq "!REVISION HISTORY:" ) { $have_hist = 1; }
	  next LINE;
	}
      }
    }


    #       End of prologue
    #       ---------------
    if ($Fld[1] eq $eop_string) {
      if ($verb) {
	print "\\end{verbatim}";
	$verb = 0;
      }
      $prologue = 0;

      if ( $opt_l ) {
	$Fld[1] = $boc_string;}
      else { next LINE; }
    }

    unless ( $opt_s ) {

      #       End of Internal Prologue
      #	------------------------
      if ($Fld[1] eq $eopi_string) {
	if ($verb) {
	  print "\\end{verbatim}";
	  $verb = 0;
	}

	$prologue = 0;
	if ($opt_l) {
	  $Fld[1] = $boc_string;}
	else { next LINE; }
      }

      #
      #          Beginning of source code section
      #          --------------------------------
      if ($Fld[1] eq $boc_string) {
	print ' ';
	print '%/////////////////////////////////////////////////////////////';
	$first = 0;
	$prologue = 0;
	$source = 1;
	$verb = 0;
	### printf "\\subsubsection*{CONTENTS:}\n\n", $Fld[3];
	###printf "{\\sf CONTENTS:}";
	unless($opt_s) { 
	  printf "\n{\\em CODE:}\n";
	  # printf "\n\\begin{verbatim}\n";
	  printf "\\begin{verbatim}\n";
	  $verb = 1;
	}
	next LINE;
      }


      #          End of source code
      #          ------------------
      if ($Fld[1] eq $eoc_string) {
	&do_eoc();
	$prologue = 0;
	next LINE;
      }


      #          Beginning of example prologue
      #          -----------------------------
      if ($Fld[1] eq $boe_string) {
	if ( $source ) { &do_eoc(); }
	print '%/////////////////////////////////////////////////////////////'; 
	$first = 0;
	$prologue = 1;
	$verb = 0;
	$source = 0;
	next LINE;
      }


      #       End of example prologue
      #       -----------------------
      if ($Fld[1] eq $eoe_string) {
	if ($verb) {
	  print "\\end{verbatim}";
	  $verb = 0;
	}#         end if
	$prologue = 0;
	if ( $opt_l ) {
	  $Fld[1] = $boc_string;}
	else { next LINE; }
      }
    }# end unless($opt_s)


    #   Prologue or Introduction, print regular line (except for !)
    #   -----------------------------------------------------------
    if ($prologue||$intro) {
      if ( $verb && $#Fld == 1 && ( $Fld[1] eq $comment_string ) ) {
	next LINE;                # to eliminate excessive blanks 
      }
      if($is_mapl) {
	if ( $verb && $#Fld == 2 && ( $Fld[1] eq 'implicit' ) ) {
	  next LINE;
	}
	if ( $verb && $#Fld == 1 && ( $Fld[1] eq 'private' ) ) {
	  next LINE;
	}
	if ( $verb && $#Fld == 1 && ( $Fld[1] eq 'contains' ) ) {
	  next LINE;
	}
      }#  endif(is_mapl)
      if ( $Fld[2] eq "\\ev" ) {   # special handling
	$_ = $comment_string . " \\end{verbatim}";
      }
      s/^$comment_string/ /;       # replace comment string with blank

      unless ( $first_verb ) { printf "\n "; }
      if ( $doing_interface ) { s/$internal_name/$Generic_name/; }
      printf '%s', $_;
      $first_verb = 0;
      next LINE;
    }# end if($prologue||$intro)


    #    Resources
    #    ---------
    if($resource && $is_mapl) {
      $in_rsrcs = 0;
      if(($Fld[1] eq "!RESOURCE_ITEM:") or ($Fld[2] eq "!RESOURCE_ITEM:")){
	&prc_rsrcs_1();
      }
      if((uc $Fld[1] eq "CALL") and (uc substr($Fld[2],6,11) eq "GETRESOURCE")){
	&prc_rsrcs_2();
	$in_rsrcs = 1;
      }
      if($in_rsrcs){
	&prnt_rsrcs();
	$in_rsrcs = 0;
      }
      next LINE;
    }


    #   State specs
    #   -----------
    if($inspec && is_mapl){
      if($Fld[1] eq "call"){
	&beg_item();
	# IM/EX/IN?
	# for some (?) reason, we have everything shifted by 1
	#   hence substr($Fld[2],9,6) instead of substr($Fld[2],8,6)
	if    (lc substr($Fld[2],9,6) eq "import") {$imexin = "IM";}
	elsif (lc substr($Fld[2],9,6) eq "export") {$imexin = "EX";}
	elsif (lc substr($Fld[2],9,6) eq "intern") {$imexin = "IN";}
	else{
	  print $Fld[2];
	  print lc substr($Fld[2],8,6);
	  print "A spec call without a type??";
	  exit 0;
	}
	next LINE;
      }
      if($Fld[2] eq "="){
	&prc_item();
      }
    }


    #   Source code: print the full line
    #   --------------------------------
    if ($source) {
      printf "%s \n", $_;
      next LINE;
    }
  }#  end inner loop for processing each line of the input file
}# end main loop for each command-line argument

print $_;
if ( $source ) { &do_eoc(); }     
print '%...............................................................';

# see comment above where these are originally set.
#print "\\setlength{\\parskip}{\\oldparskip}";
#print "\\setlength{\\parindent}{\\oldparindent}";
#print "\\setlength{\\baselineskip}{\\oldbaselineskip}";

unless ( $opt_b ) {
  print "\\end{document}";
}#end unless


#----------------------------------------------------------------------

sub CheckOpts{
  #    Checks options against a given list.  Outputs error message
  #    for any invalid option.
  #
  #    Usage:
  #       $rc = &CheckOpts ( options, valid_reg_options,
  #                                   valid_sw_options,
  #                                   quiet_mode )
  #
  #       character: options - options to be checked. (e.g. -df+x)  The
  #                            list must begin with a positive or
  #                            negative sign.  If no sign appears at the
  #                            beginning or by itself, then the argument
  #                            is not recognized as a list of options.
  #       character: valid_reg_options - list of valid regular options.
  #                            (i.e. options that are associated only
  #                            eith negative sign.)
  #       character: valid_sw_options - list of valid switch options.
  #                            (i.e. options that can be associated with
  #                            either a positive or negative sign.
  #       logical:   quiet mode (optional) If true then print no error
  #                            messages.
  #       integer:   rc      - return code
  #                            = -1 if the arguement, options, is
  #                               not recognized as a list of options
  #                            =  0 if all options are valid.
  #                            >  0 for the number of invalid options.
  #
  local($options,
	$valid_reg_options,
	$valid_sw_options,
	$quiet_mode ) = @_;

  if ( $options eq "+" ||
       $options eq "-" ) {return -1}

  local(@Options) = split( / */, $options );
  if ( $Options[ $[ ] ne "-" &&
       $Options[ $[ ] ne "+" ) {return -1;}

  local($option, $option_sign, $valid_list, $pos);
  local($errs)    = 0;
  foreach $option ( @Options ) {
    if ( $option eq "-" ||
	 $option eq "+" ) {$option_sign = $option;}
    else {
      if ( $option_sign eq "-" )
	{ $valid_list = $valid_reg_options
	    . $valid_sw_options; }
      else
	{ $valid_list = $valid_sw_options; }
      $pos = index ($valid_list,$option); 
      if ( $pos < $[ &&
	   $quiet_mode ) {
	$errs++;
	print STDERR "Invalid option: $option_sign$option \n"; 
      }
    }
  }# end foreach
  return $errs;
}#end sub GetOpts

sub GetOpts{
  #    Gets options.  If an option is valid,  then opt_[option] is
  #    set to 0 or 1 as a side effect if the option is preceeded by
  #    a positive or negative sign.
  #
  #    Usage:
  #       $rc = &GetOpts ( options, valid_options )
  #
  #       character: options - options to be checked. (e.g. -df+x)  The
  #                            list must begin with a positive or
  #                            negative sign.  If no sign appears at the
  #                            beginning or by itself, then the argument
  #                            is not recognized as a list of options.
  #       character: valid_options - list of valid options (e.g. dfhx)
  #       integer:   rc      - return code
  #                            = -1 if the arguement, options, is
  #                               not recognized as a list of options.
  #                            =  0 otherwise

  local($options,$valid_options) = @_;

  if ( $options eq "+" ||
       $options eq "-" ) {return -1}

  local(@Options)       = split( / */, $options );
  if ( $Options[ $[ ] ne "-" &&
       $Options[ $[ ] ne "+" ) {return -1;}

  local($option, $option_sign);

  foreach $option ( @Options ) {

    if ( $option eq "-" ||
	 $option eq "+" ) {
      $option_sign = $option;
    }

    else {
      if ( index ($valid_options,$option) >= $[ ) {
	if ( $option_sign eq "-" ) {${"opt_$option"} = 1;}
	if ( $option_sign eq "+" ) {${"opt_$option"} = 0;};
      }
    }
  }# end foreach
  
  return 0;
}#end sub GetOpts

sub SetOpt{
  #    Sets option flags.  For the last input option that is in a
  #    list, the flag opt_[option] is set to 1 as a side effect.
  #    For all other options in the list, opt_[option] is set to 0.
  #
  #    Usage:
  #       $rc = &SetOpt ( options, valid_options )
  #
  #       character: options - options to be checked. (e.g. -df+x)  The
  #                            list must begin with a positive or
  #                            negative sign.  If no sign appears at the
  #                            beginning or by itself, then the argument
  #                            is not recognized as a list of options.
  #       character: valid_options - list of valid options (e.g. def )
  #       integer:   rc      - return code
  #                            = -1 if the arguement, options, is
  #                               not recognized as a list of options.
  #                            =  0 otherwise
  #       Note: For the examples provided for the input arguments,
  #             $opt_d = 0, $opt_e = 0, and $opt_f = 1, since the 
  #             input option, -f, was the last in the argument,
  #             option.

  local($options,$valid_options) = @_;

  if ( $options eq "+" ||
       $options eq "-" ) {return -1}

  local(@Options)       = split( / */, $options       );
  local(@ValidOptions)  = split( / */, $valid_options );
  if ( $Options[ $[ ] ne "-" &&
       $Options[ $[ ] ne "+" ) {return -1;}

  local($option, $option_sign);

  foreach $option ( @Options ) {
    if ( $option ne "-" &&
	 $option ne "+" ) {

      if ( index ($valid_options,$option) >= $[ ) {
	foreach $valid_option (@ValidOptions ) {
	  ${"opt_$valid_option"} = 0;
	}
	${"opt_$option"} = 1;
      }
    }
  }#   end foreach
  
  return 0;
}#end sub SetOpt

sub print_help{
  print "Usage:     protex [-hbACFS] [+-nlsxf] [src_file(s)]";
  print " ";
  print " Options:";
  print "     -h   Help mode: list command line options";
  print "     -b   Bare mode, meaning no preamble, etc.";
  print "     +-n  New Page for each subsection (wastes paper)";
  print "     +-l  Listing mode, default is prologues only";
  print "     +-s  Shut-up mode, i.e., ignore any code from BOC to EOC";
  print "     +-x  No LaTeX mode, i.e., put !DESCRIPTION: in verbatim mode";
  print "     +-f  No source file info";
  print "     -A   Ada code";
  print "     -C   C++ code";
  print "     -F   F90 code";
  print "     -S   Shell script";
  print " ";
  print "  The options can appear in any order.  The options, -h and -b,";
  print "  affect the input from all files listed on command-line input.";
  print "  Each of the remaining options effects only the input from the";
  print "  files listed after the option and prior to any overriding";
  print "  option.  The plus sign turns off the option.";
}

sub print_notice{
  print "%                **** IMPORTANT NOTICE *****" ;
  print "% This LaTeX file has been automatically produced by ProTeX v. 1.1";
  print "% Any changes made to this file will likely be lost next time";
  print "% this file is regenerated from its source. Send questions ";
  print "% to Arlindo da Silva, dasilva\@gsfc.nasa.gov";
  print " ";
}# sub print_notice

sub print_preamble {
  unless ( $opt_b ) {
    print "%------------------------ PREAMBLE --------------------------";
    print "\\documentclass[11pt]{article}";
    print "\\usepackage{amsmath}";
    print "\\usepackage{epsfig}";
    print "\\usepackage{graphicx}";
    print "\\usepackage{fancyhdr}";
    print "\\usepackage{caption}";

    # long tables for spec calls and resource items
    print "\\usepackage{longtable}";

    print "\\textheight     9in";
    print "\\topmargin      0pt";
    print "\\headsep        1cm";
    print "\\headheight     0pt";
    print "\\textwidth      6in";
    print "\\oddsidemargin  0in";
    print "\\evensidemargin 0in";
    print "\\marginparpush  0pt";
    print "\\pagestyle{myheadings}";
    print "\\markboth{}{}";
    
    print "%-------------------------------------------------------------";
  }#  end unless
  
  # in your main document before you include any protex-generated files 
  # for the first time, if you define these three variables as length 
  # settings (like this:)
  #   \newlength{\oldparskip}
  #   \newlength{\oldparindent}
  #   \newlength{\oldbaselineskip}
  # then 1) comment in all the lines below, and 2) find the 3 reset lines
  # further down and comment in them as well. 
  # then protex will override the paragraph and skip settings during 
  # the source sections, but will restore the original document settings 
  # at the end.   if someone can figure out how to check to see if a
  # latex variable exists, and do a conditional section, we could make
  # this fully self-contained.
  # nsc feb 2003
  
  # #print "\\setlength{\\oldparskip}{\\parskip}";
  # print "\\setlength{\\parskip}{12pt}";
  # #print "\\setlength{\\oldparindent}{\\parindent}";
  print "\\setlength{\\parindent}{0pt}";
  # #print "\\setlength{\\oldbaselineskip}{\\baselineskip}";
  # print "\\setlength{\\baselineskip}{11pt}";
  
}# end sub print_preamble

sub print_macros {
  print " ";
  print "%--------------------- SHORT-HAND MACROS ----------------------";
  print "\\def\\bv{\\begin{verbatim}}";
  print "\\def\\ev\{\\end\{verbatim}}";
  print "\\def\\be{\\begin{equation}}";
  print "\\def\\ee{\\end{equation}}";
  print "\\def\\bea{\\begin{eqnarray}}";
  print "\\def\\eea{\\end{eqnarray}}";
  print "\\def\\bi{\\begin{itemize}}";
  print "\\def\\ei{\\end{itemize}}";
  print "\\def\\bn{\\begin{enumerate}}";
  print "\\def\\en{\\end{enumerate}}";
  print "\\def\\bd{\\begin{description}}";
  print "\\def\\ed{\\end{description}}";
  print "\\def\\({\\left (}";
  print "\\def\\){\\right )}";
  print "\\def\\[{\\left [}";
  print "\\def\\]{\\right ]}";
  print "\\def\\<{\\left  \\langle}";
  print "\\def\\>{\\right \\rangle}";
  print "\\def\\cI{{\\cal I}}";
  print "\\def\\diag{\\mathop{\\rm diag}}";
  print "\\def\\tr{\\mathop{\\rm tr}}";
  print "%-------------------------------------------------------------";
}# end sub print_macros

sub do_beg {
  unless ( $opt_b ) {
    if ( $begdoc == 0 ) {
      if ( $tpage ) {
	print "\\title{@title}";
	print "\\author{{\\sc @author}\\\\ {\\em @affiliation}}";
	print "\\date{@date}";
      }
      print "\\begin{document}";
      if ( $tpage ) {
	print "\\maketitle";
        print "\\thispagestyle{fancy}";
        print "\\renewcommand{\\headrulewidth}{0pt}";
      }
      print "\\tableofcontents";
      print "\\newpage";
      $begdoc = 1;
    }
  }
}# end sub do_beg

sub do_eoc {
  if ($verb) {
    print "\\end{verbatim}";
    $verb = 0;
  }
  $source = 0;
}# end sub do_eoc

sub set_missing {
  $have_name = 0;      # have routine name?
  $have_desc = 0;      # have description?
  $have_intf = 0;      # have interface?
  $have_hist = 0;      # have revision history?
  $name_is = "UNKNOWN";
}# end sub set_missing


sub check_if_all_there {
  $have_name || 
    die "ProTeX: invalid prologue, missing !ROUTINE: or !IROUTINE: in <$name_is>";

  $have_desc || 
    die "ProTeX: invalid prologue, missing !DESCRIPTION: in <$name_is>";

  $have_intf || 
    die "ProTeX: invalid prologue, missing !INTERFACE: in <$name_is>";

  $have_hist || 
    die "ProTeX: invalid prologue, missing !REVISION HISTORY: in <$name_is>";
}# end sub check_if_all_there

sub hed_item {
  printf "\n{ \\bf \\sf \n";
  printf "\\makebox[1.1 in][l]{Short Name } \n";
  printf "\\makebox[.9 in][l]{Units      } \n";
  printf "\\makebox[.7 in][l]{Dims       } \n";
  printf "\\makebox[.7 in][l]{Vert Loc   } \n";
  printf "\\makebox[4. in][l]{Long Name  } \n";
  printf "} \n \n";
}

sub beg_item {
  if($initem){
    # short name
#     if ($shname eq " "){
#       print "ERROR";
#       exit;
#     }
    if ($intv){
      print "\$\\overline{\\rm $shname}\$ \&";
    }
    else{
      print "$shname \&";
    }

    # type (IM/EX/IN)
    if ($imexin ne " "){print "$imexin \&";}

    # units
    if($units ne " "){print "$units \&";}
    else{print "\&";}

    # dims
    if($dims ne " "){
      if($dims eq 'GEOS\_DIMSHORZONLY') {print "xy \&";}
      if($dims eq 'GEOS\_DIMSHORZVERT') {print "xyz \&";}
      if($dims eq 'GEOS\_DIMSVERTONLY') {print "z \&";}
      if($dims eq 'GEOS\_DIMSTILEONLY') {print "tile \&";}
      if($dims eq 'GEOS\_DIMSTILETILE') {print "TileTile \&";}
      if($dims eq 'MAPL\_DIMSHORZONLY') {print "xy \&";}
      if($dims eq 'MAPL\_DIMSHORZVERT') {print "xyz \&";}
      if($dims eq 'MAPL\_DIMSVERTONLY') {print "z \&";}
      if($dims eq 'MAPL\_DIMSTILEONLY') {print "tile \&";}
      if($dims eq 'MAPL\_DIMSTILETILE') {print "TileTile \&";}
    }
    else{print "\&";}

    # vlocation
    if($locs ne " ") {
      if($locs eq 'GEOS\_VLOCATIONCENTER') {print "Center \&";}
      if($locs eq 'GEOS\_VLOCATIONEDGE'  ) {print "Edge   \&";}
      if($locs eq 'GEOS\_VLOCATIONNONE'  ) {print "None   \&";}
      if($locs eq 'MAPL\_VLOCATIONCENTER') {print "Center \&";}
      if($locs eq 'MAPL\_VLOCATIONEDGE'  ) {print "Edge   \&";}
      if($locs eq 'MAPL\_VLOCATIONNONE'  ) {print "None   \&";}
    }
    else{print "\&";}

    # # child id
    # if($child ne " ") {
    #   printf "\\makebox[4 in][l]{Promoted from child %s}\\newline\n", $child;
    # }
    # else{print "\&";}

    # long name
    if($lnname ne " ") {
      printf "$lnname \\\\";
    }
    else{print "\\\\";}
  }

  $initem=1;
  $shname =  " ";
  $lnname =  " ";
  $units  =  " ";
  $dims   =  " ";
  $child  =  " ";
  $locs   =  " ";
  $imexin =  " ";
  $intv=0;
}


sub prc_units {
  s/\+1//g;
  s/([a-zA-Z])\+([1-9][0-9]*)/{\1}\$^{\2}\$/g;
  s/\-([1-9][0-9]*)/\$^{-\1}\$/g;
}

sub clean {
  # clean value
  s/_/\\_/g;
  s/\'//g;
  s/\"//g;
  s/,//g;
  s/&//g;
}

sub prc_item {
  # Attribute name is the first field
  $name = uc($Fld[1]);
  @value=@Fld;
  shift(@value);
  shift(@value);

  # units
  $_ = join(' ', @value); &clean();
  if($name eq "UNITS"     ){ &prc_units();}
  if($name eq "UNITS"     ){ $units  =  $_;}

  if($name ne "UNITS"     ){ s/ //g;}

  # rest of the fields
  $_ = $Fld[3]; &clean();
  if($name eq "CHILD_ID"  ){ $child  =  $_;}
  if($name eq "SHORT_NAME"){ $shname =  $_;} #print $shname; print "shname";}
  if($name eq "LONG_NAME" ){ s/\_/ /g; $lnname =  $_;}
  if($name eq "DIMS"      ){ $dims   =  uc($_);}
  if($name eq "VLOCATION" ){ $locs   =  uc($_);}
  if($name eq "AVERAGING_INTERVAL" ){ $intv = 1;}
}


sub prnt_rsrcs{
  # name
  if($rsrc_name ne " ") {print "$rsrc_name \&";}
  else{
    print "no name!";
    exit 0;
  }

  # description
  if($description ne " ") {print "$description \&";}
  else{print "\&";}

  # unit
  if($unit ne " ") {print "$unit \&";}
  else{print "\&";}

  # default
  if($default ne " "){print "$default \\\\";}
  else{print "\\\\";}

  $rsrc_name = " ";
  $description = " ";
  $unit = " ";
  $default = " ";
}


sub prc_rsrcs_1{
  $unit = " ";
  $description = " ";

  @value = @Fld;
  if($value[2] eq "!RESOURCE_ITEM:") {shift(@value);}

  $_ = join(' ', @value);
  @value = split(':', $_);

  $_ = $value[2];
  &prc_units();
  $unit = $_;

  $description = $value[4];
  $description =~ s/^\s+//;  # ltrim
  $description =~ s/\s+$//;  # rtrim
}


sub prc_rsrcs_2{
  $rsrc_name =  " ";
  $default = " ";

  # get rsrc name and its default value
  $_ = split(',', $_);

  # trim $_[3]
  $_[3] =~ s/^\s+//;  # ltrim
  $_[3] =~ s/\s+$//;  # rtrim
  if(lc substr($_[3],1,5) eq "label"){
    @namesplt = split('=',$_[3]);
    $rsrc_name = $namesplt[2];
  }
  else{$rsrc_name = $_[3];}
  # replace _ by \_
  $rsrc_name =~ s/_/\\_/g;

  if($_[4]){
    @defsplt = split('=',$_[4]);
    $defsplt[1] =~ s/^\s+//;  # ltrim
    $defsplt[1] =~ s/\s+$//;  # rtrim
    if($defsplt[1] eq "default"){$default = $defsplt[2];}
  }
  # replace _ by \_
  $default =~ s/_/\\_/g;  
}

sub prc_resource1 {
  @value=@Fld;
  shift(@value);
  shift(@value);
  $_ = join(' ', @value);

  @value = split(':', $_);

  $_ = $value[1];
  &prc_units();
  $units = $_;
  $comment = $value[3];

  $in_resource=1;
}

sub prc_resource2 {
  @Tmp = split('=',$Fld[3]);
  $_ = $Tmp[$#Tmp];
  s/\'//g;
  s/\"//g;
  s/ //g;
  s/_/\\_/g;
  $name=$_;

  $default = "none";
  if($#Fld >= 4) {
    @Tmp = split('=',$Fld[4]);
    if(uc($Tmp[1]) ne "RC") {
      $_ = $Tmp[$#Tmp];
      s/ //g;
      s/_/\\_/g;
      $default = $_;}
  }
  printf "\\makebox[1.0 in][l]{\\bf            %s } \n", $name;
  printf "\\makebox[3.5 in][l]{\\bf            %s } \n", $comment;
  printf "\\makebox[1.0 in][l]{\\bf            %s } \n", $units;
  printf "\\makebox[1.0 in][l]{\\bf            %s } \n", $default;
  printf "\\newline \n";

  $in_resource = 0;
}
