diff --git a/list.h b/list.h new file mode 100644 index 0000000..1ef5083 --- /dev/null +++ b/list.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2016, Linaro Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __LIST_H__ +#define __LIST_H__ + +#include +#include + +#define container_of(ptr, type, member) ({ \ + const typeof(((type *)0)->member)*__mptr = (ptr); \ + (type *)((char *)__mptr - offsetof(type, member)); \ + }) + +struct list_head { + struct list_head *prev; + struct list_head *next; +}; + +#define LIST_INIT(list) { &(list), &(list) } + +static inline void list_init(struct list_head *list) +{ + list->prev = list->next = list; +} + +static inline bool list_empty(struct list_head *list) +{ + return list->next == list; +} + +static inline void list_add(struct list_head *list, struct list_head *item) +{ + struct list_head *prev = list->prev; + + item->next = list; + item->prev = prev; + + prev->next = list->prev = item; +} + +static inline void list_del(struct list_head *item) +{ + item->prev->next = item->next; + item->next->prev = item->prev; +} + +#define list_for_each(item, list) \ + for (item = (list)->next; item != list; item = item->next) + +#define list_for_each_safe(item, next, list) \ + for (item = (list)->next, next = item->next; item != list; item = next, next = item->next) + +#define list_entry(item, type, member) \ + container_of(item, type, member) + +#define list_entry_first(list, type, member) \ + container_of((list)->next, type, member) + +#define list_entry_next(item, member) \ + container_of((item)->member.next, typeof(*(item)), member) + +#define list_for_each_entry(item, list, member) \ + for (item = list_entry_first(list, typeof(*(item)), member); \ + &item->member != list; \ + item = list_entry_next(item, member)) + +#endif diff --git a/qmi_message.c b/qmi_message.c index c1dbfd7..a306baf 100644 --- a/qmi_message.c +++ b/qmi_message.c @@ -2,6 +2,8 @@ #include #include #include + +#include "list.h" #include "qmic.h" static const char *sz_simple_types[] = { @@ -19,7 +21,7 @@ struct qmi_message_member { bool required; unsigned array; - struct qmi_message_member *next; + struct list_head node; }; struct qmi_message { @@ -27,12 +29,12 @@ struct qmi_message { const char *name; unsigned msg_id; - struct qmi_message *next; + struct list_head node; - LIST_HEAD(qmi_message_member, members); + struct list_head members; }; -LIST_HEAD(qmi_message, qmi_messages); +static struct list_head qmi_messages = LIST_INIT(qmi_messages); void qmi_message_parse(enum message_type message_type) { @@ -51,6 +53,7 @@ void qmi_message_parse(enum message_type message_type) qm = malloc(sizeof(struct qmi_message)); qm->name = msg_id_tok.str; qm->type = message_type; + list_init(&qm->members); while (!token_accept('}', NULL)) { array = 0; @@ -89,7 +92,7 @@ void qmi_message_parse(enum message_type message_type) qmm->required = required; qmm->array = array; - LIST_ADD(qm->members, qmm); + list_add(&qm->members, &qmm->node); } if (token_accept('=', NULL)) { @@ -100,7 +103,7 @@ void qmi_message_parse(enum message_type message_type) token_expect(';', NULL); - LIST_ADD(qmi_messages, qm); + list_add(&qmi_messages, &qm->node); } static void qmi_message_emit_message_type(FILE *fp, @@ -290,10 +293,10 @@ void qmi_message_source(FILE *fp, const char *package) struct qmi_message_member *qmm; struct qmi_message *qm; - for (qm = qmi_messages.head; qm; qm = qm->next) { + list_for_each_entry(qm, &qmi_messages, node) { qmi_message_emit_message(fp, package, qm); - for (qmm = qm->members.head; qmm; qmm = qmm->next) + list_for_each_entry(qmm, &qm->members, node) { switch (qmm->type) { case TYPE_U8: case TYPE_U16: @@ -308,6 +311,7 @@ void qmi_message_source(FILE *fp, const char *package) qmi_struct_emit_accessors(fp, package, qm->name, qmm->name, qmm->id, qmm->array, qmm->qmi_struct); break; }; + } } } @@ -316,15 +320,15 @@ void qmi_message_header(FILE *fp, const char *package) struct qmi_message_member *qmm; struct qmi_message *qm; - for (qm = qmi_messages.head; qm; qm = qm->next) + list_for_each_entry(qm, &qmi_messages, node) qmi_message_emit_message_type(fp, package, qm->name); fprintf(fp, "\n"); - for (qm = qmi_messages.head; qm; qm = qm->next) { + list_for_each_entry(qm, &qmi_messages, node) { qmi_message_emit_message_prototype(fp, package, qm->name); - for (qmm = qm->members.head; qmm; qmm = qmm->next) { + list_for_each_entry(qmm, &qm->members, node) { switch (qmm->type) { case TYPE_U8: case TYPE_U16: diff --git a/qmi_struct.c b/qmi_struct.c index ffa9dbf..96405d2 100644 --- a/qmi_struct.c +++ b/qmi_struct.c @@ -1,5 +1,7 @@ #include #include + +#include "list.h" #include "qmic.h" static const char *sz_simple_types[] = { @@ -14,18 +16,18 @@ struct qmi_struct_member { const char *name; int type; - struct qmi_struct_member *next; + struct list_head node; }; struct qmi_struct { const char *name; - struct qmi_struct *next; + struct list_head node; - LIST_HEAD(qmi_struct_member, members); + struct list_head members; }; -LIST_HEAD(qmi_struct, qmi_structs); +static struct list_head qmi_structs = LIST_INIT(qmi_structs); void qmi_struct_parse(void) { @@ -40,6 +42,7 @@ void qmi_struct_parse(void) qs = malloc(sizeof(struct qmi_struct)); qs->name = struct_id_tok.str; + list_init(&qs->members); while (token_accept(TOK_TYPE, &type_tok)) { token_expect(TOK_ID, &id_tok); @@ -49,13 +52,13 @@ void qmi_struct_parse(void) qsm->name = id_tok.str; qsm->type = type_tok.num; - LIST_ADD(qs->members, qsm); + list_add(&qs->members, &qsm->node); } token_expect('}', NULL); token_expect(';', NULL); - LIST_ADD(qmi_structs, qs); + list_add(&qmi_structs, &qs->node); symbol_add(qs->name, TOK_TYPE, TYPE_STRUCT, qs); } @@ -65,10 +68,10 @@ void qmi_struct_header(FILE *fp, const char *package) struct qmi_struct_member *qsm; struct qmi_struct *qs; - for (qs = qmi_structs.head; qs; qs = qs->next) { + list_for_each_entry(qs, &qmi_structs, node) { fprintf(fp, "struct %s_%s {\n", package, qs->name); - for (qsm = qs->members.head; qsm; qsm = qsm->next) { + list_for_each_entry(qsm, &qs->members, node) { fprintf(fp, "\t%s %s;\n", sz_simple_types[qsm->type], qsm->name); } diff --git a/qmic.c b/qmic.c index 857c4e1..ba74298 100644 --- a/qmic.c +++ b/qmic.c @@ -9,6 +9,7 @@ #include #include +#include "list.h" #include "qmic.h" #define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) @@ -66,10 +67,10 @@ struct symbol { int type; struct qmi_struct *qmi_struct; - struct symbol *next; + struct list_head node; }; -LIST_HEAD(symbol, symbols); +static struct list_head symbols = LIST_INIT(symbols); void symbol_add(const char *name, int token, ...) { @@ -81,7 +82,6 @@ void symbol_add(const char *name, int token, ...) sym = malloc(sizeof(struct symbol)); sym->token = token; sym->name = name; - sym->next = NULL; switch (token) { case TOK_MESSAGE: @@ -94,7 +94,7 @@ void symbol_add(const char *name, int token, ...) break; } - LIST_ADD(symbols, sym); + list_add(&symbols, &sym->node); va_end(ap); } @@ -108,6 +108,8 @@ static struct token yylex() int base; int ch; + list_for_each_entry(sym, &symbols, node); + while ((ch = input()) && isspace(ch)) ; @@ -120,17 +122,16 @@ static struct token yylex() *p = '\0'; token.str = strdup(buf); - for (sym = symbols.head; sym; sym = sym->next) { + list_for_each_entry(sym, &symbols, node) { if (strcmp(buf, sym->name) == 0) { token.id = sym->token; token.num = sym->type; token.qmi_struct = sym->qmi_struct; - break; + return token; } } - if (!sym) - token.id = TOK_ID; + token.id = TOK_ID; return token; } else if (isdigit(ch)) { @@ -235,10 +236,10 @@ struct qmi_const { const char *name; unsigned value; - struct qmi_const *next; + struct list_head node; }; -LIST_HEAD(qmi_const, qmi_consts); +static struct list_head qmi_consts = LIST_INIT(qmi_consts); static void qmi_const_parse() { @@ -254,17 +255,18 @@ static void qmi_const_parse() qc = malloc(sizeof(struct qmi_const)); qc->name = id_tok.str; qc->value = num_tok.num; - LIST_ADD(qmi_consts, qc); + + list_add(&qmi_consts, &qc->node); } static void qmi_const_header(FILE *fp) { struct qmi_const *qc; - if (!qmi_consts.head) + if (list_empty(&qmi_consts)) return; - for (qc = qmi_consts.head; qc; qc = qc->next) + list_for_each_entry(qc, &qmi_consts, node) fprintf(fp, "#define %s %d\n", qc->name, qc->value); fprintf(fp, "\n"); diff --git a/qmic.h b/qmic.h index 1e81f50..202d0da 100644 --- a/qmic.h +++ b/qmic.h @@ -3,21 +3,6 @@ #include -#define LIST_HEAD(type, name) \ -struct { \ - struct type *head; \ - struct type *tail; \ -} name; - -#define LIST_ADD(list, elem) \ - if (list.tail) { \ - list.tail->next = elem; \ - list.tail = elem; \ - } else { \ - list.tail = elem; \ - list.head = elem; \ - } - enum { TOK_CONST = 256, TOK_ID,