2

I'm working with some embedded C code for an LCD display in which one of the files includes stdio.h and defines fputc, fgetc, and ferror. fputc calls the LCD driver code to print a character to the screen, but the other two don't actually do anything interesting.

Whenever I try to compile the project I get the following error:

src/ST7735.c:1578:5: error: expected identifier or '(' before 'int' 1578 | int ferror(FILE *f){

src/ST7735.c:1578:5: error: expected ')' before '(' token 1578 | int ferror(FILE *f){

The error goes away if I rename ferror to anything else. The other two functions don't create any issues. I also found that if I do rename the function but call ferror elsewhere in the code, the project still compiles, when I'd expect linking to fail without a definition for ferror anywhere else in the project.

I'm using the arm-none-eabi toolchain with the -nostdlib flag, but the project was originally created using Keil. I'm not sure if that is part of the explanation. I searched Google for any relevant information but couldn't find anything. Is there something special about ferror in GCC?

David D.
  • 59
  • 5
  • 6
    Sounds like some header may be defining `ferror` as a macro (which is unusual, but standard-compliant). Try compiling with `-E` and looking at the preprocessed line where the error was issued. – Dan Bonachea Jan 02 '23 at 03:20
  • 1
    @DanBonachea that was it, much appreciated. Inside the arm-none-eabi toolchain's stdio.h is #define ferror(p) __sferror(p). – David D. Jan 02 '23 at 04:48
  • Just to follow up on my previous comment which I think is incomplete: stdio.h contains '#define ferror(p) __sferror(p)' which itself expands to a plain old expression. – David D. Jan 02 '23 at 06:10
  • 1
    A compiler is allowed to implement *any* standard function as a macro (in addition to implementing it as a function). Your .c file should `#undef` every standard function it attempts to redefine. – n. m. could be an AI Jan 02 '23 at 06:10

1 Answers1

1

… one of the files includes stdio.h and defines fputc, fgetc, and ferror.

This seems like you are trying to implement those standard library functions, as in the way a C implementation must implement those functions for its users.

An implementor of standard library functions is responsible for providing both the header, <stdio.h>, and the implementations of the functions and for ensuring they work together. Including somebody else’s <stdio.h> and writing your own definitions is not generally a good approach to this. Often somebody else’s implementation of <stdio.h> contains customizations for that implementation that are not appropriate for yours. It is typically better to start by writing your own <stdio.h> that simply declares functions as they are described in the C standard.

Failing that, there might be no need to include <stdio.h> in the source file where you are defining fputc, fgetc, and ferror. Simply remove that header and define the functions.

If you do not wish to do that, then adding #undef ferror after #include <stdio.h> might resolve the immediate problem you are having. However, it might not resolve the whole problem, because, if source files that are using your routines include this same <stdio.h>, they will get the ferror macro defined in <stdio.h> and will not call the ferror routine you define. To resolve that, you will need to provide a different <stdio.h>.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312