On Fri, 24 Jul 2015 10:13:16 +0200, Takashi Iwai wrote:
On Fri, 24 Jul 2015 09:34:19 +0200, Clemens Lang wrote:
On Thu, Jul 23, 2015 at 09:03:31PM +0200, Takashi Iwai wrote:
Well, the linked-list macro is a trivial thing each beginner programmer starts writing at school. And, the API itself can't be an issue.
I agree, but that does not necessarily mean that the license wouldn't apply. Consider this thought experiment. You write a two-page prose article on how a linked list works. Obviously, the concept of a linked list is trivial -- but does that mean copyright doesn't apply to your article? I think we have a similar situation here; the concept of a list may be trivial, but that doesn't mean the implementation is.
Sure, it can be written differently. But my point is that it is (or must be) trivial to write a linked list code for C programmer. We can easily drop the existing code and replace with our own.
That is, it'd be enough just rewriting the existing list.h (e.g. renaming variables, shuffles the call order, rephrase the comments) by ourselves without introducing a big piece of codes of even a different license, IMO.
Unless you re-implement a list from scratch that provides the same API that wouldn't really help you.
So why not writing from scratch? We just need only a few things:
struct list_head list_entry() list_for_each() list_for_each_safe() list_add() list_add_tail()
FYI, below is an example replacement of list.h I wrote quickly from scratch. It turned out that LIST_HEAD(), INIT_LIST_HEAD(), list_del() and list_empty() are needed in addition.
Takashi
=== /* Doubly linked list macros compatible with Linux kernel */
#ifndef _LIST_H #define _LIST_H
#include <stddef.h>
struct list_head { struct list_head *next; struct list_head *prev; };
/* one-shot definition of a list head */ #define LIST_HEAD(x) \ struct list_head x = { &x, &x }
/* initialize a list head explicitly */ static inline void INIT_LIST_HEAD(struct list_head *p) { p->next = p->prev = p; }
#define list_entry_offset(p, type, offset) \ ((type *)((char *)(p) - (offset)))
/* list_entry - retrieve the original struct from list_head * @p: list_head pointer * @type: struct type * @member: struct field member containing the list_head */ #define list_entry(p, type, member) \ list_entry_offset(p, type, offsetof(type, member))
/* list_for_each - iterate over the linked list * @p: iterator, a list_head pointer variable * @list: list_head pointer containing the list */ #define list_for_each(p, list) \ for (p = (list)->next; p != (list); p = p->next)
/* list_for_each_safe - iterate over the linked list, safe to delete * @p: iterator, a list_head pointer variable * @s: a temporary variable to keep the next, a list_head pointer, too * @list: list_head pointer containing the list */ #define list_for_each_safe(p, s, list) \ for (p = (list)->next; s = p->next, p != (list); p = s)
/* list_add - prepend a list entry at the head * @p: the new list entry to add * @list: the list head */ static inline void list_add(struct list_head *p, struct list_head *list) { struct list_head *first = list->next;
p->next = first; first->prev = p; list->next = p; p->prev = list; }
/* list_add_tail - append a list entry at the tail * @p: the new list entry to add * @list: the list head */ static inline void list_add_tail(struct list_head *p, struct list_head *list) { struct list_head *last = list->prev;
last->next = p; p->prev = last; p->next = list; list->prev = p; }
/* list_del - delete the given list entry */ static inline void list_del(struct list_head *p) { p->prev->next = p->next; p->next->prev = p->prev; }
/* list_empty - returns 1 if the given list is empty */ static inline int list_empty(const struct list_head *p) { return p->next == p; }
#endif /* _LIST_H */