/* desinibarf.c */ typedef unsigned short uint16_t; // as typedef uint16_t U16; typedef U16 * P_U16, ** P_P_U16; typedef const U16 * PC_U16; // my 16-bit unsigned enum DATA_ID_NUMBERS // variant simple data ids { DATA_ID_REAL = 0U, DATA_ID_LOGICAL = 1U, DATA_ID_WORD16 = 2U, DATA_ID_WORD32 = 3U, DATA_ID_DATE = 4U, DATA_ID_STRING = 5U, DATA_ID_BLANK = 6U, DATA_ID_ERROR = 7U, DATA_ID_ARRAY = 8U, RPN_DAT_NEXT_NUMBER = 14U }; typedef U16 EV_IDNO; // the variant data ids are a subset of a much larger set of evaluator ids for spreadsheet functions, control etc. typedef union SS_DATA_ARG { double fp; _Bool logical_bool; unsigned int logical_integer; int integer; //SS_STRING string_wr; //SS_STRINGC string; //SS_ARRAY ss_array; //SS_DATE ss_date; //SS_ERROR ss_error; int checking_words[2]; } SS_DATA_ARG; typedef struct SS_DATA // variant data structure - data_id specifies union member { // other char flags members and/or padding here don't seem to affect the compiler barf char flagbyte1; char flagbyte2; EV_IDNO data_id; SS_DATA_ARG arg; } SS_DATA, * P_SS_DATA, ** P_P_SS_DATA; typedef const SS_DATA * PC_SS_DATA; // // some structure-returning functions for variant data initialisers ... // // ... why do we get their data in C$$constdata when those instances are not used ??? // // #define TEST_HAPPINESS // <<< uncomment for a further larf. Why is real happy and integer not ??? static inline SS_DATA ss_data_real(double f64) { // vvv this is OK SS_DATA ss_data = { .data_id = DATA_ID_REAL, .arg.fp = f64 }; return(ss_data); } static inline SS_DATA ss_data_integer(int s32) { #if defined(TEST_HAPPINESS) // vvv this is unhappy SS_DATA ss_data = { .data_id = DATA_ID_WORD32, .arg.integer = s32 }; #else // vvv this is OK SS_DATA ss_data = { .data_id = DATA_ID_WORD32 }; ss_data.arg.integer = s32; #endif return(ss_data); } #if 1 static inline SS_DATA // it doesn't matter whether the initialiser is inline or not for this particular compiler barf ss_data_blank(void) { SS_DATA ss_data = { .data_id = DATA_ID_BLANK, .arg.fp = 1.23 }; // .arg.fp just set to make it easy to see it in C$$constdata return(ss_data); } #else extern SS_DATA ss_data_blank(void); #endif typedef struct SS_NAME_READ { SS_DATA ss_data; int follow_indirection; // if you put this member before ss_data all seems fine too } SS_NAME_READ, * P_SS_NAME_READ; extern void dump_data(P_SS_NAME_READ p); // here comes the fun... // // if the .ss_data member is initialised the compiler barfs // "Fatal internal error: skipdata len/dlen clash" int main(void) { SS_NAME_READ ss_name_read = { .ss_data = ss_data_blank(), .follow_indirection = 42 }; // ss_name_read.ss_data = ss_data_blank(); // it's OK to take out the designated initialiser and do it here dump_data(&ss_name_read); return(0); } #if 0 // you can flip this out for a cleaner DecAOF #include extern void dump_data(P_SS_NAME_READ p) { printf("ss_name_read: f_i=%d\n", (int) p->follow_indirection); P_SS_DATA p_ss_data = &p->ss_data; printf("ss_data: data_id=%d\n", (int) p_ss_data->data_id); printf("[0]=0x%08X\n", p_ss_data->arg.checking_words[0]); printf("[1]=0x%08X\n", p_ss_data->arg.checking_words[1]); } #endif /* end of desinibarf.c */