Commit e37c9c60 authored by Momme Butenschoen's avatar Momme Butenschoen

Ensured compability for python 2.6 upwards and python 3 in one file, specific...

Ensured compability for python 2.6 upwards and python 3 in one file, specific python3 script is therfore obsolete.
parent 36a69965
#!/bin/bash
#
#BOP
# !DESCRIPTION:
# Convert to python 3. The script converts the file in the file
# argument to python. It creates the converted file in th py3 sub-folder.
# Additionaly the shell invokation will be changed to
# explicitly invoke python3.
#EOP
file=PyProTex.py
mkdir -p py3
2to3 -p -n -w -o py3 $file
# make the shell invokation python3 instead of python
sed -i "s/\#\!\/usr\/bin\/python\b/\#\!\/usr\/bin\/python3/" py3/$file
......@@ -340,7 +340,7 @@ class PyProTex:
try:
fid=open(self.InputFile,'r')
except:
raise RunTimeError,"Unable to open {}".format(self.InputFile)
raise RunTimeError("Unable to open {}".format(self.InputFile))
# Print page header
# -----------------
......@@ -1042,7 +1042,7 @@ class PyProTex:
def check_error(self,flag,tag):
"""Raise prologue status error flag is False."""
if not flag:
raise RunTimeError,"ProTeX: invalid prologue, missing {}: in {}".format(tag,self.name_is)
raise RunTimeError("ProTeX: invalid prologue, missing {}: in {}".format(tag,self.name_is))
def hed_item(self,):
self.Str+="\\bigskip\n{{ \\bf \sf \n"
......
#!/usr/bin/python3
#
# Copyright 2014 Plymouth Marine Laboratory
#
# This file is part of the SSB-ERSEM library.
#
# SSB-ERSEM is free software: you can redistribute it and/or modify it
# under the terms of the Lesser GNU General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# SSB-ERSEM 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 Lesser
# NU General Public License for more details.
# You should have received a copy of the Lesser GNU General Public License
# along with SSB-ERSEM. If not, see <http://www.gnu.org/licenses/>.
#
# Address:
# Plymouth Marine Laboratory
# Prospect Place, The Hoe
# Plymouth, PL1 3DH, UK
#
# Email:
# ssm@pml.ac.uk
#
# $Id: PyProTex,v14.10 $
#
#BOP
#
# !ROUTINE: PyProTex - Translates DAO Prologues to LaTeX
#
# !INTERFACE:
# PyProTex.py [-hbgACFS] ] [+-nlsxf] src_file[s]
#
# !DESCRIPTION:
# This as a python version of the protex perl tool.
# The perl tool was developed at the Goddard Space Flight Center
# by Arlindo Da Silva, Will Sawyer, and others under no specific
# license.
# The python version was created by Momme Butenschoen at the
# Plymouth Marine Laboratory
# The adaptation is based on the version 2.0 as downloaded from
# http://acmg.seas.harvard.edu/geos/wiki\_docs/protex/protex.tar.gz
#
# Python class to produce a \LaTeX compatible document
# from a DAO Fortran source code with standard Pro\TeX
# prologues.
# By default, output is directed to stdout.
#
# \noindent
# {\bf Command Line Switches:} \vspace{0.2cm}
#
# \begin{center}
# \begin{tabular}{|c|l|} \hline \hline
# -h & Human mode: descriptions only, no code information \\
# & implies -l and -s \\ \hline
# -b & Bare mode, meaning no preamble, etc. \\ \hline
# -i & internal mode: omit prologues marked !BOPI \\ \hline
# -g & Use GEOS style. Implies -n unless overidden. \\ hline
# +/-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
# none & Print help message \\ \hline \hline
# \end{tabular}
# \end{center}
#
# The options can appear in any order. The options -g, -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
#
# !AUTHOR:
# ! Momme Butensch\xf6n
#
# !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.
# 31Mar2014 M. Butenschoen Changed heading style to use sections for modules.
# 22Oct2014 M. Butenschoen Conversion to python with consistent changes
# to use part for top-level and section for 2nd
# level. Introduced -d option.
# 22Oct2014 M. Butenschoen -h option produces human-readable
# documentation with desciptions only omitting
# any iformation on the code.
# Help string is now obtained by calling without# argument
#
#EOP
#----------------------------------------------------------------------------
#BOC
from sys import argv,stderr,stdout
from time import localtime,strftime
from re import sub
from re import split as rsplit
#----------------------------------------------------------------------
class PyProTex:
def __init__(self,Choices):
"""Initiate class object with all options and settings.
Choices: PyProTex options as list of input strings in."""
#Option Classes
self.GlobOptions=["h","b","g"]
self.LangOptions=["A","C","F","S"]
self.SwOptions=["f","l","i","n","s","x"]
self.RegOptions=self.GlobOptions+self.LangOptions
#Default Options
self.opt={}
self.opt["h"]=0
self.opt["b"]=0
self.opt["g"]=0
self.opt["f"]=0
self.opt["l"]=0
self.opt["i"]=0
self.opt["n"]=0
self.opt["s"]=0
self.opt["x"]=0
self.opt["A"]=0
self.opt["C"]=0
self.opt["S"]=0
self.opt["F"]=1 #Default file format is fortran
# Optional Prologue Keywords
# --------------------------
self.keys = [ "!INTERFACE:",
"!USES:",
"!PUBLIC TYPES:",
"!PRIVATE TYPES:",
"!PUBLIC MEMBER FUNCTIONS:",
"!PRIVATE MEMBER FUNCTIONS:",
"!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
# ----------------------------
self.intro = 0 # doing introduction?
self.prologue = 0 # doing prologue?
self.first = 1 # first prologue?
self.source = 0 # source code mode?
self.verb = 0 # verbatim mode?
self.tpage = 0 # title page?
self.begdoc = 0 # has \begin{document} been written?
self.descr_verb = 0 # descriptions in LaTeX mode
self.inspec = 0 # are we processing state specs (GEOS)
self.initem = 0 # are we processing state specs item (GEOS)
self.skip = 0 # don't skip
# Set for global options
# -----------------------
for choice in Choices:
option = self.CheckOpts (choice,)
if option:
rc=self.GetOpts(choice,self.GlobOptions)
else:
print("Invalid option string: {}".format(choice),file=stderr)
self.print_help(dest=stderr)
# g option requires n option
# ---------------------
if self.opt["g"]: self.opt["n"]=1
# Set for non-global options
# -----------------------
for choice in Choices:
option = self.CheckOpts(choice,quiet_mode=1)+1
if option:
self.GetOpts(choice,self.SwOptions)
self.SetLanguage(choice)
# d option implies s option and no l option
# ---------------------
if self.opt["g"]:
self.opt["s"]=1
self.opt["l"]=0
# Determine the type of code, set corresponding search strings
# ------------------------------------------------------------
# DEFAULT: FORTRAN
if self.opt["A"]: # ADA
self.comment_string = '--'
self.boi_string = '--BOI'
self.eoi_string = '--EOI'
self.bop_string = '--BOP'
self.eop_string = '--EOP'
self.bopi_string = '--BOPI'
self.eopi_string = '--EOPI'
self.boc_string = '--BOC'
self.eoc_string = '--EOC'
self.boe_string = '--BOE'
self.eoe_string = '--EOE'
elif self.opt["C"]: # C
self.comment_string = '//'
self.boi_string = '//BOI'
self.eoi_string = '//EOI'
self.bop_string = '//BOP'
self.eop_string = '//EOP'
self.bopi_string = '//BOPI'
self.eopi_string = '//EOPI'
self.boc_string = '//BOC'
self.eoc_string = '//EOC'
self.boe_string = '//BOE'
self.eoe_string = '//EOE'
elif self.opt["S"]: # Script
self.comment_string = '#'
self.boi_string = '#BOI'
self.eoi_string = '#EOI'
self.bop_string = '#BOP'
self.eop_string = '#EOP'
self.bopi_string = '#BOPI'
self.eopi_string = '#EOPI'
self.boc_string = '#BOC'
self.eoc_string = '#EOC'
self.boe_string = '#BOE'
self.eoe_string = '#EOE'
else:
self.comment_string = '!'
self.boi_string = '!BOI'
self.eoi_string = '!EOI'
self.bop_string = '!BOP'
self.eop_string = '!EOP'
self.bopi_string = '!BOPI'
self.eopi_string = '!EOPI'
self.boc_string = '!BOC'
self.eoc_string = '!EOC'
self.boe_string = '!BOE'
self.eoe_string = '!EOE'
# Set date
# --------
self.Date = strftime("%a %b %d %T %Z",localtime())
# Initial LaTeX stuff
# -------------------
self.Str=""
self.Str+=self.print_notice() # auto-generation warning
self.Str+=self.print_preamble() # \documentclass, text dimensions, etc.
self.Str+=self.print_macros() # short-hand LaTeX macros
def __call__(self,files):
"""Process all files in argument list, line by line,
compiling the documentation Tex source into the self.Str string
attribute.
files: list of input files"""
# If no file arguments are present print help string and exit
# ---------------------
if not files: self.print_help()
for f in files:
# Set file name parameters
# ------------------------
self.InputFile = f
self.all_path_components = self.InputFile.split("/")
self.FileBaseName = self.all_path_components[-1].replace("_","\_")
# Open current file
# -----------------
try:
fid=open(self.InputFile,'r')
except:
raise RunTimeError("Unable to open {}".format(self.InputFile))
# Print page header
# -----------------
if self.opt["g"]:
self.shname = " "
self.lnname = " "
self.units = " "
self.dims = " "
self.locs = " "
else:
self.Str+="\n\markboth{{Left}}{{Source File: {}, Date: {}}}\n\n".format(self.FileBaseName,self.Date)
# Process input file line by line:
# ---------------------------------------------------------
Lines=fid.readlines()
for line in Lines:
Record=line.rstrip("\n") #strip record separator
self._processRecord(Record)
#close document
self.Str+="\n"
if self.source: self.do_eoc()
self.Str+="\n%...............................................................\n"
# see comment above where these are originally set.
#print "\\setlength{\\parskip}{\\oldparskip}";
#print "\\setlength{\\parindent}{\\oldparindent}";
#print "\\setlength{\\baselineskip}{\\oldbaselineskip}";
if not self.opt["b"]:
self.Str+="\n\\end{document}"
def _processRecord(self,Rec):
"""Process a record according to its context."""
Fld=Rec.split(None,9999) #split line by whitespace
if len(Fld)==0: return #skip empty lines
if Fld[0] == "!QUOTE:" or (self.opt["g"] and len(Fld)>1 and Fld[1] == "!!GEOS!!"):
self.Str+="\n"
for f in Fld[1:]:
self.Str+="{} ".format(f)
return
# Start the intro at new line and switch intro on
# -------------------------------------------
if Fld[0] == self.boi_string:
self.Str+="\n"
self.intro = 1
return
# If within intro and title is given print title and switch title page on
# -------------------------------------------
if len(Fld)>1 and Fld[1] == '!TITLE:':
if self.intro:
title = "{}".format(" ".join(*Fld[2]))
self.tpage = 1
return
# If within intro and author is given print title and switch title page on
# -------------------------------------------
if len(Fld)>1 and Fld[1] == '!AUTHOR:':
if self.intro:
author = Fld[2]
self.tpage = 1
return
# If within intro and affiliation is given print title and set title page
# -------------------------------------------
if len(Fld)>1 and Fld[1] == '!AFFILIATION:':
if self.intro:
affiliation = "{}".format(" ".join(*Fld[2]))
self.tpage = 1
return
# If within intro and date is given print date and switch title page on
# -------------------------------------------
if len(Fld)>1 and Fld[1] == '!DATE:':
if self.intro:
self.date="{}".format(" ".join(*Fld[2]))
self.tpage = 1
return
# If within intro and introduction is given print introduction header and switch title page on
# -------------------------------------------
if len(Fld)>1 and Fld[1] == '!INTRODUCTION:':
if self.intro:
self.self,do_beg()
self.Str+=" \n"
self.Str+="%..............................................\n"
if self.opt["g"]:
self.Str+="\part{{\Large {} }}\n".format(" ".join(*Fld[2:]))
else:
self.Str+="\part{{ {} }}\n".format(" ".join(*Fld[2:]))
return
# close introduction and switch off intro
# -------------------
if Fld[0] == self.eoi_string:
self.Str+=" \n"
self.Str+="%/////////////////////////////////////////////////////////////\n"
self.Str+="\\newpage\n"
self.intro = 0
return
# Beginning of prologue : print header and
# switch on prologue
# switch off verb, source and inspec
# ---------------------
if Fld[0] == self.bop_string:
self.skip=0
if self.source: self.do_eoc()
self.Str+=" \n"
self.Str+="%/////////////////////////////////////////////////////////////\n"
self.do_beg()
if self.first or self.opt["n"]:
if not (self.opt["b"] or self.opt["g"]):
self.Str+="\part{Routine/Function Prologues} \label{app:ProLogues}\n"
else:
self.Str+=" \n"
self.Str+="\mbox{}\hrulefill\\ \n"
self.Str+=" \n"
self.first = 0
self.prologue = 1
self.verb = 0
self.source = 0
self.inspec = 0
self.set_missing() # initialise keyword check
return
# Beginning of internal prologue (switchable)
# ------------------------------
if Fld[0] == self.bopi_string:
if self.opt["i"]:
self.prologue = 0 #No internal prologue with i option
else:
if self.source: self.do_eoc() #if source is still active close it and close verbatim
self.Str+=" \n"
self.Str+="%/////////////////////////////////////////////////////////////\n"
self.do_beg()
if self.first or self.opt["n"]:
if not (self.opt["b"] or self.opt["g"]):
self.Str+="\part{Routine/Function Prologues} \label{{app:ProLogues}}\n"
else:
self.Str+=" \n"
self.Str+="\mbox{}\hrulefill\\\ \n"
self.Str+=" \n"
self.first = 0
self.prologue = 1
self.verb = 0
self.source = 0
self.inspec = 0
self.set_missing() # initialise keyword check
return
# A new subroutine/function
# -------------------------
if len(Fld)>1 and Fld[1] == '!ROUTINE:':
if self.prologue:
self.name_is = " ".join(Fld[2:])
name=self.name_is.replace("_","\_")# Replace "_" with "\_"
if self.opt["n"] and not self.first: self.Str+="\n\\newpage\n"
if self.opt["f"]:
self.Str+="\n\\section{{{} }}\n\n".format(name)
else:
self.Str+="\n\section{{{} (Source: {})}}\n\n".format(name, self.FileBaseName)
self.have_name = 1
self.first = 0
return
# A new Module
# ------------
if len(Fld)>1 and Fld[1] == '!MODULE:':
if self.prologue:
self.name_is = " ".join(Fld[2:])
name=self.name_is.replace("_","\_")# Replace "_" with "\_"
if self.opt["n"] and not self.first: self.Str+="\n\\newpage\n"
if self.opt["g"]:
self.Str+="\n\section [{0}] {{Module {0} }}\n\n".format(name)
else:
if self.opt["f"]:
self.Str+="\n\section{{Module: {} }}\n\n".format(name)
else:
self.Str+="\n\section{{Module: {} (Source: {})}}\n\n".format(name,self.FileBaseName)
self.have_name = 1
self.have_intf = 1 # fake, does not need one.
self.first = 0
return
# A new include file
# ------------------
if len(Fld)>1 and Fld[1] == '!INCLUDE:':
if self.prologue:
self.name_is = " ".join(Fld[2:])
name=self.name_is.replace("_","\_")# Replace "_" with "\_"
if self.opt["n"] and not self.first: self.Str+="\n\\newpage\n"
if self.opt["f"]:
self.Str+="\n\subsection{{Include File {} }}\n\n".format(name)
else:
self.Str+="\n\subsection{{Include File {} (Source: {})}}\n\n".format(name,self.FileBaseName)
self.have_name = 1
self.have_intf = 1 # fake, does not need one.
self.first = 0
return
# A new INTERNAL subroutine/function
# ----------------------------------
if len(Fld)>1 and Fld[1] == '!IROUTINE:':
if self.prologue:
self.name_is = " ".join(Fld[2:])
name=self.name_is.replace("_","\_")# Replace "_" with "\_"
words = name.split()
if self.opt["n"] and not self.first: self.Str+="\n\\newpage\n"
if self.opt["g"]:
self.Str+="\n\subsection {{{}}}\n\n".format(name)
else:
self.Str+="\n\subsection {{{}}}\n\n".format(name)
self.have_name = 1
return
# A new CONTAINED subroutine/function
# ----------------------------------
if len(Fld)>1 and Fld[1] == '!CROUTINE:': # Contained routine
if self.prologue:
self.name_is = " ".join(Fld[2:])
name=self.name_is.replace("_","\_")# Replace "_" with "\_"
words = name.split()
self.Str+="\n\subsection{{{}}}\n\n".format(name)
self.have_name = 1
return
# A new CLASS
# ------------
if len(Fld)>1 and Fld[1] == '!CLASS:':
if self.prologue:
self.name_is = " ".join(Fld[2:])
name=self.name_is.replace("_","\_")# Replace "_" with "\_"
if self.opt["n"] and not first: self.Str+="\n\\newpage\n"
if self.opt["f"]:
self.Str+="\n\section{{C++: Class Interface {} }}\n\n".format( self.name_is)
else:
self.Str+="\n\section{{C++: Class Interface {} (Source: {})}}\n\n".format(self.name_is,self.FileBaseName)
self.have_name = 1
self.have_intf = 1 # fake, does not need one.
self.first = 0
return
# A new Method
# -------------------------
if len(Fld)>1 and Fld[1] == '!METHOD:':
if self.prologue:
self.name_is = " ".join(Fld[2:])
name=self.name_is.replace("_","\_")# Replace "_" with "\_"
if self.opt["n"] and not self.first:
self.Str+="\n\\newpage\n"
if self.opt["f"]:
self.Str+="\n\subsection{{{}}}\n\n".format(name)
else:
self.Str+="\n\subsection{{{} (Source: {})}}\n\n".format(name,self.FileBaseName)
self.have_name = 1
self.first = 0
return
# A new function
# -------------------------
if len(Fld)>1 and Fld[1] == '!FUNCTION:':
if self.prologue:
self.name_is = " ".join(Fld[2:])
name=self.name_is.replace("_","\_")# Replace "_" with "\_"
if self.opt["n"] and not self.first: self.Str+="\n\\newpage\n"
if self.opt["f"]:
self.Str+="\n\subsection{{{}}}\n\n".format(names)
else:
self.Str+="\n\subsection{{{}(Source: {})}}\n\n".format(name,self.FileBaseName)
self.have_name = 1
self.first = 0
return
# Description: what follows will be regular LaTeX (no verbatim)
# -------------------------------------------------------------
if "!DESCRIPTION:" in Rec:
if self.prologue:
self.skip=0
# if still active close verbatim and switch off
if self.verb:
self.Str+="\n\end{verbatim}"
self.Str+="\n{{\sf \\bf DESCRIPTION:\\\ }}\n\n"
self.verb = 0
if self.opt["x"]: #description not latex
self.Str+="\n\\begin{verbatim} "
self.verb = 1
self.descr_verb = 1
else:
for f in Fld[2:]:
self.Str+="\n{} ".format(f)
# self.Str+=" "
self.have_desc = 1
return
# Handle optional keywords (these will appear as verbatim)
# --------------------------------------------------------
if self.prologue:
for key in self.keys:
if key in Rec:
if self.opt['h']:
self.skip=1
return
else:
if self.verb: #switch off verbatim to create heading
self.Str+="\n\end{verbatim}\n"
self.verb = 0
k = "{}".format(key)
ln = len(k)
Rec=key