preprocessor: convert to capitals
In the ublas forum we're having a discussion on the best way to provide signatures in C for fortran libraries (like BLAS and LAPACK). For linking C with fortran, you sometimes need to add an underscore to the function in C, but on other platforms fortran will store the function-name in capitals. Thus on different platforms, we should preprocess our source to take the platforms' convention into account and we thus would need a macro to convert an identifier automatically to uppercase. Is that possible ? toon -- Toon Knapen http://www.fft.be Free Field Technologies tel:+32 10 45 12 26 16 Place de l'Universite fax:+32 10 45 46 26 1348 Louvain-la-Neuve http://www.femtown.org Belgium
Toon Knapen wrote:
In the ublas forum we're having a discussion on the best way to provide signatures in C for fortran libraries (like BLAS and LAPACK). For linking C with fortran, you sometimes need to add an underscore to the function in C, but on other platforms fortran will store the function-name in capitals.
Thus on different platforms, we should preprocess our source to take the platforms' convention into account and we thus would need a macro to convert an identifier automatically to uppercase. Is that possible ?
AFAIK the C++ preprocessor does not support such operations directly. It acts on preprocessor tokens and not on parts of them (which were needed to convert every character to it's uppercase representation). But what about using the Wave preprocessor for this task (http://spirit.sourceforge.net/index.php?doc=docs/wave_v0_9/index.html)? It's a matter of a day or so (if you're interested to try it), to add some non-Standard feature to Wave, which helps to overcome your problems. This may be implemented as an additional operator _Pragma: _Pragma("wave tolower(WHATEVER)") and _Pragma("wave toupper(whatever)") which then should expand to the expected result. Your other problem (the addition of a leading underscore) is certainly solvable with the help of the preprocessor. Regards Hartmut
Toon Knapen wrote:
In the ublas forum we're having a discussion on the best way to provide signatures in C for fortran libraries (like BLAS and LAPACK). For linking C with fortran, you sometimes need to add an underscore to the function in C, but on other platforms fortran will store the function-name in capitals.
Thus on different platforms, we should preprocess our source to take the platforms' convention into account and we thus would need a macro to convert an identifier automatically to uppercase. Is that possible ?
It is not _generally_ possible to pull apart the an arbitrary identifier. However, if the identifier is _already_ pulled apart, it is possible. E.g. dealing with "identifier" is not possible in a general fashion; dealing with "i d e n t i f i e r" is possible, and the identifier itself could be abstracted to something like: FORTRAN_ID( identifier ) For example, if you have these identifiers: abc, xyz, pqr #define FORTRAN_ID_abc a b c #define FORTRAN_ID_xyz x y z #define FORTRAN_ID_pqr p q r You can get: FORTRAN_ID( abc ) >> abc, _abc, or ABC FORTRAN_ID( xyz ) >> xyz, _xyz, or XYZ FORTRAN_ID( pqr ) >> pqr, _pqr, or PQR If that sounds okay, I can implement it for you. Regards, Paul Mensonides
On Tuesday 08 April 2003 21:42, Paul Mensonides wrote:
Toon Knapen wrote:
In the ublas forum we're having a discussion on the best way to provide signatures in C for fortran libraries (like BLAS and LAPACK). For linking C with fortran, you sometimes need to add an underscore to the function in C, but on other platforms fortran will store the function-name in capitals.
Thus on different platforms, we should preprocess our source to take the platforms' convention into account and we thus would need a macro to convert an identifier automatically to uppercase. Is that possible ?
It is not _generally_ possible to pull apart the an arbitrary identifier. However, if the identifier is _already_ pulled apart, it is possible. E.g. dealing with "identifier" is not possible in a general fashion; dealing with "i d e n t i f i e r" is possible, and the identifier itself could be abstracted to something like:
FORTRAN_ID( identifier )
For example, if you have these identifiers:
abc, xyz, pqr
#define FORTRAN_ID_abc a b c #define FORTRAN_ID_xyz x y z #define FORTRAN_ID_pqr p q r
You can get:
FORTRAN_ID( abc ) >> abc, _abc, or ABC FORTRAN_ID( xyz ) >> xyz, _xyz, or XYZ FORTRAN_ID( pqr ) >> pqr, _pqr, or PQR
If that sounds okay, I can implement it for you.
OK, so there are 3 different possibilities here : 1) all manual For the bindings we #ifdef on the platform to determine how to convert identifiers (to match their fortran counterpart) and then define an identifier for every function (with the additonal underscore ...) e.g. #ifdef __sgi #define DAXPY daxpy_ #endif 2) Wave (as suggested by Hartmut Kaiser) Use wave to create a header from an input-file. This puts a strong dependency on Wave and although the tool is impressive, this will make it difficult for people to add a new binding IMHO. 3) Suggestion above of Paul Mensonidis This option will give us minimal work, we could just write IIUC FORTRAN_ID( d a x p y ). (Paul: could we leave out the seperation of the characters if we always provide seperated characters directly as in the line above ?) However, this solution might limit portability. Although I'm used to option 1, I would like to go for option 3 (although maybe looking at the portability of the pp lib would not hurt) Opinions ?
Toon Knapen wrote:
1) all manual For the bindings we #ifdef on the platform to determine how to convert identifiers (to match their fortran counterpart) and then define an identifier for every function (with the additonal underscore ...)
e.g. #ifdef __sgi #define DAXPY daxpy_ #endif
2) Wave (as suggested by Hartmut Kaiser) Use wave to create a header from an input-file. This puts a strong dependency on Wave and although the tool is impressive, this will make it difficult for people to add a new binding IMHO.
Actually, what Hartmut is working on now is a general mechanism for the preprocessor to call external programs. The tolower, toupper types of things fit into this mold perfectly.
3) Suggestion above of Paul Mensonidis This option will give us minimal work, we could just write IIUC FORTRAN_ID( d a x p y ). (Paul: could we leave out the seperation of the characters if we always provide seperated characters directly as in the line above ?) However, this solution might limit portability.
Yes, you could do it either way and it won't effect portibility. I just thought that you want syntactic "cleanliness", without having to do this: # if /* style == leading-underscore */ # define FUNCTION _function # elif /* style == all-caps */ # define FUNCTION FUNCTION # else # define FUNCTION function # endif ...for every identifier used. For maximum syntactic cleanliness, you need a minimum of one macro per identifier: #define DAXPY FORTRAN_ID(d a x p y _) But this is just a shorthand for directly using FORTRAN_ID(...).
Although I'm used to option 1, I would like to go for option 3 (although maybe looking at the portability of the pp lib would not hurt)
I'm not sure what you mean here. I would use the pp-lib of course. In fact, I'd add a few things to it that should probably be added anyway. Regards, Paul Mensonides
Paul Mensonides wrote:
1) all manual For the bindings we #ifdef on the platform to determine how to convert identifiers (to match their fortran counterpart) and then define an identifier for every function (with the additonal underscore ...)
e.g. #ifdef __sgi #define DAXPY daxpy_ #endif
2) Wave (as suggested by Hartmut Kaiser) Use wave to create a header from an input-file. This puts a strong dependency on Wave and although the tool is impressive, this will make it difficult for people to add a new binding IMHO.
Actually, what Hartmut is working on now is a general mechanism for the preprocessor to call external programs. The tolower, toupper types of things fit into this mold perfectly.
There now is a special pragma: _Pragma("wave system(toupper whatever)") Where toupper is an external command, which converts the arguments supplied on the command line to upper case and puts the result into the stdout stream. Wave intercepts the stdout of the spawned command and uses this as the replacement text for the whole pragma. This way you may write (as suggested by Paul Mensonides): #define TO_UPPER(id) \ _Pragma( \ BOOST_PP_STRINGIZE(wave system(toupper id)) \ ) \ /**/ # if /* style == _func */ # define FORTRAN(id) BOOST_PP_CAT(_, id) # elif /* style == FUNC */ # define FORTRAN(id) TO_UPPER(id) # else # define FORTRAN(id) id # endif Ok, using Wave involves one more build step, but your source is more clean this way, because you do not have to write things like FORTRAN_ID( d a x p y ) Which is error prone and not obvious. If you're planning to provide the generated headers anyway (just like the MPL does for different compilers), so the Wave execution step is to be done _once_ for every binding, which shouldn't introduce any new problems. Moreover, the Wave executable does not need to be installed on the target machine. BTW: I expect to ask for a Boost rewiew for Wave soon, so maybe it will be a part of Boost anyway.
3) Suggestion above of Paul Mensonidis This option will give us minimal work, we could just write IIUC FORTRAN_ID( d a x p y ). (Paul: could we leave out the seperation of the characters if we always provide seperated characters directly as in the line above ?) However, this solution might limit portability.
Yes, you could do it either way and it won't effect portibility. I just thought that you want syntactic "cleanliness", without having to do this:
# if /* style == leading-underscore */ # define FUNCTION _function # elif /* style == all-caps */ # define FUNCTION FUNCTION # else # define FUNCTION function # endif
...for every identifier used. For maximum syntactic cleanliness, you need a minimum of one macro per identifier:
#define DAXPY FORTRAN_ID(d a x p y _)
But this is just a shorthand for directly using FORTRAN_ID(...).
Although I'm used to option 1, I would like to go for option 3 (although maybe looking at the portability of the pp lib would not hurt)
I'm not sure what you mean here. I would use the pp-lib of course. In fact, I'd add a few things to it that should probably be added anyway.
Regards Hartmut
participants (3)
-
HartmutKaiser@t-online.de
-
Paul Mensonides
-
Toon Knapen