craspberry-pic99termios

CRTSCTS not define when compiling as C99


I'm writing some serial code on a raspberry pi and switched to C99. When I did I started getting the error "error: ‘CRTSCTS’ undeclared (first use in this function)"

$ c99 -M serial01.c | grep termios.h
 /usr/include/termios.h /usr/include/arm-linux-gnueabihf/bits/termios.h \
$ gcc -M serial01.c | grep termios.h
 /usr/include/termios.h /usr/include/arm-linux-gnueabihf/bits/termios.h \

using -M reveals 2 termios.h headers. the former does not contain a definition for CRTSCTS and the latter does.

I assume the standard c89 is using the good one and c99 not but I'm not sure since the result of the -M call is identical. Can anyone explain to me why this is happening when I switch to C99 and how to fix it?


Solution

  • -std=gnu99 is the solution. More detailed below.

    Result of the gcc/c99 -M call is identical but it does not mean anything! The explanation of this behavior are preprocessor macros (specifically GNU extensions, like said Mat).

    In detail:

    cat -n main.c
         1  #include <termios.h>
         2
         3  int printf(const char *, ...);
         4
         5  int main(void)
         6  {
         7      printf("%d\n", CRTSCTS);
         8      return 0;
         9  }
    gcc main.c -o main --std=c89 -> 'CRTSCTS' undeclared compilation error
    gcc main.c -o main --std=cgnu89 -> successfully compiled
    

    This behavior is the same for c99 and gnu99!

    Like said Cameron, -M output is identical:

    gcc -M --std=c89 main.c | grep termios.h | nl
         1  main.o: main.c /usr/include/termios.h /usr/include/features.h \
         2   /usr/include/arm-linux-gnueabihf/bits/termios.h
    gcc -M --std=gnu89 main.c | grep termios.h | nl
    1  main.o: main.c /usr/include/termios.h /usr/include/features.h \
         2   /usr/include/arm-linux-gnueabihf/bits/termios.h \
    

    CRTSCTS is defined in the bits/termios.h when __USE_MISC is defined

         1  #ifdef __USE_MISC
         2  # define CIBAUD   002003600000          /* input baud rate (not used) */
         3  # define CMSPAR   010000000000          /* mark or space (stick) parity */
         4  # define CRTSCTS  020000000000          /* flow control */
    

    Let's look at __USE_MISC.

    gcc -M /usr/include/termios.h | nl
         1  termios.o: /usr/include/termios.h /usr/include/features.h \
         2   /usr/include/arm-linux-gnueabihf/bits/predefs.h \
         3   /usr/include/arm-linux-gnueabihf/sys/cdefs.h \
         4   /usr/include/arm-linux-gnueabihf/bits/wordsize.h \
         5   /usr/include/arm-linux-gnueabihf/gnu/stubs.h \
         6   /usr/include/arm-linux-gnueabihf/bits/types.h \
         7   /usr/include/arm-linux-gnueabihf/bits/typesizes.h \
         8   /usr/include/arm-linux-gnueabihf/bits/termios.h \
         9   /usr/include/arm-linux-gnueabihf/sys/ttydefaults.h
    

    First one, features.h, contains definition of __USE_MISC, but only when _BSD_SOURCE or _SVID_SOURCE is defined

    grep 'define __USE_MISC' /usr/include/features.h -B 1 | nl
         1  #if defined _BSD_SOURCE || defined _SVID_SOURCE
         2  # define __USE_MISC     1
    

    and _BSD_SOURCE and _SVID_SOURCE is defined when _GNU_SOURCE or 'nothing' is defined

         1  #ifdef _GNU_SOURCE
         2  # undef  _ISOC95_SOURCE
         3  # define _ISOC95_SOURCE 1
         4  # undef  _ISOC99_SOURCE
         5  # define _ISOC99_SOURCE 1
         6  # undef  _POSIX_SOURCE
         7  # define _POSIX_SOURCE  1
         8  # undef  _POSIX_C_SOURCE
         9  # define _POSIX_C_SOURCE        200809L
        10  # undef  _XOPEN_SOURCE
        11  # define _XOPEN_SOURCE  700
        12  # undef  _XOPEN_SOURCE_EXTENDED
        13  # define _XOPEN_SOURCE_EXTENDED 1
        14  # undef  _LARGEFILE64_SOURCE
        15  # define _LARGEFILE64_SOURCE    1
        16  # undef  _BSD_SOURCE
        17  # define _BSD_SOURCE    1
        18  # undef  _SVID_SOURCE
        19  # define _SVID_SOURCE   1
        20  # undef  _ATFILE_SOURCE
        21  # define _ATFILE_SOURCE 1
        22  #endif
    
        23  /* If nothing (other than _GNU_SOURCE) is defined,
        24     define _BSD_SOURCE and _SVID_SOURCE.  */
        25  #if (!defined __STRICT_ANSI__ && !defined _ISOC99_SOURCE && \
        26       !defined _POSIX_SOURCE && !defined _POSIX_C_SOURCE && \
        27       !defined _XOPEN_SOURCE && !defined _BSD_SOURCE && !defined _SVID_SOURCE)
        28  # define _BSD_SOURCE    1
        29  # define _SVID_SOURCE   1
        30  #endif