Documenting macros (with doxygen) for a member of a struct - c

I prefer to define certain macros inside of my struct definitions, so it's easy to see possible values for a given member. For example:
typedef struct foo_t {
uint16_t flags;
#define FOO_FLAG_BELL 0x0001
#define FOO_FLAG_BOOK 0x0002
#define FOO_FLAG_CANDLE 0x0004
#define FOO_FLAG_LANTERN 0x0008
}
Doxygen wants to list those macros at the top, with all of the other macros. I've make use of the grouping tags (//#{ and //#}) to group these macros together, and named the group with foo_t.flags, but I'd like to find a way to more-closely associate the values with the structure. Should I use \link and \endlink to somehow link to that group name?

Use enums.
typedef struct foo_t {
enum flag_define {
FOO_FLAG_BELL = 0x0001, /**< The flag for the bell or whatever. */
FOO_FLAG_BOOK = 0x0002,
FOO_FLAG_CANDLE = 0x0004,
FOO_FLAG_LANTERN = 0x0008,
} flags:16; /**< My flag thing */
} foo_t;

Related

Unclear compiler error after implementing a change in a structure using forward declarations

I believed that the strange behaviour of the XC8 compiler was due to problems with forward declarations. With help of you all I have corrected that but the strange error remains. So now I elaborate a little more on my problem.
In the MENU structure CursorStr has been implemented and gives trouble.
If I take out CursorStr and use the ButtonFunc* directly then all goes well.
Below the structs I have included the #define statements used througout the program.
typedef struct ArrowStr {
// Cursor select data
uint8_t UP[4];
uint8_t DOWN[4];
uint8_t RIGHT[4];
uint8_t LEFT[4];
}ARROW_STR;
typedef struct MenuStr MenuStr;
typedef uint8_t ButtonFunc(MenuStr *);
typedef struct CursorStr
{
ButtonFunc* ButtonUpPtr;
ButtonFunc* ButtonDownPtr;
ButtonFunc* ButtonLeftPtr;
ButtonFunc* ButtonRightPtr;
ButtonFunc* PreMenuCursorPtr;
ButtonFunc* MenuCursorPtr;
ButtonFunc* PostMenuCursorPtr;
}CURSOR_STR;
typedef struct MenuStr
{
ARROW_STR Arrows;
// not known anymore
int *ValueArray;
// Cusor position data
uint8_t ROW_POS[4];
uint8_t COL_POS[4];
// A5-A3 format strings
uint8_t Format[3][3];
INDEX ROW_INDEX;
INDEX COL_INDEX;
INDEX DIM_INDEX;
INDEX EDIT_INDEX;
INDEX FORMAT_INDEX;
uint8_t CURRENT_MENU;
CURSOR_STR CursorStr;
// ButtonFunc* ButtonUpPtr;
// ButtonFunc* ButtonDownPtr;
// ButtonFunc* ButtonLeftPtr;
// ButtonFunc* ButtonRightPtr;
// ButtonFunc* PreMenuCursorPtr;
// ButtonFunc* MenuCursorPtr;
// ButtonFunc* PostMenuCursorPtr;
uint8_t CursorX;
uint8_t CursorY;
}MENU;
// used in case of CursorStr
#define pButtonDownPtr Menu->CursorStr.ButtonDownPtr
#define pButtonUpPtr Menu->CursorStr.ButtonUpPtr
#define pButtonLeftPtr Menu->CursorStr.ButtonLeftPtr
#define pButtonRightPtr Menu->CursorStr.ButtonRightPtr
#define pPreMenuCursorPtr Menu->CursorStr.PreMenuCursorPtr
#define pMenuCursorPtr Menu->CursorStr.MenuCursorPtr
#define pPostMenuCursorPtr Menu->CursorStr.PostMenuCursorPtr
#define pCursorPtrs Menu->CursorStr
// used directly
#define pButtonDownPtr Menu->ButtonDownPtr
#define pButtonUpPtr Menu->ButtonUpPtr
#define pButtonLeftPtr Menu->ButtonLeftPtr
#define pButtonRightPtr Menu->ButtonRightPtr
#define pPreMenuCursorPtr Menu->PreMenuCursorPtr
#define pMenuCursorPtr Menu->MenuCursorPtr
#define pPostMenuCursorPtr Menu->PostMenuCursorPtr
In XC8 all compiles and runs fine with the direct approach but with the CursorStr approach a declaration conflict (1098) is reported. Of course I can reach my goal in using some calls to save, store and replace the pointers but I would like to see the CursorStr approach working because that would keep the code more simple. Again help is appreciated.
Addition:
If
typedef uint8_t ButtonFunc(MenuStr *)
is changed into
typedef uint8_t ButtonFunc(uint8_t *)
then I get understandably all kinds of warnings but the code compiles and the program works. So there must be still something with the forward declaration.
Addition2
Since I could not get what I wanted I created a workaround and changed the MENU_STR into the code below. This works without any error or warning. So for the moment I think that the problem comes from the XC8 compiler.
typedef uint8_t ButtonFunc(struct MenuStr *);
typedef uint8_t CursorFunc(void *);
typedef struct Buttons{
CursorFunc* ButtonUpPtr;
CursorFunc* ButtonDownPtr;
CursorFunc* ButtonLeftPtr;
CursorFunc* ButtonRightPtr;
CursorFunc* PreMenuCursorPtr;
CursorFunc* MenuCursorPtr;
CursorFunc* PostMenuCursorPtr;
}BUTTONS;
typedef struct MenuStr
{
ARROW_STR Arrows;
// not known anymore
int *ValueArray;
// Cusor position data
uint8_t ROW_POS[4];
uint8_t COL_POS[4];
// A5-A3 format strings
uint8_t Format[3][3];
INDEX ROW_INDEX;
INDEX COL_INDEX;
INDEX DIM_INDEX;
INDEX EDIT_INDEX;
INDEX FORMAT_INDEX;
uint8_t CURRENT_MENU;
union
{
BUTTONS ButtonsPtrs;
struct
{
ButtonFunc* ButtonUpPtr;
ButtonFunc* ButtonDownPtr;
ButtonFunc* ButtonLeftPtr;
ButtonFunc* ButtonRightPtr;
ButtonFunc* PreMenuCursorPtr;
ButtonFunc* MenuCursorPtr;
ButtonFunc* PostMenuCursorPtr;
};
};
uint8_t CursorX;
uint8_t CursorY;
}MENU;

Setting up MCU headers

I've been having some trouble setting up my libraries.
I'm looking forward to get a macro like PINSEL(P,N) with P as the number of the GPIO port and also N as the number of the pin in the port.
#ifndef uint32_t
typedef unsigned int uint32_t;
#endif
#ifndef __RW
#define __RW volatile
#endif
#ifndef __R
#define __R volatile const
#endif
typedef union{
struct {
uint32_t PINSELP4:2;
} PINSELP4[16];
struct{
__RW uint32_t PINSEL9_;
};
struct{
__RW uint32_t RES1_:24;
__RW uint32_t PINSELP4_28_:2;
__RW uint32_t PINSELP4_29_:2;
__RW uint32_t RES2_:4;
};
}PINSELP4_t;
#define PINSELP4_ ((PINSELP4_t *)(0x4002C024))
#define PINSELP4(N) PINSELP4_->PINSELP4_[N]->PINSELP4
#define PINSEL9 PINSELP4_->PINSEL9_
#define PINSELP4_28 PINSELP4_->PINSELP4_28_
#define PINSELP4_29 PINSELP4_->PINSELP4_29_
The example above shows the shorter struct of the 5 I've defined.
so then I've defined this two macros
#define PINSEL__(N)[] {PINSELP0(N),PINSELP1(N),PINSELP2(N),PINSELP3(N),PINSELP4(N)}
#define PINSEL(P,N) PINSEL__(N)[P]
I'm trying to make an "array of macros" for this to work. I'ts the only way I've figured it out. It still doesn't work. When I call the macro, I get
../src/../Includes/PINSEL_LPC1769.h:246:20: error: expected expression before '[' token
#define PINSEL__(N)[]={PINSELP0(N),PINSELP1(N),PINSELP2(N),PINSELP3(N),PINSELP4(N)}
^
as error.
I'm trying to make a really complete down layer so I can get a much clearer app layer. So if there's another way of doing this, I'll be listening.
Thank you all!

Place #define in structure

From linux kernel code
struct gpio_desc {
struct gpio_chip *chip;
unsigned long flags;
/* flag symbols are bit numbers */
#define FLAG_REQUESTED 0
#define FLAG_IS_OUT 1
#define FLAG_EXPORT 2 /* protected by sysfs_lock */
#define FLAG_SYSFS 3 /* exported via /sys/class/gpio/control */
#define FLAG_ACTIVE_LOW 6 /* value has active low */
#define FLAG_OPEN_DRAIN 7 /* Gpio is open drain type */
#define FLAG_OPEN_SOURCE 8 /* Gpio is open source type */
#define FLAG_USED_AS_IRQ 9 /* GPIO is connected to an IRQ */
#define FLAG_IS_HOGGED 11 /* GPIO is hogged */
/* Connection label */
const char *label;
/* Name of the GPIO */
const char *name;
};
what is the reason to place defines into the body of structure?
With #define it doesn't matter too much where you put them (so long as it is higher up in the file than where it is first used). Most likely those constants are used only within that structure, so it was put there so logically they would be easier to find. They could have been put anywhere above the first place they were used, but they were grouped together because of similar purpose.
It's meaningless, other than to try and define them close to the point of first use.
By the time the compiler actually sees the code, the preprocessor will have stripped those lines out of it.
In this particular example, they would be better off with a typedef'd enum for the flags and using that enum to declare the field.
There is no impact.
But in the example, for readability sake they maintained/added near to the variable declared.
They want use those "#define" for the variable "unsigned long flags;".
Below is simple example and proves no impact on the class/struct by declaring the "#Define" inside.
//gcc 4.9.3
#include <stdio.h>
struct gpio_desc {
#define FLAG_REQUESTED 0
} test;
int main()
{
printf("%d",FLAG_REQUESTED);
}
The out put is zero.

Warning: "extra ; ignored" by using C macros with ARMCC

My compiler raises the warning #381-D: extra ";" ignored in such a situation:
I have a struct defined, like the following
struct example_s
{
u8_t foo;
SOME_MACRO(bar);
};
The macro SOME_MACRO(x) does the following:
#if defined(SYSTEM_A)
#define SOME_MACRO(x) u16_t x##something
#else
#define SOME_MACRO(x) /* nothing */
#endif
Of course, the warning is correct, when SYSTEM_A is not defined. Simply because I have now a ; within the struct. But does someone know a way to avoid it correctly? I don't want to break the typical C-style by moving the ; into the macro.
One way that is a bit of a kludge but it seems to work with gcc:
#if defined(SYSTEM_A)
#define SOME_MACRO(x) u16_t x##something
#else
#define SOME_MACRO(x) int x[0] /* nothing */
#endif
With this method you end up with a struct like this:
struct example_s
{
u8_t foo;
int bar[0];
};
which has the correct size (i.e. as size as if bar had not been defined at all).
You can add an unnamed 0-width bitfield instead:
#if defined(SYSTEM_A)
#define SOME_MACRO(x) u16_t x##something
#else
#define SOME_MACRO(x) unsigned :0
#endif
you can also insert an empty anonymous struct :
#if defined(SYSTEM_A)
#define SOME_MACRO(x) u16_t x##something
#else
#define SOME_MACRO(x) struct {}
#endif

Managing and handling multiple abstract data types in C with type safety?

I have several hardware signals that get toggled based on properties relevant to scenarios in which respective signals could be toggled. The problem is that signals and the properties that define scenarios, all three could change. I am forced to think in terms of a modular framework based design in which there is SignalManager that handles signal creation and there is a SignalPropertiesData with its SignalPropertiesDataManager that associate certain SignalScenario structure and all this is created specifically for any type of signal by the SignalManager. I wish to follow the public interface, private data in the C programming paradigm.
My dilemma is C in general when it comes to type safety and this kind of problem, the only solution is to lose type safety and use 'void' for any and all types of data. Can you point me to any code or component in the vast opensource sea, which can serve as a right reference for this problem.
signal_manager.h:
#ifdef _SIGNAL_MANAGER_H
#define _SIGNAL_MANAGER_H
int createSignal(SignalDescPtr signalDescPtr);
int destroySignal();
typedef struct SignalDesc* SignalDescPtr;
#endif
signal_manager.c:
#include "signal_manager.h"
typedef struct {
char* signalName;
unsigned int signalId;
SignalPropertiesDataPtr signalProperties;
} SignalDesc;
signal_properties_data.h:
#ifdef _SIGNAL_PROPERTIES_DATA
#define _SIGNAL_PROPERTIES_DATA
typedef enum {
SIGNAL_DATA_INT_TYPE,
SIGNAL_DATA_UNSIGNED_INT_TYPE,
SIGNAL_DATA_FLOAT_TYPE,
:
SIGNAL_DATA_UNSPECIFIED_BASIC_TYPE
} eSignalBasicType;
typedef enum {
SIGNAL_DATA_LIST_ARRAY_TYPE,
SIGNAL_DATA_LIST_ADT_TYPE,
:
:
SIGNAL_DATA_LIST_UNSPECIFIED_TYPE
} eSignalComplexType
typdef union {
eSignalBasicType signalBasicType;
eSignalComplexType signalComplexType;
} eSignalType;
typedef struct {
eSignalType signalType;
unsigned int signalDataLen;
} SignalDataValueType;
typedef SignalPropertiesData* SignalPropertiesDataPtr;
result_t setSignalType(..);
result_ getSignalType(..);
result_t setSignalData(..);
result_t getSignalData(..);
result_t setSignalDataLen(..);
result_t getSignalDataLen(..);
#endif
signal_properties_data.c:
#include "signal_properties_data.h"
typdef struct {
SignalDataValueType signalPropertiesDataType;
void* signalPropertiesDataValue;
} SignalPropertiesData;
signal_properties_data_mgr.h:
#ifdef _SIGNAL_PROPERTIES_DATA_MGR_H
#define _SIGNAL_PROPERTIES_DATA_MGR_H
#include "signal_properties_data.h"
#include "signal_scenario.h"
typedef SignalScenarioDesc* SignalScenarioDescPtr;
result_t createSignalPropertiesData(SignalPropertiesDataPtr *signalPropDataPtr, eSignalType desiredSignalType);
result_t freeSignalPropertiesData(..);
result_t associateSignalToggleScenario(SignalPropertiesDataPtr *signalPropDataPtr, SignalScenPtr signalScenPtr);
result_t disassociateSignalToggleScenario(SignalPropertiesDataPtr *signalPropDataPtr, SignalScenarioDescPtr signalScenPtr);
#endif
signal_properties_data_mgr.c:
#include "signal_properties_data_mgr.h"
typedef struct {
toggleFuncPtr fptr;
} SignalScenarioDesc;
Avoid going for void *. It loses the benefits of prototypes and is not necessary,
Since this is C, you should write in signalmanager.h
#ifndef SIGNAL_MANAGER_H_INCLUDED
#define SIGNAL_MANAGER_H_INCLUDED
typedef struct SignalDesc* SignalDescPtr;
int createSignal(SignalDescPtr signalDescPtr);
int destroySignal(void);
#endif
Changes:
Critical: the idiom is #ifndef MACRO / #define MACRO / #endif. You used #ifdef which won't work.
Place typedef before it is used.
Add explicit (void) to make destroySignal(void) into a prototype. Your version simply says 'there is a function destroySignal() that returns an int but it takes an unspecified (but not variadic) argument list'.
Do not use reserved name space (leading underscore, capital letter) for the header protection guard.
I prefer not to hide pointers in data type typedefs, so I'd probably write:
#ifndef SIGNAL_MANAGER_H_INCLUDED
#define SIGNAL_MANAGER_H_INCLUDED
typedef struct SignalDesc SignalDesc;
extern int createSignal(SignalDesc *sigdesc);
extern int destroySignal(void);
#endif /* SIGNAL_MANAGER_H_INCLUDED */
I'm not sure that the interfaces to the create and destroy are correct, but that's another subject for discussion. I'd normally expect to find that the interfaces are more like:
extern SignalDesc *createSignal(const char *name, int signum);
extern void destroySignal(SignalDesc *sigdesc);
The implementation file signal_manager.c would then define the structure type and use it; the external interface is through functions that work with pointers.
#include "signal_manager.h"
#include "signal_properties_data.h"
struct SignalDesc
{
char *signalName;
unsigned int signalId;
SignalPropertiesData *signalProperties;
};
The signal_properties_data.h needs similar cleaning up:
#ifndef SIGNAL_PROPERTIES_DATA_H_INCLUDED
#define SIGNAL_PROPERTIES_DATA_H_INCLUDED
typedef enum {
SIGNAL_DATA_INT_TYPE,
SIGNAL_DATA_UNSIGNED_INT_TYPE,
SIGNAL_DATA_FLOAT_TYPE,
:
SIGNAL_DATA_UNSPECIFIED_BASIC_TYPE
} eSignalBasicType;
typedef enum {
SIGNAL_DATA_LIST_ARRAY_TYPE,
SIGNAL_DATA_LIST_ADT_TYPE,
:
:
SIGNAL_DATA_LIST_UNSPECIFIED_TYPE
} eSignalComplexType
typdef union {
eSignalBasicType signalBasicType;
eSignalComplexType signalComplexType;
} eSignalType;
typedef struct {
eSignalType signalType;
unsigned int signalDataLen;
} SignalDataValueType;
/* Huge hole in types here - or is SignalValueDataType what you're after? */
typedef struct SignalPropertiesData SignalPropertiesData;
result_t setSignalType(..);
result_t getSignalType(..);
result_t setSignalData(..);
result_t getSignalData(..);
result_t setSignalDataLen(..);
result_t getSignalDataLen(..);
#endif /* SIGNAL_PROPERTIES_DATA_H_INCLUDED */
This revised header is not self-contained yet. It does not define result_t, so it should include the header that does. I assume the ... notation in the function calls is "do not want to specify in this question" because it isn't valid in C; you must have one argument of known type before you specify the ellipsis.
It is not clear from the functions in the header why the user of the header needs to know about the types that are defined in it. Think of a header as a resource that will be shared. It 'belongs to' or describes the external interface to a file (or a small set of files). It gives the users the minimum data that they need to use the facilities provided by the code, but no more than the minimum. You sometimes find that a set of files implementing a facility will need a private header to share between themselves as well as the public header that other code ('customer' code or 'consumer' code) uses.
The key to opaque types is that the consumer doesn't need to know the internal details of a structure to be able to use pointers to the structure type (see Which part of the C Standard allows this code to compile?, Does the C standard consider that there are one or two struct uperms_entry types in this header? and How to structure header files in C for some more insight).
I am not sure that I fully understand what your needs are, but I think that you could look at WIN32 handles for a reference implementation.
A short example would be to define a macro that lets you define custom handles like this:
/* example.h */
#ifndef _EXAMPLE_H
#define _EXAMPLE_H
/* Define macro */
#define DECLARE_HANDLE(HandleName) typedef struct HandleName##Tag * HandleName
/* Declare some handles */
DECLARE_HANDLE(SomeHandle);
DECLARE_HANDLE(SomeOtherHandle);
#endif /* _EXAMPLE_H */
/* example.c */
#include "example.h"
struct SomeHandleTag {
int foo;
};
struct SomeOtherHandleTag {
int foo;
};

Resources