Reputation: 3747
I am writing a module that allows users to log information. I want to provide an interface that logs a string message, which can be called as
call m_log(msg)
So in file m_logger.f90, I will have
module m_logger
..
subroutine m_log(msg)
..
end module
In file main.f90, a user will have
program main
use m_logger
call m_log(msg)
end program
Now how can I substitute call m_log(msg)
with call m_log(msg, __FILE__, __LINE__)
?
Because of this substitution, a different subroutine subroutine m_log(msg, filename, linenum)
in the logger module will be called instead.
If I use a macro like #define m_log(msg) m_log(msg,__FILE__,__LINE__)
, it will have to be added to every user file that uses the logger.
Also, I do not want to enforce the user to pass __FILE__
and __LINE__
explicitly.
Is there a way I can do this? Or are there any other alternatives altogether?
Thanks in advance
Edit: I had a discussion on comp.lang.fortran. Adding a link for reference. here
Upvotes: 3
Views: 1579
Reputation: 527
Since you want them to be passed as compiler macros by the user, you would first have to choose different names for your macros. __FILE__
and __LINE__
are both predefined macros. These two macros are defined by preprocessor, not passed by the user. I think that might have cause some confusion.
If you would like to allow users to optionally supply the macros through compiler options, it is probably best to include #ifdef
directive in your subroutine:
subroutine m_log(msg)
implicit none
character(len=*) :: msg
character(len=something) :: file
integer ::line
!Initialize file and line to some default value
file=...
line=...
#ifdef __KVM_FILE__
file=__KVM_FILE__
#endif
#ifdef __KVM_LINE__
line=__KVM_LINE__
#endif
...
This way the user will always call the subroutine with the same syntax call m_log(something)
, but the effect will change according to your compilation macros. Of course, that would also require the user to recompile your code every time they change this macro. If this is too costly to do, you can set up a subroutine with optional argument (as in Kyle's answer), then enclose #define
macro in #ifdef
blocks, and put them into an .h file, and have your user always include that file. (similar to Vladimir's answer)
Upvotes: 0
Reputation: 60058
In this case you would have to use the same approach C uses. Define the macro you proposed
#define log(msg) m_log(msg,__FILE__,__LINE__)
in a separate file (possibly with other useful macros) and include it using #include "file.inc"
(standard Fortran include won't suffice).
If the macro has a different name, than the subroutine it actually calls, you can ensure that the user has to use the include and cannot forget it.
Upvotes: 4
Reputation: 3264
If you don't want to force __file__
and __line__
explicitly, then you can use the optional flag, such that your subroutine looks like:
subroutine m_log(msg, filename, linenum)
character(len=*) :: msg
character(len=*), optional :: filename
integer, optional :: linenum
if(present(filename)) then
<something with filename>
endif
if(present(linenum)) then
<something with linenume>
endif
<normal stuff with msg>
end subroutine
The intrinsic function present returns a true value if filename
or linenum
have any values attached to it, returning false otherwise.
Upvotes: 3