Hi,
i’m working on a menu-engine for some time now. after struggling (and learning) a lot with (about) pointers, structs and unions the last 2 days, i’m finally stuck now
I’ll post the problem first, then what i need this for.
–the problem–
one of the fields in a struct (for the menu-entries) should hold a pointer to either a function or a string. so lets have a union in the struct:
void testfunc(void)
{
}
unsigned char teststring[]={"i'm a teststring"};
typedef struct {
// i have dropped all variables here, not affecting the problem
union {
const unsigned char (*const text); //pointer to string
const void (*const menu_func)(unsigned char); //pointer to menu-function
};
} test_t;
const test_t menu[2] = {{&testfunc},{&teststring}}; //initialize the test-menu
compiles fine, but when i look into the asm code, menu contains 4*3 bytes, so it seems the compiler has converted the union into a struct without telling me:
_test db LOW(_testfunc), HIGH(_testfunc), UPPER(_testfunc), 0x00, 0x00, 0x00, LOW(_teststring), HIGH(_teststring), 0x80, 0x00, 0x00, 0x00
when i remove the outer struct, so that test_t is a union, it compiles as i expect:
_test:
DB LOW(_testfunc), HIGH(_testfunc), UPPER(_testfunc), LOW(_teststring), HIGH(_teststring), 0x80
i googled a lot and also discovered, that there have been many bugs in sdcc concerning initialization of unions, but they were either fixed or don’t apply to this case. same happens in sdcc 2.8.0 and 2.9.0. have a clue? –what i need this for– each menu-entry should have a small footprint in order to pack as many entries as possible into the 256byte-limit, and to safe code-space (even if i still have plenty left). it should be possible to enter submenus, change numeric values and change strings. what i came up with is an array of structs with each struct of 5 bytes holding 1 entry. each entry can be 1 of 4 types: type 0: submenu -> you can choose between several followup-entries (e.g. for selecting “midi-setup”, “pots”, “buttons”, …) type 1: multmenu -> you can choose between many values, all pointing to the same followup-entry (e.g. for selecting pot1-64) type 2: editval -> edit a numerical value type 3: edittxt -> edit a string depending on this type, the bytes of an entry have different meaning:
byte0 byte1 byte2-4
bit6+7: bit0-5:
00:submenu index of first subentry number of subentries pointer to entry-function (mainly for handling display stuff)
01:mltmenu index of subentry number of subentries pointer to entry-function (mainly for handling display stuff)
10:editval minimum value maximum value pointer to edit-function
11:editstr unused length of string pointer to string
i then would track the way taken through the menu in a small array (2bytes per menu-level), so i find back to where i was before, when i exit an entry. at the same time, i can read it to see earlier selections. e.g. when i alter a value for a button, that was selected in a multmenu. then i have to look up, which one it was.
i took this whole approach to be flexible, when extending the menu. if you can follow my thoughts, any comments are very welcome ![]()
concerning this union: i certainly could use a function-pointer to a stringedit-function as well and do stuff there (possibly better anyway) or even drop it entirely and do this with the other types. still i’m curious, why the compiler acts the way it does.
thanks for reading or maybe even some input ![]()
Alex