#!/usr/bin/env python3 # IRPF90 is a Fortran90 preprocessor written in Python for programming using # the Implicit Reference to Parameters (IRP) method. # Copyright (C) 2009 Anthony SCEMAMA # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # Anthony Scemama # LCPQ - IRSAMC - CNRS # Universite Paul Sabatier # 118, route de Narbonne # 31062 Toulouse Cedex 4 # scemama@irsamc.ups-tlse.fr import getopt, sys from version import version import re description = "IRPF90 Fortran preprocessor." options = {} options['a'] = [ 'assert' , 'Activates ASSERT statements. If absent, remove ASSERT statements.', 0 ] options['c'] = [ 'codelet' , 'entity:NMAX or entity:precondition:NMAX : Generate a codelet to profile a provider running NMAX times', 1 ] options['C'] = [ 'coarray' , 'All providers are coarrays', 0 ] options['d'] = [ 'debug' , 'Activates debug. The name of the current subroutine/function/provider will be printed on the standard output when entering or exiting a routine, as well as the CPU time passed inside the routine.', 0 ] options['D'] = [ 'define' , 'Defines a variable identified by the IRP_IF statements.', 1 ] options['g'] = [ 'profile' , 'Activates profiling of the code.', 0 ] options['h'] = [ 'help' , 'Print this help', 0 ] options['I'] = [ 'include' , 'Include directory', 1 ] options['j'] = [ 'ninja' , 'Use Ninja instead of make', 0 ] options['i'] = [ 'init' , 'Initialize current directory. Creates a default Makefile and the temporary working directories.', 0 ] options['l'] = [ 'align' , 'Align arrays using compiler directives and sets the $IRP_ALIGN variable. For example, --align=32 aligns all arrays on a 32 byte boundary.', 1 ] options['m'] = [ 'memory' , 'Print memory allocations/deallocations.', 0 ] options['n'] = [ 'inline' , ' : Force inlining of providers or builders', 1 ] options['o'] = [ 'checkopt' , 'Shows where optimization may be required', 0 ] options['p'] = [ 'preprocess' , 'Prints a preprocessed file to standard output. Useful for debugging files containing shell scripts.', 1 ] options['r'] = [ 'no_directives', 'Ignore all compiler directives !DEC$ and !DIR$', 0 ] options['s'] = [ 'substitute' , 'Substitute values in do loops for generating specific optimized code.', 1 ] options['t'] = [ 'touch' , 'Display which entities are touched when touching the variable given as an argument.', 1 ] options['v'] = [ 'version' , 'Prints version of irpf90', 0 ] options['w'] = [ 'warnings' , 'Activate Warnings', 0 ] options['z'] = [ 'openmp' , 'Activate for OpenMP code', 0 ] class CommandLine(object): def __init__(self): global options self._opts = None self.argv = list(sys.argv) self.executable_name = self.argv[0] def defined(self): if '_defined' not in self.__dict__: self._defined = [] for o,a in self.opts: if o in [ "-D", '--'+options['D'][0] ]: self._defined.append(a) return self._defined defined = property(fget=defined) def include_dir(self): if '_include_dir' not in self.__dict__: self._include_dir = [] for o,a in self.opts: if o in [ "-I", '--'+options['I'][0] ]: if len(a) < 1: print("Error: -I option needs a directory") if a[-1] != '/': a = a+'/' self._include_dir.append(a) return self._include_dir include_dir = property(fget=include_dir) def inline(self): if '_inline' not in self.__dict__: self._inline = "" for o,a in self.opts: if o in [ "-n", '--'+options['n'][0] ]: self._inline = a break return self._inline inline = property(fget=inline) def substituted(self): if '_substituted' not in self.__dict__: self._substituted = {} for o,a in self.opts: if o in [ "-s", '--'+options['s'][0] ]: k, v = a.split(':') v_re = re.compile(r"(\W)(%s)(\W.*$|$)"%k.strip()) self._substituted[k] = [v, v_re] return self._substituted substituted = property(fget=substituted) def codelet(self): if '_codelet' not in self.__dict__: self._codelet = [] for o,a in self.opts: if o in [ "-c", '--'+options['c'][0] ]: buffer = a.split(':') filename = 'codelet_'+buffer[0]+'.irp.f' if len(buffer) == 2: self._codelet = [buffer[0], int(buffer[1]), None, filename] elif len(buffer) == 3: self._codelet = [buffer[0], int(buffer[2]), buffer[1], filename] else: print(""" Error in codelet definition. Use: --codelet=provider:NMAX or --codelet=provider:precondition:NMAX """) sys.exit(1) return self._codelet codelet = property(fget=codelet) def preprocessed(self): if '_preprocessed' not in self.__dict__: self._preprocessed = [] for o,a in self.opts: if o in [ "-p", '--'+options['p'][0] ]: self._preprocessed.append(a) return self._preprocessed preprocessed = property(fget=preprocessed) def touched(self): if '_touched' not in self.__dict__: self._touched = [] for o,a in self.opts: if o in [ "-t", '--'+options['t'][0] ]: self._touched.append(a.lower()) return self._touched touched = property(fget=touched) def align(self): if '_align' not in self.__dict__: self._align = '1' for o,a in self.opts: if o in [ "-l", '--'+options['l'][0] ]: self._align = a return self._align align = property(fget=align) def coarray(self): if '_coarray' not in self.__dict__: self._coarray = False for o,a in self.opts: if o in [ "-C", '--'+options['C'][0] ]: self._coarray = True return self._coarray coarray = property(fget=coarray) def warnings(self): if '_warnings' not in self.__dict__: self._warnings= False for o,a in self.opts: if o in [ "-w", '--'+options['w'][0] ]: self._warnings= True return self._warnings do_warnings = property(fget=warnings) def openmp(self): if '_openmp' not in self.__dict__: self._openmp = False for o,a in self.opts: if o in [ "-z", '--'+options['z'][0] ]: self._openmp = True return self._openmp do_openmp = property(fget=openmp) def ninja(self): if '_ninja' not in self.__dict__: self._ninja = False for o,a in self.opts: if o in [ "-j", '--'+options['j'][0] ]: self._ninja = True return self._ninja do_ninja = property(fget=ninja) def directives(self): if '_directives' not in self.__dict__: self._directives = True for o,a in self.opts: if o in [ "-r", '--'+options['r'][0] ]: self._directives = False return self._directives directives = property(fget=directives) def usage(self): t = """ $EXE - $DESCR Usage: $EXE [OPTION] Options: """ t = t.replace("$EXE",self.executable_name) t = t.replace("$DESCR",description) print(t) print_options() print("") print("Version : ", version) print("") def opts(self): if self._opts is None: optlist = ["",[]] for o in options: b = [o]+options[o] if b[3] == 1: b[0] = b[0]+":" b[1] = b[1]+"=" optlist[0] += b[0] optlist[1] += [b[1]] try: self._opts, args = getopt.getopt(self.argv[1:], optlist[0], optlist[1]) except getopt.GetoptError as err: # print help information and exit: self.usage() print(str(err)) # will print something like "option -a not recognized" sys.exit(2) return self._opts opts = property(fget=opts) t = """ def do_$LONG(self): if '_do_$LONG' not in self.__dict__: self._do_$LONG = False for o,a in self.opts: if o in ("-$SHORT", "--$LONG"): self._do_$LONG = True break return self._do_$LONG do_$LONG = property(fget=do_$LONG) """ for short_opt in options: long_opt = options[short_opt][0] exec(t.replace("$LONG",long_opt).replace("$SHORT",short_opt)) #in locals() def do_run(self): if '_do_run' not in self.__dict__: self._do_run = not ( \ self.do_version or \ self.do_help or \ self.do_preprocess or \ self.do_touch or \ self.do_init ) return self._do_run do_run = property(fget=do_run) command_line = CommandLine() def print_options(): keys = list(options.keys()) keys.sort() import subprocess for k in keys: description = options[k][1] p1 = subprocess.Popen(["fold", "-s", "-w", "40"],stdout=subprocess.PIPE,stdin=subprocess.PIPE, encoding='utf8') description = p1.communicate(description)[0] description = description.replace('\n','\n'.ljust(27)) print(("-%s, --%s"%(k,options[k][0])).ljust(25), description+'\n') print("\n") if __name__ == '__main__': print_options()