From e106a4ca663d3e7493871c47063a529158ce00f4 Mon Sep 17 00:00:00 2001 From: Guillem George Date: Sat, 25 Oct 2025 21:56:43 +0200 Subject: [PATCH] backup --- minimake/src/hash_map/hash.c | 27 --- minimake/src/hash_map/hash_map.c | 277 +++++++++++++++++------------- minimake/src/lines/lines.c | 68 ++++++++ minimake/src/lines/lines.h | 25 +++ minimake/src/list/list.h | 10 +- minimake/src/list/list_advanced.c | 4 +- minimake/src/list/list_basic.c | 42 ++--- minimake/src/list/list_ultimate.c | 2 +- minimake/src/list_void/list.c | 46 ----- minimake/src/list_void/list.h | 31 ---- minimake/src/minimake.c | 136 ++++++++------- minimake/src/minimake.h | 15 +- 12 files changed, 355 insertions(+), 328 deletions(-) delete mode 100644 minimake/src/hash_map/hash.c create mode 100644 minimake/src/lines/lines.c create mode 100644 minimake/src/lines/lines.h delete mode 100644 minimake/src/list_void/list.c delete mode 100644 minimake/src/list_void/list.h diff --git a/minimake/src/hash_map/hash.c b/minimake/src/hash_map/hash.c deleted file mode 100644 index 247893b..0000000 --- a/minimake/src/hash_map/hash.c +++ /dev/null @@ -1,27 +0,0 @@ -#include -#include -#include -#include - -#include "hash_map.h" - -/* -** Hash the key using FNV-1a 32 bits hash algorithm. -*/ -size_t hash(const char *key) -{ - if (!key) - return 0; - - uint32_t hash = 2166136261; // FNV offset basis - uint32_t prime = 16777619; // FNV prime - - while (*key) - { - hash ^= *key; - hash *= prime; - key++; - } - - return hash; -} diff --git a/minimake/src/hash_map/hash_map.c b/minimake/src/hash_map/hash_map.c index 5c57115..d1609d0 100644 --- a/minimake/src/hash_map/hash_map.c +++ b/minimake/src/hash_map/hash_map.c @@ -1,133 +1,172 @@ #include "hash_map.h" #include +#include #include #include #include -struct hash_map *hashMapInit(size_t size) { - struct pair_list **data = calloc(size, sizeof(struct pair_list)); - struct hash_map *map = malloc(sizeof(struct hash_map)); - map->data = data; - map->size = size; - return map; +/* +** Hash the key using FNV-1a 32 bits hash algorithm. +*/ +size_t hash(const char *key) +{ + if (!key) + return 0; + + uint32_t hash = 2166136261; // FNV offset basis + uint32_t prime = 16777619; // FNV prime + + while (*key) + { + hash ^= *key; + hash *= prime; + key++; + } + + return hash; +} + +struct hash_map *hashMapInit(size_t size) +{ + struct pair_list **data = calloc(size, sizeof(struct pair_list)); + struct hash_map *map = malloc(sizeof(struct hash_map)); + map->data = data; + map->size = size; + return map; } bool hashMapInsert(struct hash_map *hash_map, const char *key, char *value, - bool *updated) { - if (hash_map == NULL || hash_map->data == NULL || hash_map->size == 0) { + bool *updated) +{ + if (hash_map == NULL || hash_map->data == NULL || hash_map->size == 0) + { + if (updated) + *updated = false; + return false; + } + + // Insert into hashmap (head) + + size_t entry_hash = hash(key) % hash_map->size; + // Search if key is already present + struct pair_list *elt = hash_map->data[entry_hash]; + while (elt != NULL) + { + if (strcmp(elt->key, key) == 0) + { + elt->value = value; + if (updated) + *updated = true; + return true; + } + elt = elt->next; + } + + // Create entry + struct pair_list *new_entry = malloc(sizeof(struct pair_list)); + if (new_entry == NULL) + return false; + new_entry->key = key; + new_entry->value = value; + + new_entry->next = hash_map->data[entry_hash]; + hash_map->data[entry_hash] = new_entry; + if (updated) - *updated = false; - return false; - } + *updated = false; - // Insert into hashmap (head) - - size_t entry_hash = hash(key) % hash_map->size; - // Search if key is already present - struct pair_list *elt = hash_map->data[entry_hash]; - while (elt != NULL) { - if (strcmp(elt->key, key) == 0) { - elt->value = value; - if (updated) - *updated = true; - return true; - } - elt = elt->next; - } - - // Create entry - struct pair_list *new_entry = malloc(sizeof(struct pair_list)); - if (new_entry == NULL) - return false; - new_entry->key = key; - new_entry->value = value; - - new_entry->next = hash_map->data[entry_hash]; - hash_map->data[entry_hash] = new_entry; - - if (updated) - *updated = false; - - return true; -} - -void hashMapFree(struct hash_map *hash_map) { - if (hash_map == NULL) - return; - if (hash_map->data == NULL) - return; - - for (size_t i = 0; i < hash_map->size; i++) { - struct pair_list *entry = hash_map->data[i]; - while (entry != NULL) { - struct pair_list *next = entry->next; - free(entry); - entry = next; - } - } - free(hash_map->data); - free(hash_map); -} - -void hashMapDump(struct hash_map *hash_map) { - for (size_t i = 0; i < hash_map->size; i++) { - struct pair_list *entry = hash_map->data[i]; - bool is_null = true; - if (entry != NULL) { - is_null = false; - printf("%s: %s", entry->key, entry->value); - entry = entry->next; - } - while (entry != NULL) { - printf(", %s: %s", entry->key, entry->value); - entry = entry->next; - } - if (!is_null) - putchar('\n'); - } -} - -const char *hashMapGet(const struct hash_map *hash_map, const char *key) { - if (hash_map == NULL || hash_map->data == NULL || hash_map->size == 0) - return NULL; - - size_t entry_hash = hash(key) % hash_map->size; - struct pair_list *entry = hash_map->data[entry_hash]; - while (entry != NULL && strcmp(entry->key, key) != 0) { - entry = entry->next; - } - if (entry == NULL) - return NULL; - - return entry->value; -} - -bool hashMapRemove(struct hash_map *hash_map, const char *key) { - if (hash_map == NULL || hash_map->size == 0 || hash_map->data == NULL) - return false; - - size_t entry_hash = hash(key) % hash_map->size; - struct pair_list *entry = hash_map->data[entry_hash]; - - if (entry == NULL) - return false; - if (strcmp(entry->key, key) == 0) { - hash_map->data[entry_hash] = entry->next; - free(entry); return true; - } - - if (entry->next == NULL) - return false; - while (strcmp(entry->next->key, key) != 0) { - entry = entry->next; - if (entry->next == NULL) - return false; - } - - struct pair_list *elt_to_free = entry->next; - entry->next = entry->next->next; - free(elt_to_free); - return true; +} + +void hashMapFree(struct hash_map *hash_map) +{ + if (hash_map == NULL) + return; + if (hash_map->data == NULL) + return; + + for (size_t i = 0; i < hash_map->size; i++) + { + struct pair_list *entry = hash_map->data[i]; + while (entry != NULL) + { + struct pair_list *next = entry->next; + free(entry); + entry = next; + } + } + free(hash_map->data); + free(hash_map); +} + +void hashMapDump(struct hash_map *hash_map) +{ + for (size_t i = 0; i < hash_map->size; i++) + { + struct pair_list *entry = hash_map->data[i]; + bool is_null = true; + if (entry != NULL) + { + is_null = false; + printf("%s: %s", entry->key, entry->value); + entry = entry->next; + } + while (entry != NULL) + { + printf(", %s: %s", entry->key, entry->value); + entry = entry->next; + } + if (!is_null) + putchar('\n'); + } +} + +const char *hashMapGet(const struct hash_map *hash_map, const char *key) +{ + if (hash_map == NULL || hash_map->data == NULL || hash_map->size == 0) + return NULL; + + size_t entry_hash = hash(key) % hash_map->size; + struct pair_list *entry = hash_map->data[entry_hash]; + while (entry != NULL && strcmp(entry->key, key) != 0) + { + entry = entry->next; + } + if (entry == NULL) + return NULL; + + return entry->value; +} + +bool hashMapRemove(struct hash_map *hash_map, const char *key) +{ + if (hash_map == NULL || hash_map->size == 0 || hash_map->data == NULL) + return false; + + size_t entry_hash = hash(key) % hash_map->size; + struct pair_list *entry = hash_map->data[entry_hash]; + + if (entry == NULL) + return false; + if (strcmp(entry->key, key) == 0) + { + hash_map->data[entry_hash] = entry->next; + free(entry); + return true; + } + + if (entry->next == NULL) + return false; + while (strcmp(entry->next->key, key) != 0) + { + entry = entry->next; + if (entry->next == NULL) + return false; + } + + struct pair_list *elt_to_free = entry->next; + entry->next = entry->next->next; + free(elt_to_free); + return true; } diff --git a/minimake/src/lines/lines.c b/minimake/src/lines/lines.c new file mode 100644 index 0000000..4201eea --- /dev/null +++ b/minimake/src/lines/lines.c @@ -0,0 +1,68 @@ +#include "lines.h" + +#include +#include +#include +#include +#include + +// Helps to match a string (excludes blanks and special characters) +int isChar(char c) +{ + return c != '\0' && !isblank(c) && c != ':' && c != '=' && c != '#'; +} + +int skipBlanks(char *buf, size_t buf_len) +{ + size_t i = 0; + while (i < buf_len && isblank(buf[i])) + i++; + return i; +} + +// Returns 1 if line is blank +int isBlankLine(struct line *l) +{ + size_t line_size = l->length; + char *buf = l->buffer; + + size_t i = 0; + while (i < line_size) + { + if (!isblank(buf[i])) + return 0; + if (buf[i] == '#') // Comments + return 1; + i++; + } + return 1; +} + +// 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 +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 && isChar(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; +} diff --git a/minimake/src/lines/lines.h b/minimake/src/lines/lines.h new file mode 100644 index 0000000..1eed08c --- /dev/null +++ b/minimake/src/lines/lines.h @@ -0,0 +1,25 @@ +#ifndef LINES_H +#define LINES_H + +#define STRING_BUFFER_SIZE 32 + +#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 + size_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); +char *readWord(char *buf, size_t buf_len, size_t *read_chars); + +#endif // LINES_H diff --git a/minimake/src/list/list.h b/minimake/src/list/list.h index 03a03ca..a8f9b10 100644 --- a/minimake/src/list/list.h +++ b/minimake/src/list/list.h @@ -5,7 +5,7 @@ struct list { - int 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, int value); +struct list *list_prepend(struct list *list, void* value); /* ** Return the lenght of the list. @@ -38,7 +38,7 @@ void list_destroy(struct list *list); ** Return `NULL` if an error occured. */ // START PROTO list_append -struct list *list_append(struct list *list, int value); +struct list *list_append(struct list *list, void* value); // END PROTO list_append /* @@ -48,7 +48,7 @@ struct list *list_append(struct list *list, int value); ** Return `NULL` if an error occured. */ // START PROTO list_insert -struct list *list_insert(struct list *list, int value, size_t index); +struct list *list_insert(struct list *list, void* value, size_t index); // END PROTO list_insert /* @@ -64,7 +64,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, int value); +int list_find(struct list *list, void* value); // END PROTO list_find /* diff --git a/minimake/src/list/list_advanced.c b/minimake/src/list/list_advanced.c index 75b401a..78402d1 100644 --- a/minimake/src/list/list_advanced.c +++ b/minimake/src/list/list_advanced.c @@ -4,7 +4,7 @@ #include "list.h" -struct list *list_insert(struct list *list, int value, size_t index) +struct list *list_insert(struct list *list, void *value, size_t index) { if (list == NULL || index == 0) { @@ -65,7 +65,7 @@ struct list *list_remove(struct list *list, size_t index) return list; } -int list_find(struct list *list, int value) +int list_find(struct list *list, void *value) { if (list == NULL) { diff --git a/minimake/src/list/list_basic.c b/minimake/src/list/list_basic.c index 094924b..a0672bb 100644 --- a/minimake/src/list/list_basic.c +++ b/minimake/src/list/list_basic.c @@ -3,7 +3,7 @@ #include "list.h" -struct list *list_prepend(struct list *list, int value) +struct list *list_prepend(struct list *list, void *value) { struct list *new_elt = malloc(sizeof(struct list)); if (new_elt == NULL) @@ -27,26 +27,26 @@ size_t list_length(struct list *list) return len; } -void list_print(struct list *list) -{ - if (list == NULL) - { - return; - } +// void list_print(struct list *list) +// { +// if (list == NULL) +// { +// return; +// } - while (list != NULL) - { - if (list->next != NULL) - { - printf("%d ", list->data); - } - else - { - printf("%d\n", list->data); - } - list = list->next; - } -} +// while (list != NULL) +// { +// if (list->next != NULL) +// { +// printf("%p ", list->data); +// } +// else +// { +// printf("%p\n", list->data); +// } +// list = list->next; +// } +// } void list_destroy(struct list *list) { @@ -60,7 +60,7 @@ void list_destroy(struct list *list) } } -struct list *list_append(struct list *list, int value) +struct list *list_append(struct list *list, void *value) { if (list == NULL) { diff --git a/minimake/src/list/list_ultimate.c b/minimake/src/list/list_ultimate.c index 6207398..d4a57f3 100644 --- a/minimake/src/list/list_ultimate.c +++ b/minimake/src/list/list_ultimate.c @@ -5,7 +5,7 @@ void swap_next(struct list *elt) { - int c = elt->next->data; + void *c = elt->next->data; elt->next->data = elt->data; elt->data = c; } diff --git a/minimake/src/list_void/list.c b/minimake/src/list_void/list.c deleted file mode 100644 index 24b462e..0000000 --- a/minimake/src/list_void/list.c +++ /dev/null @@ -1,46 +0,0 @@ -#include "list.h" - -#include -#include - -struct list *list_prepend(struct list *list, const void *value, - size_t data_size) -{ - struct list *new_node = malloc(sizeof(struct list)); - if (new_node == NULL) - { - return NULL; - } - void *node_data = malloc(data_size); - if (node_data == NULL) - { - return NULL; - } - new_node->data = node_data; - memcpy(node_data, value, data_size); - new_node->next = list; - return new_node; -} - -size_t list_length(struct list *list) -{ - size_t res = 0; - while (list != NULL) - { - list = list->next; - res++; - } - return res; -} - -void list_destroy(struct list *list) -{ - struct list *next; - while (list != NULL) - { - next = list->next; - free(list->data); - free(list); - list = next; - } -} diff --git a/minimake/src/list_void/list.h b/minimake/src/list_void/list.h deleted file mode 100644 index b129adc..0000000 --- a/minimake/src/list_void/list.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef LIST_H -#define LIST_H - -#include - -struct list -{ - void *data; - struct list *next; -}; - -/* -** Insert a node containing `value` at the beginning of the list. -** Return `NULL` if an error occurred. -*/ -struct list *list_prepend(struct list *list, const void *value, - size_t data_size); - -/* -** Return the length of the list. -** Return `0` if the list is empty. -*/ -size_t list_length(struct list *list); - -/* -** Release the memory used by the list. -** Does nothing if `list` is `NULL`. -*/ -void list_destroy(struct list *list); - -#endif /* ! LIST_H */ diff --git a/minimake/src/minimake.c b/minimake/src/minimake.c index 8db5234..e922791 100644 --- a/minimake/src/minimake.c +++ b/minimake/src/minimake.c @@ -1,18 +1,16 @@ -#include "list/list.h" #define _POSIX_C_SOURCE 200809L -// Default values -#define BUFFER_SIZE 1024 -#define STRING_BUFFER_SIZE 32 -#define HASHMAP_SIZE 32 +#include "minimake.h" #include #include #include #include +#include #include "hash_map/hash_map.h" -#include "minimake.h" +#include "lines/lines.h" +#include "list/list.h" // Static variables struct hash_map *variables = NULL; @@ -20,49 +18,6 @@ struct hash_map *rules = NULL; // ==== Parsing ==== -// Helps to match a string (excludes blanks and special characters) -static int isChar(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 && isChar(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; -} - -static int skipBlanks(char *buf, size_t buf_len) -{ - size_t i = 0; - while (i < buf_len && isblank(buf[i])) - i++; - return i; -} - // Registers a new variable and returns its pointer // WARNING Allocates memory on the heap, // the variables hashmap should be freed before exit @@ -115,8 +70,11 @@ static struct list *readDependencies(char *buf, size_t buf_size) res = list_append(res, dep_name); i += skipped_chars; - // TODO handle comments here + // Comments + if (buf[i] == '#') + return res; + // Unknown chars if (!isChar(buf[i]) && !isblank(buf[i]) && buf[i] != '\0') errx(2, "Unexpected character '%c'", buf[i]); } @@ -124,27 +82,70 @@ static struct list *readDependencies(char *buf, size_t buf_size) return res; } -static int isBlankLine(struct line *l) +// Searches the following lines for recipes and returns them in the form of a +// list +// WARNING begins to read the following line +static struct list *readRecipe(struct line *l) { - size_t line_size = l->length; + FILE *stream = l->file_stream; char *buf = l->buffer; + size_t buf_size = BUFFER_SIZE; - size_t i = 0; - while (i < line_size) + struct list *res = NULL; + + // Getline + while ((l->length = getline(&buf, &buf_size, stream))) { - if (!isblank(buf[i])) - return 0; - if (buf[i] == '#') // Comment - return 1; + l->number++; + + // Skip blank lines and comments + if (isBlankLine(l)) + continue; + else if (buf[0] != '\t') // Not a recipe + { + l->buffer = buf; // Update buffer ! + return res; + } + else // Add recipe to list + { + char *command = strdup(buf + 1); + if (command == NULL) + errx(1, "Internal error: couldn't duplicate string (%lu:1)", + l->number); + + res = list_append(res, command); + } } - return 1; + + l->buffer = buf; + return res; } -static struct list *readRecipe() +// Reads the value after a variable declaration +static char *readValue(char *buf, size_t buf_size) { - // Getline - // Skip blank lines and comments - // + size_t i = 0; + size_t str_buf_size = STRING_BUFFER_SIZE; + char *str_buf = malloc(sizeof(char) * str_buf_size); + + while (i < buf_size && buf[i] != '\0' && 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'; + + return str_buf; } // Takes a buffer containing the line to parse and it length @@ -175,14 +176,16 @@ static void parseLine(struct line *current_line) // Variable case '=': new_variable = createVariable(name); - // Read value + new_variable->value = readValue(buf + i, line_size); break; // Rule case ':': new_rule = createRule(name); - // Read dependencies - // Read recipe + new_rule->dependencies = readDependencies(buf + i, line_size); + new_rule->recipe = readRecipe(current_line); + parseLine(current_line); + // TODO: check for loooooops break; // Blank line @@ -226,6 +229,7 @@ void makeParse(char *path) ssize_t nread; struct line current_line; current_line.number = 1; + current_line.file_stream = stream; while ((nread = getline(&buf, &buf_size, stream)) != -1) { if (nread == -1) diff --git a/minimake/src/minimake.h b/minimake/src/minimake.h index 07a560e..b04155e 100644 --- a/minimake/src/minimake.h +++ b/minimake/src/minimake.h @@ -1,6 +1,11 @@ #ifndef MINIMAKE_H #define MINIMAKE_H +#define BUFFER_SIZE 1024 +#define HASHMAP_SIZE 32 + +#include + #include "list/list.h" // Holds variable information @@ -20,16 +25,6 @@ struct rule struct list *recipe; }; -// Holds line information -// Exists only because of EPITA's annoying 4 parameters limit -// WARNING buffer must be freed after use -struct line -{ - char* buffer; - size_t number; - size_t length; -}; - int make(char *path, int flags); #endif // ! MINIMAKE_H