Skip to content

Commit

Permalink
Update header file and documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
DaanVanVugt committed Aug 5, 2016
1 parent 84c1308 commit a7d8d83
Show file tree
Hide file tree
Showing 8 changed files with 172 additions and 110 deletions.
42 changes: 36 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,30 @@ use flogging
```

To load the logging module and its utility functions.
To use the preprovided macros, include the header file and turn on the preprocessor by compiling with -cpp
To use the preprovided macros, include the header file and turn on the preprocessor by compiling with `-cpp`
```C
#include "flogging.h"
```
This macro defines the following functions:
```fortran
log(level, format)
log_fatal(format)
log_error(format)
log_warn(format)
log_info(format)
log_debug(format)
log_trace(format)
log_root(level, format)
log_root_fatal(format)
log_root_error(format)
log_root_warn(format)
log_root_info(format)
log_root_debug(format)
log_root_trace(format)
```
Where `format` is usually `*`, but can be adjusted to suit your needs. Remember to include a single `A` specifier for the log lead.
Where `format` is usually `*`, but can be adjusted to suit your needs. Remember to include a single `A` specifier for the log lead if you set it yourself.

The functions print a log message only if the level is greater than or equal to the current minimum loglevel.
The second set of functions function includes a check to print a log message only from the root MPI process, if compiled
The second functions include a check to print a log message only from the root MPI process, if compiled
with `USE_MPI`. If not compiled with `USE_MPI`, it works the same as the log function.

If you do not want to use the preprocessor macros, you can log like this.
Expand All @@ -52,6 +50,26 @@ make USE_MPI=1
```
Then, place `libflogging.so` into your `LD_LIBRARY_PATH` and put `flogging.h` into your include path.

## Compilation flags
Compile your own code with
```
-DDISABLE_LOG_DEBUG
```
to remove any debug statements from your code. Note that you cannot use `-v` to get these back then.
By default any `log_trace` messages are not included in the executable. Compile with
```
-DENABLE_LOG_TRACE
```
to get these back. Note that you still need to use `-vv` (by default) to see the messages.
This is a good compilation flag to have in your debug build profile.

## Transitioning to flogging
You can change all of the messages in your application to the `log_info` level by
```bash
git sed 's/write ?(\*,\*)/log_info(*)/g'
```
You might need to split some lines, as the `__FILE__` and `__LINE__` macros require quite some space.
This can also be circumvented by compiling with `-ffree-line-length-none` or equivalent.

# Examples
```fortran
Expand All @@ -60,7 +78,7 @@ log(warn,*) "this is a warning"
log(info,*) "here, have some info"
log(debug,*) "and this is a debug message"
```
outputs
outputs (with default compilation flag)
```
localhost test.f90:9 ERROR this is an error
localhost test.f90:10 WARN this is a warning
Expand Down Expand Up @@ -105,6 +123,8 @@ Logging is to stderr by default. Another output unit can be selected by setting
This will probably not work well with MPI.

## Internals
The latest documentation can be found [here](http://exteris.github.io/flogging/).

The module defines a function defining whether or not to print this log message,
```fortran
logp(level)
Expand All @@ -116,3 +136,13 @@ This can be used to print messages only from the root thread, to prevent log mes
```fortran
logp(level,0)
```

## Contributing
Pull requests and comments are appreciated.

## TODO
- Argument parsing is quite flaky (try -qqqqqq and see what happens)
- Time and date output at the same time does not work yet
- Compilation flag to control argument parsing
- Log output to a different file per MPI process
- Multiple logging streams/outputs (this will be tricky)
28 changes: 14 additions & 14 deletions doc/lists/modules.html
Original file line number Diff line number Diff line change
Expand Up @@ -115,26 +115,26 @@ <h1>Modules</h1>
<g id="module~~graph~~ModuleGraph" class="graph" transform="scale(1 1) rotate(0) translate(4 70)">
<title>module~~graph~~ModuleGraph</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-70 181,-70 181,4 -4,4"/>
<!-- module~vt100 -->
<g id="module~~graph~~ModuleGraph_node1" class="node"><title>module~vt100</title>
<g id="a_module~~graph~~ModuleGraph_node1"><a xlink:href="../module/vt100.html" xlink:title="vt100">
<polygon fill="#337ab7" stroke="#337ab7" points="70.5,-66 16.5,-66 16.5,-42 70.5,-42 70.5,-66"/>
<text text-anchor="middle" x="43.5" y="-51.6" font-family="Helvetica,sans-Serif" font-size="10.50" fill="white">vt100</text>
</a>
</g>
</g>
<!-- module~flogging -->
<g id="module~~graph~~ModuleGraph_node2" class="node"><title>module~flogging</title>
<g id="a_module~~graph~~ModuleGraph_node2"><a xlink:href="../module/flogging.html" xlink:title="flogging">
<g id="module~~graph~~ModuleGraph_node1" class="node"><title>module~flogging</title>
<g id="a_module~~graph~~ModuleGraph_node1"><a xlink:href="../module/flogging.html" xlink:title="flogging">
<polygon fill="#337ab7" stroke="#337ab7" points="177,-45 123,-45 123,-21 177,-21 177,-45"/>
<text text-anchor="middle" x="150" y="-30.6" font-family="Helvetica,sans-Serif" font-size="10.50" fill="white">flogging</text>
</a>
</g>
</g>
<!-- module~vt100 -->
<g id="module~~graph~~ModuleGraph_node2" class="node"><title>module~vt100</title>
<g id="a_module~~graph~~ModuleGraph_node2"><a xlink:href="../module/vt100.html" xlink:title="vt100">
<polygon fill="#337ab7" stroke="#337ab7" points="70.5,-66 16.5,-66 16.5,-42 70.5,-42 70.5,-66"/>
<text text-anchor="middle" x="43.5" y="-51.6" font-family="Helvetica,sans-Serif" font-size="10.50" fill="white">vt100</text>
</a>
</g>
</g>
<!-- module~vt100&#45;&gt;module~flogging -->
<g id="module~~graph~~ModuleGraph_edge2" class="edge"><title>module~vt100&#45;&gt;module~flogging</title>
<path fill="none" stroke="#00ffff" stroke-dasharray="5,2" d="M70.6002,-48.755C83.3181,-46.1992 98.8209,-43.0838 112.673,-40.3002"/>
<polygon fill="#00ffff" stroke="#00ffff" points="113.756,-43.6526 122.87,-38.2509 112.377,-36.7898 113.756,-43.6526"/>
<path fill="none" stroke="#ff0000" stroke-dasharray="5,2" d="M70.6002,-48.755C83.3181,-46.1992 98.8209,-43.0838 112.673,-40.3002"/>
<polygon fill="#ff0000" stroke="#ff0000" points="113.756,-43.6526 122.87,-38.2509 112.377,-36.7898 113.756,-43.6526"/>
</g>
<!-- iso_fortran_env -->
<g id="module~~graph~~ModuleGraph_node3" class="node"><title>iso_fortran_env</title>
Expand All @@ -146,8 +146,8 @@ <h1>Modules</h1>
</g>
<!-- iso_fortran_env&#45;&gt;module~flogging -->
<g id="module~~graph~~ModuleGraph_edge1" class="edge"><title>iso_fortran_env&#45;&gt;module~flogging</title>
<path fill="none" stroke="#00ffff" stroke-dasharray="5,2" d="M87.0042,-20.5415C95.6011,-22.2691 104.563,-24.0701 112.914,-25.7482"/>
<polygon fill="#00ffff" stroke="#00ffff" points="112.238,-29.1823 122.731,-27.7211 113.617,-22.3195 112.238,-29.1823"/>
<path fill="none" stroke="#ff0000" stroke-dasharray="5,2" d="M87.0042,-20.5415C95.6011,-22.2691 104.563,-24.0701 112.914,-25.7482"/>
<polygon fill="#ff0000" stroke="#ff0000" points="112.238,-29.1823 122.731,-27.7211 113.617,-22.3195 112.238,-29.1823"/>
</g>
</g>
</svg>
Expand Down
76 changes: 38 additions & 38 deletions doc/lists/procedures.html
Original file line number Diff line number Diff line change
Expand Up @@ -128,74 +128,74 @@ <h1>Procedures</h1>
<g id="call~~graph~~CallGraph" class="graph" transform="scale(1 1) rotate(0) translate(4 448)">
<title>call~~graph~~CallGraph</title>
<polygon fill="white" stroke="none" points="-4,4 -4,-448 282,-448 282,4 -4,4"/>
<!-- proc~tput -->
<g id="call~~graph~~CallGraph_node1" class="node"><title>proc~tput</title>
<g id="a_call~~graph~~CallGraph_node1"><a xlink:href="../proc/tput.html" xlink:title="tput">
<polygon fill="#d9534f" stroke="#d9534f" points="102,-24 48,-24 48,-0 102,-0 102,-24"/>
<text text-anchor="middle" x="75" y="-9.6" font-family="Helvetica,sans-Serif" font-size="10.50" fill="white">tput</text>
</a>
</g>
</g>
<!-- proc~log_set_disable_colors -->
<g id="call~~graph~~CallGraph_node2" class="node"><title>proc~log_set_disable_colors</title>
<g id="a_call~~graph~~CallGraph_node2"><a xlink:href="../proc/log_set_disable_colors.html" xlink:title="log_set_disable_colors">
<polygon fill="#d9534f" stroke="#d9534f" points="135.5,-66 14.5,-66 14.5,-42 135.5,-42 135.5,-66"/>
<text text-anchor="middle" x="75" y="-51.6" font-family="Helvetica,sans-Serif" font-size="10.50" fill="white">log_set_disable_colors</text>
<g id="call~~graph~~CallGraph_node1" class="node"><title>proc~log_set_disable_colors</title>
<g id="a_call~~graph~~CallGraph_node1"><a xlink:href="../proc/log_set_disable_colors.html" xlink:title="log_set_disable_colors">
<polygon fill="#d9534f" stroke="#d9534f" points="135.5,-24 14.5,-24 14.5,-0 135.5,-0 135.5,-24"/>
<text text-anchor="middle" x="75" y="-9.6" font-family="Helvetica,sans-Serif" font-size="10.50" fill="white">log_set_disable_colors</text>
</a>
</g>
</g>
<!-- proc~logp -->
<g id="call~~graph~~CallGraph_node3" class="node"><title>proc~logp</title>
<g id="a_call~~graph~~CallGraph_node3"><a xlink:href="../proc/logp.html" xlink:title="logp">
<polygon fill="#d94e8f" stroke="#d94e8f" points="102,-108 48,-108 48,-84 102,-84 102,-108"/>
<text text-anchor="middle" x="75" y="-93.6" font-family="Helvetica,sans-Serif" font-size="10.50" fill="white">logp</text>
<g id="call~~graph~~CallGraph_node2" class="node"><title>proc~logp</title>
<g id="a_call~~graph~~CallGraph_node2"><a xlink:href="../proc/logp.html" xlink:title="logp">
<polygon fill="#d94e8f" stroke="#d94e8f" points="102,-66 48,-66 48,-42 102,-42 102,-66"/>
<text text-anchor="middle" x="75" y="-51.6" font-family="Helvetica,sans-Serif" font-size="10.50" fill="white">logp</text>
</a>
</g>
</g>
<!-- mpi_comm_rank -->
<g id="call~~graph~~CallGraph_node13" class="node"><title>mpi_comm_rank</title>
<polygon fill="#777777" stroke="#777777" points="278,-108 186,-108 186,-84 278,-84 278,-108"/>
<text text-anchor="middle" x="232" y="-93.6" font-family="Helvetica,sans-Serif" font-size="10.50" fill="white">mpi_comm_rank</text>
<polygon fill="#777777" stroke="#777777" points="278,-66 186,-66 186,-42 278,-42 278,-66"/>
<text text-anchor="middle" x="232" y="-51.6" font-family="Helvetica,sans-Serif" font-size="10.50" fill="white">mpi_comm_rank</text>
</g>
<!-- proc~logp&#45;&gt;mpi_comm_rank -->
<g id="call~~graph~~CallGraph_edge1" class="edge"><title>proc~logp&#45;&gt;mpi_comm_rank</title>
<path fill="none" stroke="#ffff00" d="M102.294,-96C122.335,-96 150.644,-96 175.612,-96"/>
<polygon fill="#ffff00" stroke="#ffff00" points="175.712,-99.5001 185.712,-96 175.712,-92.5001 175.712,-99.5001"/>
<path fill="none" stroke="#ff7f00" d="M102.294,-54C122.335,-54 150.644,-54 175.612,-54"/>
<polygon fill="#ff7f00" stroke="#ff7f00" points="175.712,-57.5001 185.712,-54 175.712,-50.5001 175.712,-57.5001"/>
</g>
<!-- proc~log_set_output_time -->
<g id="call~~graph~~CallGraph_node4" class="node"><title>proc~log_set_output_time</title>
<g id="a_call~~graph~~CallGraph_node4"><a xlink:href="../proc/log_set_output_time.html" xlink:title="log_set_output_time">
<polygon fill="#d9534f" stroke="#d9534f" points="129.5,-150 20.5,-150 20.5,-126 129.5,-126 129.5,-150"/>
<text text-anchor="middle" x="75" y="-135.6" font-family="Helvetica,sans-Serif" font-size="10.50" fill="white">log_set_output_time</text>
<g id="call~~graph~~CallGraph_node3" class="node"><title>proc~log_set_output_time</title>
<g id="a_call~~graph~~CallGraph_node3"><a xlink:href="../proc/log_set_output_time.html" xlink:title="log_set_output_time">
<polygon fill="#d9534f" stroke="#d9534f" points="129.5,-108 20.5,-108 20.5,-84 129.5,-84 129.5,-108"/>
<text text-anchor="middle" x="75" y="-93.6" font-family="Helvetica,sans-Serif" font-size="10.50" fill="white">log_set_output_time</text>
</a>
</g>
</g>
<!-- proc~logl -->
<g id="call~~graph~~CallGraph_node5" class="node"><title>proc~logl</title>
<g id="a_call~~graph~~CallGraph_node5"><a xlink:href="../proc/logl.html" xlink:title="logl">
<polygon fill="#d94e8f" stroke="#d94e8f" points="102,-192 48,-192 48,-168 102,-168 102,-192"/>
<text text-anchor="middle" x="75" y="-177.6" font-family="Helvetica,sans-Serif" font-size="10.50" fill="white">logl</text>
<g id="call~~graph~~CallGraph_node4" class="node"><title>proc~logl</title>
<g id="a_call~~graph~~CallGraph_node4"><a xlink:href="../proc/logl.html" xlink:title="logl">
<polygon fill="#d94e8f" stroke="#d94e8f" points="102,-150 48,-150 48,-126 102,-126 102,-150"/>
<text text-anchor="middle" x="75" y="-135.6" font-family="Helvetica,sans-Serif" font-size="10.50" fill="white">logl</text>
</a>
</g>
</g>
<!-- proc~stput -->
<g id="call~~graph~~CallGraph_node6" class="node"><title>proc~stput</title>
<g id="a_call~~graph~~CallGraph_node6"><a xlink:href="../proc/stput.html" xlink:title="stput">
<polygon fill="#d9534f" stroke="#d9534f" points="259,-192 205,-192 205,-168 259,-168 259,-192"/>
<text text-anchor="middle" x="232" y="-177.6" font-family="Helvetica,sans-Serif" font-size="10.50" fill="white">stput</text>
<g id="call~~graph~~CallGraph_node5" class="node"><title>proc~stput</title>
<g id="a_call~~graph~~CallGraph_node5"><a xlink:href="../proc/stput.html" xlink:title="stput">
<polygon fill="#d9534f" stroke="#d9534f" points="259,-150 205,-150 205,-126 259,-126 259,-150"/>
<text text-anchor="middle" x="232" y="-135.6" font-family="Helvetica,sans-Serif" font-size="10.50" fill="white">stput</text>
</a>
</g>
</g>
<!-- proc~logl&#45;&gt;proc~stput -->
<g id="call~~graph~~CallGraph_edge2" class="edge"><title>proc~logl&#45;&gt;proc~stput</title>
<path fill="none" stroke="#00ff00" d="M102.294,-180C127.644,-180 166.225,-180 194.537,-180"/>
<polygon fill="#00ff00" stroke="#00ff00" points="194.837,-183.5 204.836,-180 194.836,-176.5 194.837,-183.5"/>
<path fill="none" stroke="#7fff00" d="M102.294,-138C127.644,-138 166.225,-138 194.537,-138"/>
<polygon fill="#7fff00" stroke="#7fff00" points="194.837,-141.5 204.836,-138 194.836,-134.5 194.837,-141.5"/>
</g>
<!-- proc~log_set_skip_terminal_check -->
<g id="call~~graph~~CallGraph_node7" class="node"><title>proc~log_set_skip_terminal_check</title>
<g id="a_call~~graph~~CallGraph_node7"><a xlink:href="../proc/log_set_skip_terminal_check.html" xlink:title="log_set_skip_terminal_check">
<polygon fill="#d9534f" stroke="#d9534f" points="150,-234 1.42109e-14,-234 1.42109e-14,-210 150,-210 150,-234"/>
<text text-anchor="middle" x="75" y="-219.6" font-family="Helvetica,sans-Serif" font-size="10.50" fill="white">log_set_skip_terminal_check</text>
<g id="call~~graph~~CallGraph_node6" class="node"><title>proc~log_set_skip_terminal_check</title>
<g id="a_call~~graph~~CallGraph_node6"><a xlink:href="../proc/log_set_skip_terminal_check.html" xlink:title="log_set_skip_terminal_check">
<polygon fill="#d9534f" stroke="#d9534f" points="150,-192 1.42109e-14,-192 1.42109e-14,-168 150,-168 150,-192"/>
<text text-anchor="middle" x="75" y="-177.6" font-family="Helvetica,sans-Serif" font-size="10.50" fill="white">log_set_skip_terminal_check</text>
</a>
</g>
</g>
<!-- proc~tput -->
<g id="call~~graph~~CallGraph_node7" class="node"><title>proc~tput</title>
<g id="a_call~~graph~~CallGraph_node7"><a xlink:href="../proc/tput.html" xlink:title="tput">
<polygon fill="#d9534f" stroke="#d9534f" points="102,-234 48,-234 48,-210 102,-210 102,-234"/>
<text text-anchor="middle" x="75" y="-219.6" font-family="Helvetica,sans-Serif" font-size="10.50" fill="white">tput</text>
</a>
</g>
</g>
Expand Down
2 changes: 1 addition & 1 deletion doc/tipuesearch/tipuesearch_content.js

Large diffs are not rendered by default.

61 changes: 45 additions & 16 deletions include/flogging.h
Original file line number Diff line number Diff line change
@@ -1,17 +1,46 @@
/* This code is governed by the MIT license. See LICENSE for details. */
/* The lines below have little spacing to ease the line-length requirement */
/* There is no conflict with the fortran intrinsic log because that only has one argument */
#define log(level,format) if(logp(level))write(logu,format)trim(logl(level,__FILE__,__LINE__))//" ",
#define log_fatal(format) if(logp(LOG_FATAL))write(logu,format)trim(logl(LOG_FATAL,__FILE__,__LINE__))//" ",
#define log_error(format) if(logp(LOG_ERROR))write(logu,format)trim(logl(LOG_ERROR,__FILE__,__LINE__))//" ",
#define log_warn(format) if(logp(LOG_WARN))write(logu,format)trim(logl(LOG_WARN,__FILE__,__LINE__))//" ",
#define log_info(format) if(logp(LOG_INFO))write(logu,format)trim(logl(LOG_INFO,__FILE__,__LINE__))//" ",
#define log_debug(format) if(logp(LOG_DEBUG))write(logu,format)trim(logl(LOG_DEBUG,__FILE__,__LINE__))//" ",
#define log_trace(format) if(logp(LOG_TRACE))write(logu,format)trim(logl(LOG_TRACE,__FILE__,__LINE__))//" ",
#define log_root(level,format) if(logp(level,0))write(logu,format)trim(logl(level,__FILE__,__LINE__))//" ",
#define log_root_fatal(format) if(logp(LOG_FATAL,0))write(logu,format)trim(logl(LOG_FATAL,__FILE__,__LINE__))//" ",
#define log_root_error(format) if(logp(LOG_ERROR,0))write(logu,format)trim(logl(LOG_ERROR,__FILE__,__LINE__))//" ",
#define log_root_warn(format) if(logp(LOG_WARN,0))write(logu,format)trim(logl(LOG_WARN,__FILE__,__LINE__))//" ",
#define log_root_info(format) if(logp(LOG_INFO,0))write(logu,format)trim(logl(LOG_INFO,__FILE__,__LINE__))//" ",
#define log_root_debug(format) if(logp(LOG_DEBUG,0))write(logu,format)trim(logl(LOG_DEBUG,__FILE__,__LINE__))//" ",
#define log_root_trace(format) if(logp(LOG_TRACE,0))write(logu,format)trim(logl(LOG_TRACE,__FILE__,__LINE__))//" ",

/* Log level constants */
#define LOG_LEVEL_FATAL_DEF 1
#define LOG_LEVEL_ERROR_DEF 2
#define LOG_LEVEL_WARN_DEF 3
#define LOG_LEVEL_INFO_DEF 4
#define LOG_LEVEL_DEBUG_DEF 5
#define LOG_LEVEL_TRACE_DEF 6

/* The lines below have little spacing to ease the fortran line-length requirement */
#define log_fatal(format) if(logp(LOG_LEVEL_FATAL_DEF))write(logu,format)trim(logl(LOG_LEVEL_FATAL_DEF,__FILE__,__LINE__))//" ",
#define log_error(format) if(logp(LOG_LEVEL_ERROR_DEF))write(logu,format)trim(logl(LOG_LEVEL_ERROR_DEF,__FILE__,__LINE__))//" ",
#define log_warn(format) if(logp(LOG_LEVEL_WARN_DEF))write(logu,format)trim(logl(LOG_LEVEL_WARN_DEF,__FILE__,__LINE__))//" ",
#define log_info(format) if(logp(LOG_LEVEL_INFO_DEF))write(logu,format)trim(logl(LOG_LEVEL_INFO_DEF,__FILE__,__LINE__))//" ",

#ifdef DISABLE_LOG_DEBUG
#define log_debug(format) if(.false.)write(logu,format)trim(logl(LOG_LEVEL_DEBUG_DEF,__FILE__,__LINE__))//" ",
#else
#define log_debug(format) if(logp(LOG_LEVEL_DEBUG_DEF))write(logu,format)trim(logl(LOG_LEVEL_DEBUG_DEF,__FILE__,__LINE__))//" ",
#endif

#ifdef ENABLE_LOG_TRACE
#define log_trace(format) if(logp(LOG_LEVEL_TRACE_DEF))write(logu,format)trim(logl(LOG_LEVEL_TRACE_DEF,__FILE__,__LINE__))//" ",
#else
#define log_trace(format) if(.false.)write(logu,format)trim(logl(LOG_LEVEL_TRACE_DEF,__FILE__,__LINE__))//" ",
#endif



#define log_root_fatal(format) if(logp(LOG_LEVEL_FATAL_DEF,0))write(logu,format)trim(logl(LOG_LEVEL_FATAL_DEF,__FILE__,__LINE__))//" ",
#define log_root_error(format) if(logp(LOG_LEVEL_ERROR_DEF,0))write(logu,format)trim(logl(LOG_LEVEL_ERROR_DEF,__FILE__,__LINE__))//" ",
#define log_root_warn(format) if(logp(LOG_LEVEL_WARN_DEF,0))write(logu,format)trim(logl(LOG_LEVEL_WARN_DEF,__FILE__,__LINE__))//" ",
#define log_root_info(format) if(logp(LOG_LEVEL_INFO_DEF,0))write(logu,format)trim(logl(LOG_LEVEL_INFO_DEF,__FILE__,__LINE__))//" ",

#ifdef DISABLE_LOG_DEBUG
#define log_root_debug(format) if(.false.)write(logu,format)trim(logl(LOG_LEVEL_DEBUG_DEF,__FILE__,__LINE__))//" ",
#else
#define log_root_debug(format) if(logp(LOG_LEVEL_DEBUG_DEF,0))write(logu,format)trim(logl(LOG_LEVEL_DEBUG_DEF,__FILE__,__LINE__))//" ",
#endif

#ifdef ENABLE_LOG_TRACE
#define log_root_trace(format) if(logp(LOG_LEVEL_TRACE_DEF,0))write(logu,format)trim(logl(LOG_LEVEL_TRACE_DEF,__FILE__,__LINE__))//" ",
#else
#define log_root_trace(format) if(.false.)write(logu,format)trim(logl(LOG_LEVEL_TRACE_DEF,__FILE__,__LINE__))//" ",
#endif
Loading

0 comments on commit a7d8d83

Please sign in to comment.