Fortran query and print out function or subroutine name - debugging

Is it possible in Fortran to query the name of the function or subroutine that I am in? I.e., what do I put in place of '???' to get it to print 'my_subroutine' on the screen?
subroutine my_subroutine()
write(*,*) ???
end subroutine my_subroutine
I am trying to find a way to implement a custom debugger/profiler using nothing but a text editor's search and replace mechanism. Programmatically querying my position in the code would be helpful.

No, you can't. What you want to achieve is called reflection and it is not available in Fortran (nor in C or C++ for what matters).

You can use the preprocessor to print out the file name and line number. You might want take advantage of the predefined preprocessor symbols __LINE__ and __FILE__. Here's an example:
A preprocessor macro is defined in header file (so that it can be used in multiple locations), call it errormsg.h:
#define ERRORMSG(msg) write(0,'("There was an error at ",I4," in file ",/,A,/,"Error message: ",A)') __LINE__,__FILE__,msg
Then you can include this header file in your program, library or module files, for example:
#include "errormsg.h"
program main
ERRORMSG("not really an error...")
call foo()
end program
subroutine foo()
ERRORMSG("not an error too!")
end subroutine
The ERRORMSG("not really an error...") seems like weird syntax for fortran code, but it get's replaced by the c-preprocessor using the macro definition. So when this is compiled, it looks like:
write(0,'("There was an error at ",I4," in file ",/,A,/,"Error message: ",A)') __LINE__,__FILE__,"not really an error"
For my ERRORMSG macro, I chose to use the 0 file unit to print to stderr. You obviously have the freedom to write the message how ever you like, as long as it results in syntactical correct FORTRAN code.
Getting this to compile requires you to pass flags to the compiler, and they differ slightly from compiler to compiler. This worked for me, for example:
gfortran -cpp -o errorTest errorTest.f90
That is, for gfortran, -cpp invokes the c-preprocessor before compiling. The output from the above program looks like this:
There was an error at 5 in file
errorTest.f90
Error message: not really an error...
There was an error at 13 in file
errorTest.f90
Error message: not an error too!
This might have the effect you are looking for, especially if you write only one subroutine per file.

I found an easy semi-automated way out of this situation: use regex to add a hardcoded definition of __FUNCTION__ right after the SUBROUTINE declaration. Done from within the makefile will take care that every compilation refreshes the __FUNCTION__ macro.
Suppose we have a F77 listing that looks like this
file 'my-file.F'
SUBROUTINE my_sub(var1, var2, var3)
INCLUDE 'some-include.PRM'
INTEGER var1
INTEGER var2
! the rest of my code here
WRITE(*,*)__FUNCTION__
END SUBROUTINE
I want to convert it to
file 'my_file.F.F'
SUBROUTINE my_sub(var1, var2, var3)
#undef __FUNCTION__
#define __FUNCTION__ "my_sub"
INCLUDE 'some-include.PRM'
INTEGER var1
INTEGER var2
! the rest of my code here
WRITE(*,*)__FUNCTION__
END SUBROUTINE
Note the amended code is now located in another source file: my-file.F.F
To do this I added the following lines to 'Makefile'
my-file.o: my-file.F
perl -pne 's/^(\s+SUBROUTINE\s*)([^(]+)(\(.*\))/$$1$$2$$3\n#undef __FUNCTION__\n#define __FUNCTION__ _S($$2)/ixms' $< > $<.F; \
$(FC) $(CPPFLAGS) $(FCFLAGS) -c $<.F -o $#
Assuming FC is defined as the fortran compiler executable, this should perform the following procedure on all the subroutines in the file:
undefine a __FUNCTION__ macro that was possibly defined earlier.
Add a __FUNCTION__ directive two lines below the SUBROUTINE definition, containing the subroutine's name.
save the file under another name.
compile the new source into the required object file.
The result should be my-file.o in this case.
You may have noticed that I'm using the macro _S() as well. This is a 'stringify' macro. You just need to add it to the top of your fortran file (I place it inside a config.h that I include everywhere)
There is a different implementation for GNU and intel:
#ifdef __INTEL_COMPILER
#define _S(x) #x
#else
#define _S(x) "x"
#endif

There are sometimes non-standard features in compilers to help you to print where you currently are. These are highly compiler specific and should be used only for debugging.
In gfortran you can use subroutine BACKTRACE. From the manual:
BACKTRACE shows a backtrace at an arbitrary place in user code.
Program execution continues normally afterwards.
The output will look like an error message, but it may be helpful.

Why don't you just hard write the name of the subroutine you're in, in the WRITE statement?
You cannot programmatically (dynamically) give or change the name of the subroutine, therefore I see no reason to try to access it either that way (about that: while I'm not sure that it is impossible to access it somehow, I'm quite sure that it is the wrong way to go ... you will cause yourself more trouble going that way, than just hard coding it).
Btw, why are you trying to print it out anyway? Wouldn't a well phrased diagnostic message be more informative?

Related

Getting "cannot find symbol .... while executing load ..." error when trying to run Hello World as a C extension (dll) example

I have used the C code from the following verbatim: https://wiki.tcl-lang.org/page/Hello+World+as+a+C+extension
/*
* hello.c -- A minimal Tcl C extension.
*/
#include <tcl.h>
static int
Hello_Cmd(ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
{
Tcl_SetObjResult(interp, Tcl_NewStringObj("Hello, World!", -1));
return TCL_OK;
}
/*
* Hello_Init -- Called when Tcl loads your extension.
*/
int DLLEXPORT
Hello_Init(Tcl_Interp *interp)
{
if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
return TCL_ERROR;
}
/* changed this to check for an error - GPS */
if (Tcl_PkgProvide(interp, "Hello", "1.0") == TCL_ERROR) {
return TCL_ERROR;
}
Tcl_CreateObjCommand(interp, "hello", Hello_Cmd, NULL, NULL);
return TCL_OK;
}
My command for compiling is nearly verbatim except for the last character, indicating Tcl version 8.6 rather than 8.4, and it compiles without error:
gcc -shared -o hello.dll -DUSE_TCL_STUBS -I$TCLINC -L$TCLLIB -ltclstub86
Then I created the following Tcl program:
load hello.dll Hello
puts "got here"
But when running it with tclsh get the following error:
cannot find symbol "Hello_Init"
while executing
"load ./hello.dll Hello"
(file "hello.tcl" line 1)
So I am essentially following a couple of suggestions from Donal Fellows answer here: cannot find symbol "Embeddedrcall_Init" The OP there however commented that, like me, the suggestion(s) hadn't resolved their issue. One thing that I didn't try from that answer was "You should have an exported (extern "C") function symbol in your library" -- could that be the difference maker? Shouldn't it have been in the example all along then?
At the suggestion of somebody on comp.lang.tcl I found "DLL Export Viewer" but when I run it against the DLL it reports 0 functions found :( What am I doing wrong?
Could it be an issue with MinGW/gcc on Windows, and I need to bite the bullet and do this with Visual Studio? That's overkill I'd like to avoid if possible.
The core of the problem is that your function Hello_Init is not ending up in the global symbol table exported by the resulting DLL. (Some linkers would put such things in as _Hello_Init instead of Hello_Init; Tcl adapts to them transparently.) The symbol must be there for Tcl's load command to work: without it, there's simply no consistent way to tell your extension code what the Tcl_Interp context handle is (which allows it to make commands, variables, etc.)
(If you'd been working with C++, one of the possible problem is a missing extern "C" whose actual meaning is to turn off name mangling. That's probably not the problem here.)
Since you are on Windows — going by the symbols in your DLL, such as EnterCriticalSection and GetLastError — the problem is probably linked to exactly how you are linking. I'm guessing that Tcl is defining your function to have __declspec(dllexport) (assuming you've not defined STATIC_BUILD, which absolutely should not be used when building a DLL) and yet that's not getting respected. Assuming you're using a modern-enough version of GCC… which you probably are.
I'm also going through the process of how to build tcl extensions in C and had exactly the same problem when working though this same example using tcl 8.6.
i.e. I was compiling using MinGW GCC (64-bit), and used the following:
gcc -shared -o hello.dll -DUSE_TCL_STUBS "-IC:\\ActiveTcl\\include" "-LC:\\ActiveTcl\\lib" -ltclstub86
And like the OP I got no compile error, but when loading the dll at a tclsh prompt tcl complained :
'cannot find symbol "Hello_Init"'
I can't say that I understand, but I was able to find a solution that works thanks to some trial and error, and some information on the tcl wiki here
https://wiki.tcl-lang.org/page/Building+Tcl+DLL%27s+for+Windows
In my case I had to adjust the compiler statement to the following
gcc -shared -o hello.dll hello.c "-IC:\\ActiveTcl\\include" "-LC:\\ActiveTcl\\bin" -ltcl86t
Obviously those file paths are specific to my system, but basically
I had to add an explicit reference to the .c file
I had to include the tcl86t dll library from the tcl bin directory
I had to remove the -DUSE_TCL_STUBS flag ( meaning that the references -LC:\\ActiveTcl\\lib and -ltclstub86 could also be removed)
(attempting to use the -DUSE_TCL_STUBS flag caused the compiler to complain with C:\ActiveTcl\lib/tclstub86.lib: error adding symbols: File format not recognized )
This successfully compiled a dll that I could load, and then call the hello function to print my 'Hello World' message.
Something else I stumbled over, and which wasn't immediately obvious:
reading https://www.tcl.tk/man/tcl8.6/TclCmd/load.htm, tcl epxects to find an 'init' function based on a certain naming convention.
if the C extension does not define a package name then the name of that init function will be derived from the dll filename.
This caused a few problems for me (when compiling via Eclipse IDE), as the dll name was being automatically determined from the eclipse projet name.
For example, if I recompile the same example, but call the .dll something else, eg.
gcc -shared -o helloWorldExenstion.dll hello.c "-IC:\\ActiveTcl\\include" "-LC:\\ActiveTcl\\bin" -ltcl86t
Then at tclsh prompt:
% load helloWorldExtension
cannot find symbol "Helloworldextension_Init"

Pre-processing C code with GCC

I have some C source files that need to be pre-processed so that I can use another application to add Code Coverage instrumentation code in my file.
To do so, I use GCC (I'm using this on a LEON2 processor so it's a bit modified but it's essentially GCC 3.4.4) with the following command line:
sparc-elf-gcc -DUNIT_TEST -I. ../Tested_Code/0_BSW/PKG_CMD/MEMORY.c -E > MEMORY.i
With a standard file this works perfectly, but this one the programmer used a #ifndef UNIT_TEST close and no matter what I do the code won't be pre-processed. I don't understand why since I'm passing -DUNIT_TEST to GCC explicitly defining it.
Does anyone have any clue what could cause this? I checked the resulting .i file and as expected my UNIT_TEST code is not present in it so I get an error when instrumenting it.
Anything wrapped in an #ifndef will only be parsed if it's NOT defined so you need to remove that definition to get all the code that is inside that block. GCC can't spit out preprocessed info for all the #ifdef and #ifndef if at preprocessing times symbols are/aren't defined.

How to get only file name in preprocessor?

I am (was) using the __FILE__ and __LINE__ macros for printing diagnostic messages out of my code. This works quite well when you use GCC with make, the file is as short as you specified it on the command line. I recently switched to using CodeLite which uses fully qualified file names (at least under windows) when building. Suddenly my diagnostic output is almost not readable.
It there a way to get only the file component of the filename in the preprocessor? I can live with a non portable GCC specific solution. (I will fallback to plain __FILE__ other cases.)
Sure I can pass the contents of __FILE__ through a function and extract only the file component, but string operations was not what I had in mind for diagnostic messages that should not change runtime behavior...
NOTE: I use the filename the way GNU uses it. A Path is collection of filenames and a filename is either a relative or absolute identifier of a file. A filename can be made up of a directory component and file component.
If you are using GNU Make then you can simply pass -D BASE_FILE_NAME=\"$*.c\" in on the preprocessing stage of compilation (if you're doing them separately, or at compilation if in a single stage, which is the norm).
This depends upon the way you have your file names determined. Mine come from a list of plain file names and are prefixed with directories using functions in the makefile at a later stage.
IE, this works well for me, but your mileage may vary! :-)
A simplified version of my make "code" :
CLASSES = main.c init.c
PREPROCESSED = $(patsubst %.c,$(PPCDIR)/%.pp.c,$(CLASSES))
$(PREPROCESSED): $(PPCDIR)/%.pp.c: %.c $(ALLH)
$(GCC) $(GCCOPTS) -D BASE_FILE_NAME=\"$*\" -E $< > $#
The simply use BASE_FILE_NAME in your code as you like :-)
There is no known preprocessor macro that provides the functionality. Passing __FILE__ through a function seams like the only sensible option.
In reply to FredCooke above, you can exchange this line:
-D BASE_FILE_NAME=\"$*.c\"
With:
-D BASE_FILE_NAME=\"$(<F)\"
This will give you proper file name expansion, for .cpp as well.
As has already been mentioned in other answers, the only portable way to do this is by passing in a define from the compiler, there are however compiler spesific extensions:
Clang: __FILE_NAME__
GCC: __BASE_FILE__

How to force gcc to link like g++?

In this episode of "let's be stupid", we have the following problem: a C++ library has been wrapped with a layer of code that exports its functionality in a way that allows it to be called from C. This results in a separate library that must be linked (along with the original C++ library and some object files specific to the program) into a C program to produce the desired result.
The tricky part is that this is being done in the context of a rigid build system that was built in-house and consists of literally dozens of include makefiles. This system has a separate step for the linking of libraries and object files into the final executable but it insists on using gcc for this step instead of g++ because the program source files all have a .c extension, so the result is a profusion of undefined symbols. If the command line is manually pasted at a prompt and g++ is substituted for gcc, then everything works fine.
There is a well-known (to this build system) make variable that allows flags to be passed to the linking step, and it would be nice if there were some incantation that could be added to this variable that would force gcc to act like g++ (since both are just driver programs).
I have spent quality time with the gcc documentation searching for something that would do this but haven't found anything that looks right, does anybody have suggestions?
Considering such a terrible build system write a wrapper around gcc that exec's gcc or g++ dependent upon the arguments. Replace /usr/bin/gcc with this script, or modify your PATH to use this script in preference to the real binary.
#!/bin/sh
if [ "$1" == "wibble wobble" ]
then
exec /usr/bin/gcc-4.5 $*
else
exec /usr/bin/g++-4.5 $*
fi
The problem is that C linkage produces object files with C name mangling, and that C++ linkage produces object files with C++ name mangling.
Your best bet is to use
extern "C"
before declarations in your C++ builds, and no prefix on your C builds.
You can detect C++ using
#if __cplusplus
Many thanks to bmargulies for his comment on the original question. By comparing the output of running the link line with both gcc and g++ using the -v option and doing a bit of experimenting, I was able to determine that "-lstdc++" was the magic ingredient to add to my linking flags (in the appropriate order relative to other libraries) in order to avoid the problem of undefined symbols.
For those of you who wish to play "let's be stupid" at home, I should note that I have avoided any use of static initialization in the C++ code (as is generally wise), so I wasn't forced to compile the translation unit containing the main() function with g++ as indicated in item 32.1 of FAQ-Lite (http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html).

How to utilize prepocessor variables when using Intel Visual Fortran

I would like to compile a Fortran 90 (fixed format) library under Windows. However, I cannot understand the error of prepocessor variables.
Say the sample file is VF_TestPreprocessor.F:
program VF_TestPreprocessor
implicit Integer(A-Z)
Parameter (TestAlpha=22,TestBeta=TestGamma)
print *, TestBeta
end program VF_TestPreprocessor
Under Linux, I can use ifort VF_TestPreprocessor.F -DTestGamma=25 to compile, and run.
However, under windows, I cannot use ifort VF_TestPreprocessor.F /DTestGamma=25 to compile. The error message is error #6592: This symbol must be a defined parameter, an enumerator, or an argument of an inquiry function that evaluates to a compile-time constant. [TestGamma]. Could you help to analyse the error?
It looks like ifort doesn't run the preprocessor. I have no experience with ifort, but this page (the first hit in Google on ifort preprocessor) says that on Windows the preprocessor is only run on files ending in an extension of .fpp.
So, I guess there are (at least) two solutions:
Rename your files to end in .fpp;
invoke ifort with the /fpp switch.

Resources