diff --git a/README.md b/README.md deleted file mode 100644 index 7cc185b..0000000 --- a/README.md +++ /dev/null @@ -1,73 +0,0 @@ -# Minimake - -Minimake is a small project written in about a week in C99. Its goal was to reproduce the main features of the well known GNU Make utility. - -> **Note** This is a school project, therefore it probably won't interest you if you are looking for something useful. - -## Build - -```sh -make -``` -or even better -```sh -minimake -``` - -## How it works - -If you're not familiar with Make, what it does is that it reads a file named -`Makefile` in the current directory which contains instructions to build a -project in the form of recipes. It includes support for variables, dependencies -, implicit rules and more. - -Then depending on the user input it automatically executes a recipe with its dependencies. - - -Here is what a basic one can look like -```make -BENCH_FLAGS = --all - -test_and_bench: - bash ./runtests.sh - bash ./runbenchs.sh $(BENCH_FLAGS) -``` - -But it will more realisticly look like that - -```make -CC = gcc -CFLAGS = -std=c99 -pedantic -Werror -Wall -Wextra -Wvla -LDFLAGS= - -DBG_CFLAGS = -fsanitize=address -g -DBG_LDFLAGS= -fsanitize=address - - -SRC_DIR = src -LIB_SRCS = lines/lines.c hash_maps/hash_maps.c lists/lists.c files/files.c -MAIN_SRCS = main.c minimake.c - -SRCS = $(MAIN_SRCS:%=$(SRC_DIR)/%) $(LIB_SRCS:%=$(SRC_DIR)/%) -OBJS = $(SRCS:.c=.o) - -TARGET= minimake -DBG_TARGET = minimake-dbg - -$(TARGET): $(OBJS) - $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS) - @echo $(OBJS) - -debug: CFLAGS += $(DBG_CFLAGS) -debug: LDFLAGS += $(DBG_LDFLAGS) -debug: $(OBJS) - $(CC) -o $(DBG_TARGET) $^ $(LDFLAGS) $(LDLIBS) - -check: - dash ./tests/run.sh - -clean: - $(RM) $(TARGET) - $(RM) $(OBJS) - -``` diff --git a/micromake/src/Microfile b/micromake/src/Microfile new file mode 100644 index 0000000..607b02a --- /dev/null +++ b/micromake/src/Microfile @@ -0,0 +1,3 @@ +qwertyu: +cbejw: a bc d +dmwq :d wdwd diff --git a/micromake/src/micromake.c b/micromake/src/micromake.c new file mode 100644 index 0000000..fda3fe2 --- /dev/null +++ b/micromake/src/micromake.c @@ -0,0 +1,119 @@ +#define _POSIX_C_SOURCE 200809L +#define BUFFER_SIZE 1024 +#define STRING_BUFFER_SIZE 32 + +#include +#include +#include +#include + +// Helps to match a string (excludes blanks and special characters) +static int is_char(char c) +{ + return c != '\0' && !isblank(c) && c != ':' && c != '=' && c != '#'; +} + +// Returns the next word from buf until buf_len, +// and the numbers of read characters in *read_chars +// WARNING allocates the result on the heap +static char *readWord(char *buf, size_t buf_len, size_t *read_chars) +{ + size_t i = 0; + size_t str_buf_size = STRING_BUFFER_SIZE; + char *str_buf = malloc(sizeof(char) * str_buf_size); + while (i < buf_len && is_char(buf[i])) + { + // Reallocate more space if necessary + if (i >= str_buf_size - 1) + { + str_buf_size += STRING_BUFFER_SIZE; + str_buf = realloc(str_buf, str_buf_size); + if (str_buf == NULL) + errx(2, "Could not realloc"); + } + + str_buf[i] = buf[i]; + i++; + } + + str_buf[i] = '\0'; + *read_chars = i; + + return str_buf; +} + +int skip_blanks(char *buf, size_t buf_len) +{ + size_t i = 0; + while (i < buf_len && isblank(buf[i])) + i++; + return i; +} + +int main(int argc, char **argv) +{ + if (argc < 2) + errx(2, "Not enough arguments"); + if (argc > 2) + errx(2, "Not enough arguments"); + + // Open file + FILE *stream = fopen(argv[1], "r"); + if (stream == 0) + errx(2, "Could not open file"); + + // Allocate buffer + size_t buf_size = BUFFER_SIZE; + char *buf = malloc(sizeof(char) * buf_size); + if (buf == NULL) + errx(2, "Could not allocate more memory"); + + // Read + ssize_t nread; + while ((nread = getline(&buf, &buf_size, stream)) != -1) + { + size_t u_nread = nread; + size_t i = 0; + // Skip blanks + i += skip_blanks(buf + i, nread - i); + + // Read target name + size_t skipped_chars = 0; + char *rule_name = readWord(buf + i, nread - i, &skipped_chars); + if (skipped_chars != 0) + printf("%s:", rule_name); + i += skipped_chars; + + // Skip until ':' + i += skip_blanks(buf + i, nread - i); + if (buf[i] != ':') + errx(2, "Unexpected character '%c' after rule declaration '%s'", + buf[i], rule_name); + i++; + + // Read deps + while (i < u_nread) + { + // Skip blanks + i += skip_blanks(buf + i, nread - i); + + // Read word + size_t skipped_chars = 0; + char *dep_name = readWord(buf + i, nread - i, &skipped_chars); + if (skipped_chars != 0) + printf(" %s", dep_name); + free(dep_name); + i += skipped_chars; + + if (!is_char(buf[i]) && !isblank(buf[i]) && buf[i] != '\0') + errx(2, "Unexpected character '%c'", buf[i]); + } + + i++; + free(rule_name); + } + + free(buf); + fclose(stream); + return 0; +} diff --git a/microshell/microshell.c b/microshell/microshell.c new file mode 100644 index 0000000..4a7b661 --- /dev/null +++ b/microshell/microshell.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + if (argc < 2) + err(1, "Not enough args"); + + int id = fork(); + if (id < 0) + err(1, "Cannot fork"); + + if (id == 0) + { + int res = 0; + wait(&res); + // printf("%d\n", res); + return res; + } + else + { + int res = execl("/bin/sh", "supershell", "-c", argv[1], NULL); + printf("process exit status: %d\n", res); + // exit(res); + return res; + } +} diff --git a/Makefile b/minimake/Makefile similarity index 100% rename from Makefile rename to minimake/Makefile diff --git a/src/files/files.c b/minimake/src/files/files.c similarity index 89% rename from src/files/files.c rename to minimake/src/files/files.c index b27627d..2d46ecb 100644 --- a/src/files/files.c +++ b/minimake/src/files/files.c @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -59,6 +60,9 @@ int run_command(char *command) fflush(stdout); fflush(stderr); + // char *executable; + // size_t args_offset = readword(command, strlen(command), &executable); + int id = fork(); if (id < 0) { @@ -68,13 +72,14 @@ int run_command(char *command) if (id == 0) { - int res = execl("/bin/sh", "(make)", "-c", command, NULL); - exit(res); + int res = 0; + wait(&res); + // printf("Got return code: %d\n", res); + return res; } else { - int res = 0; - wait(&res); + int res = execl("/bin/sh", "(make)", "-c", command, NULL); return res; } } diff --git a/src/files/files.h b/minimake/src/files/files.h similarity index 68% rename from src/files/files.h rename to minimake/src/files/files.h index d4893c3..da7c555 100644 --- a/src/files/files.h +++ b/minimake/src/files/files.h @@ -3,12 +3,11 @@ #define _XOPEN_SOURCE 500 +#include "../lists/lists.h" #include -#include "../lists/lists.h" - -char *get_makefile(struct list *files); -ssize_t get_file_lastmodiftime(char *filename); +char* get_makefile(struct list *files); +ssize_t get_file_lastmodiftime(char* filename); int run_command(char *command); int file_exists(char *filename); diff --git a/src/hash_maps/hash_maps.c b/minimake/src/hash_maps/hash_maps.c similarity index 100% rename from src/hash_maps/hash_maps.c rename to minimake/src/hash_maps/hash_maps.c diff --git a/src/hash_maps/hash_maps.h b/minimake/src/hash_maps/hash_maps.h similarity index 95% rename from src/hash_maps/hash_maps.h rename to minimake/src/hash_maps/hash_maps.h index 634c993..97a84da 100644 --- a/src/hash_maps/hash_maps.h +++ b/minimake/src/hash_maps/hash_maps.h @@ -24,7 +24,7 @@ struct hash_map size_t hash(const char *str); struct hash_map *hashmap_init(size_t size); bool hashmap_insert(struct hash_map *hash_map, char *key, void *value, - bool *updated); + bool *updated); void hashmap_free(struct hash_map *hash_map); void hashmap_dump(struct hash_map *hash_map); void *hashmap_get(const struct hash_map *hash_map, char *key); diff --git a/src/lines/lines.c b/minimake/src/lines/lines.c similarity index 81% rename from src/lines/lines.c rename to minimake/src/lines/lines.c index 238b576..fcd33e1 100644 --- a/src/lines/lines.c +++ b/minimake/src/lines/lines.c @@ -219,45 +219,3 @@ size_t read_declaration(struct line *line, size_t index, char **word) *word = res; return i - index; } - -// Takes a string, expands its variables and returns the resulting buffer -// WARNING allocates the result on the heap, free result after use -char *expand_str(char *str) -{ - size_t str_i = 0; - size_t buf_i = 0; - size_t buf_size = BUFFER_SIZE; - char *buf = malloc(BUFFER_SIZE * sizeof(char)); - while (str[str_i] != '\0') - { - // Reallocate more space if necessary - resize_buf(&buf, buf_size, buf_i); - - // Expand variable - if (buf[buf_i] == '$') - { - // Temporary variables - char *expanded_var; - char *tmp_res_buf; - struct line false_line = { - .buffer = buf, .file_stream = NULL, .length = 0, .number = 0 - }; - str_i += expand_variable(&false_line, str_i + 1, &expanded_var); - buf_size = append_str(buf, expanded_var, buf_i, &tmp_res_buf); - // Replace buf with buf + expanded_variable - buf_i = strlen(tmp_res_buf); - free(buf); - // free(expanded_var); - buf = tmp_res_buf; - continue; - } - - buf[buf_i] = str[str_i]; - buf_i++; - str_i++; - } - - buf[buf_i] = '\0'; - - return buf; -} diff --git a/src/lines/lines.h b/minimake/src/lines/lines.h similarity index 73% rename from src/lines/lines.h rename to minimake/src/lines/lines.h index 5782327..081d305 100644 --- a/src/lines/lines.h +++ b/minimake/src/lines/lines.h @@ -4,25 +4,25 @@ #define STRING_BUFFER_SIZE 32 #include -#include #include +#include // Holds line information // Exists only because of EPITA's annoying 4 parameters limit // WARNING buffer must be freed after use struct line { - char *buffer; // Line content - ssize_t length; // Line length - size_t number; // Line number in file - FILE *file_stream; // Full file stream + char* buffer; // Line content + ssize_t length; // Line length + size_t number; // Line number in file + FILE* file_stream; // Full file stream }; int ischar(char c); int isblankline(struct line *l); int skipblanks(char *buf, size_t buf_len); size_t readword(char *buf, size_t buf_len, char **word); -size_t resize_buf(char **buf, size_t buf_size, size_t index); +size_t resize_buf(char** buf, size_t buf_size, size_t index); char *insert_str(char *base, char *str, size_t index); size_t read_declaration(struct line *line, size_t index, char **word); size_t append_str(char *base, char *str, size_t index, char **res); diff --git a/minimake/src/lists/.gitignore b/minimake/src/lists/.gitignore new file mode 100644 index 0000000..3309b20 --- /dev/null +++ b/minimake/src/lists/.gitignore @@ -0,0 +1 @@ +list.c diff --git a/src/lists/lists.c b/minimake/src/lists/lists.c similarity index 100% rename from src/lists/lists.c rename to minimake/src/lists/lists.c diff --git a/src/lists/lists.h b/minimake/src/lists/lists.h similarity index 88% rename from src/lists/lists.h rename to minimake/src/lists/lists.h index 116bd1f..8c4114f 100644 --- a/src/lists/lists.h +++ b/minimake/src/lists/lists.h @@ -1,11 +1,11 @@ -#ifndef LISTS_H -#define LISTS_H +#ifndef LIST_H +#define LIST_H #include struct list { - void *data; + void* data; struct list *next; }; @@ -13,7 +13,7 @@ struct list ** Insert a node containing `value` at the beginning of the list. ** Return `NULL` if an error occured. */ -struct list *list_prepend(struct list *list, void *value); +struct list *list_prepend(struct list *list, void* value); /* ** Return the lenght of the list. @@ -44,7 +44,7 @@ void list_deep_destroy(struct list *l); ** Return `NULL` if an error occured. */ // START PROTO list_append -struct list *list_append(struct list *list, void *value); +struct list *list_append(struct list *list, void* value); // END PROTO list_append /* @@ -54,7 +54,7 @@ struct list *list_append(struct list *list, void *value); ** Return `NULL` if an error occured. */ // START PROTO list_insert -struct list *list_insert(struct list *list, void *value, size_t index); +struct list *list_insert(struct list *list, void* value, size_t index); // END PROTO list_insert /* @@ -70,7 +70,7 @@ struct list *list_remove(struct list *list, size_t index); ** Return `-1` if nothing is found. */ // START PROTO list_find -int list_find(struct list *list, void *value); +int list_find(struct list *list, void* value); // END PROTO list_find /* @@ -107,4 +107,4 @@ int list_find(struct list *list, void *value); // struct list *list_split(struct list *list, size_t index); // END PROTO list_split -#endif /* ! LISTS_H */ +#endif /* ! LIST_H */ diff --git a/src/main.c b/minimake/src/main.c similarity index 100% rename from src/main.c rename to minimake/src/main.c diff --git a/src/minimake.c b/minimake/src/minimake.c similarity index 92% rename from src/minimake.c rename to minimake/src/minimake.c index 4368296..675702c 100644 --- a/src/minimake.c +++ b/minimake/src/minimake.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include "files/files.h" @@ -18,14 +17,14 @@ // Static variables -static char *program_name; +char *program_name; -static struct hash_map *variables = NULL; -static struct hash_map *rules = NULL; +struct hash_map *variables = NULL; +struct hash_map *rules = NULL; // Keeps track of variables and rules order -static struct list *variables_list = NULL; -static struct list *rules_list = NULL; +struct list *variables_list = NULL; +struct list *rules_list = NULL; // ==== Misc ==== @@ -338,7 +337,6 @@ size_t expand_variable(struct line *line, size_t index, char **value) // Get corresponding value *value = get_variable_value(var_name, line->number); - free(var_name); } return 2; @@ -462,43 +460,18 @@ void make_parse(char *path) // ==== Runtime ==== -// Return 1 if rule is up to date, 0 otherwise -static int uptodate(struct rule *rule) -{ - struct stat path_stat; - - if (lstat(rule->name, &path_stat) != 0) // target doesn't exists - return 0; - - struct list *dependencies = rule->dependencies; - while (dependencies != NULL) - { - char *depname = dependencies->data; - if (lstat(depname, &path_stat) != 0) // Dependecy doesn't exists - return 0; - } - return 1; -} - // Expands and run a specified rule static int run_rule(struct rule *rule) { - // Check if p to date - if (uptodate(rule)) - { - printf("%s: '%s' is up to date.", program_name, rule->name); - return 0; - } - struct list *commands = rule->recipe; struct list *dependencies = rule->dependencies; + // Expand dependencies variables + // TODO + // Build dependencies while (dependencies != NULL) { - // Expand variable - // TODO - // Check file existence if (!file_exists(dependencies->data)) { @@ -516,15 +489,6 @@ static int run_rule(struct rule *rule) dependencies->data); } } - - dependencies = dependencies->next; - } - - // Empty recipe - if (commands == NULL) - { - printf("%s: Nothing to be done for '%s'.\n", program_name, rule->name); - return 0; } while (commands != NULL) @@ -587,15 +551,9 @@ int make(char *path, struct list *rules, char *exec_name, int flags) make_parse(path); - // Print if (flags & FLAGS_PRINT) - { dump_database(); - free_all(); - return 0; - } - // Run int status = make_run(rules); free_all(); return status; @@ -633,7 +591,7 @@ void dump_database(void) // Print char *key = elt->data; - printf("'%s' = '%s'\n", key, val); + printf("%s = %s\n", key, val); elt = elt->next; } @@ -648,7 +606,7 @@ void dump_database(void) drop(GENERIC_ERR, "Could not get rule '%s' in database", elt->data); // Print name - printf("(%s):", rule->name); + printf("(%s) :", rule->name); // Print dependencies struct list *dep = rule->dependencies; diff --git a/src/minimake.h b/minimake/src/minimake.h similarity index 91% rename from src/minimake.h rename to minimake/src/minimake.h index 7bb5f39..f6ed073 100644 --- a/src/minimake.h +++ b/minimake/src/minimake.h @@ -18,8 +18,8 @@ #include #include -#include "lines/lines.h" #include "lists/lists.h" +#include "lines/lines.h" // Holds variable information // WARNING its values must be freed after use @@ -33,12 +33,12 @@ struct variable // WARNING its values must be freed after use struct rule { - char *name; + char* name; struct list *dependencies; struct list *recipe; }; -int make(char *path, struct list *rules, char *argv0, int flags); +int make(char *path, struct list* rules, char *argv0, int flags); void make_parse(char *path); int make_run(struct list *rules); void drop(int status, char *format, ...); diff --git a/tests/Makefile.syntax-test b/minimake/tests/Makefile.syntax-test similarity index 100% rename from tests/Makefile.syntax-test rename to minimake/tests/Makefile.syntax-test diff --git a/tests/Makefile.test3 b/minimake/tests/Makefile.test3 similarity index 100% rename from tests/Makefile.test3 rename to minimake/tests/Makefile.test3 diff --git a/minimake/tests/Makefile.test4 b/minimake/tests/Makefile.test4 new file mode 100644 index 0000000..45ee423 --- /dev/null +++ b/minimake/tests/Makefile.test4 @@ -0,0 +1,5 @@ +rule1: + echo Toto + +rule2: + @echo Toto diff --git a/tests/Makefile2.syntax-test b/minimake/tests/Makefile2.syntax-test similarity index 100% rename from tests/Makefile2.syntax-test rename to minimake/tests/Makefile2.syntax-test diff --git a/tests/run.sh b/minimake/tests/run.sh similarity index 100% rename from tests/run.sh rename to minimake/tests/run.sh diff --git a/simple_ls/simple_ls.c b/simple_ls/simple_ls.c new file mode 100644 index 0000000..508c5df --- /dev/null +++ b/simple_ls/simple_ls.c @@ -0,0 +1,37 @@ +#include +#include +#include + +static void simple_ls(char *path) +{ + if (path == NULL) + errx(1, "Internal error: Passed NULL path"); + + DIR *dir = opendir(path); + if (dir == NULL) + errx(1, "Internal error: cannot open directory"); + + struct dirent *element; + while ((element = readdir(dir))) + { + puts(element->d_name); + } + + int res = closedir(dir); + if (res == -1) + errx(1, "Could not close dir"); +} + +int main(int argc, char **argv) +{ + if (argc < 2) + simple_ls("."); + else + { + for (int i = 1; i < argc; i++) + { + simple_ls(argv[i]); + } + } + return 0; +} diff --git a/tests/Makefile.empty b/tests/Makefile.empty deleted file mode 100644 index e9228f2..0000000 --- a/tests/Makefile.empty +++ /dev/null @@ -1 +0,0 @@ -empty_target: diff --git a/tests/Makefile.test4 b/tests/Makefile.test4 deleted file mode 100644 index 4da97dd..0000000 --- a/tests/Makefile.test4 +++ /dev/null @@ -1,7 +0,0 @@ -rule1: - echo Toto - echo Tata - echo Tutu - -rule2: - @echo Toto encore diff --git a/tests/Makefile.vars b/tests/Makefile.vars deleted file mode 100644 index b5ce417..0000000 --- a/tests/Makefile.vars +++ /dev/null @@ -1,4 +0,0 @@ -V=2 - -main: - echo $V