Thank you for this information. Adding the concept of context is indeed the right idea. I was doing it as follows
void function (grub_device_t dev) { grub_device_t it; auto int look_for_dev (grub_device_t); int look_for_dev (grub_device_t grub_device_t other_dev) { return compare (dev, other_dev) } grub_iterate_list_brk (grub_devices, look_for_dev, it); } but it has to be compared with something like void function (grub_device_t dev) { grub_device_t it = grub_devices; while (it) { if ( compare (dev, it) ) break; } } which is obviously simpler. Maybe the only two functions that are really needed are add and del ? Also, I found out yesterday that the compiler throws out warning about strict aliasing when using the iterate function. I had to add -fno-strict-aliasing to get rid of them. Eric Salomé wrote: > Hi, > > I didn’t take a good look at current iterate functions in Grub 2, yet. > > > > Most iterations needs a “init” (before treatment of first item) and a > “fini” (after treatment of last item). > > Further more, one might want to make iteration functions “re-entrant” > (or recursive), or call-back other functions in a generic way. > > > > One way to get to such behavior easily cost a bit more than the example > you provided : > > you may just add an argument (let’s call it the context object) to the > call of the iterate function : > > > > #define grub_iterate_list(list, func, context) \ > {typeof(list) el = list; while (el) {func(context, el); el=el->next;} > func(context, NULL)} > or > > #define grub_iterate_list(list, func) \ > {void * context = NULL; typeof(list) el = list; while (el) > {func(&context, el); el=el->next;} func(&context, NULL)} > but I prefer the first define as it allows transmission of a full > context to the iteration function. > > > > my_struct * my_ctxt; > > > > my_ctxt = NULL; grub_iterate_list(list, my_func, &my_ctxt); > > > > void my_func (my_struct ** ctxt, my_item * item) { > > if (item == NULL) { > > /* End of iteration : Do any cleanup */ > > if (*ctxt == NULL) return; > > free (*ctxt) …… > > ….. > > return; > > } > > if (*ctxt == NULL) { > > /* First iteration : Do any initialization */ > > *ctxt = malloc (sizeof (my_struct)); …. > > ….. > > } > > /* Do the iteration stuff */ > > ….. > > return; > > } > > > > In grub_iterate_list_brk, you can use context to send a patern or model > object to compare each item of the list with. > > > > The draw back is it makes iteration function a bit less readable, but a > lot more powerful. > > > > _________________________________________ > > Eric Salomé – Paris, France > > > > -----Message d'origine----- > De : [EMAIL PROTECTED] > [mailto:[EMAIL PROTECTED] De la part de > Guffens, Vincent > Envoyé : lundi 8 mai 2006 01:14 > À : grub-devel@gnu.org > Objet : a simple list > > > > Hi, > > I need to use a simple list to register the pci devices, drivers and so > on. I notice that there are lists like that already in the code so what > would you think about having a list.h file like that ? > > /* A very simple list. > * > * If you want a list of struct myitem > * you do > * > * struct myitem *item_list; > * > * where myitem MUST have its next pointer as the FIRST field > * > * and you can then add, delete the EL item, > * grub_add_list (&item_list, el); > * grub_del_list (&item_list, el); > * > * or call HOOK(item) for each element of the list > * grub_iterate_list (item_list, hook); > * > * This brk version will point el to the list item for which > * HOOK(EL) returns a non-null value > * grub_iterate_list_brk (item_list, hook, el); > * > */ > > struct obj { > struct obj *next; /* MUST BE FIRST */ > }; > > #define grub_del_list(list, el) _grub_del_list((struct obj**) list, > (struct obj*) el) > #define grub_add_list(list, el) _grub_add_list((struct obj**) list, > (struct obj*) el) > #define grub_find_list(list, el) \ > (typeof(list)) _grub_find_list((struct obj*) list, (struct obj*) el) > #define grub_iterate_list(list, func) \ > {typeof(list) el = list; while (el) {func(el); el=el->next;}} > #define grub_iterate_list_brk(list, func, it) \ > {typeof(list) el = list; it = 0; \ > while (el) {if (func(el)) {it = el; break;} el=el->next; }} > > static inline struct obj* _grub_find_list (struct obj *list, struct obj > *el) > { > struct obj *it = list; > for (it = list; it; it=it->next) > { > if (it == el) return el; > } > return 0; > }; > > static inline void _grub_add_list (struct obj **list, struct obj *el) > { > if ( (!el) || (_grub_find_list (*list, el)) ) > return; > > el->next = *list; > *list = el; > }; > > static inline void _grub_del_list (struct obj **list, struct obj *el) > { > struct obj **p; > struct obj *q; > > for (p = list, q = *p; q; p = &(q->next), q = q->next) > if (q == el) > { > *p = q->next; > break; > } > }; > > > > > ------------------------------------------------------------------------ > > _______________________________________________ > Grub-devel mailing list > Grub-devel@gnu.org > http://lists.gnu.org/mailman/listinfo/grub-devel -- Vincent Guffens Intelligent Systems & Networks Group Research associate, Imperial College _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org http://lists.gnu.org/mailman/listinfo/grub-devel