Tobias Waldekranz.com 8 gadi atpakaļ
vecāks
revīzija
ad5d87a1da
11 mainītis faili ar 302 papildinājumiem un 33 dzēšanām
  1. 1 0
      Makefile
  2. 1 1
      arch-x86_64.c
  3. 58 0
      func.c
  4. 51 7
      global.c
  5. 2 2
      ply.c
  6. 126 0
      printxf.c
  7. 25 0
      printxf.h
  8. 7 0
      printxf_test.c
  9. 24 16
      type.c
  10. 5 5
      type.h
  11. 2 2
      type_test.c

+ 1 - 0
Makefile

@@ -14,6 +14,7 @@ ply: $(objs)
14 14
 
15 15
 arch-x86_64_test: arch-x86_64_test.o arch-x86_64.o type.o
16 16
 type_test: type_test.o type.o
17
+printxf_test: printxf_test.o printxf.o
17 18
 
18 19
 check: $(cprogs)
19 20
 	$(foreach prog,$(cprogs),./$(prog);)

+ 1 - 1
arch-x86_64.c

@@ -39,7 +39,7 @@ struct tfield f_pt_regs_fields[] = {
39 39
 	{ .name = "rsp",      .type = &t_ulong },
40 40
 	{ .name = "ss",       .type = &t_ulong },
41 41
 
42
-	{ .type = &t_void }
42
+	{ .type = NULL }
43 43
 };
44 44
 
45 45
 struct type t_pt_regs = {

+ 58 - 0
func.c

@@ -0,0 +1,58 @@
1
+#include <errno.h>
2
+
3
+#include "func.h"
4
+#include "node.h"
5
+#include "sym.h"
6
+#include "type.h"
7
+
8
+int func_validate_expr(const struct func *func, struct node *n, int strict)
9
+{
10
+	struct tfield *f;
11
+	struct node *arg;
12
+	int nargs = 0;
13
+
14
+	for (f = func->type->func.args, arg = n->expr.args;
15
+	     f && arg; f++, arg = arg->next, nargs++) {
16
+		if ((!strict && (arg->sym->type->ttype == T_VOID))
17
+		    || (f->type->ttype == T_VOID)
18
+		    || type_compatible(arg->sym->type, f->type) )
19
+			continue;
20
+
21
+		node_error(n, stderr, "type mismatch for argument %d, expected %T, got %T",
22
+			   nargs, f->type, arg->sym->type);
23
+	}
24
+
25
+	return 0;
26
+}
27
+
28
+int func_static_validate(const struct func *func, struct node *n)
29
+{
30
+	if ((n->ntype == N_NUM) || (n->ntype == N_STRING)) {
31
+	}
32
+
33
+	switch (n->ntype) {
34
+	case N_EXPR:
35
+		if (func->type->ttype != T_FUNC) {
36
+			node_error(n, stderr, "'%s' is not callable",
37
+				   n->expr.func);
38
+			return -EINVAL;
39
+		}
40
+		return func_validate_expr(func, n, 0);
41
+
42
+	case N_IDENT:
43
+		if (func->type->ttype == T_FUNC) {
44
+			node_error(n, stderr, "'%s' is a function",
45
+				   n->ident.name);
46
+			return -EINVAL;
47
+		}
48
+		/* fall-through */
49
+	case N_NUM:
50
+	case N_STRING:
51
+		/* ident, num, str. nothing to validate. just copy
52
+		 * type info to the symbol if statically known */
53
+		n->sym->type = func->type;
54
+		break;
55
+	}
56
+
57
+	return 0;
58
+}

+ 51 - 7
global.c

@@ -12,6 +12,8 @@
12 12
 #include "type.h"
13 13
 
14 14
 
15
+/* :map */
16
+
15 17
 static struct type *global_map_ktype(struct node *n)
16 18
 {
17 19
 	struct node *map, *key;
@@ -22,7 +24,7 @@ static struct type *global_map_ktype(struct node *n)
22 24
 
23 25
 	map = n->expr.args;
24 26
 
25
-	if (node_nargs(n) == 2)
27
+	if (nargs == 2)
26 28
 		return map->next->sym->type;
27 29
 
28 30
 	ktype = calloc(1, sizeof(*ktype));
@@ -36,8 +38,6 @@ static struct type *global_map_ktype(struct node *n)
36 38
 		f->type = key->sym->type;
37 39
 	}
38 40
 
39
-	f->type = &t_void;
40
-
41 41
 	asprintf(&ktype->sou.name, ":%s_key", map->ident.name);
42 42
 	ktype->ttype = T_STRUCT;
43 43
 	ktype->sou.fields = kfields;
@@ -46,6 +46,40 @@ static struct type *global_map_ktype(struct node *n)
46 46
 	return ktype;
47 47
 }
48 48
 
49
+static int global_map_type_infer(struct prog *prog, struct node *n)
50
+{
51
+	struct node *map = n->expr.args;
52
+
53
+	if (n->sym->type || !map->sym->type)
54
+		return 0;
55
+
56
+	assert(map->sym->type->ttype == T_MAP);
57
+
58
+	/* given `m[key]` where m's type is known, infer that the
59
+	 * expression's type is equal to m's value type. */
60
+	n->sym->type = map->sym->type->map.vtype;
61
+	return 0;
62
+}
63
+
64
+static int global_map_static_verify(struct node *n)
65
+{
66
+	int nargs = node_nargs(n);
67
+
68
+	if (nargs < 2) {
69
+		node_error(n, stderr, "map without key");
70
+		return -EINVAL;
71
+	}
72
+
73
+	if (n->expr.args->ntype != N_IDENT) {
74
+		node_error(n, stderr, "map must be identifier");
75
+		return -EINVAL;
76
+	}
77
+
78
+	return 0;
79
+}
80
+
81
+/* :assign */
82
+
49 83
 static int global_assign_type_infer_map(struct node *n)
50 84
 {
51 85
 	struct node *map, *key;
@@ -73,6 +107,8 @@ static int global_assign_type_infer(struct prog *prog, struct node *n)
73 107
 		return 0;
74 108
 
75 109
 	if (!lval->sym->type) {
110
+		/* given `a = b` where b's type is known but not a's,
111
+		 * infer that a's type must be equal to b's */
76 112
 		lval->sym->type = rval->sym->type;
77 113
 
78 114
 		if (node_is_map(lval))
@@ -115,18 +151,26 @@ static int global_assign_static_verify(struct node *n)
115 151
 	return -EINVAL;
116 152
 }
117 153
 
154
+
155
+/* pid */
156
+
118 157
 struct type t_pid = {
119 158
 	.ttype = T_TYPEDEF,
120 159
 
121 160
 	.tdef = { .name = ":pid", .type = &t_u32 },
122 161
 };
123 162
 
163
+
164
+/* time */
165
+
124 166
 struct type t_time = {
125
-	.ttype = T_TYPEDEF,
167
+	.ttype = T_TYPEDEF,	/* TODO: should be a T_FUNC with a static
168
+				 * signature */
126 169
 
127 170
 	.tdef = { .name = ":time", .type = &t_s64 },
128 171
 };
129 172
 
173
+
130 174
 static const struct func global_funcs[] = {
131 175
 	{ .name = ":block", .type = &t_void, },
132 176
 
@@ -135,13 +179,13 @@ static const struct func global_funcs[] = {
135 179
 	
136 180
 	{
137 181
 		.name = ":assign",
138
-		.static_verify = global_assign_static_verify,
139 182
 		.type_infer = global_assign_type_infer,
183
+		.static_verify = global_assign_static_verify,
140 184
 	},
141 185
 	{
142 186
 		.name = ":map",
143
-		/* .static_verify = global_map_static_verify, */
144
-		/* .type_infer = global_map_type_infer, */
187
+		.type_infer = global_map_type_infer,
188
+		.static_verify = global_map_static_verify,
145 189
 	},
146 190
 
147 191
 	{ .name = "pid",  .type = &t_pid, },

+ 2 - 2
ply.c

@@ -529,8 +529,8 @@ int main(void)
529 529
 	printf("\n\n-- globals\n");
530 530
 	symtab_dump(ctx->globals, stdout);
531 531
 
532
-	printf("\n\n-- decls\n");
533
-	type_dump_decls(stdout);
532
+	/* printf("\n\n-- decls\n"); */
533
+	/* type_dump_decls(stdout); */
534 534
 
535 535
 	if (err)
536 536
 		printf("ERR: %d\n", err);

+ 126 - 0
printxf.c

@@ -0,0 +1,126 @@
1
+#include <stdarg.h>
2
+#include <stdint.h>
3
+#include <stdio.h>
4
+#include <stdlib.h>
5
+#include <string.h>
6
+
7
+#include "printxf.h"
8
+
9
+struct printxf printxf_default;
10
+
11
+/* allow domains an easy way to defer standard specifiers to the
12
+ * system's implementation. */
13
+int printxf_vfprintf(struct printxf *pxf,
14
+		     FILE *fp, const char *spec, va_list ap)
15
+{
16
+	return vfprintf(fp, spec, ap);
17
+}
18
+
19
+int __printxf_wsegment(FILE *fp, const char **fmt, size_t ssize, size_t *tsize)
20
+{
21
+	size_t wsize;
22
+
23
+	wsize = fwrite(*fmt, 1, ssize, fp);
24
+	*tsize += wsize;
25
+	*fmt   += wsize;
26
+
27
+	return (wsize < ssize) ? EOF : 0;
28
+}
29
+
30
+int vfprintxf(struct printxf *pxf, FILE *fp, const char *fmt, va_list ap)
31
+{
32
+	size_t tsize = 0, wsize, ssize;
33
+	vfprintxf_fn handler;
34
+	char spec[16];
35
+
36
+	pxf = pxf ? : &printxf_default;
37
+
38
+	if (!fmt)
39
+		return 0;
40
+
41
+	while (*fmt) {
42
+		ssize = strcspn(fmt, "%");
43
+
44
+		/* leading segment containing no format specifiers. */
45
+		if (ssize && __printxf_wsegment(fp, &fmt, ssize, &tsize))
46
+			break;
47
+
48
+		if (fmt[0] == '\0') {
49
+			/* this was the last segment */
50
+			break;
51
+		} else if ((fmt[0] == '%')
52
+			   && ((fmt[1] == '\0') || (fmt[1] == '%'))) {
53
+			/* "%" or "%%", write "%" */
54
+			if (!fwrite("%", 1, 1, fp))
55
+				break;
56
+
57
+			tsize++;
58
+			fmt += fmt[1] ? 2 : 1;
59
+			continue;
60
+		}
61
+		
62
+		ssize = strspn(fmt + 1, " #$'*+,-.0123456789:;L_hjlqtvz") + 1;
63
+
64
+		if (!fmt[ssize]) {
65
+			/* corner case. fmt ends with an unterminated
66
+			 * format. e.g. "evilness: 100%" */
67
+			__printxf_wsegment(fp, &fmt, ssize, &tsize);
68
+			break;
69
+		}
70
+
71
+		handler = pxf->vfprintxf[fmt[ssize] & 0x7f];
72
+		if (!handler) {
73
+			/* unsupported specifier, write the entire
74
+			 * specifier unformatted to the output */
75
+			if (__printxf_wsegment(fp, &fmt, ssize + 1, &tsize))
76
+				break;
77
+
78
+			continue;
79
+		}
80
+
81
+		ssize++;
82
+		memset(spec, '\0', sizeof(spec));
83
+		strncpy(spec, fmt, (ssize >= sizeof(spec)) ? sizeof(spec) - 1 : ssize);
84
+		fmt += ssize;
85
+
86
+		tsize += handler(pxf, fp, spec, ap);
87
+	}
88
+
89
+	return tsize;
90
+}
91
+
92
+int fprintxf(struct printxf *pxf, FILE *fp, const char *fmt, ...)
93
+{
94
+	va_list ap;
95
+	int ret;
96
+
97
+	va_start(ap, fmt);
98
+	ret = vfprintxf(pxf, fp, fmt, ap);
99
+	va_end(ap);
100
+	return ret;
101
+}
102
+
103
+int vprintxf(struct printxf *pxf, const char *fmt, va_list ap)
104
+{
105
+	return vfprintxf(pxf, stdout, fmt, ap);
106
+}
107
+
108
+int printxf(struct printxf *pxf, const char *fmt, ...)
109
+{
110
+	va_list ap;
111
+	int ret;
112
+
113
+	va_start(ap, fmt);
114
+	ret = vprintxf(pxf, fmt, ap);
115
+	va_end(ap);
116
+	return ret;
117
+}
118
+
119
+__attribute__((constructor))
120
+static void printxf_init(void)
121
+{
122
+	const char *std = "aAcdeEfFgGiosuxX";
123
+
124
+	for (; *std; std++)
125
+		printxf_default.vfprintxf[(int)*std] = &printxf_vfprintf;
126
+}

+ 25 - 0
printxf.h

@@ -0,0 +1,25 @@
1
+#ifndef _PRINTXF_H
2
+#define _PRINTXF_H
3
+
4
+#include <stdio.h>
5
+
6
+struct printxf;
7
+
8
+typedef int (*vfprintxf_fn)(struct printxf *pxf,
9
+			    FILE *fp, const char *spec, va_list ap);
10
+
11
+extern int printxf_vfprintf(struct printxf *pxf,
12
+			    FILE *fp, const char *spec, va_list ap);
13
+
14
+struct printxf {
15
+	vfprintxf_fn vfprintxf[0x80];
16
+};
17
+
18
+extern struct printxf printxf_default;
19
+
20
+int vfprintxf(struct printxf *pxf, FILE *stream, const char *fmt, va_list ap);
21
+int  fprintxf(struct printxf *pxf, FILE *stream, const char *fmt, ...);
22
+int  vprintxf(struct printxf *pxf,               const char *fmt, va_list ap);
23
+int   printxf(struct printxf *pxf,               const char *fmt, ...);
24
+
25
+#endif	/* _PRINTXF_H */

+ 7 - 0
printxf_test.c

@@ -0,0 +1,7 @@
1
+#include "printxf.h"
2
+
3
+
4
+int main(void)
5
+{
6
+	printxf(NULL, "testing %% %.*s %d\n", 3, "w000t", 13);
7
+}

+ 24 - 16
type.c

@@ -1,9 +1,11 @@
1 1
 #include <assert.h>
2 2
 #include <errno.h>
3
+#include <stdarg.h>
3 4
 #include <stdio.h>
4 5
 #include <stdlib.h>
5 6
 #include <string.h>
6 7
 
8
+#include "printxf.h"
7 9
 #include "type.h"
8 10
 
9 11
 static void __sgr(FILE *fp, int sgr, const char *s)
@@ -37,7 +39,7 @@ static void type_dump_func(struct type *t, const char *name, FILE *fp)
37 39
 		return;
38 40
 	}
39 41
 
40
-	for (arg = t->func.args; arg->type != T_VOID; arg++) {
42
+	tfields_foreach(arg, t->func.args) {
41 43
 		if (arg != t->func.args)
42 44
 			fputs(", ", fp);
43 45
 
@@ -49,46 +51,39 @@ static void type_dump_func(struct type *t, const char *name, FILE *fp)
49 51
 
50 52
 void type_dump(struct type *t, const char *name, FILE *fp)
51 53
 {
52
-	if (!t)
53
-		goto print_void;
54
-
54
+	if (!t) {
55
+		__faint(fp, "(none)");
56
+		goto print_name;
57
+	}
55 58
 
56 59
 	switch (t->ttype){
57 60
 	case T_VOID:
58
-	print_void:
59 61
 		__faint(fp, "void");
60
-		fputs(name ? " " : "", fp);
61
-		__bold(fp, name);
62 62
 		break;
63 63
 	case T_TYPEDEF:
64 64
 		__faint(fp, t->tdef.name);
65
-		fputs(name ? " " : "", fp);
66
-		__bold(fp, name);
67 65
 		break;
68 66
 	case T_SCALAR:
69 67
 		__faint(fp, t->scalar.name);
70
-		fputs(name ? " " : "", fp);
71
-		__bold(fp, name);
72 68
 		break;
73 69
 	case T_POINTER:
74 70
 		type_dump(t->ptr.type, NULL, fp);
75 71
 		fputs(" *", fp);
76 72
 		__bold(fp, name);
77
-		break;
73
+		return;
78 74
 	case T_ARRAY:
79 75
 		type_dump(t->array.type, NULL, fp);
80 76
 		fputs(name ? " " : "", fp);
81 77
 		__bold(fp, name);
82 78
 		fprintf(fp, "[%zu]", t->array.len);
83
-		break;
79
+		return;
84 80
 	case T_STRUCT:
85 81
 		fputs("struct ", fp);
86 82
 		__faint(fp, t->sou.name);
87
-		__bold(fp, name);
88 83
 		break;
89 84
 	case T_FUNC:
90 85
 		type_dump_func(t, name, fp);
91
-		break;
86
+		return;
92 87
 	case T_MAP:
93 88
 		type_dump(t->map.vtype, NULL, fp);
94 89
 		fputs(name ? " " : "", fp);		
@@ -96,8 +91,11 @@ void type_dump(struct type *t, const char *name, FILE *fp)
96 91
 		fputc('{', fp);
97 92
 		type_dump(t->map.ktype, NULL, fp);
98 93
 		fputc('}', fp);
99
-		break;
94
+		return;
100 95
 	}
96
+print_name:
97
+	fputs(name ? " " : "", fp);
98
+	__bold(fp, name);
101 99
 }
102 100
 
103 101
 static void type_dump_decl_sou(struct type *t, FILE *fp)
@@ -138,6 +136,14 @@ void type_dump_decl(struct type *t, FILE *fp)
138 136
 	}
139 137
 }
140 138
 
139
+int type_vfprintxf(struct printxf *pxf, FILE *fp, const char *spec, va_list ap)
140
+{
141
+	struct type *t;
142
+
143
+	t = va_arg(ap, struct type *);
144
+	type_dump(t, NULL, fp);
145
+	return 0;
146
+}
141 147
 
142 148
 struct type *type_normalize(struct type *t)
143 149
 {
@@ -492,4 +498,6 @@ __attribute__((constructor))
492 498
 static void type_init(void)
493 499
 {
494 500
 	type_add_list(builtin_types);
501
+
502
+	printxf_default.vfprintxf['T'] = type_vfprintxf;
495 503
 }

+ 5 - 5
type.h

@@ -33,24 +33,24 @@ struct tmap {
33 33
 struct tfield {
34 34
 	char *name;
35 35
 	struct type *type;
36
-
37
-	/* function arguments */
38
-	int optional:1;
39 36
 };
40 37
 
41 38
 #define tfields_foreach(_f, _fields) \
42
-	for ((_f) = (_fields); (_f)->type->ttype != T_VOID; (_f)++)
39
+	for ((_f) = (_fields); (_f)->type; (_f)++)
43 40
 
44 41
 struct tstruct {
45 42
 	char *name;
43
+	struct tfield *fields;
46 44
 
47 45
 	int packed:1;
48
-	struct tfield *fields;
49 46
 };
50 47
 
51 48
 struct tfunc {
52 49
 	struct type *type;
53 50
 	struct tfield *args;
51
+
52
+	int vargs:1;
53
+	int aggregation:1;
54 54
 };
55 55
 
56 56
 enum ttype {

+ 2 - 2
type_test.c

@@ -62,7 +62,7 @@ static int struct_basic(void *_null)
62 62
 		{ .name = "c", .type = type_array_of(&t_char, 3) },
63 63
 		{ .name = "d", .type = &t_short },
64 64
 
65
-		{ .type = &t_void }
65
+		{ .type = NULL }
66 66
 	};
67 67
 	struct type t_t1 = {
68 68
 		.ttype = T_STRUCT,
@@ -95,7 +95,7 @@ static int struct_packed(void *_null)
95 95
 		{ .name = "c", .type = type_array_of(&t_char, 3) },
96 96
 		{ .name = "d", .type = &t_short },
97 97
 
98
-		{ .type = &t_void }
98
+		{ .type = NULL }
99 99
 	};
100 100
 	struct type t_t1 = {
101 101
 		.ttype = T_STRUCT,