summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Sotoudeh <matthew@masot.net>2024-04-20 17:08:04 -0700
committerMatthew Sotoudeh <matthew@masot.net>2024-04-20 17:08:04 -0700
commitee0ea049f6bae5d1ffc137e17b1858cb1e154b13 (patch)
tree45db7626cd4dfe0ca32d9e665c648ad38f66ea1a
parent3d808effbdb543c92db815a112c786b44c8a9e12 (diff)
support --gamma-to-c flag
-rw-r--r--README.txt3
-rw-r--r--gamma_version/Makefile3
-rw-r--r--gamma_version/fakeobj.c8
-rw-r--r--gamma_version/gamma.h3
-rw-r--r--gamma_version/main.c25
-rw-r--r--gamma_version/utils.c26
6 files changed, 59 insertions, 9 deletions
diff --git a/README.txt b/README.txt
index e98b023..7610d02 100644
--- a/README.txt
+++ b/README.txt
@@ -33,6 +33,9 @@ Selling points include:
relatively easy to port as a preprocessor for other languages, e.g.,
Hare.
+ - The gamma version of gamma allows you to pass --gamma-to-c, which will
+ create the directory "c.out" and write a C version of the codebase to it.
+
####### Code Samples #######
> uint32_t vector_push::[type T](struct vector::[T] *vector, T item) {
diff --git a/gamma_version/Makefile b/gamma_version/Makefile
index 81bd4e5..afd265c 100644
--- a/gamma_version/Makefile
+++ b/gamma_version/Makefile
@@ -18,7 +18,8 @@ OBJS=build/main.o \
build/hashmap.o \
build/hash_functions.o \
build/vector.o \
- build/debug.o
+ build/debug.o \
+ build/utils.o
build/gc: $(OBJS)
$(CC) $(CFLAGS) -o $@ $^
diff --git a/gamma_version/fakeobj.c b/gamma_version/fakeobj.c
index 544ada1..10fae7a 100644
--- a/gamma_version/fakeobj.c
+++ b/gamma_version/fakeobj.c
@@ -37,6 +37,7 @@ void preproc(char *src, char *dst) {
if (str_ends_with(ARGV[i], ".c")) continue;
if (str_ends_with(ARGV[i], ".a")) continue;
if (str_ends_with(ARGV[i], ".o")) continue;
+ if (!strcmp(ARGV[i], "--gamma-to-c")) continue;
if (!strcmp(ARGV[i], "-c")) continue;
if (!strcmp(ARGV[i], "-o")) { i++; continue; }
new_argv[new_argc++] = ARGV[i];
@@ -57,6 +58,7 @@ void write_fakeobj(char *src, char *dst, int i) {
if (str_ends_with(ARGV[j], ".c")) continue;
if (str_ends_with(ARGV[j], ".o")) continue;
if (str_ends_with(ARGV[j], ".a")) continue;
+ if (!strcmp(ARGV[j], "--gamma-to-c")) continue;
if (!strcmp(ARGV[j], "-c")) continue;
if (!strcmp(ARGV[j], "-o")) { j++; continue; }
new_argv[new_argc++] = ARGV[j];
@@ -73,6 +75,7 @@ void write_fakeobj(char *src, char *dst, int i) {
goto fake_obj;
real_obj:
+ if (GAMMA_TO_C) goto fake_obj;
// rewrite the args and call
new_argv[new_argc++] = "-c";
new_argv[new_argc++] = src;
@@ -137,12 +140,9 @@ char **read_fakeobj(char *path, char *c_dst) {
assert(len == read(fd, argv[i], len));
}
- struct stat statbuf;
- fstat(fd, &statbuf);
-
int out_fd = open(c_dst, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
assert(out_fd >= 0);
- sendfile(out_fd, fd, NULL, statbuf.st_size);
+ gamma_sendfile(out_fd, fd);
close(out_fd);
close(fd);
diff --git a/gamma_version/gamma.h b/gamma_version/gamma.h
index 673636b..d1937e7 100644
--- a/gamma_version/gamma.h
+++ b/gamma_version/gamma.h
@@ -100,7 +100,10 @@ struct call *replace_variables(struct call *container, struct call *container_in
void fprint_string(FILE *out, struct uniq_string *string);
char **read_fakeobj(char *path, char *c_dst);
void write_fakeobj(char *src, char *dst, int i);
+void gamma_sendfile(int dst_fd, int src_fd);
+void copy_file(char *dst, char *src);
extern char **ARGV;
extern int ARGC;
extern char *TMPDIR;
+extern int GAMMA_TO_C;
diff --git a/gamma_version/main.c b/gamma_version/main.c
index a402e1b..780c80f 100644
--- a/gamma_version/main.c
+++ b/gamma_version/main.c
@@ -35,6 +35,7 @@ char **get_object_files(char *dir, size_t *n_object_files) {
char **ARGV;
int ARGC;
char *TMPDIR;
+int GAMMA_TO_C;
int main(int argc, char **argv) {
// ======= Make a working copy of argv =======
@@ -48,6 +49,12 @@ int main(int argc, char **argv) {
strcpy(TMPDIR, "/tmp/gamma.XXXXXX");
assert(mkdtemp(TMPDIR));
+ // ======= Handle --gamma-to-c ... =======
+ // If "--gamma-to-c" in args, then set the GAMMA_TO_C global.
+ for (int i = 0; i < ARGC; i++)
+ if (!strcmp(ARGV[i], "--gamma-to-c"))
+ GAMMA_TO_C = 1;
+
// ======= Handle -c ... =======
// If "-c" in args, then check if there are any templates/etc. and compile
// either a .o or a fake-.o
@@ -172,12 +179,22 @@ int main(int argc, char **argv) {
fflush(c_file);
fclose(c_file);
- assert(fake_argvs[file->id]);
- int pid = fork();
- if (!pid) execvp(fake_argvs[file->id][0], fake_argvs[file->id]);
- waitpid(pid, 0, 0);
+ if (GAMMA_TO_C) {
+ // move every C file from the arguments to the out directory
+ mkdir("c.out", 0755);
+ char out_name[128] = {0};
+ sprintf(out_name, "c.out/%ld.c", file->id);
+ copy_file(out_name, c_path);
+ } else {
+ assert(fake_argvs[file->id]);
+ int pid = fork();
+ if (!pid) execvp(fake_argvs[file->id][0], fake_argvs[file->id]);
+ waitpid(pid, 0, 0);
+ }
}
+ if (GAMMA_TO_C) goto cleanup;
+
// NOW all the arguments should be set up properly, so just run the command
execvp(ARGV[0], ARGV);
diff --git a/gamma_version/utils.c b/gamma_version/utils.c
new file mode 100644
index 0000000..8877974
--- /dev/null
+++ b/gamma_version/utils.c
@@ -0,0 +1,26 @@
+#include "gamma.h"
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/sendfile.h>
+
+void gamma_sendfile(int dst_fd, int src_fd) {
+ // sendfile(out_fd, fd, NULL, statbuf.st_size);
+ struct stat stat;
+ fstat(src_fd, &stat);
+
+ size_t n_bytes = stat.st_size - lseek(src_fd, 0, SEEK_CUR);
+
+ char *data = malloc(n_bytes);
+ assert(read(src_fd, data, n_bytes) == n_bytes);
+ write(dst_fd, data, n_bytes);
+}
+
+void copy_file(char *dst, char *src) {
+ int s = open(src, O_RDONLY),
+ d = open(dst, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
+ gamma_sendfile(d, s);
+ close(s);
+ close(d);
+}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback