From: Konrad Eisele <eiselekd@gmail.com>
To: Christopher Li <sparse@chrisli.org>
Cc: Konrad Eisele <konrad@gaisler.com>,
Linux-Sparse <linux-sparse@vger.kernel.org>
Subject: Re: Fwd: dependency tee from c parser entities downto token
Date: Sat, 12 May 2012 19:46:48 +0200 [thread overview]
Message-ID: <4FAEA208.3090601@gmail.com> (raw)
In-Reply-To: <CANeU7QnEyUExcxaoVEeamhu1m+Z_pg0TpKBP00hh+gyPgdq66w@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 4762 bytes --]
On 05/12/2012 01:02 PM, Christopher Li wrote:
> On Fri, May 11, 2012 at 2:48 PM, Konrad Eisele<eiselekd@gmail.com> wrote:
>>
>> This seems ok. expanding_macro has to be global not static to be
>> used... (?)
>
> The expand_macro call back use the parent argument which get
> from expanding_macro list. The caller should be able to create tree
> from the leaf node using the parent pointer.
>
> Feel free to change to use the expanding_macro instead if that make
> building the tree easier.
>
>> I think the fact that argument expansion is recursive and
>> body expansion is non-recursive is one of the things that
>> make the preprocessor kindof hard to grasp.
>
> The body expansion can't be recursive on same macro otherwise
> it can result in unlimited expansion. The C stander specify
> the macro expand this way.
>
>>
>> I cannot say this before I've tried it.
>>
>> I'd like to straighten things out a bit: My last emails
>> where a bit too harsh and I'd like to apologize. Sorry
>> for that.
>
> No problem at all. I figure you just want to the patch to
> get included.
>
>> The next step then is: I'll write a patch to add a
>> test-prog that uses this api to trace the token generation
>> and generate a tree for it.
>> For a start I'll printout for all tokens of a preprocessor
>> run all macros-expansions that generated them.
>
> That is great. I have a test-macro program in that
> branch which is very close to print out all the tokens.
Appended is a test-patch that adds test-mdep testcase.
The file mdep.c is used to record that macro
expansion, each token will have a reference to its
source.
test-mdep.c does pre-process (as test-macro.c) then
prints out the token trace through macros for each
token: @{ } is used to mark the active path.
An example file is added: a.h
$test-mdep a.h
...
0004: 8
body in D1 :4 @{8} 10 9 5 <untaint: D1>
arg0 in D1 :@{8} 10 9
body in D0 :1 @{D1}(8 10 9) 2 D2(11) 3 <untaint: D0>
a.h:6:6
...
Token nr 4 of the preprocess stream is "8". The
generation path of "8" is marked @{8}...
Not 100%, still, I think already readable. (Actually
the printout order should be reversed (starting from file scope
and drilling down the macro expansions...)
I still dont handle empty expansions. I'll see weather I can come up
with something here...
>
>> Now, I've learned not to run too fast towards the
>> goal, (which is still "dependency tee from c parser entities downto
>> token"), maybe you can think about how to achieve the next steps
>> in an API :
>> - An #include #ifdef #else #endif pushdown-stack
>> to record the nestings for each token
>
> Let me think about this. Just thinking out lound,
> The #include and #ifdef can consider as a special kind
> of predefine macro as well.
No, only a linked list that model the nexting levels.
Then a preprocessor hook that can register lookup_macro()
macro lookups inside # preprocessor lines. An example
makes it clear:
#if defined(a) && defined(b)
#if defined(c)
#endif
#if defined(e)
#endif
#endif
Result in:
[a b]+<-[c]
+<-[e]
This can be easily done with a push-pop brackets
and a callback in lookup_macro().
Also:
#if defined(a)
#elif defined(c)
#endif
[a]+<-[c]
#if defined(a)
#else
#endif
<-[empty]<-[a]
...
Another point I also need is to have an option so that inside
do_handle_define() the symbol structures are never reused but
alloc_symbol() is always used for undef and define, this is
because I need to be able to also track the undef and define
history for a macro at a certain position. I think this should be
easy to add because you just need to define define-undef on
top of each other...
>
>> - How to connect all this to the AST.
>
> For symbol, it relative easy because symbol has pos range
> and aux pointer.
I thought about taking "struct symbol_list *syms = sparse(file)"
as the root. Then mark all elements that are used by them as dependent.
I dont have enough insight to say how I can determine things like
which "static inline" are used or how to traverse the
"typedef" dependency.
The goal is to have a "shrink" application that can strip away
all c-lines (pre-pre-process level) that are not used by a specific
command invocation of the compiler. Also a tool that can quickly show
for a specific identifier everything that is connected to it, again on
pre-preprocessor source level. kind-of something like:
...
func1() {
struct string_list *filelist = NULL; int i;
}
..
I point to "string_list" and then all lines that are related
to struct string_list, (#ifdef nestings, macros, all member typedefs)
etc are shown and all the rest stripped away, again on human
readable c source level.
>
> Do you need to attach the dependency for the statment and
> expression as well?
>
> Chris
>
[-- Attachment #2: 0001-mdep.c-test.patch --]
[-- Type: text/plain, Size: 15568 bytes --]
From aff7f53ce89d24512c0ba2f66b981718538ae1c8 Mon Sep 17 00:00:00 2001
From: Konrad Eisele <eiselekd@gmail.de>
Date: Sat, 12 May 2012 18:43:16 +0200
Subject: [PATCH] mdep.c test
---
Makefile | 5 +-
a.h | 6 ++
a2.h | 2 +
lib.c | 19 +++--
mdep.c | 248 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
pre-process.c | 3 +-
test-macro.c | 10 +-
test-mdep.c | 62 ++++++++++++++
token.h | 8 ++-
tokenize.c | 8 +-
10 files changed, 351 insertions(+), 20 deletions(-)
create mode 100644 a.h
create mode 100644 a2.h
create mode 100644 mdep.c
create mode 100644 test-mdep.c
diff --git a/Makefile b/Makefile
index 4abcbdd..b688054 100644
--- a/Makefile
+++ b/Makefile
@@ -44,7 +44,7 @@ PKGCONFIGDIR=$(LIBDIR)/pkgconfig
PROGRAMS=test-lexing test-parsing obfuscate compile graph sparse \
test-linearize example test-unssa test-dissect ctags \
- test-macro
+ test-mdep test-macro
INST_PROGRAMS=sparse cgcc
INST_MAN1=sparse.1 cgcc.1
@@ -96,7 +96,8 @@ LIB_H= token.h parse.h lib.h symbol.h scope.h expression.h target.h \
LIB_OBJS= target.o parse.o tokenize.o pre-process.o symbol.o lib.o scope.o \
expression.o show-parse.o evaluate.o expand.o inline.o linearize.o \
sort.o allocate.o compat-$(OS).o ptrlist.o \
- flow.o cse.o simplify.o memops.o liveness.o storage.o unssa.o dissect.o
+ flow.o cse.o simplify.o memops.o liveness.o storage.o unssa.o dissect.o \
+ mdep.o
LIB_FILE= libsparse.a
SLIB_FILE= libsparse.so
diff --git a/a.h b/a.h
new file mode 100644
index 0000000..63da9e8
--- /dev/null
+++ b/a.h
@@ -0,0 +1,6 @@
+//#include <stdio.h>
+#define D0(d0a0,d0a1) 1 D1(d0a0) 2 D2(d0a1) 3
+#define D1(d1a0) 4 d1a0 5
+#define D2(d2a0)
+#define D3(d3a0) 8 d3a0 9
+1 2 D0(D3(10),11) 3 4
diff --git a/a2.h b/a2.h
new file mode 100644
index 0000000..098fbc2
--- /dev/null
+++ b/a2.h
@@ -0,0 +1,2 @@
+#define A(a,b) b 3
+A(1,2)
diff --git a/lib.c b/lib.c
index 1876fc9..51879d9 100644
--- a/lib.c
+++ b/lib.c
@@ -577,6 +577,7 @@ static char **handle_switch_ftabstop(char *arg, char **next)
return next;
}
+int fnobuildin = 0;
static char **handle_switch_f(char *arg, char **next)
{
arg++;
@@ -588,6 +589,9 @@ static char **handle_switch_f(char *arg, char **next)
if (!strncmp(arg, "no-", 3)) {
arg += 3;
+ if (!strncmp(arg, "buildin", 7)) {
+ fnobuildin = 1;
+ }
}
/* handle switch here.. */
return next;
@@ -875,7 +879,7 @@ static struct symbol_list *sparse_tokenstream(struct token *token)
token = preprocess(token);
if (preprocess_only) {
- show_tokenstream(token);
+ show_tokenstream(token, 0);
putchar('\n');
return NULL;
}
@@ -963,12 +967,13 @@ struct symbol_list *sparse_initialize(int argc, char **argv, struct string_list
// Initialize type system
init_ctype();
- create_builtin_stream();
- add_pre_buffer("#define __CHECKER__ 1\n");
- if (!preprocess_only)
- declare_builtin_functions();
-
- list = sparse_initial();
+ if (!fnobuildin) {
+ create_builtin_stream();
+ add_pre_buffer("#define __CHECKER__ 1\n");
+ if (!preprocess_only)
+ declare_builtin_functions();
+ list = sparse_initial();
+ }
/*
* Protect the initial token allocations, since
diff --git a/mdep.c b/mdep.c
new file mode 100644
index 0000000..6af8467
--- /dev/null
+++ b/mdep.c
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2012 Konrad Eisele <eiselekd@gmail.com>
+ * BSD-License
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the <organization>. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include "token.h"
+#include "allocate.h"
+#include "compat.h"
+#include "parse.h"
+#include "symbol.h"
+#include "token.h"
+#include "lib.h"
+
+static void expand_macro(struct token *macro, struct symbol *sym,
+ struct token *parent, struct token **replace,
+ struct token **replace_tail, struct token *last);
+static void expand_arg(struct token *macro, struct symbol *sym, int arg,
+ struct token *orig, struct token *expanded);
+struct pp;
+struct pp_e;
+
+struct preprocess_hook pp = {
+ .expand_macro = expand_macro,
+ .expand_arg = expand_arg
+};
+
+unsigned int pps = 0;
+
+void mdep_init(void) {
+ preprocess_hook = &pp;
+ pps = init_stream("<pp>", -1, 0);
+}
+
+enum tags {
+ ATTR_TOK = 1,
+ ATTR_TOKP = 2,
+};
+
+struct hash_v {
+ struct hash_v *n;
+ long key;
+ enum tags tag;
+ void *v;
+};
+
+__DECLARE_ALLOCATOR(struct hash_v, hash_v);
+__ALLOCATOR(struct hash_v, "hash value", hash_v);
+
+#define HASH_LEN (1024*4)
+struct hash {
+ struct hash_v *f;
+} h[HASH_LEN];
+
+static int hash_func(long key, enum tags tag) {
+ unsigned int k = ((unsigned int)key) >> 4;
+ return ((k) ^ (k >> 16) ^ (k >> 24) ^ tag) & (HASH_LEN-1);
+}
+
+void **lookup_attr(long key, enum tags tag, int create) {
+ int i = hash_func(key, tag);
+ struct hash *hp = &h[i];
+ struct hash_v *p;
+ struct hash_v **c = &hp->f;
+ while((p = *c)) {
+ if ((p ->tag == tag)
+ && (p ->key == key)) {
+ return &p->v;
+ }
+ c = &p->n;
+ }
+ if (create) {
+ p = __alloc_hash_v(0);
+ p->key = key;
+ p->tag = tag;
+ p->v = 0;
+ *c = p;
+ return &p->v;
+ }
+ return 0;
+}
+
+enum pp_typ {
+ MARG = 1,
+ MBODY,
+};
+
+struct pp {
+ enum pp_typ t;
+ union {
+ unsigned int argi;
+ };
+ struct pp_e *f;
+ struct symbol *sym;
+ struct token *tok;
+ struct token *s, *d;
+};
+
+struct pp_e {
+ struct pp_e *n;
+ struct pp *p;
+ struct position from;
+ int idx;
+};
+
+__DECLARE_ALLOCATOR(struct pp, pp_v);
+__ALLOCATOR(struct pp, "pp trace", pp_v);
+__DECLARE_ALLOCATOR(struct pp_e, pp_e_v);
+__ALLOCATOR(struct pp_e, "pp trace element", pp_e_v);
+int n_tokid = 1;
+
+void pp_dope_list(struct pp *p, struct token **d, int dope, struct token *list, struct token *end, int prt)
+{
+ struct pp_e **e = &p->f;
+ struct token *n;
+ int idx = 0;
+ while ((!eof_token(list)) && list != end ) {
+ if (dope) {
+ void **v;
+ int id = n_tokid++;
+ struct pp_e *n = __alloc_pp_e_v(0);
+ n->from = list->pos;
+ n->idx = idx;
+ n->n = 0;
+ n->p = p;
+ *e = n;
+ v = lookup_attr(id, ATTR_TOK, 1);
+ *v = n;
+ list->pos.line = id;
+ list->pos.stream = pps;
+ e = &n->n;
+ }
+ n = __alloc_token(0);
+ *n = *list;
+ /*printf(" %s\n", show_token(list));*/
+ n->next = &eof_token_entry;
+ *d = n;
+ d = &n->next;
+ list = list->next;
+ idx++;
+
+
+ }
+}
+
+struct pp *new_pp(struct token *m, int t) {
+ struct pp *n = __alloc_pp_v(0);
+ n->t = t;
+ n->f = 0;
+ return n;
+}
+
+static void expand_macro(struct token *macro, struct symbol *sym, struct token *parent,
+ struct token **replace, struct token **replace_tail, struct token *last)
+{
+ struct pp *p = new_pp(macro, MBODY);
+ p->sym = sym;
+ p->tok = macro;
+ pp_dope_list(p, &p->s, 0, sym->expansion, 0, 0);
+ pp_dope_list(p, &p->d, 1, *replace, last, 0);
+}
+
+static void expand_arg(struct token *macro, struct symbol *sym, int arg,
+ struct token *orig, struct token *expanded)
+{
+ struct pp *p = new_pp(macro, MARG);
+ p->argi = arg;
+ p->sym = sym;
+ p->tok = macro;
+ pp_dope_list(p, &p->s, 0, orig, 0, 0);
+ pp_dope_list(p, &p->d, 1, expanded, 0, 0);
+}
+
+void mdep_show_tokenstream(struct token *token, struct token *end, int idx)
+{
+ int i = 0;
+ while (token != end && !eof_token(token)) {
+ int prec = 1;
+ struct token *next = token->next;
+ const char *separator = "";
+ if (next->pos.whitespace)
+ separator = " ";
+ if (next->pos.newline) {
+ separator = "\n\t\t\t\t\t";
+ prec = next->pos.pos;
+ if (prec > 4)
+ prec = 4;
+ }
+ if (i == idx)
+ fprintf(stderr,"@{%s}%.*s", show_token(token), prec, separator);
+ else
+ fprintf(stderr,"%s%.*s", show_token(token), prec, separator);
+ token = next;
+ i++;
+ }
+}
+
+void mdep_trace (struct token *tok, char *pre)
+{
+ void **v; int id; struct position pos = tok->pos;
+ struct pp_e *e; struct pp *p;
+ pre = pre ? pre : "";
+ if(!tok || eof_token (tok))
+ return;
+ while(1) {
+ if (pos.stream != pps) {
+ char *name = stream_name(pos.stream);
+ fprintf(stderr, "%s%s:%d:%d\n", pre,
+ name, pos.line, pos.pos);
+ break;
+ }
+ id = pos.line;
+ if (!(v = lookup_attr(id, ATTR_TOK, 0))) {
+ break;
+ }
+ e = (struct pp_e *)*v;
+ p = e->p;
+ fprintf(stderr, "%s",pre);
+ if (p->t == MARG) {
+ fprintf(stderr,"arg%d in %s :", p->argi, show_token(p->tok));
+ } else {
+ fprintf(stderr,"body in %s :", show_token(p->tok));
+ }
+ mdep_show_tokenstream(p->d, 0,e->idx); fprintf (stderr,"\n");
+ pos = e->from;
+ }
+}
+
+/*
+Local Variables:
+c-basic-offset:4
+indent-tabs-mode:nil
+End:
+*/
diff --git a/pre-process.c b/pre-process.c
index fb3430a..4eee864 100644
--- a/pre-process.c
+++ b/pre-process.c
@@ -385,6 +385,7 @@ static void expand_arguments(int count, struct arg *args)
struct token *arg = args[i].arg;
if (!arg)
arg = &eof_token_entry;
+ args[i].expanded = &eof_token_entry;
if (args[i].n_str)
args[i].str = stringify(arg);
if (args[i].n_normal) {
@@ -661,7 +662,7 @@ static int expand(struct token **list, struct symbol *sym)
last = token->next;
tail = substitute(list, sym->expansion, args);
if (preprocess_hook && preprocess_hook->expand_macro)
- preprocess_hook->expand_macro(token, sym, parent, list, tail);
+ preprocess_hook->expand_macro(token, sym, parent, list, tail, last);
*tail = last;
return 0;
diff --git a/test-macro.c b/test-macro.c
index b30ee50..3115bef 100644
--- a/test-macro.c
+++ b/test-macro.c
@@ -22,9 +22,9 @@
static void expand_arg(struct token *macro, struct symbol *sym, int i, struct token *orig, struct token *expanded)
{
printf("arg%d in %s :", i, show_token(macro));
- show_tokenstream(orig);
+ show_tokenstream(orig, 0);
printf(" -> ");
- show_tokenstream(expanded);
+ show_tokenstream(expanded, 0);
printf("\n");
}
@@ -35,7 +35,7 @@ static void expand_macro(struct token *macro, struct symbol *sym, struct token *
printf("macro %s inside", show_token(macro));
printf(" %s\n", show_token(parent));
printf("expand result: ");
- show_tokenstream(*replace);
+ show_tokenstream(*replace, 0);
printf("\n");
}
@@ -55,11 +55,11 @@ void test_macro(char *filename)
die("No such file: %s", filename);
token = tokenize(filename, fd, NULL, includepath);
- show_tokenstream(token);
+ show_tokenstream(token, 0);
printf("\n");
token = preprocess(token);
printf("After preprocessing\n");
- show_tokenstream(token);
+ show_tokenstream(token, 0);
}
int main(int argc, char **argv)
diff --git a/test-mdep.c b/test-mdep.c
new file mode 100644
index 0000000..eca0357
--- /dev/null
+++ b/test-mdep.c
@@ -0,0 +1,62 @@
+/*
+ * Parse and linearize the tree for testing.
+ *
+ * Copyright (C) 2012 Christophre Li
+ *
+ */
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "lib.h"
+#include "allocate.h"
+#include "token.h"
+#include "parse.h"
+#include "symbol.h"
+#include "expression.h"
+
+void test_mdep(char *filename)
+{
+ struct token *token;
+ int fd; int idx = 0;
+ fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ die("No such file: %s", filename);
+
+ token = tokenize(filename, fd, NULL, includepath);
+ token = preprocess(token);
+ printf("Dump token stream:\n");
+
+ while (!eof_token(token)) {
+ struct token *next = token->next;
+ printf("%04d: %s\n", idx, show_token(token));
+ mdep_trace (token, " ");
+ token = next; idx++;
+ }
+
+}
+
+int main(int argc, char **argv)
+{
+ struct string_list *filelist = NULL;
+ char *file;
+
+ mdep_init();
+
+ sparse_initialize(argc, argv, &filelist);
+ FOR_EACH_PTR_NOTAG(filelist, file) {
+ test_mdep(file);
+ } END_FOR_EACH_PTR_NOTAG(file);
+ return 0;
+}
+
+/*
+Local Variables:
+c-basic-offset:4
+indent-tabs-mode:nil
+End:
+*/
diff --git a/token.h b/token.h
index 985d1f5..8ddccd5 100644
--- a/token.h
+++ b/token.h
@@ -173,7 +173,7 @@ struct token {
struct preprocess_hook {
void (*expand_macro)(struct token *macro, struct symbol *sym, struct token *parent,
- struct token **replace, struct token **replace_tail);
+ struct token **replace, struct token **replace_tail, struct token *last);
void (*expand_arg)(struct token *macro, struct symbol *sym, int arg,
struct token *orig, struct token *expanded);
};
@@ -206,7 +206,7 @@ extern const char *show_special(int);
extern const char *show_ident(const struct ident *);
extern const char *show_string(const struct string *string);
extern const char *show_token(const struct token *);
-extern void show_tokenstream(struct token *token);
+extern void show_tokenstream(struct token *token, struct token *end);
extern struct token * tokenize(const char *, int, struct token *, const char **next_path);
extern struct token * tokenize_buffer(void *, unsigned long, struct token **);
@@ -223,4 +223,8 @@ static inline int match_ident(struct token *token, struct ident *id)
return token->pos.type == TOKEN_IDENT && token->ident == id;
}
+/* mdep.c */
+extern void mdep_init (void);
+extern void mdep_trace (struct token *tok, char *pre);
+
#endif
diff --git a/tokenize.c b/tokenize.c
index b626f3f..6d0978f 100644
--- a/tokenize.c
+++ b/tokenize.c
@@ -127,6 +127,8 @@ const char *show_token(const struct token *token)
if (!token)
return "<no token>";
+ if (token == &eof_token_entry)
+ return "<eof>";
switch (token_type(token)) {
case TOKEN_ERROR:
return "syntax error";
@@ -180,9 +182,9 @@ const char *show_token(const struct token *token)
}
}
-void show_tokenstream(struct token *token)
+void show_tokenstream(struct token *token, struct token *end)
{
- while (!eof_token(token)) {
+ while (token != end && !eof_token(token)) {
int prec = 1;
struct token *next = token->next;
const char *separator = "";
@@ -194,7 +196,7 @@ void show_tokenstream(struct token *token)
if (prec > 4)
prec = 4;
}
- printf("%s%.*s", show_token(token), prec, separator);
+ fprintf(stderr,"%s%.*s", show_token(token), prec, separator);
token = next;
}
}
--
1.7.4.4
next prev parent reply other threads:[~2012-05-12 17:43 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-04-24 9:54 dependency tee from c parser entities downto token Konrad Eisele
2012-04-25 20:10 ` [PATCH] depend.c: build up a dependency tree from c entities downto tokens: entries in the tree are: macro-depend: tree of #if nesting macro-expansions: possible macro expansion source of a token tok->macro-expansions->macro tok->macro-depend->macro c entities are linked in via [stmt|expr|sym]->start-end-token Konrad Eisele
2012-04-30 22:58 ` dependency tee from c parser entities downto token Christopher Li
2012-05-02 7:27 ` Konrad Eisele
2012-05-03 23:52 ` Christopher Li
2012-05-04 7:33 ` Konrad Eisele
2012-05-04 9:25 ` Christopher Li
2012-05-04 10:36 ` Konrad Eisele
2012-05-04 12:36 ` Konrad Eisele
2012-05-04 15:30 ` Josh Triplett
2012-05-04 20:53 ` Konrad Eisele
2012-05-04 22:30 ` Christopher Li
2012-05-05 0:32 ` Josh Triplett
2012-05-05 8:59 ` Konrad Eisele
2012-05-05 8:56 ` Konrad Eisele
2012-05-04 18:02 ` Christopher Li
2012-05-04 21:46 ` Konrad Eisele
2012-05-04 21:56 ` Konrad Eisele
2012-05-04 23:05 ` Christopher Li
2012-05-05 8:54 ` Konrad Eisele
2012-05-05 11:12 ` Christopher Li
2012-05-05 16:59 ` Konrad Eisele
[not found] ` <CANeU7Qn7vUzLQAF6JGRECro_pPDnL7MCswkrNACe1wohLHZu7g@mail.gmail.com>
2012-05-05 19:56 ` Fwd: " Christopher Li
2012-05-05 23:38 ` Konrad Eisele
2012-05-06 18:34 ` Christopher Li
2012-05-07 6:12 ` Konrad Eisele
2012-05-07 22:06 ` Christopher Li
2012-05-08 6:38 ` Konrad Eisele
2012-05-09 9:18 ` Christopher Li
2012-05-09 9:48 ` Konrad Eisele
2012-05-09 22:50 ` Christopher Li
2012-05-10 6:19 ` Konrad Eisele
2012-05-10 6:38 ` Konrad Eisele
2012-05-10 9:37 ` Christopher Li
2012-05-10 9:51 ` Konrad Eisele
2012-05-10 11:25 ` Christopher Li
2012-05-10 12:14 ` Konrad Eisele
2012-05-10 12:28 ` Konrad Eisele
2012-05-11 19:40 ` Christopher Li
2012-05-11 21:48 ` Konrad Eisele
2012-05-12 11:02 ` Christopher Li
2012-05-12 17:46 ` Konrad Eisele [this message]
2012-05-12 17:57 ` Konrad Eisele
2012-05-13 8:52 ` Konrad Eisele
2012-05-15 6:30 ` Christopher Li
2012-05-15 7:52 ` Konrad Eisele
2012-05-15 9:44 ` Christopher Li
2012-05-15 13:03 ` Konrad Eisele
2012-05-14 10:53 ` Christopher Li
2012-05-10 9:03 ` Christopher Li
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4FAEA208.3090601@gmail.com \
--to=eiselekd@gmail.com \
--cc=konrad@gaisler.com \
--cc=linux-sparse@vger.kernel.org \
--cc=sparse@chrisli.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).