浏览代码

drink the LISP koolaid

Tobias Waldekranz.com 8 年之前
父节点
当前提交
a721c3bd2b
共有 8 个文件被更改,包括 292 次插入180 次删除
  1. 7 0
      arch-x86_64.c
  2. 1 0
      arch.h
  3. 85 1
      global.c
  4. 4 8
      kprobe.c
  5. 76 86
      node.c
  6. 73 56
      node.h
  7. 22 27
      ply.c
  8. 24 2
      type.c

+ 7 - 0
arch-x86_64.c

68
 	},
68
 	},
69
 };
69
 };
70
 
70
 
71
+type_t t_pt_regsp = {
72
+	.ttype = T_POINTER,
73
+	.t.pointer = {
74
+		.type = &t_pt_regs,
75
+	}
76
+};
77
+
71
 type_t *arch_types[] = {
78
 type_t *arch_types[] = {
72
 	&t_s8, &t_s8p, &t_u8, &t_u8p,
79
 	&t_s8, &t_s8p, &t_u8, &t_u8p,
73
 	&t_s16, &t_s16p, &t_u16, &t_u16p,
80
 	&t_s16, &t_s16p, &t_u16, &t_u16p,

+ 1 - 0
arch.h

24
 extern type_t t_u64p;
24
 extern type_t t_u64p;
25
 
25
 
26
 extern type_t t_pt_regs;
26
 extern type_t t_pt_regs;
27
+extern type_t t_pt_regsp;
27
 
28
 
28
 #endif	/* _PLY_ARCH_H */
29
 #endif	/* _PLY_ARCH_H */

+ 85 - 1
global.c

1
+#include <errno.h>
2
+#include <string.h>
3
+
1
 #include "ply.h"
4
 #include "ply.h"
2
 
5
 
6
+/* pid */
7
+
8
+type_t t_pid_t = {
9
+	.ttype = T_TYPEDEF,
10
+
11
+	.t.tdef = {
12
+		.name = "__ply_pid_t",
13
+		.type = &t_u32,
14
+	},
15
+};
16
+
17
+type_t t_pid_func = {
18
+	.ttype = T_FUNC,
19
+
20
+	.t.func = {
21
+		.name = "pid",
22
+		.type = &t_pid_t,
23
+		.args = NULL,
24
+	},
25
+};
26
+
27
+type_t *ts_pid[] = { &t_pid_t, &t_pid_func, NULL };
28
+
29
+
30
+/* quantize */
31
+
32
+type_t t_u64_64 = {
33
+	.ttype = T_ARRAY,
34
+	.t.array = {
35
+		.type = &t_u64,
36
+		.len = 64,
37
+	},
38
+};
39
+
40
+type_t t_quantize_t = {
41
+	.ttype = T_TYPEDEF,
42
+
43
+	.t.tdef = {
44
+		.name = "__ply_quantize_t",
45
+		.type = &t_u64_64,
46
+	},
47
+};
48
+
49
+field_t f_quantize_args[] = {
50
+	{ .type = &t_s64 },
51
+	{ .type = NULL }
52
+};
53
+
54
+type_t t_quantize_func = {
55
+	.ttype = T_FUNC,
56
+
57
+	.t.func = {
58
+		.name = "quantize",
59
+		.type = &t_quantize_t,
60
+		.args = f_quantize_args,
61
+	},
62
+};
63
+
64
+type_t *ts_quantize[] = { &t_u64_64, &t_quantize_t, &t_quantize_func, NULL };
65
+
3
 int global_resolve(prog_t *prog, node_t *n)
66
 int global_resolve(prog_t *prog, node_t *n)
4
 {
67
 {
5
-	return 0;
68
+	type_t **ts = NULL;
69
+	type_t *t;
70
+	int err;
71
+
72
+	if (!strcmp(n->ident, "pid")) {
73
+		ts = ts_pid;
74
+		t = &t_pid_func;
75
+	} else if (!strcmp(n->ident, "quantize")) {
76
+		ts = ts_quantize;
77
+		t = &t_quantize_func;
78
+	} else {
79
+		return -ENOENT;
80
+	}
81
+
82
+	if (ts) {
83
+		err = type_add_list(ts);
84
+		if (err)
85
+			return err;
86
+	}
87
+
88
+	n->type = t;
89
+	return sym_add(prog->locals, n->ident, t);
6
 }
90
 }
7
 
91
 
8
 int global_probe(prog_t *prog)
92
 int global_probe(prog_t *prog)

+ 4 - 8
kprobe.c

19
 
19
 
20
 int kprobe_resolve(prog_t *prog, node_t *n)
20
 int kprobe_resolve(prog_t *prog, node_t *n)
21
 {
21
 {
22
-	struct kprobe *kp = prog->provider_data;
23
 	type_t *t;
22
 	type_t *t;
24
-	char *name;
25
 
23
 
26
-	name = n->atom.ident;
27
-
28
-	if (is_arg(name))
24
+	if (is_arg(n->ident))
29
 		t = &t_ul;
25
 		t = &t_ul;
30
-	else if (!strcmp(name, "ctx"))
31
-		t = &t_pt_regs;
26
+	else if (!strcmp(n->ident, "ctx"))
27
+		t = &t_pt_regsp;
32
 	else
28
 	else
33
 		return -ENOENT;
29
 		return -ENOENT;
34
 
30
 
35
 	n->type = t;
31
 	n->type = t;
36
-	return sym_add(prog->locals, name, t);
32
+	return sym_add(prog->locals, n->ident, t);
37
 }
33
 }
38
 
34
 
39
 int kprobe_probe(prog_t *prog)
35
 int kprobe_probe(prog_t *prog)

+ 76 - 86
node.c

6
 
6
 
7
 #include "node.h"
7
 #include "node.h"
8
 
8
 
9
-void node_print_atom(node_t *n, FILE *fp)
9
+void nprint(node_t *n, FILE *fp)
10
 {
10
 {
11
-	switch (n->atom.atype) {
12
-	case A_IDENT:
13
-		fputs(n->atom.ident, fp);
11
+	switch (n->ntype) {
12
+	case N_CONS:
13
+		fputs("<CONS>", fp);
14
+		break;
15
+	case N_OP:
16
+		fputc(n->op, fp);
17
+		break;
18
+	case N_IDENT:
19
+		fputs(n->ident, fp);
14
 		break;
20
 		break;
15
-	case A_NUM:
16
-		fprintf(fp, "%#"PRIx64, n->atom.num);
21
+	case N_NUM:
22
+		fprintf(fp, "%#"PRIx64, n->num);
17
 		break;
23
 		break;
18
-	case A_STRING:
19
-		fprintf(fp, "\"%s\"", n->atom.string);
24
+	case N_STRING:
25
+		fprintf(fp, "\"%s\"", n->string);
20
 		break;
26
 		break;
21
 
27
 
22
 	default:
28
 	default:
23
-		fputs("INVALID_ATOM", fp);
29
+		fputs("<INVALID>", fp);
24
 	}
30
 	}
25
 }
31
 }
26
 
32
 
27
-void node_print_expr(node_t *n, FILE *fp)
33
+int __node_dump_pre(node_t *n, void *_info)
28
 {
34
 {
29
-	if (!isprint(n->expr.etype)) {
30
-		fputs("INVALID_EXPR", fp);
31
-		return;
32
-	}
35
+	ndump_info_t *info = _info;
33
 
36
 
34
-	fputc(n->expr.etype, fp);
35
-}
36
-
37
-void node_print(node_t *n, FILE *fp)
38
-{
39
 	switch (n->ntype) {
37
 	switch (n->ntype) {
40
-	case N_ATOM:
41
-		node_print_atom(n, fp);
42
-		break;
43
-	case N_EXPR:
44
-		node_print_expr(n, fp);
38
+	case N_CONS:
39
+		info->indent += 2;
45
 		break;
40
 		break;
46
 
41
 
47
 	default:
42
 	default:
48
-		fputs("INVALID_NODE", fp);
43
+		fprintf(info->fp, "%*s", info->indent, "");
44
+		nprint(n, info->fp);
45
+		fputc('\n', info->fp);
49
 	}
46
 	}
50
-}
51
-
52
-int __node_dump_pre(node_t *n, void *_info)
53
-{
54
-	node_dump_info_t *info = _info;
55
-
56
-	fprintf(info->fp, "%*s", info->indent, "");
57
-	node_print(n, info->fp);
58
-	fputc('\n', info->fp);
59
 
47
 
60
-	if (n->ntype == N_EXPR) {
61
-		info->indent += 2;
62
-	}
63
 	return 0;
48
 	return 0;
64
 }
49
 }
65
 
50
 
66
 int __node_dump_post(node_t *n, void *_info)
51
 int __node_dump_post(node_t *n, void *_info)
67
 {
52
 {
68
-	node_dump_info_t *info = _info;
53
+	ndump_info_t *info = _info;
69
 	node_t *next;
54
 	node_t *next;
70
 
55
 
71
-	if (n->ntype == N_EXPR)
56
+	if (n->ntype == N_CONS)
72
 		info->indent -= 2;
57
 		info->indent -= 2;
73
 
58
 
74
 	return 0;
59
 	return 0;
75
 }
60
 }
76
 
61
 
77
-void node_dump(node_t *n, node_dump_info_t *info)
62
+void ndump(node_t *n, ndump_info_t *info)
78
 {
63
 {
79
 
64
 
80
-	node_walk(n, __node_dump_pre, __node_dump_post, info);
65
+	nwalk(n, __node_dump_pre, __node_dump_post, info);
81
 }
66
 }
82
 
67
 
83
-int node_walk(node_t *n,
84
-	      int (*pre)(node_t *, void *),
85
-	      int (*post)(node_t *, void *),
86
-	      void *ctx)
68
+
69
+int nwalk(node_t *n,
70
+	  int (*pre)(node_t *, void *),
71
+	  int (*post)(node_t *, void *),
72
+	  void *ctx)
87
 {
73
 {
88
 	int err = 0;
74
 	int err = 0;
89
 	
75
 	
90
 	if (pre && (err = pre(n, ctx)))
76
 	if (pre && (err = pre(n, ctx)))
91
 		return err;
77
 		return err;
92
 
78
 
93
-	if (n->ntype == N_EXPR) {
94
-		node_t *a = n->expr.arg;
79
+	if (n->ntype == N_CONS) {
80
+		err = ncar(n) ? nwalk(ncar(n), pre, post, ctx) : 0;
81
+		if (err)
82
+			return err;
95
 
83
 
96
-		for (a = n->expr.arg; a; a = a->next) {
97
-			err = node_walk(a, pre, post, ctx);
98
-			if (err)
99
-				return err;
100
-		}
84
+		err = ncdr(n) ? nwalk(ncdr(n), pre, post, ctx) : 0;
85
+		if (err)
86
+			return err;
101
 	}
87
 	}
102
 
88
 
103
 	if (post && (err = post(n, ctx)))
89
 	if (post && (err = post(n, ctx)))
106
 	return 0;
92
 	return 0;
107
 }
93
 }
108
 
94
 
95
+
96
+/* high-level constructors */
97
+
98
+node_t *ncall(char *name, node_t *args)
99
+{
100
+	return ncons(nop('('), ncons(nident(name), args));
101
+}
102
+
103
+node_t *nmap(char *name, node_t *key)
104
+{
105
+	return ncons(nop('{'), ncons(nident(name), key));
106
+}
107
+
108
+/* basic constructors */
109
+
109
 static node_t *__node(ntype_t ntype)
110
 static node_t *__node(ntype_t ntype)
110
 {
111
 {
111
 	node_t *n = calloc(1, sizeof(*n));
112
 	node_t *n = calloc(1, sizeof(*n));
115
 	return n;
116
 	return n;
116
 }
117
 }
117
 
118
 
118
-node_t *node_ident(char *name)
119
+node_t *ncons(node_t *car, node_t *cdr)
119
 {
120
 {
120
-	node_t *n = __node(N_ATOM);
121
+	node_t *n = __node(N_CONS);
122
+
123
+	assert(car);
124
+	car->up = n;
121
 
125
 
122
-	n->atom.atype = A_IDENT;
123
-	n->atom.ident = name;
126
+	if (cdr)
127
+		cdr->up = n;
128
+
129
+	n->cons.car = car;
130
+	n->cons.cdr = cdr;
124
 	return n;
131
 	return n;
125
 }
132
 }
126
 
133
 
127
-node_t *node_num(int64_t num)
134
+node_t *nop(op_t op)
128
 {
135
 {
129
-	node_t *n = __node(N_ATOM);
130
-
131
-	n->atom.atype = A_NUM;
132
-	n->atom.num = num;
136
+	node_t *n = __node(N_OP);
137
+	n->op = op;
133
 	return n;
138
 	return n;
134
 }
139
 }
135
 
140
 
136
-node_t *node_string(char *string)
141
+node_t *nident(char *name)
137
 {
142
 {
138
-	node_t *n = __node(N_ATOM);
139
-
140
-	n->atom.atype = A_STRING;
141
-	n->atom.string = string;
143
+	node_t *n = __node(N_IDENT);
144
+	n->ident = name;
142
 	return n;
145
 	return n;
143
 }
146
 }
144
 
147
 
145
-node_t *node_expr(etype_t etype, node_t *arg)
148
+node_t *nnum(int64_t num)
146
 {
149
 {
147
-	node_t *n = __node(N_EXPR);
148
-	node_t *next;
149
-
150
-	n->expr.etype = etype;
151
-	n->expr.arg = arg;
152
-
153
-	for (next = arg; next; next = next->next)
154
-		next->up = n;
155
-
150
+	node_t *n = __node(N_NUM);
151
+	n->num = num;
156
 	return n;
152
 	return n;
157
 }
153
 }
158
 
154
 
159
-node_t *node_cons(node_t *head, node_t *tail)
155
+node_t *nstring(char *string)
160
 {
156
 {
161
-	node_t *next;
162
-
163
-	assert(!head->next);
164
-	head->next = tail;
165
-
166
-	for (next = tail; next; next = next->next)
167
-		next->up = head->up;
168
-
169
-	return head;
157
+	node_t *n = __node(N_STRING);
158
+	n->string = string;
159
+	return n;
170
 }
160
 }

+ 73 - 56
node.h

6
 
6
 
7
 #include "type.h"
7
 #include "type.h"
8
 
8
 
9
-typedef struct atom atom_t;
10
-typedef struct expr expr_t;
11
 typedef struct node node_t;
9
 typedef struct node node_t;
12
 
10
 
13
-typedef enum atype {
14
-	A_INVALID,
15
-	A_IDENT,
16
-	A_NUM,
17
-	A_STRING,
18
-} atype_t;
19
-
20
-struct atom {
21
-	atype_t atype;
22
-
23
-	union {
24
-		char *ident;
25
-		int64_t num;
26
-		char *string;
27
-	};
11
+struct cons {
12
+	node_t *car;
13
+	node_t *cdr;
28
 };
14
 };
29
 
15
 
30
-typedef enum etype {
31
-	E_INVALID = '\0',
32
-
33
-	E_AGG = '@',
34
-	E_CALL = '(',
35
-	E_DEREF = '*',
36
-	E_DOT = '.',
37
-	E_MAP = 'm',
38
-	E_SCOPE = '{',
39
-	
40
-} etype_t;
41
-
42
-struct expr {
43
-	etype_t etype;
44
-	node_t *arg;
45
-};
16
+typedef enum op {
17
+	OP_AGG = '@',
18
+	OP_CALL = '(',
19
+	OP_DEREF = '*',
20
+	OP_DOT = '.',
21
+	OP_MAP = '{',
22
+} op_t;
46
 
23
 
47
 typedef enum ntype {
24
 typedef enum ntype {
48
-	N_INVALID,
49
-	N_ATOM,
50
-	N_EXPR,
25
+	N_CONS,
26
+
27
+	N_OP,
28
+	N_IDENT,
29
+	N_NUM,
30
+	N_STRING,
51
 } ntype_t;
31
 } ntype_t;
52
 
32
 
53
 struct node {
33
 struct node {
54
 	ntype_t ntype;
34
 	ntype_t ntype;
55
-	node_t *up;
56
-	node_t *next;
57
-
58
-	type_t *type;
59
 
35
 
60
 	union {
36
 	union {
61
-		atom_t atom;
62
-		expr_t expr;
37
+		/* atom_t atom; */
38
+		struct cons cons;
39
+
40
+		op_t op;
41
+		char *ident;
42
+		int64_t num;
43
+		char *string;
63
 	};
44
 	};
45
+
46
+	node_t *up;
47
+	type_t *type;
64
 };
48
 };
65
 
49
 
66
-/* walk a node tree */
50
+/* debug */
51
+typedef struct ndump_info {
52
+	FILE *fp;
53
+	int indent;
54
+} ndump_info_t;
55
+
56
+void ndump(node_t *n, ndump_info_t *info);
57
+
67
 
58
 
68
 typedef int (*walk_fn)(node_t *, void *);
59
 typedef int (*walk_fn)(node_t *, void *);
69
-int node_walk(node_t *n, walk_fn pre, walk_fn post, void *ctx);
60
+int nwalk(node_t *n, walk_fn pre, walk_fn post, void *ctx);
70
 
61
 
62
+/* high-level constructors */
63
+node_t *ncall(char *name, node_t *args);
64
+node_t *nmap (char *name, node_t *key);
71
 
65
 
72
-/* node constructors */
73
 
66
 
74
-node_t *node_ident (char *name);
75
-node_t *node_num   (int64_t num);
76
-node_t *node_string(char *string);
77
-node_t *node_expr  (etype_t etype, node_t *arg);
78
-node_t *node_cons  (node_t *head, node_t *tail);
67
+/* basic constructors */
68
+node_t *ncons  (node_t *car, node_t *cdr);
69
+node_t *nop    (op_t op);
70
+node_t *nident (char *name);
71
+node_t *nnum   (int64_t num);
72
+node_t *nstring(char *string);
79
 
73
 
80
 
74
 
81
-/* debug */
75
+/* utilities */
82
 
76
 
83
-typedef struct node_dump_info {
84
-	FILE *fp;
85
-	int indent;
86
-} node_dump_info_t;
77
+static inline int nop_is(node_t *n, op_t op)
78
+{
79
+	if (!n || (n->ntype != N_OP))
80
+		return 0;
81
+
82
+	return n->op == op;
83
+}
84
+
85
+static inline node_t *ncar(node_t *n)
86
+{
87
+	if (!n || (n->ntype != N_CONS))
88
+		return NULL;
89
+
90
+	return n->cons.car;
91
+}
92
+
93
+static inline node_t *ncdr(node_t *n)
94
+{
95
+	if (!n || (n->ntype != N_CONS))
96
+		return NULL;
97
+
98
+	return n->cons.cdr;
99
+}
100
+
101
+static inline node_t *nup(node_t *n)
102
+{
87
 
103
 
88
-void node_dump(node_t *n, node_dump_info_t *info);
104
+	return n? n->up : NULL;
105
+}
89
 
106
 
90
 #endif	/* _PLY_NODE_H */
107
 #endif	/* _PLY_NODE_H */

+ 22 - 27
ply.c

58
 
58
 
59
 	prog->probe = "k:SyS_read"; /* { reads{pid()} @ quantize(arg2) } */
59
 	prog->probe = "k:SyS_read"; /* { reads{pid()} @ quantize(arg2) } */
60
 	prog->ast =
60
 	prog->ast =
61
-		node_expr('@',
62
-			  node_cons(
63
-				  node_expr('m',
64
-					    node_cons(
65
-						    node_ident("reads"),
66
-						    node_expr('(', node_ident("pid"))
67
-						    )
68
-					  ),
69
-				  node_expr('(',
70
-					    node_cons(
71
-						    node_ident("quantize"),
72
-						    node_ident("arg2")
73
-						    )
74
-					  )
75
-				  )
61
+		ncons(nop('@'),
62
+		      ncons(
63
+			      nmap("reads", ncons(ncall("pid", NULL), NULL)),
64
+			      ncall("quantize", ncons(nident("arg2"), NULL))
65
+			      )
76
 			);
66
 			);
77
 
67
 
78
 	prog->provider = provider_get("k");
68
 	prog->provider = provider_get("k");
84
 {
74
 {
85
 	prog_t *prog = _prog;
75
 	prog_t *prog = _prog;
86
 	provider_t *global = provider_get(":");
76
 	provider_t *global = provider_get(":");
77
+	node_t *op;
87
 	int err;
78
 	int err;
88
 
79
 
89
-	if ((n->ntype != N_ATOM) || (n->atom.atype != A_IDENT))
80
+	if (n->ntype != N_IDENT)
90
 		return 0;
81
 		return 0;
91
 
82
 
92
 	/* .IDENT/->IDENT is a struct/union member, skip */
83
 	/* .IDENT/->IDENT is a struct/union member, skip */
93
-	if (n->up
94
-	    && (n->up->ntype == N_EXPR)
95
-	    && ((n->up->expr.etype == E_DOT) || (n->up->expr.etype == E_DEREF))
96
-	    && (n != n->up->expr.arg))
84
+	op = ncar(nup(nup(n)));
85
+	if (op && nop_is(op, '.'))
97
 		return 0;
86
 		return 0;
98
 
87
 
99
 	err = prog->provider->resolve(prog, n);
88
 	err = prog->provider->resolve(prog, n);
100
-	if (!err || err != -ENOENT)
89
+	if (!err || (err != -ENOENT))
101
 		return err;
90
 		return err;
102
 
91
 
103
-	return global->resolve(prog, n);
92
+	err = global->resolve(prog, n);
93
+	if (!err || (err != -ENOENT))
94
+		return err;
95
+
96
+	/* neither provider identifier nor global ditto => user
97
+	 * variable, add it as a global symbol of unknown type. */
98
+	return sym_add(prog->globals, n->ident, NULL);
104
 }
99
 }
105
 
100
 
106
 int pass_walk(pass_t *pass, prog_t *prog)
101
 int pass_walk(pass_t *pass, prog_t *prog)
107
 {
102
 {
108
-	return node_walk(prog->ast, pass->pre, pass->post, prog);
103
+	return nwalk(prog->ast, pass->pre, pass->post, prog);
109
 }
104
 }
110
 
105
 
111
 pass_t passes[] = {
106
 pass_t passes[] = {
116
 
111
 
117
 int main(void)
112
 int main(void)
118
 {
113
 {
119
-	node_dump_info_t info = {
114
+	ndump_info_t info = {
120
 		.indent = 2,
115
 		.indent = 2,
121
 		.fp = stdout,
116
 		.fp = stdout,
122
 	};
117
 	};
132
 	}
127
 	}
133
 
128
 
134
 	printf("AST\n===\n");
129
 	printf("AST\n===\n");
135
-	node_dump(prog->ast, &info);
130
+	ndump(prog->ast, &info);
136
 	printf("\nLOCALS\n======\n");
131
 	printf("\nLOCALS\n======\n");
137
 	symtab_dump(prog->locals, stdout);
132
 	symtab_dump(prog->locals, stdout);
138
 	printf("\nGLOBALS\n=======\n");
133
 	printf("\nGLOBALS\n=======\n");
139
 	symtab_dump(prog->globals, stdout);
134
 	symtab_dump(prog->globals, stdout);
140
-	printf("\nTYPES\n=====\n");
141
-	types_dump_cdecl(stdout);
135
+	/* printf("\nTYPES\n=====\n"); */
136
+	/* types_dump_cdecl(stdout); */
142
 	return err;
137
 	return err;
143
 }
138
 }

+ 24 - 2
type.c

65
 	field_t *arg;
65
 	field_t *arg;
66
 
66
 
67
 	type_dump(t->t.func.type, fp);
67
 	type_dump(t->t.func.type, fp);
68
-	fprintf(fp, " (*%s)(", t->t.func.name);
68
+	fprintf(fp, " (*%s)(", t->t.func.name ? : "");
69
+
70
+	if (!t->t.func.args) {
71
+		fputs("void)", fp);
72
+		return;
73
+	}
69
 
74
 
70
 	for (arg = t->t.func.args; arg->type; arg++) {
75
 	for (arg = t->t.func.args; arg->type; arg++) {
71
 		if (arg != t->t.func.args)
76
 		if (arg != t->t.func.args)
79
 
84
 
80
 void type_dump(type_t *t, FILE *fp)
85
 void type_dump(type_t *t, FILE *fp)
81
 {
86
 {
87
+	if (!t) {
88
+		fputs("<NONE>", fp);
89
+		return;
90
+	}
91
+
82
 	switch (t->ttype){
92
 	switch (t->ttype){
83
 	case T_TYPEDEF:
93
 	case T_TYPEDEF:
84
 		fputs(t->t.tdef.name, fp);
94
 		fputs(t->t.tdef.name, fp);
228
 	}
238
 	}
229
 }
239
 }
230
 
240
 
241
+int type_cmp(const void *_a, const void *_b)
242
+{
243
+	const type_t *a = *((type_t **)_a);
244
+	const type_t *b = *((type_t **)_b);
245
+
246
+	return a - b;
247
+}
231
 
248
 
232
 int type_add(type_t *t)
249
 int type_add(type_t *t)
233
 {
250
 {
251
+	if (bsearch(t, types.type, types.len, sizeof(*types.type), type_cmp))
252
+		return 0;
253
+
254
+	type_size_set(t);
255
+
234
 	types.type = realloc(types.type, ++types.len * sizeof(*types.type));
256
 	types.type = realloc(types.type, ++types.len * sizeof(*types.type));
235
 	types.type[types.len - 1] = t;
257
 	types.type[types.len - 1] = t;
258
+	qsort(types.type, types.len, sizeof(*types.type), type_cmp);
236
 
259
 
237
-	type_size_set(t);
238
 	return 0;
260
 	return 0;
239
 }
261
 }
240
 
262