C quiz για τους καλοκαιρινούς μήνες
Christos Houtouridis
hoo2.ch.pub at gmail.com
Mon Jul 18 13:14:53 EEST 2011
Χαιρετώ τη λίστα!
Ας φανταστούμε τα εξής αρχεία:
/*=============== VS_UI.h ===============*/
#ifndef __VS_UI_h__
#define __VS_UI_h__
//#include "VS_Core.h"
#include <stdio.h>
#define UP ('a')
#define DOWN ('b')
#define ESC ('c')
#define LEFT ('d')
#define ENTER ('e')
#define RIGHT ('f')
typedef const char* Caption_t;
typedef struct MenuObject* MenuObject_pt;
typedef void (*MenuFunc_pt) (void);
typedef union node
{
MenuFunc_pt task;
MenuObject_pt menu;
}Node_t;
typedef struct MenuObject
{
Caption_t cap;
Node_t link;
int8_t isMenu;
}MenuObject_t;
static uint8_t UI_retFlag = 0;
extern const MenuObject_t Menu_Main[];
extern const MenuObject_t Menu_Sub[];
void task_a(void);
void task_b(void);
void task_C (void);
/*=== UI Functions ====*/
void UI_Menu (MenuObject_pt mo);
#ifdef __INLINE
__INLINE void UI_MenuBack (void) { UI_retFlag = 1; }
#else
#define UI_MenuBack() (UI_retFlag = 1)
#endif
#endif //#ifndef __VS_UI_h__
/*=============== VS_UI.c ===============*/
#include "VS_UI.h"
/* Menu Diagram */
const MenuObject_t Menu_Main[] =
{
{"",0,0},
{">A ", task_A, 0},
{"sub", Menu_Sub, 1},
{"ESC", UI_MenuBack, 0},
{0,0,0}
};
const MenuObject_t Menu_Sub[];[] =
{
{"",0,0},
{">B ", task_B, 0},
{">C ", task_C, 0},
{0,0,0}
};
void task_A (void) { printf ("tza"); return; }
void task_B (void) { printf ("tza"); return; }
void task_C (void) { printf ("tza"); return; }
void UI_Menu (MenuObject_pt mo)
{
uint8_t i;
int16_t InChar = 0;
UI_retFlag = 0; //RST flag
if (mo[0].link.task) mo[0].link.task(); //Optional function call
for ( printf("\f"), i=1 ; mo[i].link.task ; )
{
printf("\r%s", mo[i].cap); //Print each caption
InChar = getchar(); //Get user choice
switch (InChar)
{
case UP: --i; break; //Navigating
case DOWN: ++i; break;
case ESC: //Actions
case LEFT:
UI_retFlag = 0;
return;
case RIGHT:
case ENTER:
if (mo[i].isMenu)
UI_Menu( mo[i].link.menu ); //Call menu
else
mo[i].link.task(); //Call function
default:
break;
}
if (!i)
{
for ( i=1 ; mo[i].link.task ; ++i);
--i;
}
if (! mo[i].link.task) i = 1;
if (UI_retFlag) { UI_retFlag = 0; return; }
}
return;
}
/*=========== main.c ============*/
#include "VS_UI.h"
int main (void)
{
UI_Menu (Menu_Main); //Stop Monitoring
while (1) // Main loop
;
}
Να απολογηθώ εδώ ότι έχω ψαλιδίσει "αρκετά" τον κώδικα για να χωρέσει αλλά
ίσως κάποιος να έλεγε ότι έπρεπε να κάνω καλύτερη δουλειά.
Το παραπάνω κομμάτι κώδικα υποτίθεται πως εμφανίζει ένα υποτυπώδες μενού σε
μια μικροσκοπική συσκευή με έναν ARM Cortex-M3.
Η λογική είναι η εξής. Κάνοντας πίνακες με ένα συγκεκριμένο τρόπο έτσι ώστε
να αρχικοποιείται σωστά η δομή MenuObject μπορείς να δημιουργήσεις ότι δομή
θέλεις στο menu σου. Η UI_Menu() δέχεται ένα δείκτη στον πίνακα με
αντικείμενα τύπου MenuObject_t που έκανες και εμφανίζει τις επιλογές που
υπάρχουν εκεί μέσα. O χρήστης(το πλάσμα που χειρίζεται το τελικό προϊόν)
μπορεί να πλοηγηθεί στο τρέχον μενού (τρέχον πίνακας) βλέποντας ένα μήνυμα
στην κάθε τρέχουσα επιλογή. Αν επιλέξει μία (πατήσει ENTER) τότε ελέγχεται
αν το member isMenu είναι true. Αν ναι τότε το τρέχον αντικείμενο είναι
υπομενού και έχουμε recursive call της UI_Menu() με τον νέο πίνακα. Αν το
isMenu είναι false τότε κάνουμε call σαν συνάρτηση μέσω του δείκτη σε void
(*) (void) στο τρέχον task που εμφανιζόταν εκείνη τη στιγμή.
Το παραπάνω κομμάτι κώδικα το έχω χρησημοποιήσει παλιότερα με τον compiler
keil για 8051 και δούλευε μια χαρά (απλά εκεί έπρεπε να δηλώσεις ότι τη
UI_Menu() σαν reentrant).
- Όταν προσπαθώ να το κάνω compile με τον CC_ARM της keil πάλι (πλέον
mdk-arm) με εμπέζει και μου λέει
error: #144: a value of type "const MenuObject_t *" cannot be used to
initialize an entity of type "MenuFunc_pt"
στην γραμμή της αρχικοποίησης του πίνακα με το Menu_Sub.
- Αν δεν χρησιμοποιήσω υπομενού το compile γίνεται κανονικά και το
εκτελέσιμο "παίζει" κανονικά μόνο με tasks (ένα layer menu)
- Αν αλλάξω τη σειρά των member στο union τότε o compiler παραπονιέται ΚΑΙ
για:
error: #144: a value of type "void (*)(void)" cannot be used to initialize
an entity of type "MenuObject_pt"
"Υποτίθεται" πως ο compiler είναι ANSI C plus μερικά μπλιμπλίκια και δεν
έχει διαφορές. Απλά παραπάνω μπιχλιμπίδια.
Any ideas?
Φιλικά
Χρήστος
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.hellug.gr/pipermail/linux-greek-users/attachments/20110718/8a7f9e9b/attachment.html>
More information about the Linux-greek-users
mailing list