Author: PQCraft <0456523@gmail.com>
A little setup work
.gitignore | 16 ++++++++ Makefile | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/errors.h | 11 +++++ src/filesystem.c | 10 +++++ src/filesystem.h | 49 ++++++++++++++++++++++++++ src/main.c | 56 +++++++++++++++++++++++++++++ src/string.c | 17 +++++++++ src/string.h | 10 +++++ src/vlb.h | 81 +++++++++++++++++++++++++++++++++++++++++++
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..d6a0d2816321e1d809008a71de53546c63c30385 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +* +!/docs/ +!/docs/** +!/examples/ +!/examples/** +!/src/ +!/src/** +!/tests/ +!/tests/** +!/*.md +!/*.sh +!/LICENSE +!/Makefile +.** +!/.gitattributes +!/.gitignore diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..abb5b71cf554a93f30698c4f2ffc902c0ca4050a --- /dev/null +++ b/Makefile @@ -0,0 +1,94 @@ +ifneq ($(OS),Windows_NT) + PLAT := $(shell uname -s | tr '[:upper:]' '[:lower:]') +else + PLAT := win32 +endif + +SRCDIR ?= src +OBJDIR ?= obj +OUTDIR ?= . + +SYSROOT ?= /usr +SYSBIN ?= $(SYSROOT)/bin + +ifneq ($(DEBUG),y) + OBJDIR := $(OBJDIR)/release +else + OBJDIR := $(OBJDIR)/debug + ifeq ($(ASAN),y) + OBJDIR := $(OBJDIR)_asan + endif +endif + +SOURCES := $(wildcard $(SRCDIR)/*.c) +OBJECTS := $(patsubst $(SRCDIR)/%.c,$(OBJDIR)/%.o,$(SOURCES)) + +BIN := $(OUTDIR)/fabricate +ifeq ($(PLAT),win32) + BIN := $(BIN).exe +endif + +CC ?= gcc +LD := $(CC) +_CC := $(TOOLCHAIN)$(CC) +_LD := $(TOOLCHAIN)$(LD) + +_CFLAGS := $(CFLAGS) -std=c99 -Wall -Wextra -Wuninitialized -Wundef +_CPPFLAGS := $(CPPFLAGS) +_LDFLAGS := $(LDFLAGS) +_LDLIBS := $(LDLIBS) + +ifneq ($(DEBUG),y) + _CPPFLAGS += -DNDEBUG +else + _CFLAGS += -g -Wdouble-promotion + O ?= g + ifeq ($(ASAN),y) + _CFLAGS += -fsanitize=address -fno-omit-frame-pointer + _LDFLAGS += -fsanitize=address + endif +endif +_CFLAGS += -O$(O) + +.SECONDEXPANSION: + +define mkdir +if [ ! -d '$(1)' ]; then echo 'Creating $(1)/...'; mkdir -p '$(1)'; fi; true +endef +define rm +if [ -f '$(1)' ]; then echo 'Removing $(1)...'; rm -f '$(1)'; fi; true +endef +define rmdir +if [ -d '$(1)' ]; then echo 'Removing $(1)/...'; rm -rf '$(1)'; fi; true +endef + +deps.filter := %.c %.h +deps.option := -MM +define deps +$$(filter $$(deps.filter),,$$(shell $(_CC) $(CFLAGS) $(CPPFLAGS) -E $(deps.option) $(1))) +endef + +build: $(BIN) + @: + +$(OUTDIR) $(OBJDIR): + @$(call mkdir,$@) + +$(OBJDIR)/%.o: $(SRCDIR)/%.c $(call deps,$(SRCDIR)/%.c) | $(OBJDIR) + @echo Compiling $<... + @$(_CC) -c $(_CFLAGS) $(_CPPFLAGS) $< -o $@ + @echo Compiled $< + +$(BIN): $(OBJECTS) | $(OUTDIR) + @echo Linking $@... + @$(_LD) $(_LDFLAGS) $^ $(_LDLIBS) -o $@ + -@cd -- $(OUTDIR) && [ -e fab ] || ln -s -- fabricate fab + @echo Linked $@ + +clean: + @$(call rmdir,$(OBJDIR)) + +distclean: clean + @$(call rm,$(BIN)) + +.PHONY: build clean distclean diff --git a/src/errors.h b/src/errors.h new file mode 100644 index 0000000000000000000000000000000000000000..a04378283a87a378df72ebce542a6aab8543655d --- /dev/null +++ b/src/errors.h @@ -0,0 +1,11 @@ +#ifndef FAB_ERRORS_H +#define FAB_ERRORS_H + +#include <stdio.h> + +extern const char* argv0; + +#define ERR_INT() fprintf(stderr, "%s: Internal error\n", argv0) +#define ERR_NOFAB() fprintf(stderr, "%s: No .fab file found\n", argv0) + +#endif diff --git a/src/filesystem.c b/src/filesystem.c new file mode 100644 index 0000000000000000000000000000000000000000..5966d86bf499febe0331e97b137133e19a18b069 --- /dev/null +++ b/src/filesystem.c @@ -0,0 +1,10 @@ +#include "filesystem.h" + +FileInfo* Ls(const char* path, size_t* count) { + // TODO + return NULL; +} +void FreeLs(FileInfo* info) { + free(info[-1].name); + free(info); +} diff --git a/src/filesystem.h b/src/filesystem.h new file mode 100644 index 0000000000000000000000000000000000000000..f11e296748172cad3890fbf65d8ad10303b3cb61 --- /dev/null +++ b/src/filesystem.h @@ -0,0 +1,49 @@ +#ifndef FAB_FILESYSTEM_H +#define FAB_FILESYSTEM_H + +#include "vlb.h" + +#include <stdbool.h> +#include <stdint.h> +#include <stddef.h> +#include <dirent.h> + +typedef uint8_t FileType; +enum { + FILETYPE_UNKNOWN, + FILETYPE_FILE, + FILETYPE_DIR, + FILETYPE_SPECIAL +}; + +typedef struct { + char* name; + FileType type; +} FileInfo; + +typedef struct { + struct VLB(char) path; + FileInfo current; + #ifndef _WIN32 + DIR* dir; + #else + WIN32_FIND_DATA find; + HANDLE file; + bool first; + #endif +} LsState; + +FileType ProbeFileType(const char* name); // Windows already has GetFileType +bool ProbeFileInfo(const char* name, FileInfo*); + +bool BeginLs(const char*, LsState*); +const FileInfo* ReadLs(LsState*); +void EndLs(LsState*); + +FileInfo* Ls(const char*, size_t* count); +void FreeLs(FileInfo*); + +bool Rm(const char*); +bool RmDir(const char*); + +#endif diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000000000000000000000000000000000000..40a8de452041be3badd9f634d15b44e3a6049c74 --- /dev/null +++ b/src/main.c @@ -0,0 +1,56 @@ +#include "errors.h" +#include "filesystem.h" +#include "string.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stddef.h> + +const char* argv0; + +static char* filename; + +static int ParseOptions(int argc, char** argv) { + for (int i = 1; i < argc; ++i) { + if (argv[i][0] != '-') { + + } else { + + } + } + return 0; +} + +static int UseFirstFabFile_Cmp(const void* a, const void* b) { + return strcmp(((const FileInfo*)a)->name, ((const FileInfo*)b)->name); +} +static int UseFirstFabFile(void) { + size_t count; + FileInfo* ls = Ls(".", &count); + if (!ls) {ERR_INT(); return 2;} + + qsort(ls, count, sizeof(*ls), UseFirstFabFile_Cmp); + + for (size_t i = 0; i < count; ++i) { + if (ls[i].type != FILETYPE_DIR && MatchWildcard("*.fab", ls[i].name)) { + filename = DupStr(ls[i].name); + if (!filename) {ERR_INT(); return 2;} + FreeLs(ls); + return 0; + } + } + + FreeLs(ls); + ERR_NOFAB(); + return 1; +} + +int main(int argc, char** argv) { + argv0 = argv[0]; + int ret; + if ((ret = ParseOptions(argc + 1, argv - 1))) return ret; + if (!filename && (ret = UseFirstFabFile())) return ret; + // TODO + return 0; +} diff --git a/src/string.c b/src/string.c new file mode 100644 index 0000000000000000000000000000000000000000..ae8cff32f6c730b1841a428a82e5dbebc2ec4ee2 --- /dev/null +++ b/src/string.c @@ -0,0 +1,17 @@ +#include "string.h" + +#include <string.h> +#include <stdlib.h> + +char* DupStr(const char* str) { + size_t len = strlen(str) + 1; + char* buf = malloc(len); + if (!buf) return NULL; + memcpy(buf, str, len); + return buf; +} + +bool MatchWildcard(const char* pat, const char* text) { + // TODO + return false; +} diff --git a/src/string.h b/src/string.h new file mode 100644 index 0000000000000000000000000000000000000000..247d9ac101a9b6ce2b606203bb2092317cef87a4 --- /dev/null +++ b/src/string.h @@ -0,0 +1,10 @@ +#ifndef FAB_STRING_H +#define FAB_STRING_H + +#include <stdbool.h> + +char* DupStr(const char* str); + +bool MatchWildcard(const char* pat, const char* text); + +#endif diff --git a/src/vlb.h b/src/vlb.h new file mode 100644 index 0000000000000000000000000000000000000000..4229577581b09c200930b52e3f4551956e49a96e --- /dev/null +++ b/src/vlb.h @@ -0,0 +1,81 @@ +#ifndef FAB_VLB_H +#define FAB_VLB_H + +#include <stddef.h> +#include <stdlib.h> + +#define VLB(T) {\ + T* data;\ + size_t len;\ + size_t size;\ +} + +#define VLB_OOM_NOP + +#define VLB__EXP(VLB__b, VLB__en, VLB__ed, VLB__do, ...) do {\ + if ((VLB__b).len != (VLB__b).size) {\ + VLB__do;\ + } else {\ + register size_t VLB__tmp = (VLB__b).size;\ + VLB__tmp = VLB__tmp * (VLB__en) / (VLB__ed);\ + if (VLB__tmp <= (VLB__b).size) VLB__tmp = (VLB__b).size + 1;\ + void* VLB__ptr = realloc((VLB__b).data, VLB__tmp * sizeof(*(VLB__b).data));\ + if (VLB__ptr) {(VLB__b).data = VLB__ptr; VLB__do; (VLB__b).size = VLB__tmp;}\ + else {__VA_ARGS__}\ + }\ +} while (0) +#define VLB__EXP_MULTI(VLB__b, VLB__l, VLB__en, VLB__ed, ...) do {\ + if ((VLB__l) > (VLB__b).size) {\ + register size_t VLB__tmp = (VLB__b).size;\ + do {\ + register size_t VLB__old = VLB__tmp;\ + VLB__tmp = VLB__tmp * (VLB__en) / (VLB__ed);\ + if (VLB__tmp <= VLB__old) VLB__tmp = VLB__old + 1;\ + } while (VLB__tmp < (VLB__l));\ + void* VLB__ptr = realloc((VLB__b).data, VLB__tmp * sizeof(*(VLB__b).data));\ + if (VLB__ptr) {(VLB__b).data = VLB__ptr; (VLB__b).len = (VLB__l); (VLB__b).size = VLB__tmp;}\ + else {__VA_ARGS__}\ + } else if ((VLB__l) > (VLB__b).len) {\ + (VLB__b).len = (VLB__l);\ + }\ +} while (0) + +#define VLB_INIT(VLB__b, VLB__sz, ...) do {\ + (VLB__b).data = malloc((VLB__sz) * sizeof(*(VLB__b).data));\ + if ((VLB__b).data || !(VLB__sz)) {\ + (VLB__b).len = 0;\ + (VLB__b).size = (VLB__sz);\ + } else {\ + __VA_ARGS__\ + }\ +} while (0) +#define VLB_ZINIT(VLB__b) do {\ + (VLB__b).data = NULL;\ + (VLB__b).len = 0;\ + (VLB__b).size = 0;\ +} while (0) +#define VLB_FREE(b) free((b).data) + +#define VLB_ADD(VLB__b, VLB__d, VLB__en, VLB__ed, ...) do {\ + VLB__EXP((VLB__b), (VLB__en), (VLB__ed), (VLB__b).data[(VLB__b).len++] = (VLB__d), __VA_ARGS__);\ +} while (0) +#define VLB_NEXTPTR(VLB__b, VLB__o, VLB__en, VLB__ed, ...) do {\ + VLB__EXP((VLB__b), (VLB__en), (VLB__ed), (VLB__o) = &(VLB__b).data[(VLB__b).len++], __VA_ARGS__);\ +} while (0) + +#define VLB_EXPANDBY(VLB__b, VLB__a, VLB__en, VLB__ed, ...) do {\ + register size_t VLB__l = (VLB__b).len + (VLB__a);\ + VLB__EXP_MULTI((VLB__b), (VLB__l), (VLB__en), (VLB__ed), __VA_ARGS__);\ +} while (0) +#define VLB_EXPANDTO(VLB__b, VLB__l, VLB__en, VLB__ed, ...) do {\ + VLB__EXP_MULTI((VLB__b), (VLB__l), (VLB__en), (VLB__ed), __VA_ARGS__);\ +} while (0) +#define VLB_SHRINK(VLB__b, ...) do {\ + if ((VLB__b).len != (VLB__b).size) {\ + void* VLB__ptr = realloc((VLB__b).data, (VLB__b).len * sizeof(*(VLB__b).data));\ + if (VLB__ptr || !(VLB__b).len) {(VLB__b).data = VLB__ptr; (VLB__b).size = (VLB__b).len;}\ + else {__VA_ARGS__}\ + }\ +} while (0) + +#endif