Re: preprocessing directive with no new-line character

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 07/18/2017 02:46 PM, Dennis Clarke wrote:

Do you have 0x0A at the end of your text file ?

No:

zira:~> hd tst.c
00000000  69 6e 74 20 6d 61 69 6e  20 28 76 6f 69 64 29 0a  |int main
(void).|
00000010  7b 0a 20 20 72 65 74 75  72 6e 20 30 3b 0a 7d 0a  |{.
return 0;.}.|
00000020  23 64 65 66 69 6e 65 20  46 4f 4f                 |#define
FOO|
0000002b

And BTW, Clang behaves as expected:

zira:~> clang-4.0 -std=c99 -pedantic tst.c -o tst
tst.c:5:12: warning: no newline at end of file [-Wnewline-eof]
#define FOO
           ^
1 warning generated.

So, I think that's a bug in GCC. Do you agree?

I agree.  C requires non-empty source files to end in an unescaped
new-line character.  POSIX further requires that source files be
text files (and defines the term text file as a file organized
into zero or more lines of at most LINE_MAX characters each).

C++ 11 (and later) has a weaker requirement that makes the above
test case valid.

Fascinating. I never would have thought that a zero line length file
would be accepted as valid. However gcc ( older rev 4.9.2 ) will
accept this :

$ printf "int main ( int argc, char* argv[] ) { return 0; }" > tzero.c

$ wc tzero.c
       0      12      49 tzero.c

$ hdump -Ax -v -tx1 tzero.c
     0:  69 6e 74 20 6d 61 69 6e 20 28 20 69 6e 74 20 61
    10:  72 67 63 2c 20 63 68 61 72 2a 20 61 72 67 76 5b
    20:  5d 20 29 20 7b 20 72 65 74 75 72 6e 20 30 3b 20
    30:  7d
    31:

$ /usr/local/gcc4/bin/gcc -m64 -std=c99 -pedantic \
-D_TS_ERRNO -D_POSIX_PTHREAD_SEMANTICS \
-D_LARGEFILE64_SOURCE -S -o tzero.s tzero.c

$ cat tzero.s
        .file   "tzero.c"
        .section        ".text"
        .align 4
        .global main
        .type   main, #function
        .proc   04
main:
        save    %sp, -176, %sp
        mov     %i0, %g1
        stx     %i1, [%fp+2183]
        st      %g1, [%fp+2175]
        mov     0, %g1
        sra     %g1, 0, %g1
        mov     %g1, %i0
        return  %i7+8
         nop
        .size   main, .-main
        .ident  "GCC: (genunix Fri Jan  2 11:56:03 GMT 2015) 4.9.2"


Whereas c99 ( Oracle Studio 12.4 ) rejects the input file :

$ c99 -errfmt=error -erroff=%none -errshort=full \
-m64 -xmemalign=8s -xnolibmil -Xc -xregs=no%appl -xlibmieee \
-Qy -xbuiltin=%none -D_TS_ERRNO -D_POSIX_PTHREAD_SEMANTICS \
-D_LARGEFILE64_SOURCE -S -o tzero.s tzero.c
"tzero.c", line 1: warning: newline not last character in file

I think "zero or more lines of at most LINE_MAX characters each" won't
work. There must be more than "zero lines" in the input.  What is the
actual spec?

Yes, C requires every non-empty source file to have at least
one line.  The C11 standard says in 5.1.1.2 Translation phases,
p2:

  A source file that is not empty shall end in a new-line character,
  which shall not be immediately preceded by a backslash character
  before any such splicing takes place.

The POSIX specification for the c99 command specifies that its
input be a text file:

  pubs.opengroup.org/onlinepubs/9699919799/utilities/c99.html#tag_20_11_07

with Text File being defined here:


pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_403

The C++ requirement is also in Phases of translation:

  A source file that is not empty and that does not end in
  a new-line character, or that ends in a new-line character
  immediately preceded by a backslash character before any such
  splicing takes place, shall be processed as if an additional
  new-line character were appended to the file.


This is really splitting hairs of course.

It actually has been a source of subtle bugs.  POSIX defines
the behavior of most utilities (e.g., awk, grep, and sed) for
text files but not for others.  Some implementations (I think
even some GNU utilities) don't behave the same way when their
input doesn't meet that requirement.  Being undefined, their
behavior can be pretty bizarre (i.e., it's not constrained
to justnot processing the remainder of the file past the last
newline, but can extend to the lines prior to it).

Martin



[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux