├── .gitignore
├── .travis.yml
├── LICENSE
├── LICENSE.gpl
├── Makefile
├── README.md
├── buildtests.sh
├── deploy.sh
├── doc.md
├── fobos
├── get_deps
├── key.enc
├── logger_example.f90
├── media
└── sample-output.png
├── src
└── logging.f90
└── tests
├── logging_tests.pf
└── testSuites.inc
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files
2 | *.slo
3 | *.lo
4 | *.o
5 | *.obj
6 |
7 | # Precompiled Headers
8 | *.gch
9 | *.pch
10 |
11 | # Compiled Dynamic libraries
12 | *.so
13 | *.dylib
14 | *.dll
15 |
16 | # Fortran module files
17 | *.mod
18 | *.smod
19 |
20 | # Compiled Static libraries
21 | *.lai
22 | *.la
23 | *.a
24 | *.lib
25 |
26 | # Executables
27 | *.exe
28 | *.out
29 | *.app
30 |
31 | *.d
32 | *~
33 | *.gcda
34 | *.gcno
35 | *.gcov
36 | tests.x
37 |
38 | doc/
39 | build/
40 | tests_build/
41 | outputfile.log
42 | randon_file_name*.txt
43 | tests/driver.F90
44 | tests/logging_tests.F90
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 |
3 | language: c
4 |
5 | os:
6 | - linux
7 |
8 | env:
9 | global:
10 | - GH_REF: github.com/Fortran-FOSS-Programmers/flogging
11 | - ENCRYPTION_LABEL: "59525d4507cc"
12 | - COMMIT_AUTHOR_EMAIL: "cmacmackin@gmail.com"
13 |
14 | addons:
15 | apt:
16 | sources:
17 | - ubuntu-toolchain-r-test
18 | packages:
19 | - gcc-5
20 | - gfortran-5
21 | - python-pip
22 | - python-virtualenv
23 | - graphviz
24 |
25 | cache:
26 | apt: true
27 | pip: true
28 | directories:
29 | - $HOME/.cache/pip
30 | - $HOME/.local
31 |
32 | install:
33 | - export LOCAL_ROOT=$HOME/.local
34 | - export LOCAL_BIN=$LOCAL_ROOT/bin
35 | - export LOCAL_LIB=$LOCAL_ROOT/lib
36 | - export LOCAL_INC=$LOCAL_ROOT/include
37 | - export PATH=$LOCAL_BIN:/usr/local/bin:/usr/bin:$PATH
38 | - mkdir -p $LOCAL_ROOT
39 | - mkdir -p $LOCAL_BIN
40 | - mkdir -p $LOCAL_LIB
41 | - mkdir -p $LOCAL_INC
42 | - if [ ! -d $HOME/venv ]; then virtualenv $HOME/venv; fi
43 | - if [ -e $LOCAL_BIN/gcov ]; then rm $LOCAL_BIN/gcov; fi
44 | - ln -s `which gcov-5` $LOCAL_BIN/gcov
45 | - if [ -e $LOCAL_BIN/gfortran ]; then rm $LOCAL_BIN/gfortran; fi
46 | - ln -s `which gfortran-5` $LOCAL_BIN/gfortran
47 | # - source $HOME/venv/bin/activate
48 | - pip install --user --upgrade graphviz
49 | - pip install --user --upgrade ford && ford --version
50 | - pip install --user --upgrade ghp-import
51 | - pip install --user --upgrade codecov
52 | - pip install --user --upgrade FoBiS.py
53 | - pip install --user --upgrade pygooglechart
54 | - |
55 | if [ ! -d $HOME/pFUnit ]; then
56 | git clone git://git.code.sf.net/p/pfunit/code $HOME/pFUnit
57 | cd $HOME/pFUnit
58 | else
59 | cd $HOME/pFUnit
60 | git pull
61 | fi
62 | - export F90_VENDOR=GNU
63 | - export F90=gfortran-5
64 | - make tests
65 | - make install INSTALL_DIR=$LOCAL_BIN/pfunit-serial
66 | - export PFUNIT=$LOCAL_BIN/pfunit-serial
67 | - cd -
68 | - |
69 | if [ ! -d $HOME/face ]; then
70 | git clone https://github.com/szaghi/FACE $HOME/face
71 | cd $HOME/face
72 | else
73 | cd $HOME/face
74 | git pull
75 | fi
76 | - FoBiS.py build -mode face-static-gnu
77 | - cp `FoBiS.py rule -mode face-static-gnu -get_output_name` $LOCAL_LIB
78 | - cp `FoBiS.py rule -mode face-static-gnu -get build_dir`/mod/face.mod $LOCAL_INC
79 | - cd -
80 |
81 | script:
82 | - ./buildtests.sh
83 |
84 | after_success:
85 | - echo "SUCCESS!"
86 | - gcov $(FoBiS.py rule -mode gnu-static -get build_dir)/$(FoBiS.py rule -mode gnu-static -get obj_dir)/*.gcno -p
87 | - codecov -X gcov
88 | - ./deploy.sh
89 |
90 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/LICENSE.gpl:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 | {one line to give the program's name and a brief idea of what it does.}
635 | Copyright (C) {year} {name of author}
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | {project} Copyright (C) {year} {fullname}
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright 2016 Christopher MacMackin
3 | #
4 | # This program is free software; you can redistribute it and/or modify
5 | # it under the terms of the GNU General Public License as published by
6 | # the Free Software Foundation; either version 3 of the License, or
7 | # (at your option) any later version.
8 | #
9 | # This program is distributed in the hope that it will be useful,
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | # GNU General Public License for more details.
13 | #
14 | # You should have received a copy of the GNU General Public License
15 | # along with this program; if not, write to the Free Software
16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17 | # MA 02110-1301, USA.
18 | #
19 |
20 | # Directories
21 | SDIR := ./src
22 | TDIR := ./tests
23 | MDIR := ./mod
24 | ODIR := ./objs
25 | PFUNIT = $(HOME)/Code/pfunit-$(F90)
26 |
27 | # Output
28 | EXEC :=
29 | TEXEC := tests.x
30 | LIB := flogging.a
31 | PREFIX := $(HOME)/.local
32 | LIBDIR := $(PREFIX)/lib
33 | INCDIR := $(PREFIX)/include
34 | BINDIR := $(PREFIX)/bin
35 |
36 | # Include paths internal to project
37 | PROJECT_INCDIRS := $(FMDIR) $(TDIR)
38 |
39 | # The compiler
40 | VENDOR ?= GNU
41 | VENDOR_ = $(shell echo $(VENDOR) | tr A-Z a-z)
42 |
43 | ifeq ($(VENDOR_),intel)
44 | F90 := ifort
45 | FCFLAGS := -O0 -g -I$(INC) -module $(MDIR) -traceback -assume realloc_lhs
46 | LDFLAGS := -O0 -g -traceback
47 | COVFLAGS :=
48 | else
49 | F90 := gfortran-6
50 | FCFLAGS := -O0 -g -fcheck=all -J$(MDIR)
51 | LDFLAGS := -O0 -g
52 | COVFLAGS := -fprofile-arcs -ftest-coverage
53 | endif
54 |
55 | FPP := fypp
56 | FPP_FLAGS := -DDEBUG -n
57 |
58 | # Include paths
59 | FCFLAGS += $(PROJECT_INCDIRS:%=-I%) -I$(INCDIR) -I/usr/include -I$(PFUNIT)/mod
60 |
61 | # Libraries for use at link-time
62 | LIBS := -L$(LIBDIR) -lface
63 | LDFLAGS += $(LIBS)
64 |
65 | # A regular expression for names of modules provided by external libraries
66 | # and which won't be contained in the module directory of this codebase
67 | EXTERNAL_MODS := ^iso_(fortran_env|c_binding)|ieee_(exceptions|arithmetic|features)|openacc|omp_lib(_kinds)?|mpi|pfunit_mod|face$$
68 |
69 | # Extensions of Fortran files, case insensitive
70 | F_EXT := f for f90 f95 f03 f08 f15
71 |
72 | # Temporary work variables
73 | _F_EXT := $(F_EXT) $(shell echo $(F_EXT) | tr a-z A-Z)
74 | null :=
75 | space := $(null) $(null)
76 | EXT_PATTERN_GREP := '.*\.\($(subst $(space),\|,$(_F_EXT))\)'
77 | EXT_PATTERN_SED := 's/([^ ]*)\.($(subst $(space),|,$(_F_EXT)))/\1.o/g;'
78 | FPP_PATTERN_GREP := '.*\.\(fpp\|FPP\)'
79 | FPP_PATTERN_SED := 's/([^ ]*)\.(fpp|FPP)/\1.o/g;'
80 |
81 | # Objects to compile
82 | OBJS := $(shell find $(SDIR) -iregex $(EXT_PATTERN_GREP) | sed -r $(EXT_PATTERN_SED))
83 | OBJS += $(shell find $(SDIR) -iregex $(FPP_PATTERN_GREP) | sed -r $(FPP_PATTERN_SED))
84 | TOBJS := $(patsubst %.pf,%.o,$(wildcard $(TDIR)/*.pf))
85 |
86 | .PRECIOUS: %.F90
87 |
88 | # "make" builds all
89 | all: all_objects tests
90 |
91 | all_objects: $(OBJS)
92 |
93 | exec: $(EXEC)
94 |
95 | $(EXEC): $(OBJS)
96 | $(F90) $^ $(LDFLAGS) -o $@
97 |
98 | install_exec: exec
99 | cp $(EXEC) $(BINDIR)
100 |
101 | tests: $(TEXEC)
102 | ./$(TEXEC)
103 |
104 | $(TEXEC): $(TOBJS) $(LIB)
105 | $(F90) -I$(PFUNIT)/include $(PFUNIT)/include/driver.F90 $(COVFLAGS) \
106 | $(FCFLAGS) $^ $(LIBS) -L$(PFUNIT)/lib -lpfunit -o $@
107 |
108 | lib: $(LIB)
109 |
110 | $(LIB): $(OBJS)
111 | $(AR) rcs $@ $^
112 |
113 | install_lib: lib
114 | cp $(LIB) $(LIBDIR)
115 | cp $(MDIR)/*.mod $(INCDIR)
116 |
117 | ifeq ($(MAKECMDGOALS),clean)
118 | else ifeq ($(MAKECMDGOALS),doc)
119 | else
120 | -include $(OBJS:.o=.d) $(TOBJS:.o=.d)
121 | endif
122 |
123 | %.d: %.pf get_deps
124 | ./get_deps $< $$\(MDIR\) "$(EXTERNAL_MODS)" $(PROJECT_INCDIRS) > $@
125 |
126 | %.d: %.fpp get_deps
127 | ./get_deps $< \$$\(MDIR\) "$(EXTERNAL_MODS)" $(PROJECT_INCDIRS) > $@
128 |
129 | %.d: %.FPP get_deps
130 | ./get_deps $< \$$\(MDIR\) "$(EXTERNAL_MODS)" $(PROJECT_INCDIRS) > $@
131 |
132 | # General rule for building Fortran files, where $(1) is the file extension
133 | define fortran_rule
134 | %.o: %.$(1) $(FMOD) | $(MDIR)
135 | $$(F90) $$(COVFLAGS) $$(FCFLAGS) -c $$< -o $$@
136 |
137 | %.d: %.$(1) get_deps
138 | ./get_deps $$< \$$$$\(MDIR\) "$$(EXTERNAL_MODS)" $$(PROJECT_INCDIRS) > $$@
139 | endef
140 |
141 | # Register compilation rules for each Fortran extension
142 | $(foreach EXT,$(_F_EXT),$(eval $(call fortran_rule,$(EXT))))
143 |
144 | %.F90: %.pf
145 | $(PFUNIT)/bin/pFUnitParser.py $< $@
146 |
147 | %.F90: %.fpp
148 | $(FPP) $(FPP_FLAGS) $< $@
149 |
150 | %.F90: %.FPP
151 | $(FPP) $(FPP_FLAGS) $< $@
152 |
153 | $(MDIR):
154 | @mkdir -p $@
155 |
156 | clean: clean_obj clean_mod clean_deps clean_backups
157 |
158 | clean_obj:
159 | @echo Deleting all object files
160 | @/bin/rm -rf $(OBJS) $(TOBJS)
161 |
162 | clean_mod:
163 | @echo Deleting all module files
164 | @/bin/rm -rf $(MDIR)
165 |
166 | clean_deps:
167 | @echo Deleting all dependency files
168 | @/bin/rm -rf $(OBJS:.o=.d) $(TOBJS:.o=.d)
169 |
170 | clean_exec:
171 | @echo Deleting executable file
172 | @/bin/rm -rf $(EXEC)
173 |
174 | clean_backups:
175 | @echo Deleting emacs backup files
176 | @/bin/rm -rf $(shell find '.' -name '*~') $(shell find '.' -name '\#*\#')
177 |
178 | doc: documentation.md
179 | ford $<
180 |
181 | .PHONEY: all all_objects exec install_exec tests lib install_lib clean \
182 | clean_obj clean_mod clean_backups doc
183 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Flogging: Fortran Logging Library
2 | [](./LICENSE)
3 | [](https://github.com/cmacmackin/flogging/releases)
4 | [](https://travis-ci.org/cmacmackin/flogging)
5 | [](https://codecov.io/gh/cmacmackin/flogging)
6 |
7 | Flogging provides an easy-to-use interface for logging events and
8 | errors in Fortran applications and libraries. Its use and
9 | functionality is similar to that of
10 | [logging](https://docs.python.org/2/library/logging.html) library in
11 | Python. It is meant to be used for providing warnings, error messages,
12 | debug information, or routine output which should be logged. It is not
13 | ideal for all output, such as that used to prompt the user for input.
14 |
15 |
16 | ## Documentation
17 |
18 | Often in software it is desirable to print output to the screen and to
19 | a log-file simultaneously. Furthermore, it is often useful to
20 | to vary the amount of output depending on verbosity settings. These
21 | requirements tend to result in at least four lines of coding being
22 | needed to output even a single line of information, and more if, e.g.,
23 | the time of the IO is to be included in the information.
24 |
25 | The solution to this is a logging library. This library encapsulates
26 | in its procedures all of the logic needed to accomplish the above
27 | requirements. At the start of execution, it can be told how verbose it
28 | should be and then will be able to handle all decisions about what
29 | should be printed. Furthermore, it will include in the message a
30 | time-stamp, a colour-coded label for the type of message, and it
31 | provide a standard format for messages.
32 |
33 | Flogger provides a module called `logger_mod`, which implements an
34 | object called a `logger`. This contains methods for outputting the
35 | following types of messages:
36 |
37 | - **debug:** Information which will only be useful for debugging, such
38 | as announcing when entering and exiting a procedure
39 | - **trivia:** Information about normal operation which is detailed or
40 | obscure and thus would not usually be of interest
41 | - **info:** Information about the normal operation of the program
42 | - **warning:** Information produced when something happens which
43 | results in suboptimal completion of the program
44 | - **error:** Information about something which will result in
45 | incorrect completion of the program
46 | - **fatal:** Information that an event has occurred which will result
47 | in immediate termination of the program, without completion
48 |
49 | Each type of message is assigned a priority, ranging from 10 (debug)
50 | to 60 (fatal). The priority value for each type of message is
51 | specified in a parameter of the same name. Depending on the priority
52 | of the message, it may be printed to a log file, standard out, and/or
53 | standard error.
54 |
55 | While users can instantiate a logger instance and use that, it is
56 | recommended that they use the `master_logger` object provided in the
57 | `logger_mod` module. This way, multiple libraries can make calls to
58 | the same logger and all information will end up in the same log file.
59 |
60 | ### Usage
61 |
62 | Before using the master logger, `logger_init` must be called to set
63 | the logging file and what priority messages will be printed. The
64 | call signature is
65 | ```fortran
66 | subroutine logger_init(logfile, stderr_threshold, stdout_threshold, &
67 | logfile_threshold)
68 | ```
69 | Arguments are:
70 |
71 | - **logfile:** A character string containing the name of the file to
72 | which output will be written
73 | - **stderr_threshold:** (Optional) An integer which specifies the
74 | minimum priority a message must have in order to be printed to
75 | standard error. Defaults to *error*.
76 | - **stdout_threshold:** (Optional) An integer which specifies the
77 | minimum priority a message must have in order to be printed to
78 | standard out. Defaults to *info*.
79 | - **logfile_threshold:** (Optional) An integer which specifies the
80 | minimum priority a message must have in order to be printed to the
81 | log file. Defaults to *trivia*.
82 |
83 | A message is logged by calling the type-bound subroutine with the same
84 | name as the desired message type. These subroutines take the following
85 | arguments:
86 |
87 | - **source**: A character string specifying the name of the
88 | program or procedure in which thee logger is being called.
89 | - **message**: A character string containing the message to be
90 | printed.
91 |
92 | ### Example
93 |
94 | ```fortran
95 | program logging_example
96 | use logger_mod, only: logger_init, logger => master_logger
97 |
98 | ! Initialise the logger prior to use
99 | call logger_init()
100 |
101 | ! Write some debugging information
102 | call logger%debug('logger_example','Starting program logger_example')
103 |
104 | ! Perform some calculation
105 | ! ...
106 | call logger%info('logger_example','Found result of calculation')
107 |
108 | ! Perform another calculation
109 | ! ...
110 | ! Oh no, an error has occurred
111 | call logger%error('logger_example','Calculation failed due to error')
112 |
113 | call logger%debug('logger_example','Ending program logger_example')
114 | end program logging_example
115 | ```
116 |
117 | This produces the following output to the screen.
118 |
119 | 
120 |
121 | Note that debug information is not displayed, as its priority falls
122 | below the default threshold for this.
123 |
124 | ### API
125 |
126 | Detailed [API documentation](https://cmacmackin.github.io/flogging) is
127 | available in the Github pages of this repository and can be generated
128 | locally using the [FORD](https://github.com/cmacmackin/ford) tool.
129 |
130 |
131 | ## Installation
132 |
133 | The easiest way to install Flogging is via the
134 | [FLATPack](https://github.com/Fortran-FOSS-Programmers/FLATPack)
135 | repository for the [Spack](https://spack.readthedocs.io/en/latest/)
136 | package manager. It can be installed with the command
137 | ```
138 | spack install flogging
139 | ```
140 |
141 | If compiling manually, you will need to have the
142 | [FACE](https://github.com/szaghi/FACE) library installed. It is
143 | recommended that you compile Flogging using the
144 | [FoBiS.py](https://github.com/szaghi/FoBiS) (≥v2.2.2) tool,
145 | which can be installed from
146 | [PyPI](https://pypi.python.org/pypi/FoBiS.py/). The provided `fobos`
147 | configuration file allows the library to be compiled with the command
148 | ```
149 | FoBiS.py build -mode COMPILER-LIBTYPE -dlib FACELOCATION -i FACEMODLOCATION
150 | ```
151 | where `COMPILER` is either `gnu` or `intel`, `LIBTYPE` is either
152 | `static` or `shared`, `FACELOCATION` is the path to the directory
153 | containing the compiled FACE library in either static or shared
154 | format, and `FACEMODLOCATION` is the path to the directory containing
155 | the `.mod` file for FACE.
156 |
157 | A makefile is provided with this repository, but is not officially
158 | supported. It has been configured for the developer's computer and
159 | will not work elsewhere without modification.
160 |
161 |
162 | ## To Do
163 |
164 | - Make thread-safe
165 | - Make IO asynchronous
166 | - Make useful for SIMD parallel programming architectures
167 | - Allow user to ask to print directly to the IO unit(s)
168 | - Allow user to specify a custom format for log messages
169 |
170 |
171 | ## License
172 |
173 | Flogging is licensed under the GNU Lesser General Public License (LGPL) v3.0 or
174 | later. The terms are provided in the file `LICENSE`. The LGPL make reference
175 | to the GNU General Public License (GPL), which is provided in the file `GPL`.
176 | In brief, the LGPL allows this library to be linked to software under any
177 | license (with a few, minor, restrictions). However, should a modified version
178 | of the _library itself_ be released, it must be licensed under the terms of
179 | the LGPL or GPL.
180 |
--------------------------------------------------------------------------------
/buildtests.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 | set -v
5 |
6 | FoBiS.py build -mode gnu-static -dlib ${LOCAL_ROOT}/lib -i ${LOCAL_ROOT}/include -coverage
7 | for f in tests/*.pf
8 | do
9 | ${PFUNIT}/bin/pFUnitParser.py $f ${f%.*}.F90
10 | done
11 | if [ -e tests/driver.F90 ]; then rm tests/driver.F90; fi
12 | ln -s ${PFUNIT}/include/driver.F90 tests/
13 | mkdir -p tests_build $(FoBiS.py rule -mode tests -get build_dir)
14 | if FoBiS.py build -mode tests -coverage ; then
15 | $(FoBiS.py rule -mode tests -get_output_name)
16 | gcov $(FoBiS.py rule -mode gnu-static -get build_dir)/$(FoBiS.py rule -mode gnu-static -get obj_dir)/*.gcno -p
17 | else
18 | echo "Failed to build tests."
19 | exit 1
20 | fi
21 |
--------------------------------------------------------------------------------
/deploy.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | set -e # Exit with nonzero exit code if anything fails
3 | set -v
4 |
5 | SOURCE_BRANCH="master"
6 | TARGET_BRANCH="gh-pages"
7 |
8 | function doCompile {
9 | ford doc.md
10 | cp -R doc/* out/
11 | }
12 |
13 | # Pull requests and commits to other branches shouldn't try to deploy, just build to verify
14 | if [ "$TRAVIS_PULL_REQUEST" != "false" -o "$TRAVIS_BRANCH" != "$SOURCE_BRANCH" ]; then
15 | echo "Skipping deploy; just doing a build."
16 | doCompile
17 | exit 0
18 | fi
19 |
20 | # Save some useful information
21 | REPO=`git config remote.origin.url`
22 | SSH_REPO=${REPO/https:\/\/github.com\//git@github.com:}
23 | SHA=`git rev-parse --verify HEAD`
24 |
25 | # Clone the existing gh-pages for this repo into out/
26 | # Create a new empty branch if gh-pages doesn't exist yet (should only happen on first deply)
27 | git clone $REPO out
28 | cd out
29 | git checkout $TARGET_BRANCH || git checkout --orphan $TARGET_BRANCH
30 | cd ..
31 |
32 | # Clean out existing contents
33 | rm -rf out/**/* || exit 0
34 |
35 | # Run our compile script
36 | doCompile
37 |
38 | # Now let's go have some fun with the cloned repo
39 | cd out
40 | git config user.name "Travis CI"
41 | git config user.email "$COMMIT_AUTHOR_EMAIL"
42 |
43 | # If there are no changes to the compiled out (e.g. this is a README update) then just bail.
44 | if [ -z "`git diff --exit-code`" ]; then
45 | echo "No changes to the output on this push; exiting."
46 | exit 0
47 | fi
48 |
49 | # Commit the "changes", i.e. the new version.
50 | # The delta will show diffs between new and old versions.
51 | git add .
52 | git commit -m "Deploy to GitHub Pages: ${SHA}"
53 |
54 | # Get the deploy key by using Travis's stored variables to decrypt key.enc
55 | ENCRYPTED_KEY_VAR="encrypted_${ENCRYPTION_LABEL}_key"
56 | ENCRYPTED_IV_VAR="encrypted_${ENCRYPTION_LABEL}_iv"
57 | ENCRYPTED_KEY=${!ENCRYPTED_KEY_VAR}
58 | ENCRYPTED_IV=${!ENCRYPTED_IV_VAR}
59 | openssl aes-256-cbc -K $ENCRYPTED_KEY -iv $ENCRYPTED_IV -in ../key.enc -out key -d
60 | chmod 600 key
61 | eval `ssh-agent -s`
62 | ssh-add key
63 |
64 | # Now that we're all set up, we can push.
65 | git push $SSH_REPO $TARGET_BRANCH
66 |
--------------------------------------------------------------------------------
/doc.md:
--------------------------------------------------------------------------------
1 | project: Flogging
2 | project_dir: ./src
3 | output_dir: ./doc
4 | author: Chris MacMackin
5 | author_description: I am a graduate student at the University of Oxford, studying the melting and evolution of ice shelves. I enjoy programming, with my favourite languages being Fortran (for numerical work) and Python (for scripting and everything else).
6 | website: https://cmacmackin.github.io
7 | github: https://github.com/cmacmackin
8 | email: cmacmackin@gmail.com
9 | summary: Flogging provides an easy-to-use interface for logging events and
10 | errors in Fortran applications and libraries. Its use and
11 | functionality is similar to that of
12 | [logging](https://docs.python.org/2/library/logging.html) library in
13 | Python. It is meant to be used for providing warnings, error messages,
14 | debug information, or routine output which should be logged. It is not
15 | ideal for all output, such as that used to prompt the user for input.
16 | project_github: https://github.com/cmacmackin/flogging
17 | project_download: https://github.com/cmacmackin/flogging/archive/v1.0.0.tar.gz
18 | display: public
19 | protected
20 | source: true
21 | media_dir: ./media
22 |
23 | {!README.md!}
24 |
--------------------------------------------------------------------------------
/fobos:
--------------------------------------------------------------------------------
1 | [modes]
2 | modes = gnu-shared gnu-static intel-shared intel-static tests
3 |
4 | [common-variables]
5 | $CFLAGS_GNU = -c -Ofast
6 | $LFLAGS_GNU = -Ofast
7 | $CFLAGS_GNU_SHARED = -fPIC
8 | $LFLAGS_GNU_SHARED = -Wl,--no-undefined -Wl,-soname,libflogging.so.1
9 | $CFLAGS_INTEL = -c -fast
10 | $LFLAGS_INTEL = -fast
11 | $CFLAGS_INTEL_SHARED = -fpic
12 | $LFLAGS_INTEL_SHARED = -Wl,--no-undefined -Wl,-soname,libflogging.so.1
13 | $STATIC_LIB = libflogging.a
14 | $SHARED_LIB = libflogging.so.1.0.1
15 |
16 | [gnu-shared]
17 | template = template-build
18 | help = Compile to a shared library using gfortran
19 | compiler = gnu
20 | mklib = shared
21 | cflags = $CFLAGS_GNU $CFLAGS_GNU_SHARED
22 | lflags = $LFLAGS_GNU $LFLAGS_GNU_SHARED
23 | output = $SHARED_LIB
24 |
25 | [gnu-static]
26 | template = template-build
27 | help = Compile to a static library using gfortran
28 | compiler = gnu
29 | mklib = static
30 | cflags = $CFLAGS_GNU
31 | lflags = $LFLAGS_GNU
32 | output = $STATIC_LIB
33 |
34 | [intel-shared]
35 | template = template-build
36 | help = Compile to a shared library using ifort
37 | compiler = intel
38 | mklib = shared
39 | cflags = $CFLAGS_INTEL $CFLAGS_INTEL_SHARED
40 | lflags = $LFLAGS_INTEL $LFLAGS_INTEL_SHARED
41 | output = $SHARED_LIB
42 |
43 | [intel-static]
44 | template = template-build
45 | help = Compile to a static library using ifort
46 | compiler = intel
47 | mklib = static
48 | cflags = $CFLAGS_INTEL
49 | lflags = $LFLAGS_INTEL
50 | output = $STATIC_LIB
51 |
52 | [tests]
53 | help = Builds the unit tests. Not guaranteed to work.
54 | compiler = gnu
55 | src = ./tests
56 | build_dir = ./tests_build
57 | vlibs = ./build/libflogging.a
58 | include = ./build/include ${PFUNIT}/mod
59 | lib_dir = ${PFUNIT}/lib ${LOCAL_ROOT}/lib
60 | ext_libs = pfunit face
61 | cflags = -c -g -Og
62 | lflags = -g -Og
63 | target = driver.F90
64 | output = tests
65 | colors = True
66 |
67 | [template-build]
68 | src = ./src
69 | build_dir = ./build
70 | obj_dir = obj
71 | mod_dir = include
72 | ext_libs = face
73 | target = logging.f90
74 | colors = True
75 | cflags_heritage = True
76 |
77 | [rule-gcov]
78 | help = Generate coverage information
79 | rule_1 = gcov ./build/obj/*.gcno -pb
80 |
--------------------------------------------------------------------------------
/get_deps:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # -*- coding: utf-8 -*-
3 | #
4 | # get_deps
5 | #
6 | # Copyright 2016 Christopher MacMackin
7 | #
8 | # This program is free software; you can redistribute it and/or modify
9 | # it under the terms of the GNU General Public License as published by
10 | # the Free Software Foundation; either version 3 of the License, or
11 | # (at your option) any later version.
12 | #
13 | # This program is distributed in the hope that it will be useful,
14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | # GNU General Public License for more details.
17 | #
18 | # You should have received a copy of the GNU General Public License
19 | # along with this program; if not, write to the Free Software
20 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21 | # MA 02110-1301, USA.
22 | #
23 |
24 | # A script which prints the dependencies for a given Fortran source file in
25 | # a format suitable for inclusion into a Makefile.
26 | #
27 | # Invocation:
28 | #
29 | # ./get_deps FORTRAN_FILE MOD_DIRECTORY IGNORE [INCLUDE_DIR [INCLUDE_DIR ...]]
30 | #
31 | # FORTRAN_FILE
32 | # The path to the source file for which dependencies are to be
33 | # printed.
34 | #
35 | # MOD_DIRECTORY
36 | # The directory into which compiled module files will be placed.
37 | #
38 | # IGNORE
39 | # A regular expression for module names which should not be listed as
40 | # dependencies (i.e. because they are for external libraries or
41 | # intrinsic modules).
42 | #
43 | # INCLUDE_DIR
44 | # Directories which may contain an include file (when it is not
45 | # next to or below the file doing the including in the source
46 | # tree).
47 | #
48 |
49 |
50 | import re
51 | from sys import argv
52 | import os
53 |
54 | # Taken from my project FORD
55 | USE_RE = re.compile(r"""^[^!'"#]*use(?:\s*(?:,\s*((?:non_)?intrinsic)\s*)?::\s*|\s+)(\w+)\s*""",re.IGNORECASE)
56 | MODULE_RE = re.compile(r"""^[^!'"#]*(? 4:
66 | incdirs += argv[4:]
67 |
68 | def get_moddir(modname):
69 | return os.path.join(moddir, modname)
70 |
71 | modules = set()
72 | dependencies = set()
73 | includes = set()
74 |
75 | src = open(filename,'r')
76 | for line in src:
77 | use = USE_RE.search(line)
78 | if use:
79 | if not use.group(1) == 'intrinsic' and not ignore_re.search(use.group(2)):
80 | dependencies.add(get_moddir(use.group(2).lower() + '.mod'))
81 | else:
82 | mod = MODULE_RE.search(line)
83 | if mod:
84 | modules.add(get_moddir(mod.group(1).lower() + '.mod'))
85 | modules.add(get_moddir(mod.group(1).lower() + '.smod'))
86 | else:
87 | submod = SUBMODULE_RE.search(line)
88 | if submod:
89 | modules.add(get_moddir(submod.group(1).lower() + '@'
90 | + submod.group(3).lower() + '.smod'))
91 | if submod.group(2) and not ignore_re.search(mod.group(1)):
92 | dependencies.add(get_moddir(submod.group(1).lower() + '@'
93 | + submod.group(2).lower()
94 | + '.smod'))
95 | elif not ignore_re.search(submod.group(1)):
96 | dependencies.add(get_moddir(submod.group(1).lower() + '.smod'))
97 | else:
98 | inc = INCLUDE_RE.search(line)
99 | if inc:
100 | ifile = inc.group(3)
101 | includes.update(tuple(os.path.join(idir,ifile) for idir in incdirs))
102 |
103 | src.close()
104 |
105 | basename = os.path.splitext(filename)[0]
106 | if len(modules) > 0:
107 | print(' '.join(modules) + ': ' + filename + ' ' + basename + '.o')
108 | if len(dependencies) + len(includes) > 0:
109 | print(basename + '.o: ' + ' '.join(dependencies) +
110 | ' $(wildcard ' + ' '.join(includes) + ')')
111 | # for dep in dependencies:
112 | # print(dep + ':')
113 |
114 |
115 |
--------------------------------------------------------------------------------
/key.enc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cmacmackin/flogging/2429bae8080bce33771fb888bf47395ce518d5b2/key.enc
--------------------------------------------------------------------------------
/logger_example.f90:
--------------------------------------------------------------------------------
1 | program logging_example
2 | use logger_mod, only: logger_init, logger => master_logger
3 |
4 | ! Initialise the logger prior to use
5 | call logger_init('outputfile.log')
6 |
7 | ! Write some debugging information
8 | call logger%debug('logger_example','Starting program logger_example')
9 |
10 | ! Perform some calculation
11 | ! ...
12 | call logger%info('logger_example','Found result of calculation')
13 |
14 | ! Perform another calculation
15 | ! ...
16 | ! Oh no, an error has occurred
17 | call logger%error('logger_example','Calculation failed due to error')
18 |
19 | call logger%debug('logger_example','Ending program logger_example')
20 | end program logging_example
21 |
22 |
--------------------------------------------------------------------------------
/media/sample-output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cmacmackin/flogging/2429bae8080bce33771fb888bf47395ce518d5b2/media/sample-output.png
--------------------------------------------------------------------------------
/src/logging.f90:
--------------------------------------------------------------------------------
1 | !
2 | ! logging.f90
3 | ! This file is part of flogging.
4 | !
5 | ! Copyright 2016 Chris MacMackin
6 | !
7 | ! This program is free software; you can redistribute it and/or
8 | ! modify it under the terms of the GNU Lesser General Public License
9 | ! as published by the Free Software Foundation; either version 3 of
10 | ! the License, or (at your option) any later version.
11 | !
12 | ! This program is distributed in the hope that it will be useful, but
13 | ! WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | ! Lesser General Public License for more details.
16 | !
17 | ! You should have received a copy of the GNU Lesser General Public
18 | ! License along with this program; if not, write to the Free Software
19 | ! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 | ! 02110-1301, USA.
21 | !
22 |
23 | module logger_mod
24 | !* Author: Christopher MacMackin
25 | ! Date: December 2016
26 | ! License: LGPLv3
27 | !
28 | ! Provides routines for printing different types of messages to
29 | ! standard out, standard error, and/or a log file.
30 | !
31 | use iso_fortran_env, only: i8 => int64, error_unit, output_unit
32 | use face, only: colourise => colorize ! Correct the spelling... ;-)
33 | implicit none
34 | private
35 |
36 | integer, parameter, public :: debug = 10
37 | !! Priority level for output only useful for debugging
38 | integer, parameter, public :: trivia = 20
39 | !! Priority level for output which may be useful but is very
40 | !! detailed or not especially important.
41 | integer, parameter, public :: info = 30
42 | !! Priority level for output generated by the normal execution of
43 | !! the program.
44 | integer, parameter, public :: warning = 40
45 | !! Priority level for output which indicates some part of the
46 | !! program is not behaving as it ideally should.
47 | integer, parameter, public :: error = 50
48 | !! Priority level for output which indicates an error has
49 | !! occurred which will affect the continued execution of the
50 | !! program.
51 | integer, parameter, public :: fatal = 60
52 | !! Priority level for output which notifies the user than a
53 | !! serious error has occured which will result in the immediate
54 | !! termination of the program.
55 |
56 | integer, parameter :: default_stderr_threshold = error
57 | !! Default priority level needed for a message to be printed to
58 | !! standard-error.
59 | integer, parameter :: default_stdout_threshold = info
60 | !! Default priority level needed for a message to be printed to
61 | !! standard out.
62 | integer, parameter :: default_logfile_threshold = trivia
63 | !! Default priority level needed for a message to be printed to
64 | !! the log file.
65 |
66 | integer, parameter :: closed_unit = -9999
67 | integer, parameter :: infinity = huge(1)
68 |
69 | character(len=29), parameter :: default_format = "('[',a,']','[',a,']',"// &
70 | "*(1x,a))"
71 |
72 | type, public :: logger
73 | !* Author: Chris MacMackinc
74 | ! Date: December 2016
75 | !
76 | ! An object to handle output of information about the executing
77 | ! program to the terminal and to a log-file.
78 | !
79 | private
80 | integer :: stdout = output_unit
81 | !! Unit corresponding to STDOUT
82 | integer :: stderr = error_unit
83 | !! Unit corresponding to STDERR
84 | integer :: fileunit = closed_unit
85 | !! Unit corresponding to log-file
86 | character(len=:), allocatable :: logfile
87 | !! Name of the log-file
88 | integer :: stderr_threshold = infinity
89 | !! Cutoff for which messages with greater or equal priority will
90 | !! be written to STDERR.
91 | integer :: stdout_threshold = infinity
92 | !! Cutoff for which messages with greater or equal priority will
93 | !! be written to STDOUT.
94 | integer :: logfile_threshold = infinity
95 | !! Cutoff for which messages with greater or equal priority will
96 | !! be written to the log-file.
97 | contains
98 | procedure :: message => logger_message
99 | !! Write a message of a given priority to the appropriate
100 | !! location(s)
101 | procedure :: debug => logger_debug
102 | !! Write debug information
103 | procedure :: trivia => logger_trivia
104 | !! Write trivial run-time information
105 | procedure :: info => logger_info
106 | !! Write run-time information
107 | procedure :: warning => logger_warning
108 | !! Write warning message
109 | procedure :: error => logger_error
110 | !! Write error message
111 | procedure :: fatal => logger_fatal
112 | !! Write notification of fatal error
113 | procedure :: destroy => logger_destroy
114 | !! Closes the log-file
115 | procedure :: is_open => logger_is_open
116 | !! Return `.true.` if the log-file is open for writing
117 | final :: logger_finalize
118 | end type logger
119 |
120 | interface logger
121 | module procedure :: constructor
122 | end interface
123 |
124 | type(logger), public :: master_logger
125 | !! The main logger object for a program to use. Must be
126 | !! initialised in the main program with a call to [[logger_init]].
127 |
128 | public :: logger_init
129 |
130 | contains
131 |
132 | function constructor(logfile, stderr_threshold, stdout_threshold, &
133 | logfile_threshold) result(this)
134 | type(logger) :: this
135 | character(len=*), intent(in) :: logfile
136 | !! Name of the log-file to which output will be written
137 | integer, intent(in), optional :: stderr_threshold
138 | !! Threshold priority, at and above which messages will be
139 | !! written to standard error. Defaults to `error`.
140 | integer, intent(in), optional :: stdout_threshold
141 | !! Threshold priority, at and above which messages will be
142 | !! written to standard out. Defaults to `info`.
143 | integer, intent(in), optional :: logfile_threshold
144 | !! Threshold priority, at and above which messages will be
145 | !! written to the log file. Defaults to `trivia`.
146 | integer :: flag
147 | this%logfile = logfile
148 | open(newunit=this%fileunit,file=this%logfile,action='write', &
149 | asynchronous='yes',iostat=flag,status='replace')
150 | if (flag /= 0) error stop 'Error opening log file.'
151 | if (present(stderr_threshold)) then
152 | this%stderr_threshold = stderr_threshold
153 | else
154 | this%stderr_threshold = default_stderr_threshold
155 | end if
156 | if (present(stdout_threshold)) then
157 | this%stdout_threshold = stdout_threshold
158 | else
159 | this%stdout_threshold = default_stdout_threshold
160 | end if
161 | if (present(logfile_threshold)) then
162 | this%logfile_threshold = logfile_threshold
163 | else
164 | this%logfile_threshold = default_logfile_threshold
165 | end if
166 | end function constructor
167 |
168 | subroutine logger_finalize(this)
169 | !* Author: Chris MacMackin
170 | ! Date: December 2016
171 | !
172 | ! Closes the log-file of this logger object.
173 | !
174 | type(logger), intent(inout) :: this
175 | call this%destroy()
176 | end subroutine logger_finalize
177 |
178 | subroutine logger_init(logfile, stderr_threshold, stdout_threshold, &
179 | logfile_threshold)
180 | !* Author: Chris MacMackin
181 | ! Date: December 2016
182 | !
183 | ! Initalises the master logging object. This subroutine must be
184 | ! called before the master logger is used. It should only be
185 | ! called once.
186 | !
187 | character(len=*), intent(in) :: logfile
188 | !! Name of the log-file to which output will be written
189 | integer, intent(in), optional :: stderr_threshold
190 | !! Threshold priority, at and above which messages will be
191 | !! written to standard error. Defaults to `error`.
192 | integer, intent(in), optional :: stdout_threshold
193 | !! Threshold priority, at and above which messages will be
194 | !! written to standard out. Defaults to `info`.
195 | integer, intent(in), optional :: logfile_threshold
196 | !! Threshold priority, at and above which messages will be
197 | !! written to the log file. Defaults to `trivia`.
198 | master_logger = logger(logfile, stderr_threshold, stdout_threshold, &
199 | logfile_threshold)
200 | end subroutine logger_init
201 |
202 | function get_designator(priority,ansi_colours) result(des)
203 | !* Author: Chris MacMackin
204 | ! Date: December 2016
205 | !
206 | ! For a given priority, returns the appropriate, optionally
207 | ! colourised, designator.
208 | !
209 | integer, intent(in) :: priority
210 | !! The priority level for which to get the designator
211 | logical, intent(in), optional :: ansi_colours
212 | !! Whether to colourise the disgnator. This should only be done
213 | !! if the designator is printed to the terminal. Defaults to
214 | !! `.true.`.
215 | character(len=:), allocatable :: des
216 | integer :: descriminator
217 | logical :: col
218 | if (present(ansi_colours)) then
219 | col = ansi_colours
220 | else
221 | col = .true.
222 | end if
223 | descriminator = priority/10
224 | if (descriminator < 1) then
225 | des = ''
226 | else if (descriminator < 2) then
227 | des = ' '
228 | if (col) des = colourise(des(:len(des)-1),color_fg='cyan',style='bold_on')//' '
229 | else if (descriminator < 3) then
230 | des = ' '
231 | if (col) des = colourise(des(:len(des)-1),color_fg='blue',style='bold_on')//' '
232 | else if (descriminator < 4) then
233 | des = ' '
234 | if (col) des = colourise(des(:len(des)-1),color_fg='green',style='bold_on')//' '
235 | else if (descriminator < 5) then
236 | des = ' '
237 | if (col) des = colourise(des(:len(des)-1),color_fg='yellow',style='bold_on')//' '
238 | else if (descriminator < 6) then
239 | des = ' '
240 | if (col) des = colourise(des(:len(des)-1),color_fg='red',style='bold_on')//' '
241 | else
242 | des = ' '
243 | if (col) des = colourise(des(:len(des)-1),color_bg='red',style='bold_on')//' '
244 | end if
245 | end function get_designator
246 |
247 | function current_time()
248 | !* Author: Chris MacMackin
249 | ! Date: November 2016
250 | !
251 | ! Returns the formatted current date and time.
252 | !
253 | character(len=20) :: current_time
254 | integer(i8), dimension(8) :: time_vals
255 | character(len=3), dimension(12), parameter :: months = ['Jan', &
256 | 'Feb', &
257 | 'Mar', &
258 | 'Apr', &
259 | 'May', &
260 | 'Jun', &
261 | 'Jul', &
262 | 'Aug', &
263 | 'Sep', &
264 | 'Oct', &
265 | 'Nov', &
266 | 'Dec']
267 | character(len=42), parameter :: time_format = '(a3,1x,i2,1x,i4,1x,'// &
268 | 'i2.2,":",i2.2,":",i2.2)'
269 | call date_and_time(values=time_vals)
270 | write(current_time,time_format) months(time_vals(2)), time_vals(3), &
271 | time_vals(1), time_vals(5), time_vals(6), &
272 | time_vals(7)
273 | end function current_time
274 |
275 | subroutine logger_message(this,source,priority,message)
276 | !* Author: Chris MacMackin
277 | ! Date: December 2016
278 | !
279 | ! Write the provided message to STDERR, STDOUT, and/or a log-file,
280 | ! based on its priority level.
281 | !
282 | class(logger), intent(in) :: this
283 | character(len=*), intent(in) :: source
284 | !! The name of the procedure which produced the error
285 | integer, intent(in) :: priority
286 | !! The importance of the message, determining where it will be
287 | !! written.
288 | character(len=*), intent(in) :: message
289 | !! The information to be written.
290 | character(len=:), allocatable :: output
291 | if (priority >= this%stderr_threshold) then
292 | output = get_designator(priority)//message
293 | write(this%stderr,default_format) current_time(), source, output
294 | else if (priority >= this%stdout_threshold) then
295 | output = get_designator(priority)//message
296 | write(this%stdout,default_format) current_time(), source, output
297 | end if
298 | if (priority >= this%logfile_threshold) then
299 | output = get_designator(priority,.false.)//message
300 | write(this%fileunit,default_format) current_time(), source, output
301 | end if
302 | end subroutine logger_message
303 |
304 | subroutine logger_debug(this,source,message)
305 | !* Author: Chris MacMackin
306 | ! Date: December 2016
307 | !
308 | ! Writes debug information to STDERR, STDOUT, and/or a log-file.
309 | !
310 | class(logger), intent(in) :: this
311 | character(len=*), intent(in) :: source
312 | !! The name of the procedure which produced the error
313 | character(len=*), intent(in) :: message
314 | !! The information to be written.
315 | call this%message(source,debug,message)
316 | end subroutine logger_debug
317 |
318 |
319 | subroutine logger_trivia(this,source,message)
320 | !* Author: Chris MacMackin
321 | ! Date: December 2016
322 | !
323 | ! Writes unimportant run-time information to STDERR, STDOUT,
324 | ! and/or a log-file.
325 | !
326 | class(logger), intent(in) :: this
327 | character(len=*), intent(in) :: source
328 | !! The name of the procedure which produced the error
329 | character(len=*), intent(in) :: message
330 | !! The information to be written.
331 | call this%message(source,trivia,message)
332 | end subroutine logger_trivia
333 |
334 | subroutine logger_info(this,source,message)
335 | !* Author: Chris MacMackin
336 | ! Date: December 2016
337 | !
338 | ! Writes run-time information to STDERR, STDOUT, and/or a log-file.
339 | !
340 | class(logger), intent(in) :: this
341 | character(len=*), intent(in) :: source
342 | !! The name of the procedure which produced the error
343 | character(len=*), intent(in) :: message
344 | !! The information to be written.
345 | call this%message(source,info,message)
346 | end subroutine logger_info
347 |
348 | subroutine logger_warning(this,source,message)
349 | !* Author: Chris MacMackin
350 | ! Date: December 2016
351 | !
352 | ! Writes warning information to STDERR, STDOUT, and/or a log-file.
353 | !
354 | class(logger), intent(in) :: this
355 | character(len=*), intent(in) :: source
356 | !! The name of the procedure which produced the error
357 | character(len=*), intent(in) :: message
358 | !! The information to be written.
359 | call this%message(source,warning,message)
360 | end subroutine logger_warning
361 |
362 | subroutine logger_error(this,source,message)
363 | !* Author: Chris MacMackin
364 | ! Date: December 2016
365 | !
366 | ! Writes error information to STDERR, STDOUT, and/or a log-file.
367 | !
368 | class(logger), intent(in) :: this
369 | character(len=*), intent(in) :: source
370 | !! The name of the procedure which produced the error
371 | character(len=*), intent(in) :: message
372 | !! The information to be written.
373 | call this%message(source,error,message)
374 | end subroutine logger_error
375 |
376 | subroutine logger_fatal(this,source,message)
377 | !* Author: Chris MacMackin
378 | ! Date: December 2016
379 | !
380 | ! Writes fatal information to STDERR, STDOUT, and/or a log-file.
381 | !
382 | class(logger), intent(in) :: this
383 | character(len=*), intent(in) :: source
384 | !! The name of the procedure which produced the error
385 | character(len=*), intent(in) :: message
386 | !! The information to be written.
387 | call this%message(source,fatal,message)
388 | end subroutine logger_fatal
389 |
390 | subroutine logger_destroy(this)
391 | !* Author: Chris MacMackin
392 | ! Date: December 2016
393 | !
394 | ! Closes the log-file of this logger object. Destroys only the
395 | ! logger object, *not* the output.
396 | !
397 | class(logger), intent(inout) :: this
398 | if (this%fileunit == closed_unit) return
399 | close(this%fileunit)
400 | this%fileunit = closed_unit
401 | this%stderr_threshold = infinity
402 | this%stdout_threshold = infinity
403 | this%logfile_threshold = infinity
404 | end subroutine logger_destroy
405 |
406 | pure function logger_is_open(this)
407 | !* Author: Chris MacMackin
408 | ! Date: December 2016
409 | !
410 | ! Returns `.true.` if the log-file is open for writing.
411 | !
412 | class(logger), intent(in) :: this
413 | logical :: logger_is_open
414 | logger_is_open = (this%fileunit /= closed_unit)
415 | end function logger_is_open
416 |
417 | end module logger_mod
418 |
--------------------------------------------------------------------------------
/tests/logging_tests.pf:
--------------------------------------------------------------------------------
1 | !
2 | ! logging_tests.pf
3 | ! This file is part of flogging.
4 | !
5 | ! Copyright 2016 Chris MacMackin
6 | !
7 | ! This program is free software; you can redistribute it and/or
8 | ! modify it under the terms of the GNU Lesser General Public License
9 | ! as published by the Free Software Foundation; either version 3 of
10 | ! the License, or (at your option) any later version.
11 | !
12 | ! This program is distributed in the hope that it will be useful, but
13 | ! WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 | ! Lesser General Public License for more details.
16 | !
17 | ! You should have received a copy of the GNU Lesser General Public
18 | ! License along with this program; if not, write to the Free Software
19 | ! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 | ! 02110-1301, USA.
21 | !
22 |
23 | module logging_tests
24 | use iso_fortran_env, only: r8 => real64, iostat_end
25 | use pfunit_mod
26 | use logger_mod
27 | implicit none
28 |
29 | @TestCase
30 | type, extends(testcase), public :: log_test
31 | type(logger) :: nonmaster_log, threshold_log
32 | character(len=18) :: nonmaster_file = 'test_nonmaster.log'
33 | character(len=18) :: threshold_file = 'test_threshold.log'
34 | character(len=15) :: master_file = 'test_master.log'
35 | integer :: threshold = info
36 | contains
37 | procedure :: setup
38 | procedure :: teardown
39 | end type log_test
40 |
41 | contains
42 |
43 | subroutine setup(this)
44 | class(log_test), intent(inout) :: this
45 | this%nonmaster_log = logger(this%nonmaster_file, error, 0, this%threshold)
46 | this%threshold_log = logger(this%threshold_file, 1000, 1000, this%threshold)
47 | call logger_init(this%master_file, 1000, 1000, 0)
48 | end subroutine setup
49 |
50 | subroutine teardown(this)
51 | class(log_test), intent(inout) :: this
52 | if (this%nonmaster_log%is_open()) call this%nonmaster_log%destroy()
53 | if (master_logger%is_open()) call master_logger%destroy()
54 | call execute_command_line('rm '//this%nonmaster_file)
55 | call execute_command_line('rm '//this%threshold_file)
56 | call execute_command_line('rm '//this%master_file)
57 | end subroutine teardown
58 |
59 | subroutine test_output(filename, msg_type, src, msg)
60 | character(len=*), intent(in) :: filename, msg_type, src, msg
61 | character(len=256) :: line
62 | integer :: u, flag, is, ie
63 | open(newunit=u,file=filename,action='read',status='old',iostat=flag)
64 | @assertEqual(0,flag,message='Error opening log file "'//filename//'"')
65 | read(u,'(256a)',iostat=flag) line
66 | close(u)
67 | @assertEqual(0,flag,message='Error reading log file "'//filename//'"')
68 | is = 24
69 | ie = 24 + len(src) - 1
70 | @assertEqual(src,line(is:ie),message='Incorrect message source printed to file.')
71 | is = ie + 4
72 | if (len(msg_type) == 0) is = is - 1
73 | ie = is + len(msg_type) - 1
74 | @assertEqual(msg_type,line(is:ie),message='Incorrect message type printed to file.')
75 | is = ie + 3
76 | if (len(msg_type) == 0) is = is - 2
77 | ie = is + len(msg)
78 | @assertEqual(msg,line(is:ie),message='Incorrect '//msg_type//' message printed to file.')
79 | end subroutine test_output
80 |
81 | subroutine test_threshold(priority, threshold, filename, msg_type, src, msg)
82 | integer :: priority, threshold
83 | character(len=*), intent(in) :: filename, msg_type, src, msg
84 | character(len=256) :: line
85 | integer :: u, flag, is, ie
86 | if (priority >= threshold) then
87 | call test_output(filename, msg_type, src, msg)
88 | else
89 | open(newunit=u,file=filename,action='read',status='old',iostat=flag)
90 | @assertEqual(0,flag,message='Error opening log file "'//filename//'"')
91 | read(u,'(256a)',iostat=flag) line
92 | @assertEqual(iostat_end,flag,message=msg_type//' message printed to log when below threshold priority.')
93 | end if
94 | end subroutine test_threshold
95 |
96 | @Test
97 | subroutine test_constructor(this)
98 | class(log_test), intent(inout) :: this
99 | call this%nonmaster_log%destroy()
100 | this%nonmaster_log = logger(this%nonmaster_file,1)
101 | this%nonmaster_log = logger('randon_file_name.txt',1,1)
102 | this%nonmaster_log = logger('randon_file_name2.txt',1,logfile_threshold=1)
103 | this%nonmaster_log = logger('randon_file_name3.txt',1,1,1)
104 | this%nonmaster_log = logger('randon_file_name4.txt',stdout_threshold=1)
105 | this%nonmaster_log = logger('randon_file_name5.txt',stdout_threshold=1, &
106 | logfile_threshold=1)
107 | this%nonmaster_log = logger('randon_file_name6.txt',logfile_threshold=1)
108 | end subroutine test_constructor
109 |
110 | @Test
111 | subroutine test_priority_1(this)
112 | class(log_test), intent(inout) :: this
113 | character(len=10), parameter :: src = 'test_priority_1'
114 | character(len=23), parameter :: msg = 'This is a message with priority 1.'
115 | call master_logger%message(src,1,msg)
116 | call master_logger%destroy()
117 | call test_output(this%master_file,'',src,msg)
118 | call this%threshold_log%message(src, 1, msg)
119 | call this%threshold_log%destroy()
120 | @assertTrue(1" should'
222 | write(*,*) 'be bold and have the colour which is named on the right.'
223 | associate(l => this%nonmaster_log)
224 | call l%debug('test_colours','This should be cyan')
225 | call l%trivia('test_colours','This should be blue')
226 | call l%info('test_colours','This should be green')
227 | call l%warning('test_colours','This should be yellow')
228 | call l%error('test_colours','This should be red')
229 | call l%fatal('test_colours','This should have a red background')
230 | end associate
231 | end subroutine test_colours
232 |
233 | end module logging_tests
234 |
--------------------------------------------------------------------------------
/tests/testSuites.inc:
--------------------------------------------------------------------------------
1 | #ifdef NEVERDEFINEDEVEREVEREVER
2 | ! Need this to trick FoBiS.py into realizing that the driver program
3 | ! depends on all of the test modules
4 | use logging_tests
5 | #endif
6 | ADD_TEST_SUITE(logging_tests_suite)
7 |
--------------------------------------------------------------------------------