This is the mail archive of the
fortran@gcc.gnu.org
mailing list for the GNU Fortran project.
RFC: Non-traditional CPP
- From: Tobias Burnus <burnus at net-b dot de>
- To: "'fortran at gcc dot gnu dot org'" <fortran at gcc dot gnu dot org>
- Date: Wed, 30 Jul 2008 19:56:10 +0200
- Subject: RFC: Non-traditional CPP
Hello,
currently, CPP is called in traditional CPP mode to prevent all kind of
problems, however, this limits the supported features. Several other
Fortran compilers support newer CPP features and also users keep
requesting/expecting them. (See also PR 28662 and PR 29671 and
http://groups.google.com/group/comp.lang.fortran/browse_thread/thread/f6a26f74557d7324
)
My idea is to enhance libcpp such to allow newer CPP features with Fortran.
The attached draft patch properly recognizes comment lines and ignores
those. I'm positive that this is not enough but currently I do not see
where it will fail. I therefore need your help. I also plan to add an
option to CPP for Fortran preprocessing.
The easiest way to test is to run: gfortran -E file.F90 (please also
check fixed-form .F files.).
I know that the following case fails (without traditional it now prints
a warning). The problem is that '...& \n &....' is not recognized as
one long string.
#define Paul Hans
! Paul's string
print *,'Hello &
&Paul'
end
Anything else? Other suggestions, comments, remark to the patch?
Tobias
PS: Two test cases to make sure I don't loose them. Esp. fixed-form test
cases are needed.
#define a 2
#if (a != 2)
print *, 'Wrong'
#else
print *, 'OK'
#endif
end
! Should the // be a comment sign or for
! concating the string? ifort and sunf95
! don't regard it as comment marker,
! gfortran does neither.
#define STR 'From A ' // /* ... */ 'to Z'
print *, STR//'!'
end
Index: libcpp/include/cpplib.h
===================================================================
--- libcpp/include/cpplib.h (Revision 138294)
+++ libcpp/include/cpplib.h (Arbeitskopie)
@@ -280,6 +280,12 @@ struct cpp_options
"#import". */
unsigned char objc;
+ /* Nonzero means handle Fortran files. */
+ unsigned char fortran;
+
+ /* Nonzero means handle fixed-format Fortran files. */
+ unsigned char fixed_fortran;
+
/* Nonzero means don't copy comments into the output file. */
unsigned char discard_comments;
Index: libcpp/lex.c
===================================================================
--- libcpp/lex.c (Revision 138294)
+++ libcpp/lex.c (Arbeitskopie)
@@ -686,12 +686,14 @@ save_comment (cpp_reader *pfile, cpp_tok
len--;
/* If we are currently in a directive, then we need to store all
- C++ comments as C comments internally, and so we need to
- allocate a little extra space in that case.
+ C++ comments as C comments internally, and so we
+ need to allocate a little extra space in that case.
Note that the only time we encounter a directive here is
when we are saving comments in a "#define". */
- clen = (pfile->state.in_directive && type == '/') ? len + 2 : len;
+ clen = (pfile->state.in_directive && type == '/')
+ ? len + 2
+ : len;
buffer = _cpp_unaligned_alloc (pfile, clen);
@@ -699,12 +701,14 @@ save_comment (cpp_reader *pfile, cpp_tok
token->val.str.len = clen;
token->val.str.text = buffer;
- buffer[0] = '/';
memcpy (buffer + 1, from, len - 1);
+ buffer[0] = CPP_OPTION (pfile, fortran) ? type : '/';
+
/* Finish conversion to a C comment, if necessary. */
if (pfile->state.in_directive && type == '/')
{
+ buffer[0] = '/';
buffer[1] = '*';
buffer[clen - 2] = '*';
buffer[clen - 1] = '/';
@@ -994,6 +998,7 @@ _cpp_lex_direct (cpp_reader *pfile)
result->flags |= PREV_WHITE;
}
buffer = pfile->buffer;
+
update_tokens_line:
result->src_loc = pfile->line_table->highest_line;
@@ -1009,6 +1014,17 @@ _cpp_lex_direct (cpp_reader *pfile)
LINEMAP_POSITION_FOR_COLUMN (result->src_loc, pfile->line_table,
CPP_BUF_COLUMN (buffer, buffer->cur));
+ /* Skip fixed-form Fortran comment lines, i.e. lines where in
+ column one a "!", "*" or "C" is. */
+ if (CPP_OPTION (pfile, fixed_fortran) && CPP_BUF_COL (buffer) == 1
+ && (c == '!' || c == '*' || c == 'C' || c == 'c'))
+ {
+ comment_start = buffer->cur;
+ skip_line_comment (pfile);
+ save_comment (pfile, result, comment_start, c);
+ return result;
+ }
+
switch (c)
{
case ' ': case '\t': case '\f': case '\v': case '\0':
@@ -1094,7 +1110,8 @@ _cpp_lex_direct (cpp_reader *pfile)
/* Warn about comments only if pedantically GNUC89, and not
in system headers. */
if (CPP_OPTION (pfile, lang) == CLK_GNUC89 && CPP_PEDANTIC (pfile)
- && ! buffer->warned_cplusplus_comments)
+ && ! buffer->warned_cplusplus_comments
+ && (!CPP_OPTION (pfile, fortran) || pfile->state.in_directive))
{
cpp_error (pfile, CPP_DL_PEDWARN,
"C++ style comments are not allowed in ISO C90");
@@ -1103,7 +1120,9 @@ _cpp_lex_direct (cpp_reader *pfile)
buffer->warned_cplusplus_comments = 1;
}
- if (skip_line_comment (pfile) && CPP_OPTION (pfile, warn_comments))
+ if ((!CPP_OPTION (pfile, fortran) || pfile->state.in_directive)
+ && skip_line_comment (pfile)
+ && CPP_OPTION (pfile, warn_comments))
cpp_error (pfile, CPP_DL_WARNING, "multi-line comment");
}
else if (c == '=')
@@ -1260,9 +1279,22 @@ _cpp_lex_direct (cpp_reader *pfile)
}
break;
+ case '!':
+ /* Ignore Fortran comments. For fixed-form source, a "!" at
+ column 6 is not a comment. */
+ if (CPP_OPTION (pfile, fortran) && !pfile->state.in_directive
+ && CPP_BUF_COL (buffer) != 6)
+ {
+ comment_start = buffer->cur;
+ skip_line_comment (pfile);
+ save_comment (pfile, result, comment_start, c);
+ }
+ else
+ IF_NEXT_IS ('=', CPP_NOT_EQ, CPP_NOT);
+ break;
+
case '*': IF_NEXT_IS ('=', CPP_MULT_EQ, CPP_MULT); break;
case '=': IF_NEXT_IS ('=', CPP_EQ_EQ, CPP_EQ); break;
- case '!': IF_NEXT_IS ('=', CPP_NOT_EQ, CPP_NOT); break;
case '^': IF_NEXT_IS ('=', CPP_XOR_EQ, CPP_XOR); break;
case '#': IF_NEXT_IS ('#', CPP_PASTE, CPP_HASH); break;
Index: gcc/fortran/cpp.c
===================================================================
--- gcc/fortran/cpp.c (Revision 138327)
+++ gcc/fortran/cpp.c (Arbeitskopie)
@@ -444,7 +444,9 @@ gfc_cpp_post_options (void)
gcc_assert (cpp_option);
/* TODO: allow non-traditional modes, e.g. by -cpp-std=...? */
- cpp_option->traditional = 1;
+ cpp_option->traditional = 0;
+ cpp_option->fortran = 1;
+ cpp_option->fixed_fortran = gfc_current_form == FORM_FIXED ? 1 : 0;
cpp_option->cplusplus_comments = 0;
cpp_option->pedantic = pedantic;