If C-preprocessing is part of the C standard, why is it considered non-standard for Fortran?

Occasionally I read about source preprocessing being desired to be part of the Fortran standard, thanks to its ubiquitousness in Fortran software and usefulness to auto-generate code at or before compile-time. For example, @gak wrote in Which five features should Fortran 202Y implement? - #54 by gak :

I agree that this would be a good thing. But reading this, I thought: C preprocessing is part of the C-standard. Why is it then non-standard when used in Fortran code? Sure, it’s not in the Fortran standard. But, would you not call a Fortran program with C-preprocessing directives a standard-conforming mixed Fortran-C program?

A counter-argument could be that a source file with standard-conforming Fortran code mixed with standard-conforming C code, as a whole is not standard-conforming with either language.

In an analogy with MPI, one reason (among many others) to not standardize MPI in Fortran is that MPI is already its own standard. Could we then argue that C-preprocessing should not be standardized in Fortran because it’s already standardized in C?

4 Likes

IMO, a C style preprocessor would be a major mistake for Fortran. It was relatively OK for the time, but modern AST based pre-processors (eg lisp based macro systems) are significantly more powerful and less error prone.

3 Likes

This falls into a meta-category of things that I wish we standardized more, for the sake of program portability.

Preprocessing needs to be aware of Fortran source code requirements. The compilers that already support cpp-like preprocessing implement it inconsistently. Peter Klausler put together a fine proposal of the behaviors that the preprocessor should have and a survey of the behavior that several compilers do have.

There are other places in the Fortran standard where we reference the C standard. I just don’t think it would be sufficient for Fortran program portability just to reference the C standard as our standard in this regard.

I’d love to be wrong about that.

3 Likes

See also this issue:

1 Like

A separate consideration from the question in the original post is this.

A vision for the standard can be a state where preprocessing is entirely unnecessary.

With such a vision, it makes sense to me to not include any preprocessor support in the standard.

Should the language evolve to include

  1. good support for Generics and
  2. enhanced processor-stage (e.g., compile-time) computing instructions in standard language e.g., the equivalent of working with system/program environment/constant definitions (basic #define CPP stuff),

Then in the domains I am familiar with, the work practice can move toward Fortran source that includes NO preprocessing whatsoever and this will be viewed highly favorably in support of Fortran.

Preprocessing introduces a language (often Turing incomplete) within a language and it does affect overall productivity negatively - there is adverse impact on readability and maintainability with the use of preprocessors.

It is nearly there now with current standard and enhanced interoperability with C, meaning there are Fortran codebases that strive to avoid preprocessing generally, however they can’t help but carefully and in a highly controlled manner limit some amount of preprocessing (or directive-enhanced compilation) carefully to a few processor-specific (e.g., OS-specific, whether Windows vs *UX) sources only. But this does come at a certain price because of language limitations such as with Generics e.g., code duplication or the use of INCLUDE files in executable sections of code and avoiding processors that do not offer Fortran 2018 support.

Better language enhancement that overcomes the need for preprocessing can be a better direction.

6 Likes

I think that is everyone’s hope. The problem is partly because innovations in computing arise faster than the standard adapts to; or are temporial themselves and should not become part of the standard. The model-related intrinsics and the addition of kinds along with the reduction in the types of platforms available reduced one of the most common reasons to conditionally compile but then without a standard POSIX-like library everyone needed preprocessing to handle C interfaces. As the ISO_C_BINDING is becoming more common that need has been greatly reduced but replaced by user-written standard interfaces that can be quite cumbersome to produce; but then there are GPU-specific interfaces or a need to support multiple parallel interfaces (which co-arrays will hopefully reduce); as most other languages have made it much easier to place documentation into source as plain text or markdown (or LaTex, …) Fortran does not have a block text method supported; and so on. I have thought I was done with conditional compilation more than once. If would have been useful each time if even a basic pre-processor had been available that was standardized. I definitely want Fortran code to be free of preprocessing directives and think it has made great if slow progress in that direction, but I no longer expect it will be unneeded any time soon, particularly without an accepted stdlib (which would very likely require preprocessing to produce even if it isolated general users from it). So I absolutely agree and have been a proponent of the goal to not require preprocessing, I just do not expect it to be met. A lot of people that may never have needed preprocessing seem to need it now for the current stdlib project to template generic routines, interface to basic file system and OS features, generate semi-automated documentation, … . When do you think that will be unneeded even if (as I think it is) that it is and has been an active if unstated goal of the Fortran standard? I was once just as optimistic of the same goal.

1 Like

I personally have found that a proprocessor simplifies the code and the maintenance of codes. Mostly this involves conditional compilation. Any time you want the code to work one way for one combination of hardware and software and a different way for another combination, then conditional compilation can be the best solution. But there are other uses too. Here is one example of something that I do fairly often during development.

module xxx
   ... module stuff here...
end module xxx
#ifdef TESTMODULE
program testxxx
   use xxx
   ...code to test the module...
end program testxxx
#endif

As I’m developing the module, I define the macro TESTMODULE and I can compile and test the code all at once. Then after it is working, I leave the code unchanged, but simply don’t define the macro, and I just get the module code to be used in the normal way. It is all self-contained in one file, with no complicated shell scripts or anything to control the process.

I think the fortran preprocessor project failed for a couple of reasons. First, it was not universally supported. At the time, I was supporting my codes on a dozen or more different machines, all of which supported the de facto C preprocessor syntax and none of which supported the proposed fortran preprocessor. I was even willing to switch if it worked well, because the C preprocessor itself has some problems, but it never got to the point where it was a practical alternative.

Then the other reason it failed is that most of the fortran committee seemed to think that the language was flexible enough so that a preprocessor was unnecessary. Once support within the committee evaporated to below critical mass, they were quick to withdraw the proposal. As a programmer, struggling to support code on multiple machines, I did not agree with the committee on this point. And I have to admit that I still do not agree now, some 20+ years later, although I do agree that the language evolution since f77 has resulted in less need for a preprocessor. But less is not zero, so even now, there is a need for a standard preprocessor that works well with fortran codes.

2 Likes

I’m not sure this is a good analogy sibce the MPI standard has been designed for compatibility with Fortran. See Chapter 19 of the MPI 4.0 document (as PDF, 4.3 MB, 1139 pages). There are other reasons to keep the Fortran and MPI standards separate, separation of concerns being one of them, and keeping the language lightweight a second one. (The words of Dennis Ritchie on C seem fitting here.)

The C standard on the other hand, is oblivious of the fact that Fortran exists, and that pseudo cpp-like processors are being (mis)used by Fortran practitioners for lack of better alternative. Quoting from gcc.gnu.org:

The C preprocessor is intended to be used only with C, C++, and Objective-C source code. In the past, it has been abused as a general text processor. It will choke on input which does not obey C’s lexical rules. For example, apostrophes will be interpreted as the beginning of character constants, and cause errors. Also, you cannot rely on it preserving characteristics of the input which are not significant to C-family languages.

The Intel Fortran compiler documenation pages on the fpp preprocessor summarize a few more differences in addition to the ones already mentioned.

There is a desire to define a cpp-like “companion processor” for Fortran 202y. It was the most-requested item on the list assigned to the JoR subgroup (Journal of Requirements). We are hoping to start investigating this before the October INCITS/Fortran meeting.

4 Likes