C Macro get token value instead of token name - c

Please see the code snipped, in c, below and look at the comments. Is there anyway to make this possible? Does the preprocessor already know that spn_1 = 18? Is there anyway to use the value of spn_1 as a token name?
#define TEST_M(_spn) struct astruct _test_struct_##_spn = { .spn = _spn, };
enum spns {
spn_1 = 18,
};
struct astruct {
int spn;
};
TEST_M(spn_1)
// What I want:
// struct astruct _test_struct_18 = { .spn = 18, };
// What I get:
// struct astruct _test_struct_spn_1 = { .spn = 18, };
// I can do, but I want attach a name to 18:
// TEST_M(18)

Since you want the preprocessor to replace a token by its value, you need the preprocessor for this. So the first step is to use #define instead of an enumeration.
But because of the sequence that macros are expanded, the second step is to use an intermediate macro.
#define TEST_M2(_spn) struct astruct _test_struct_##_spn = { .spn = _spn, };
#define TEST_M(_spn) TEST_M2(_spn)
#define SPN_1 18
struct astruct {
int spn;
};
TEST_X(SPN_1)
TEST_X(18)
This also works with literal numbers.
With GCC you can check the resulting source if you use its option "-E".

Related

Initialize union inside of struct: cannot find why Missing brace around initializer

I am trying to initialize properly this struct:
typedef struct
{
TU_ApplicationData uApplicationData;
TS_SHA_Padding sSHA_Padding;
TU_ApplicationNonVolatileData uApplicationNonVoltatileData;
TS_SHA_Digest sSHA_Digest;
}TS_ApplicationFooter;
As you can see, it is composed with other structure:
typedef struct
{
uint32_t u32ApplicationVersion_Major;
uint32_t u32ApplicationVersion_Minor;
fpJumpHandler fpApplicationJumpHandler;
uint32_t u32BootApplicationStartAddress;
uint32_t u32BootApplicationAllocationSize;
uint32_t u32UserApplicationStartAddress;
uint32_t u32UserApplicationAllocationSize;
}TS_ApplicationData;
typedef union
{
uint32_t au32ApplicationData[32];
TS_ApplicationData sApplicationData;
}TU_ApplicationData;
typedef struct
{
uint32_t u32SHA_1PaddingBytes[16];
}TS_SHA_Padding;
typedef struct
{
uint8_t u8ApplicationNonVoltatileData[256];
}TU_ApplicationNonVolatileData;
typedef struct
{
uint32_t au32ApplicationHashTag[16];
}TS_SHA_Digest;
I cannot find the proper way to initialize the TS_ApplicationFooter structure. The best way that I have is the following, but it returns me the warning: "missing braces around initializer [-Wmissing-braces]".
const TS_ApplicationFooter sUserApplicationFooter =
{ /* Warning point here */
.uApplicationData=
{
.au32ApplicationData={0},
.sApplicationData=
{
.u32ApplicationVersion_Major=U32_USB_CDC_USER_APP_SW_RELEASE_MAJOR_VERSION,
.u32ApplicationVersion_Minor=U32_USB_CDC_USER_APP_SW_RELEASE_MINOR_VERSION,
.fpApplicationJumpHandler=NULL,
.u32BootApplicationStartAddress=U32_BOOT_LOADER_APPLICATION_START_ADDRESS,
.u32BootApplicationAllocationSize=U32_BOOT_LOADER_APPLICATION_ALLOCATED_SIZE,
.u32UserApplicationStartAddress=U32_USER_APPLICATION_START_ADDRESS,
.u32UserApplicationAllocationSize=U32_USER_APPLICATION_ALLOCATED_SIZE
}
},
.sSHA_Padding={0},
.uApplicationNonVoltatileData={0},
.sSHA_Digest={0}
};
Do you have any idea on how I could initialize this structure without having any warning of this kind ?
You should add extra braces around the last three members to appease GCC:
...
.sSHA_Padding={{0}},
.uApplicationNonVoltatileData={{0}},
.sSHA_Digest={{0}}
};
This might be a bug in GCC. Clang does not show this warning, even if compiled with -Wall -W -Wmissing-braces -pedantic.
Alternatively, since as soon as you initialize one member member of a struct, all other members that are not explicitly initialized are initialized to zero, you can just omit them.
Furthermore, you should only initialize exactly one member of a union! I recommend you rewrite the whole initialization like so:
const TS_ApplicationFooter sUserApplicationFooter =
{
.uApplicationData =
{
.sApplicationData =
{
.u32ApplicationVersion_Major = U32_USB_CDC_USER_APP_SW_RELEASE_MAJOR_VERSION,
.u32ApplicationVersion_Minor = U32_USB_CDC_USER_APP_SW_RELEASE_MINOR_VERSION,
.u32BootApplicationStartAddress = U32_BOOT_LOADER_APPLICATION_START_ADDRESS,
.u32BootApplicationAllocationSize = U32_BOOT_LOADER_APPLICATION_ALLOCATED_SIZE,
.u32UserApplicationStartAddress = U32_USER_APPLICATION_START_ADDRESS,
.u32UserApplicationAllocationSize = U32_USER_APPLICATION_ALLOCATED_SIZE
}
},
};

Best way to extract all enums from C project

I'm writing my own enums-based backtrace. Basically each function call will append it's error to a pre-defined stack which will eventually include all errors across all function calls.
I want to create an efficient way to parse it. In the end I got int backtrace[] with enum values from all over my codebase, and I'd like to relate each enum value to it's name.
This should of course be done post-failure (not at runtime), so what I'm missing is a way, maybe as a part of the compilation step, to dump all my enums and there values to a file. Then i can write a script that parse the errors.
Is there an easy (cross-platform) static tool that does that?
Not sure how you log the errors, but how about:
typedef enum
{
E_SUCCESS = 0,
E_FAIL,
...
} error_t;
typedef struct
{
error_t code;
char * error_name;
} backtrace_entry_t;
backtrace_entry_t backtrace[..];
#define FUNC_EXIT(error_code__) \
do { \
backtrace[func_id].code = (error_code__); \
backtrace[func_id].error_name = #error_code__; \
} while (0)
Then, when you call FUNC_EXIT(E_SUCCESS);, you'll get for the backtrace for the function to be: {.code = 0, .error_name = "E_SUCCESS"}
The problem is, you can't get the right name if you call FUNC_EXIT(var);, where var is some local variable.
Another option, although still not an automagical one:
typedef enum
{
E_SUCCESS = 0,
E_FAIL,
...
NOF_ERROR_CODES
} error_t;
#define MAP_E_CODE_TO_NAME(error_code__) [error_code__] = #error_code__
const char * error_to_name_mapping[NOF_ERROR_CODES] = {
MAP_E_CODE_TO_NAME(E_SUCCESS),
MAP_E_CODE_TO_NAME(E_FAIL),
...
};
Will give a const char * array with {"E_SUCCESS", "E_FAIL", ...}, which you can use like this:
printf("The name of error code %d is '%s'", error, error_to_name_mapping[error]);
The problem here is that you have to have positive value to errors with increasing values.

Static array initialization in C

Consider the following statements
typedef struct {
int member1;
int member2;
}Custom_t;
void ISR(void)
{
static Custom_t struct1[SOME_CONSTANT];
......
......
}
How can I initialize all member2 variable to a single value in C programming?
If I iniatilize the structure like the one shown below, then there is chance of somebody changing the "SOME_CONSTANT" in a header file and forgetting to update the list.
Another solution would be to give the structure a global scope for the current file. But the only function which uses the structure is the ISR().
void ISR(void)
{
static Custom_t struct1[SOME_CONSTANT] = {
{0, 3},
{0, 3},
......
......
};
......
......
}
Is there any method to solve this problem in C?
You can use Designated Initializers and do it in this way:
#include <stdio.h>
#define SOME_CONSTANT 30
typedef struct {
int member1;
int member2;
} Custom_t;
int main(void)
{
static Custom_t struct1[SOME_CONSTANT] =
{
[0 ... SOME_CONSTANT - 1].member2 = 30
};
printf("%d\n", struct1[25].member2);
printf("%d\n", struct1[19].member2);
printf("%d\n", struct1[0].member2);
return 0;
}
How about to add hard-coded compiling time checking against SOME_CONSTANT in the .c file (e.g. right before the initializer)?
#if SOME_CONSTANT != <some_hard_code_value>
#error "SOME_CONSTANT is not equal to <some_hard_code_value>"
#endif
The rational of this "hard-code" is whenever the SOME_CONSTANT is changed, the initializer need be updated, as well as the compiling time checking.
You don't need to specify the array size in advance, you can compute it later:
static Custom_t struct1[] = {
{0, 3},
{0, 3},
{13,3},
};
#define SOME_CONSTANT (sizeof struct1 /sizeof struct1[0])
or: use __LINE__ to compute the number of elements.
I've had to do something like this with projects with a configurable number of sensors :
[custom_t.h]
typedef struct {
int member1;
int member2;
}Custom_t;
#define MAX_CUSTOM_T 4
Custom_t *new_Custom_t (int member1, int member2);
[custom_t.c]
#include "custom_t.h"
static Custom_t g_Customt[MAX_CUSTOM_T];
static uint8 g_numCustom_t = 0;
Custom_t *new_Custom_t (int member1, int member2)
{
if ( g_numCustom_t < MAX_CUSTOM_T )
{
Custom_t *new_obj = &g_Customt[g_numCustom_t++];
new_obj->member1 = member1;
new_obj->member1 = member2;
return new_obj;
}
else
{
// throw exception?
// or go into while(1)?
// or software breakpoint if debug?
// or just...
return NULL;
}
}
[main.c]
#include "custom_t.h"
Custom_t *myCustom1;
Custom_t *myCustom2;
Custom_t *myCustom3;
somefunc()
{
myCustom1 = new_Custom_t (0,3);
myCustom2 = new_Custom_t (1,3);
myCustom3 = new_Custom_t (2,3);
// do stuff
}
It means if you want to create a new one, you may or may not need to update MAX_CUSTOM_T depending on its size already, but will just have to add a new line call to new_Custom_t(int,int). A Disadvantage though is it is slightly complex for what you might need, and if you ever want to add more members to initialize, you'll need to update the parameters passed into the new_ function to suit. This can be done instead with a sending a single separate structure for parameters rather than multiple parameters (a bit like MPLAB harmony).

C initializer element is not constant - pointers in struct

Code snippets appear below
/// System Parameters for the gateway
typedef struct {
bool mobile_gateway; // true = GPS receiver used, else false
uint16_t gw_ordinal_number; // Starting at 1, the ordinal gateway number
} CONFIG_SYSTEM_PARMS;
// Data types for the system parameters
typedef enum {
CFGPARM_TYPE_BOOL,
CFGPARM_TYPE_UINT,
CFGPARM_TYPE_INT,
CFGPARM_TYPE_DOUBLE,
CFGPARM_NUM_TYPES
} CONFIG_PARM_DATA_TYPES;
// These mnemonic names and data types correspond to the system parameters
#define SYS_PARM_MOBILE_GATEWAY_MNEM "MOBILEGW"
#define SYS_PARM_GATEWAY_NUMBER_MNEM "GWNUM"
#define SYS_PARM_MOBILE_GATEWAY_TYPE CFGPARM_TYPE_BOOL
#define SYS_PARM_GATEWAY_NUMBER_TYPE CFGPARM_TYPE_UINT
typedef struct {
char FILLER; // TODO - Define User Parms later...
} CONFIG_USER_PARMS;
static const uint16_t TOTAL_CONFIG_PARM_BYTESIZE = sizeof(CONFIG_SYSTEM_PARMS) + sizeof(CONFIG_USER_PARMS);
typedef struct {
const char *sysparm_mnemonic;
CONFIG_PARM_DATA_TYPES sysparm_data_type;
void *sysparm_data_ptr;
} CONFIG_PARM_LOOKUP_TABLE;
// ****************************************
static LT_LOGGER_DATA gateway_log_data;
static CONFIG_SYSTEM_PARMS *config_sys_parms_ptr = &gateway_log_data.config_system_parms;
// **************************************************
// Lookup table for the System Parms
//
// CAA: This is a stinking mess - There is no easy way to define &gateway_log_data.config_system_parms
// outside of the following initialization, so the result is more verbose than it should be
static const CONFIG_PARM_LOOKUP_TABLE config_parm_lookup_table[] = {
{ SYS_PARM_MOBILE_GATEWAY_MNEM, SYS_PARM_MOBILE_GATEWAY_TYPE, &config_sys_parms_ptr->mobile_gateway},
{ SYS_PARM_GATEWAY_NUMBER_MNEM, SYS_PARM_GATEWAY_NUMBER_TYPE, &gateway_log_data.config_system_parms.gw_ordinal_number},
// FILLER to mark end of list
{ "", 0, NULL}
};
The question is this:
Why, am I getting the error : initializer element is not constant (near initialization for 'config_parm_lookup_table[0].sysparm_data_ptr')
when the initializer for config_parm_lookup_table[1].sysparm_data_ptr is effectively using the same construct?
Obviously, I have a work-around, but it seems verbose.

Initializing structure by named members

I'm trying to wrap my head around the syntax provided in http://publib.boulder.ibm.com/infocenter/lnxpcomp/v7v91/index.jsp?topic=%2Fcom.ibm.vacpp7l.doc%2Flanguage%2Fref%2Fclrc03strin.htm :
struct
{
int a[5], b;
} game[] =
{
[0].a = { 1 },
[1].a[0] = 2
};
Ideally, I'd find some way to do the following:
struct
{
int a, b;
} foo =
{
.a = 4,
.b = 5
};
My reason for wanting to have a by-name initialization of a structure is that my own stucture has many members, so I want better clarity. I shouldn't just initialize them in separate statements because this is a performance-sensitive embedded application where the members are actually bitfields, so a single struct init generates fewer instructions than multiple member initializations.
Which C standard allows for by-name member init like that?
It's not immediately clear what you're asking, but with a c99 compiler, your first attempt could be written as
struct
{
int a[5], b;
} game[] =
{
[0] = {.a = { 1 }},
[1] = {.a[0] = 2}
};
I'm doing something similar in an embedded app under C99. I have a variable called phaseInstill that is "assigned" to a struct:
phaseInstill = (PhaseVolumeStatus)
{
.complete = false,
.ticksInstilled = 0,
.volumeInstilled = 0,
.volumeRemaining = instillVolume
};
Where PhaseVolumeStatus is defined as:
typedef struct
{
Value volumeRemaining; /*!> ml */
Value volumeInstilled; /*!> ml */
Value ticksInstilled; /*!> ticks */
bool complete;
} PhaseVolumeStatus;
I don't have a bitfield example handy, but I don't recall it working any differently in any other of my uses.

Resources