summaryrefslogtreecommitdiff
path: root/flags.c
diff options
context:
space:
mode:
Diffstat (limited to 'flags.c')
-rw-r--r--flags.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/flags.c b/flags.c
new file mode 100644
index 0000000..2cd7b13
--- /dev/null
+++ b/flags.c
@@ -0,0 +1,68 @@
+#define _XOPEN_SOURCE 700
+#include <fcntl.h>
+#include <regex.h>
+#include <sys/mman.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "maje.h"
+
+#define MAX_MATCHES (2)
+
+static struct majeflag * find_flags(const struct majefile *file, const regex_t * restrict re, struct majeflag *flags)
+{
+ int fd = open(file->path, O_RDONLY);
+ if (fd == -1) {
+ return NULL;
+ }
+
+ void *map = mmap(NULL, (size_t)file->st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (map == MAP_FAILED) {
+ close(fd);
+ return NULL;
+ }
+
+ regmatch_t match[MAX_MATCHES];
+
+ void *base = map;
+ while (regexec(re, base, MAX_MATCHES, match, 0) == 0) {
+ if (match[1].rm_so == -1) {
+ break;
+ }
+ char flag[FILENAME_MAX] = { 0 };
+ char *start = (char*)base + match[1].rm_so;
+ memcpy(flag, start, match[1].rm_eo - match[1].rm_so);
+ flags = insert_flag(flags, flag);
+ base = start + match[1].rm_eo;
+ }
+
+ munmap(map, file->st.st_size);
+ close(fd);
+
+ return flags;
+}
+
+struct majeflag *add_flags(const struct majefile *source, struct majeflag *flags)
+{
+ static regex_t re = { .re_nsub = (size_t)-1 };
+ if (re.re_nsub == (size_t)-1) {
+ if (regcomp(&re,
+ "(MAJE_[[:upper:]]+=[^[:space:]]+)",
+ REG_EXTENDED | REG_NEWLINE) != 0) {
+ fprintf(stderr, "maje: regcomp(MAJE) failed\n");
+ abort();
+ }
+ }
+
+ struct majeflag *ret = find_flags(source, &re, flags);
+
+ if (ret != NULL) {
+ while (ret->prev != NULL) {
+ ret = ret->prev;
+ }
+ }
+
+ return ret;
+}