diff options
-rw-r--r-- | main.c | 61 | ||||
-rw-r--r-- | maje.c | 50 | ||||
-rw-r--r-- | maje.h | 3 | ||||
-rw-r--r-- | make.c | 47 | ||||
-rw-r--r-- | sources.c | 38 |
5 files changed, 199 insertions, 0 deletions
@@ -0,0 +1,61 @@ +#define _XOPEN_SOURCE 700 +#include <assert.h> +#include <fcntl.h> +#include <regex.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <stdbool.h> +#include <unistd.h> + +#include "maje.h" + +static bool matches(const char * restrict path, const regex_t * restrict re) +{ + bool ret = false; + + int fd = open(path, O_RDONLY); + if (fd == -1) { + return false; + } + + struct stat st = { 0 }; + if (fstat(fd, &st) != 0) { + close(fd); + return false; + } + + void *map = mmap(NULL, (size_t)st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (map == MAP_FAILED) { + close(fd); + return false; + } + + + if (regexec(re, map, (size_t)st.st_size, NULL, 0) == 0) { + ret = true; + } + + munmap(map, st.st_size); + close(fd); + + return ret; +} + +char *find_main(char **sources) +{ + regex_t re; + int rc = regcomp(&re, "int[[:space:]]+main[[:space:]\(]", REG_EXTENDED | REG_NEWLINE | REG_NOSUB); + assert(rc == 0); + char *ret = NULL; + + for (char **src = sources; *src != NULL; src++) { + if (matches(*src, &re)) { + ret = *src; + break; + } + } + + regfree(&re); + + return ret; +} @@ -0,0 +1,50 @@ +#define _XOPEN_SOURCE 700 +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +#include "maje.h" + +static void usage(char *progname) +{ + printf("usage: %s [dir]\n", progname); +} + +int main(int argc, char *argv[]) +{ + char *srcdir = NULL; + + int c; + while ((c = getopt(argc, argv, "")) != -1) { + switch (c) { + default: + usage(argv[0]); + return 1; + } + } + + srcdir = argv[optind]; + + if (srcdir == NULL) { + srcdir = "."; + } + + char **sources = find_source_files(srcdir); + char *mainname = find_main(sources); + if (!mainname) { + printf("libraries not yet supported\n"); + return 0; + } + char *target = strdup(mainname); + target[strlen(target) - 2] = '\0'; + + FILE *makefile = fopen("Makefile", "w"); + if (makefile == NULL) { + perror("fopen"); + return 1; + } + + make_makefile("Makefile", sources, target); + + return 0; +} @@ -0,0 +1,3 @@ +char **find_source_files(const char *path); +char *find_main(char **sources); +void make_makefile(const char *makefile, char **sources, const char *target); @@ -0,0 +1,47 @@ +#define _XOPEN_SOURCE 700 +#include <stdio.h> + +#include "maje.h" + +static void make_header(FILE *makefile, const char *target) +{ + fprintf(makefile, ".POSIX:\n"); + fprintf(makefile, "default: all\n"); + + fprintf(makefile, "CC=c99\n"); + fprintf(makefile, "CFLAGS=-Wall -Wextra -Wpedantic -Werror -g\n"); + + fprintf(makefile, "all: %s\n", target); + + fprintf(makefile, "clean:\n"); + fprintf(makefile, "\trm -f %s *.o\n", target); +} + +static void addfile(FILE *makefile, const char *src, const char *target) +{ + fprintf(makefile, "%s: %s\n", src, src); + fprintf(makefile, "%s: %s\n", target, src); +} + +void make_makefile(const char *makepath, char **sources, const char *target) +{ + FILE *makefile = fopen(makepath, "w"); + if (makefile == NULL) { + perror("fopen: Makefile"); + return; + } + + make_header(makefile, target); + for (char **src = sources; *src != NULL; src++) { + addfile(makefile, *src, target); + } + + fprintf(makefile, "%s:\n", target); + fprintf(makefile, "\t$(CC) -o $@"); + for (char **src = sources; *src != NULL; src++) { + fprintf(makefile, " %s", *src); + } + fprintf(makefile, "\n"); + + fclose(makefile); +} diff --git a/sources.c b/sources.c new file mode 100644 index 0000000..3defa73 --- /dev/null +++ b/sources.c @@ -0,0 +1,38 @@ +#define _XOPEN_SOURCE 700 +#include <ftw.h> +#include <string.h> +#include <stdlib.h> + +#include "maje.h" + +static char **filelist = NULL; +static size_t nfiles = 0; + +static int addfile(const char *path, const struct stat *st, int flags, struct FTW *ft) +{ + (void)st; (void)flags; (void)ft; + + if (path[0] == '.' && path[1] == '/') { + path += 2; + } + + if (strcmp(path + strlen(path) - 2, ".c") == 0) { + char **tmp = realloc(filelist, sizeof(*filelist) * (nfiles + 2)); + if (tmp == NULL) { + return 1; + } + filelist = tmp; + + filelist[nfiles] = strdup(path); + filelist[nfiles + 1] = NULL; + nfiles++; + } + + return 0; +} + +char ** find_source_files(const char *dir) +{ + nftw(dir, addfile, -1, 0); + return filelist; +} |