Please help with this C syntax error - Page 1
Forum section: electronics / general

author: peter-h
author_rank: Super Contributor
timestamp: June 05, 2025, 09:31:17 pm
content: Code:#define GCODE const#define FCODE /* nothing */#define SGUCHAR uint8_ttypedef struct _GPALETTE_RGB{SGUCHAR r;SGUCHAR g;SGUCHAR b;} GPALETTE_RGB;#ifdef LCD_CONTROLLER_ST7789static GCODE GPALETTE_RGB FCODE ghw_palette =#include <gcolor_4_ST7789.pal>;#endifand the .pal file contains thisCode:/*V P C 0 16 8 8 8 8 16 24 0 gcolor_4.pal LCDIcon FileDescriptor: Do not edit or move */{{0x00U, 0x00U, 0x00U},{0xFFU, 0x00U, 0x00U},{0xC0U, 0x80U, 0x00U},{0xFFU, 0x80U, 0x00U},{0xFFU, 0xFFU, 0x00U},{0x00U, 0xFFU, 0x00U},{0x00U, 0xC0U, 0x00U},{0x00U, 0xFFU, 0xFFU},{0x00U, 0x80U, 0xFFU},{0x00U, 0x00U, 0xFFU},{0x80U, 0x00U, 0xFFU},{0xA0U, 0xA0U, 0xFFU},{0xFFU, 0x00U, 0xFFU},{0x80U, 0x80U, 0x80U},{0xC0U, 0xC0U, 0xC0U},{0xFFU, 0xFFU, 0xFFU}}In Cube IDE I get an undefined "syntax error" in the editor, but it compiles without apparent errors. Can't tell if it runs because I am days away from getting to a buildable state (it is a commercial graphics library; a huge mess of very similar files for different LCD controllers).I thought the "#define FCODE /* nothing */" is a problem but removing the FCODE makes no difference.The syntax error is showing on the three lines starting with static GCODE GPALETTE_...

author: ataradov
author_rank: Super Contributor
timestamp: June 05, 2025, 10:03:58 pm
content: Have you tried to remove the include? It is likely that Cube parser does not understand inclusion of a *.pal file.It might also not like that "#include" does not start at the beginning of a line. Technically at least '#' need to be at the beginning and 'include' may be aligned any way. But i don't know if any checker is that strict.

author: MarkF
author_rank: Super Contributor
timestamp: June 05, 2025, 10:06:53 pm
content: Is there a reason for separating the declaration from the data?Try this:Code:#define GCODE const#define FCODE /* nothing */#define SGUCHAR uint8_ttypedef struct _GPALETTE_RGB{SGUCHAR r;SGUCHAR g;SGUCHAR b;} GPALETTE_RGB;#ifdef LCD_CONTROLLER_ST7789#include <gcolor_4_ST7789.pal>#endifCode:/*V P C 0 16 8 8 8 8 16 24 0 gcolor_4.pal LCDIcon FileDescriptor: Do not edit or move */static GCODE GPALETTE_RGB FCODE ghw_palette ={0x00U, 0x00U, 0x00U,0xFFU, 0x00U, 0x00U,0xC0U, 0x80U, 0x00U,0xFFU, 0x80U, 0x00U,0xFFU, 0xFFU, 0x00U,0x00U, 0xFFU, 0x00U,0x00U, 0xC0U, 0x00U,0x00U, 0xFFU, 0xFFU,0x00U, 0x80U, 0xFFU,0x00U, 0x00U, 0xFFU,0x80U, 0x00U, 0xFFU,0xA0U, 0xA0U, 0xFFU,0xFFU, 0x00U, 0xFFU,0x80U, 0x80U, 0x80U,0xC0U, 0xC0U, 0xC0U,0xFFU, 0xFFU, 0xFFU};

author: gamalot
author_rank: Super Contributor
timestamp: June 05, 2025, 10:08:08 pm
content: Have you defined GHW_PALETTE_SIZE?

author: peter-h
author_rank: Super Contributor
timestamp: June 06, 2025, 05:38:14 am
content: QuoteIndeed; that is it. I also tried .h but no difference. The Cube parser simply does not like thestatic blah blah ghw_palette =#include <anyfile>The reason for having the data via a #include is because there is a palette editor which operates on these files, so keeping them externally is desirable. In reality I am using 16 bit colour so should not need a palette anyway. With 8 bit colour one might need it, for a RGB LCD display. TBH I am learning about this stuff...Thank you all. I thought I was doing something really dumb.

author: radiolistener
author_rank: Super Contributor
timestamp: June 06, 2025, 11:36:38 am
content: try to remove these preprocessor blah blah substitutions and replace with normal declaration:Code:static const GPALETTE_RGB ghw_palette = {};

author: SiliconWizard
author_rank: Super Contributor
timestamp: June 06, 2025, 03:48:10 pm
content: Quote from: gamalot on June 05, 2025, 10:08:08 pmAnd, I think we have a winner here. That would be the only missing part that I can spot as well.I don't see a definition for GHW_PALETTE_SIZE either (unless it's defined elsewhere that we don't see here), which the internal Cube's analyzer is likely to spot as an error.Where is GHW_PALETTE_SIZE defined in the project?

author: golden_labels
author_rank: Super Contributor
timestamp: June 06, 2025, 06:09:34 pm
content: Quote from: SiliconWizard on June 06, 2025, 03:48:10 pmNot the only one. It also doesn’t include any other header, despite at least “stdint.h” or “inttypes.h” are required for it to compile. So I assumed so far the code is incomplete. IfGHW_PALETTE_SIZEwas undefined, this would also be untrue: “it compiles without apparent errors.”Which of course doesn’t mean you are wrong, and OP should check any hint. The reason is: if the code is incomplete, our picture of the issue is incomplete.peter-h, when asking for help with code, it is good tominimalcode, thatshows symptoms, butotherwise compiles/works. This is not only for convenience of whoever replies. It is, above all, an extremely effective debugging and problem solving technique. The path you need to take to provide such an example snippet, in most cases leads you to a better understanding and the discovery what exactly breaks.Since the code compiles, but (I assume) the editor reports an error, and under assumption that SiliconWizard is not right: many tools processing C are only supporting a C-ish language. Part guessed, part only in devs’ imagination. While inclusion of that file is valid in C and happens during the preprocessing stage, before “C proper” is even analyzed, the IDE may be doing some pattern matching instead. And that may fail with a less common construct.An alternative explanation is a different paths configuration in the IDE and in the compiler. Includes with angle brackets must be in tool’s search path, unlike includes with quotation marks. Are both tools having the same configuration in that regard?

author: peter-h
author_rank: Super Contributor
timestamp: June 06, 2025, 06:23:32 pm
content: GHW_PALETTE_SIZEisdefined. If it wasn't, it would not compile.OK next time I will post moreGood point about the brackets. In my project they seem to be interchangeable i.e. everything is in the search path.

author: HwAoRrDk
author_rank: Super Contributor
timestamp: June 06, 2025, 06:25:41 pm
content: If it compiles without issue, it could just be something dumb like the CubeIDE editor's syntax checker doesn't like/understand it, when it is in fact perfectly legitimate usage of the pre-processor.Edit:I wonder if it's just the #include statement being followed immediately by just a semi-colon.

author: IanB
author_rank: Super Contributor
timestamp: June 06, 2025, 07:13:51 pm
content: A standard approach to this kind of problem is to make the C compiler output the result of the pre-processor to a separate file, and then examine that file to see if it is what you expect. If it looks OK, compile that file and examine the compiler diagnostics from that.Note that in your opening post, you have not shown what the compiler diagnostic messages are?

author: SiliconWizard
author_rank: Super Contributor
timestamp: June 06, 2025, 08:37:55 pm
content: Quote from: HwAoRrDk on June 06, 2025, 06:25:41 pmIt sure is that. Now that may have helped the OP if we could spot what makes it choke, but I think it's impossible without seeing more.I do suspect that the IDE's internal analyzer doesn't properly preprocess the source code, at least not to the extent/with the options that the compiler does, which is something very common with those built-in analyzers. It can also happen with language servers in VS Code.Keep in mind those analyzers are optimized so as not to take several seconds every time you type something, so they can't be as complete as the real deal. I wouldn't give them much attention.

author: ejeffrey
author_rank: Super Contributor
timestamp: June 06, 2025, 08:41:59 pm
content: This is 100% just an issue with the IDE syntax checker. They are significantly different than compilers. They generally have to work much more locally to be fast and since it's expected the file has many errors they would prevent a traditional parse. I would expect that it does something like this. The IDE maintains a table of each known header along with the definitions it creates. When it sees an #include it adds the definitions, but doesn't actually process the include as text substitution.This happens to also mirror how import statements work in languages that are not C/C++.

author: IanB
author_rank: Super Contributor
timestamp: June 06, 2025, 08:56:42 pm
content: It might be possible to overcome the IDE syntax confusion by adjusting the code as below, and then adjusting the include file accordingly. This would make the syntax look valid even if ignoring the contents of the include file:Code:#ifdef LCD_CONTROLLER_ST7789static GCODE GPALETTE_RGB FCODE ghw_palette = {#include <gcolor_4_ST7789.pal>};#endif

author: helius
author_rank: Super Contributor
timestamp: June 07, 2025, 02:22:14 am
content: Comments are removed before preprocessor commands are followed. That means that the lineCode:#define FCODE /* nothing */is syntactically equivalent toCode:#define FCODEbecause the comment is replaced by a single space before the macro definition is scanned. Since a macro is supposed to be defined as a sequence of tokens, this looks like a syntax error.Isgcolor_4_ST7789.palpart of the IDE or part of your project? The angle-bracket syntax for file inclusion is for headers that are part of the system. Use the double-quote syntax for headers from the project.

author: IanB
author_rank: Super Contributor
timestamp: June 07, 2025, 02:58:26 am
content: Quote from: helius on June 07, 2025, 02:22:14 amAgreed, although I believe "#define FCODE" would define it as "nothing" and so it would be replaced with nothing (i.e. eliminated) in the source text.

author: Siwastaja
author_rank: Super Contributor
timestamp: June 07, 2025, 05:38:34 am
content: This is what you are occasionally going to see with IDEs with their internal code parsers. They are not compilers; bug reports are not filed as eagerly as for actual compilers; they don't even try to guarantee compliance with whatever language they are parsing; they are just "helpful" semi-compilers that may or may not understand some parts of the language.Sometimes you just need to ignore the errors and warnings they give and go on. Of course sometimes they error out in an awkward way, for example, refuse to work at all (offer suggestions, pop-ups etc) if they think there is "error" above the current position.So to be clear, there is absolutely nothing wrong or unusual in your code. Perfectly valid, and often used pattern. Just, to quote yourself, CubeIDE being buggy piece of shit, like IDEs usually are. You just need to cope with that. It is up to you to choose:* Trying random modifications on your code until it passes CubeIDE's buggy parser,* Ignore the error if that does not prevent you from working* Change IDE, but the situation is unlikely to go much better.

author: peter-h
author_rank: Super Contributor
timestamp: June 07, 2025, 05:49:49 am
content: QuoteIt is my project, but the file format is fixed due to the font/icon editor which the graphics library vendor (Ramtex) supplies. That bit of code is also in the graphics library.Whether I will ever use that icon editor is another matter. It is an efficient way to do graphics for "instrument displays", however.Yes I normally use double quotes in my code. Keep things simple

author: Siwastaja
author_rank: Super Contributor
timestamp: June 07, 2025, 08:50:00 am
content: Quote from: helius on June 07, 2025, 02:22:14 amNo, #define FCODE is not only valid, it's also one of the most commonly used preprocessor patterns in nearly every real-world code base, like this:#define FEATURE...#ifdef FEATURE...#endifIt is beyond imagination that any IDE, tool or parser would fail on that.

author: dietert1
author_rank: Super Contributor
timestamp: June 07, 2025, 09:10:38 am
content: It's pretty easy to understand: The syntax checker goes by file. That #include to pull in the color data results in unexpected/unknown syntax, and it's a reasonable first result to qualify that as bad syntax. The include file itself is also invalid syntax, in case you check it.Regards, Dieter

author: Siwastaja
author_rank: Super Contributor
timestamp: June 07, 2025, 09:46:54 am
content: Quote from: dietert1 on June 07, 2025, 09:10:38 amWhere exactly? I see no problems with it.

author: dietert1
author_rank: Super Contributor
timestamp: June 07, 2025, 10:37:51 am
content: It doesn't read the include file, which can have anything.

author: Siwastaja
author_rank: Super Contributor
timestamp: June 07, 2025, 01:03:34 pm
content: Quote from: dietert1 on June 07, 2025, 10:37:51 amOh yeah. And it should be reading the file, that is literally the only meaning of #include. Because it does not, it breaks down. It's of course a "performance" optimization, but that's only an excuse - a modern compiler eats megabytes of code in seconds and not only parse and tokenize it correctly, also create optimized machine code in that time. An IDE does not need to do such compilation on every keypress - it could well assign some time in background to read that file once it changes and tokenize it then.But as it fails to do, it breaks on code which has nothing wrong. A bug report could be filed, but will likely not lead anywhere. This is how life is with IDEs: their code parsers are small partial subset of the relevant languages, and there is not enough resourcing on the projects to make them better. We just need to ignore their unnecessary warnings and trust the compilers instead.

author: nctnico
author_rank: Super Contributor
timestamp: June 07, 2025, 01:48:37 pm
content: Quote from: peter-h on June 05, 2025, 09:31:17 pmIf it is not the syntax checker wanting to process complete C files only, then most likely the include path is not added to the project in a way the IDE's syntax checker can find it and thus it gives a parsing error. The typical fix is to add the path where the include is to the project settings (under paths & symbols).

author: peter-h
author_rank: Super Contributor
timestamp: June 08, 2025, 06:56:20 am
content: i don't know where one might set up a path given that the compiler and linker etc find all the files just fine in the project paths already set up.But sure it is a possibility to specify the full path to the include file in the editor. So I tried it; no difference.Had that .pal file been structured to contain the whole valid C syntax, it would have been OK

author: dietert1
author_rank: Super Contributor
timestamp: June 08, 2025, 07:39:28 am
content: Some embedded development environments support inclusion of data files at link time. I remember using that method with IAR EWArm to include HTML files, javascripts, images and style sheets of a web server. One gives to the linker the file path, a label to reference the base address in the C sources and a section id.Regards, Dieter

author: peter-h
author_rank: Super Contributor
timestamp: June 11, 2025, 06:05:34 am
content: Here is another mystery syntax errorSGBOOL is uint8_tSGUINT is uint16_tGCONSTP is constGPALETTE_RGB istypedef struct _GPALETTE_RGB{SGUCHAR r;SGUCHAR g;SGUCHAR b;} GPALETTE_RGB;PFCODE is/* Memory type qualifier used for pointer to fixed data (if GCODE var * is not enough) */#define PFCODE /* nothing */

author: radiolistener
author_rank: Super Contributor
timestamp: June 11, 2025, 06:39:06 am
content: try to use typedef instead of preprocessor #defines

author: peter-h
author_rank: Super Contributor
timestamp: June 11, 2025, 07:09:44 am
content: The #defines for e.g. uint8_t are everywhere in this bit of code (not mine). The problem is elsewhere and may be in the typedef'd struct.

author: paulca
author_rank: Super Contributor
timestamp: June 11, 2025, 11:00:21 am
content: In Uni when it came to C and C++ we were forbidden to do many things.One of them was to use contractions. The reason being,for( ; AMACRO++; AMACRO<limit )Becomes a completely random bit of code once the preprocessing has finished with it. It might, if you are lucky produce a compile error. If you are unlucky it will do something that appears valid, most of the time.Usingfor( ; AMACRO=AMACRO+1; AMACRO<limit )Will catch more cases of inappropriate use of AMACRO than the former will. You are first ensuring the AMACRO can "store" a result in the first place. If it's a function call wrapper, then ++ will either post increment a register that will immediately be discarded or it will bomb out with a wicked compiler error.MACRO_DEFINED_FUNCTION( parameters ) -1UIs this asking for trouble? and relying exclusively on how that MACRO is implemented and if it was ever intended to be used that way.In C++ it gets worse when operators can be macro'd!The way to debug these things is unfortunately to add the "keep preprocessing output" flag and go and look at what ACTUALLY got compiled.I don't know if it solves your problem, but just a "word from the wise", (my uni, not me).

author: peter-h
author_rank: Super Contributor
timestamp: June 11, 2025, 11:06:04 am
content: I am also surprised you can have a #define of nothing.

author: dietert1
author_rank: Super Contributor
timestamp: June 11, 2025, 01:46:31 pm
content: This may be a missing bracket above within the same source file. I mean the function doesn't have a certain syntax error but a function wasn't expected..

author: ejeffrey
author_rank: Super Contributor
timestamp: June 13, 2025, 01:10:08 am
content: Quote from: peter-h on June 11, 2025, 11:06:04 amYou probably aren't if you think about it. It's extremely common. It's mostly used along side #ifdef, so the macros are usually never expanded. For instance the standard pattern of #include guards doesn't specify a value.It's also common when you need something to conditionally expand. This is frequently used when you need non-standard qualifiers on some platforms. For instance windows DLLs require functions to have the dllexport storage class attribute so the following pattern is common:Code:#ifdef WINDOWS#define DLLEXPORT dllexport#else#define DLLEXPORT#endifDLLEXPORT int foo(int x);You can use the same pattern for different calling conventions (cdecl vs fastcall vs isr), section attributes, or anything else that would be an error in some situations.

author: gamalot
author_rank: Super Contributor
timestamp: June 13, 2025, 08:36:51 pm
content: Quote from: peter-h on June 11, 2025, 11:06:04 amIt is very common in include garding.Code:#ifndef FOO_H#define FOO_H......#endif /* FOO_H */