summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--c/examples/dynamic_typing/dietpass.c63
-rw-r--r--c/examples/refcounting/dietpass.c55
-rw-r--r--c/examples/zero_init/dietpass.c9
-rw-r--r--c/libdietc.h2
-rw-r--r--c/libdietc.l20
-rw-r--r--c/string_helpers.c48
6 files changed, 111 insertions, 86 deletions
diff --git a/c/examples/dynamic_typing/dietpass.c b/c/examples/dynamic_typing/dietpass.c
index 62c0f9e..6c32f00 100644
--- a/c/examples/dynamic_typing/dietpass.c
+++ b/c/examples/dynamic_typing/dietpass.c
@@ -3,10 +3,10 @@
#include <stdlib.h>
#include <string.h>
#include <libdietc.h>
+#include <string_helpers.c>
-static void insert_line(struct instruction **insertion_point, char *line);
-static int is_void_pointer(struct type *type);
-static char *describe_type(struct instruction **insertion_point, struct type *type);
+static int is_void_pointer(struct type *);
+static char *describe_type(struct instruction *, struct type *);
int main(int argc, char **argv) {
assert(argc == 2);
@@ -23,12 +23,9 @@ int main(int argc, char **argv) {
char *rhs = libdietc_tokdup(libdietc_nth_token(i->line, 5));
struct type *rhs_type = libdietc_object_type(program, rhs);
- struct instruction *insertion_point = i;
- char *descriptor = describe_type(&insertion_point, rhs_type);
- char *line = malloc(strlen(descriptor) + strlen(rhs) + 512);
- sprintf(line, "\tannotate_type((void*)%s, %s);", rhs, descriptor);
- insert_line(&insertion_point, line);
- i = insertion_point;
+ char *descriptor = describe_type(i, rhs_type);
+ char *line = sbuild("\tannotate_type((void*)%s, %s);", rhs, descriptor);
+ libdietc_insert_before(i, line);
}
}
libdietc_print(program);
@@ -42,32 +39,31 @@ static int is_void_pointer(struct type *type) {
return 1;
}
-static char *describe_type(struct instruction **insertion_point, struct type *type) {
+static char *describe_type(struct instruction *before, struct type *type) {
assert(type);
static unsigned long count = 0;
- char *name = calloc(512, sizeof(char));
- sprintf(name, "dtype_%d", count++);
+ char *name = sbuild("dtype_%d", count++);
- char *line = calloc(strlen(name) + 1024, sizeof(char));
+ char *line = 0;
char *base_ty = NULL;
switch (type->kind) {
case TYPE_BASIC:
- sprintf(line, "\tvoid *%s = make_basic(\"%s\", sizeof(%s));",
- name, type->basic, type->basic);
+ line = sbuild("\tvoid *%s = make_basic(\"%s\", sizeof(%s));",
+ name, type->basic, type->basic);
break;
case TYPE_ARRAY:
- base_ty = describe_type(insertion_point, type->base);
- sprintf(line, "\tvoid *%s = make_array(%s, %ld);",
- name, base_ty, type->length);
+ base_ty = describe_type(before, type->base);
+ line = sbuild("\tvoid *%s = make_array(%s, %ld);",
+ name, base_ty, type->length);
break;
case TYPE_POINTER:
- base_ty = describe_type(insertion_point, type->base);
- sprintf(line, "\tvoid *%s = make_pointer(%s);", name, base_ty);
+ base_ty = describe_type(before, type->base);
+ line = sbuild("\tvoid *%s = make_pointer(%s);", name, base_ty);
break;
case TYPE_STRUCT:
case TYPE_UNION: {
- sprintf(line, "\tvoid *%s = make_struct(sizeof(Type_%ld));", name, type->id);
- insert_line(insertion_point, line);
+ line = sbuild("\tvoid *%s = make_struct(sizeof(Type_%ld));", name, type->id);
+ libdietc_insert_before(before, line);
unsigned long n = 0;
for (struct type *m = type->members; m; m = m->next_member) n++;
struct type **fields = calloc(n, sizeof(*fields));
@@ -75,13 +71,12 @@ static char *describe_type(struct instruction **insertion_point, struct type *ty
for (struct type *m = type->members; m; m = m->next_member) fields[--i] = m;
for (i = 0; i < n; i++) {
- char *prepend_buffer = calloc(2048, sizeof(char));
- char *fd = describe_type(insertion_point, fields[i]);
- sprintf(prepend_buffer,
- "\tprepend_member(%s, %s, \"%s\", __builtin_offsetof(Type_%ld, %s));",
- name, fd, fields[i]->field_name, type->id,
- fields[i]->field_name);
- insert_line(insertion_point, prepend_buffer);
+ char *fd = describe_type(before, fields[i]);
+ char *prepend_buffer = sbuild(
+ "\tprepend_member(%s, %s, \"%s\", __builtin_offsetof(Type_%ld, %s));",
+ name, fd, fields[i]->field_name, type->id,
+ fields[i]->field_name);
+ libdietc_insert_before(before, prepend_buffer);
}
return name;
}
@@ -89,14 +84,6 @@ static char *describe_type(struct instruction **insertion_point, struct type *ty
assert(0); // not supported yet
break;
}
- insert_line(insertion_point, line);
+ libdietc_insert_before(before, line);
return name;
}
-
-static void insert_line(struct instruction **insertion_point, char *line) {
- struct instruction *new = calloc(1, sizeof(*new));
- new->line = line;
- new->next = (*insertion_point)->next;
- (*insertion_point)->next = new;
- *insertion_point = new;
-}
diff --git a/c/examples/refcounting/dietpass.c b/c/examples/refcounting/dietpass.c
index 33e2531..395eac2 100644
--- a/c/examples/refcounting/dietpass.c
+++ b/c/examples/refcounting/dietpass.c
@@ -3,10 +3,9 @@
#include <stdlib.h>
#include <string.h>
#include <libdietc.h>
+#include <string_helpers.c>
static int startswith(char *s, char *p);
-static struct instruction *instruction_before(struct instruction *i, char *line);
-static struct instruction *instruction_after(struct instruction *i, char *line);
static char **pointer_expressions(char *name, struct type *type);
static void rewrite(struct instruction *i, char *old, char *new);
@@ -41,22 +40,19 @@ int main(int argc, char **argv) {
sscanf(type_name, "Type_%ld", &type_id);
char **ptr_exprs = pointer_expressions(name, program.id2type[type_id]);
for (char **expr = ptr_exprs; *expr; expr++) {
- char *line = calloc(strlen(*expr) + 128, sizeof(char));
- sprintf(line, "\t%s = 0;", *expr);
- i = instruction_after(i, line);
+ char *line = sbuild("\t%s = 0;", *expr);
+ i = libdietc_insert_after(i, line);
}
// is this the return expression?
if (!strcmp(name, return_expr)) { // yes
for (char **expr = ptr_exprs; *expr; expr++) {
- char *line = calloc(strlen(*expr) + 128, sizeof(char));
- sprintf(line, "\trefcount_returning(%s);", *expr);
- instruction_before(return_instruction, line);
+ char *line = sbuild("\trefcount_returning(%s);", *expr);
+ libdietc_insert_before(return_instruction, line);
}
} else { // no
for (char **expr = ptr_exprs; *expr; expr++) {
- char *line = calloc(strlen(*expr) + 128, sizeof(char));
- sprintf(line, "\trefcount_write(0, %s);", *expr);
- instruction_after(before_return, line);
+ char *line = sbuild("\trefcount_write(0, %s);", *expr);
+ libdietc_insert_after(before_return, line);
}
}
} else if (strstr(i->line, " = ")) {
@@ -83,17 +79,14 @@ int main(int argc, char **argv) {
// *before* the instruction, need to insert backups
unsigned long backup_count = count;
for (char **e = ptr_exprs; *e; e++) {
- char *line = calloc(strlen(*e) + 128, sizeof(char));
- assert(strlen(*e));
- sprintf(line, "\tvoid *backup_%lu = (%s);", count++, *e);
- instruction_before(i, line);
+ char *line = sbuild("\tvoid *backup_%lu = (%s);", count++, *e);
+ libdietc_insert_before(i, line);
}
// *then* execute the instruction
// *then* call refcount_write
for (char **e = ptr_exprs; *e; e++) {
- char *line = calloc(strlen(*e) + 128, sizeof(char));
- sprintf(line, "\trefcount_write(%s, backup_%lu);", *e, backup_count++);
- i = instruction_after(i, line);
+ char *line = sbuild("\trefcount_write(%s, backup_%lu);", *e, backup_count++);
+ i = libdietc_insert_after(i, line);
}
}
}
@@ -107,26 +100,6 @@ static int startswith(char *s, char *p) {
return !strncmp(s, p, strlen(p));
}
-static struct instruction *instruction_before(struct instruction *i, char *line) {
- struct instruction *new = calloc(1, sizeof(*new));
- *(i->pprev) = new;
- new->pprev = i->pprev;
- new->line = line;
- new->next = i;
- i->pprev = &(new->next);
- return new;
-}
-
-static struct instruction *instruction_after(struct instruction *i, char *line) {
- struct instruction *new = calloc(1, sizeof(*new));
- new->line = line;
- new->next = i->next;
- i->next->pprev = &(new->next);
- new->pprev = &(i->next);
- i->next = new;
- return new;
-}
-
static char **empty_list() {
return calloc(1, sizeof(char *));
}
@@ -151,8 +124,7 @@ static char **pointer_expressions(char *name, struct type *type) {
case TYPE_ARRAY: {
char **list = empty_list();
for (unsigned long i = 0; i < type->length; i++) {
- char *line = calloc(strlen(name) + 128, sizeof(char));
- sprintf(line, "((%s)[%ld])", name, i);
+ char *line = sbuild("((%s)[%ld])", name, i);
list = append_list(list, line);
}
return list;
@@ -161,8 +133,7 @@ static char **pointer_expressions(char *name, struct type *type) {
case TYPE_UNION: {
char **list = empty_list();
for (struct type *m = type->members; m; m = m->next_member) {
- char *subname = calloc(strlen(name) + strlen(m->field_name) + 4, sizeof(char));
- sprintf(subname, "%s.%s", name, m->field_name);
+ char *subname = sbuild("%s.%s", name, m->field_name);
char **sublist = pointer_expressions(subname, m);
for (char **subline = sublist; *subline; subline++)
list = append_list(list, *subline);
diff --git a/c/examples/zero_init/dietpass.c b/c/examples/zero_init/dietpass.c
index e145a91..962337c 100644
--- a/c/examples/zero_init/dietpass.c
+++ b/c/examples/zero_init/dietpass.c
@@ -3,6 +3,7 @@
#include <stdlib.h>
#include <string.h>
#include <libdietc.h>
+#include <string_helpers.c>
int main(int argc, char **argv) {
assert(argc == 2);
@@ -12,12 +13,8 @@ int main(int argc, char **argv) {
for (struct instruction *i = f->instructions; i; i = i->next) {
if (strncmp(i->line, "\tType_", strlen("\tType_"))) continue;
char *name = libdietc_tokdup(strchrnul(i->line, ' ') + 1);
- struct instruction *n = calloc(1, sizeof(*n));
- n->line = malloc(strlen(name) + 512);
- sprintf(n->line, "memset(&%s, 0, sizeof(%s));", name, name);
- n->next = i->next;
- i->next = n;
- i = n;
+ char *line = sbuild("memset(&%s, 0, sizeof(%s));", name, name);
+ i = libdietc_insert_after(i, line);
}
}
libdietc_print(program);
diff --git a/c/libdietc.h b/c/libdietc.h
index 4dea137..081bf2b 100644
--- a/c/libdietc.h
+++ b/c/libdietc.h
@@ -94,3 +94,5 @@ void libdietc_print(struct program program);
char *libdietc_nth_token(char *string, int n);
struct type *libdietc_object_type(struct program program, char *name);
struct type *libdietc_lhs_type(struct program program, struct instruction *instruction);
+struct instruction *libdietc_insert_before(struct instruction *i, char *line);
+struct instruction *libdietc_insert_after(struct instruction *i, char *line);
diff --git a/c/libdietc.l b/c/libdietc.l
index 51c8e91..abdb914 100644
--- a/c/libdietc.l
+++ b/c/libdietc.l
@@ -280,3 +280,23 @@ struct type *libdietc_lhs_type(struct program program, struct instruction *instr
name = libdietc_tokdup(libdietc_nth_token(instruction->line, 0));
return libdietc_object_type(program, name);
}
+
+struct instruction *libdietc_insert_before(struct instruction *i, char *line) {
+ struct instruction *new = calloc(1, sizeof(*new));
+ *(i->pprev) = new;
+ new->pprev = i->pprev;
+ new->line = line;
+ new->next = i;
+ i->pprev = &(new->next);
+ return new;
+}
+
+struct instruction *libdietc_insert_after(struct instruction *i, char *line) {
+ struct instruction *new = calloc(1, sizeof(*new));
+ new->line = line;
+ new->next = i->next;
+ i->next->pprev = &(new->next);
+ new->pprev = &(i->next);
+ i->next = new;
+ return new;
+}
diff --git a/c/string_helpers.c b/c/string_helpers.c
new file mode 100644
index 0000000..636bad3
--- /dev/null
+++ b/c/string_helpers.c
@@ -0,0 +1,48 @@
+#include <stdio.h>
+#include <stdarg.h>
+
+static char *sbuild(char *format, ...) {
+ // (1) overapproximate the length of the string. adapted from man va_start
+ unsigned long max_len = 1;
+ char *s;
+ va_list ap;
+ va_start(ap, format);
+ for (char *c = format; *c; c++) {
+ if (*c != '%') {
+ max_len++;
+ continue;
+ }
+
+ switch (*(++c)) {
+ case 's':
+ s = va_arg(ap, char*);
+ max_len += strlen(s);
+ break;
+ case 'l': // not quite accurate
+ va_arg(ap, unsigned long);
+ max_len += 64;
+ break;
+ case 'd':
+ va_arg(ap, int);
+ max_len += 32;
+ break;
+ case 'u':
+ va_arg(ap, unsigned);
+ max_len += 32;
+ break;
+ case 'f':
+ va_arg(ap, double);
+ max_len += 64;
+ break;
+ default: assert(0);
+ }
+ }
+ va_end(ap);
+
+ char *str = calloc(max_len, sizeof(char));
+ va_list ap_;
+ va_start(ap_, format);
+ vsprintf(str, format, ap_);
+ va_end(ap_);
+ return str;
+}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback