From 3e40eeff2d87d2b504c37046353c161b9aaa7318 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sat, 19 Nov 2022 23:32:51 +0100 Subject: [PATCH 1/5] feat(package): started rewrite in C --- .editorconfig | 2 +- .gitignore | 2 +- src/package/c/dynarray.c | 43 +++++++++++++++++ src/package/c/dynarray.h | 14 ++++++ src/package/c/package.c | 94 ++++++++++++++++++++++++++++++++++++ src/package/c/package.h | 25 ++++++++++ src/package/c/package_info.c | 46 ++++++++++++++++++ src/package/c/package_info.h | 39 +++++++++++++++ 8 files changed, 263 insertions(+), 2 deletions(-) create mode 100644 src/package/c/dynarray.c create mode 100644 src/package/c/dynarray.h create mode 100644 src/package/c/package.c create mode 100644 src/package/c/package.h create mode 100644 src/package/c/package_info.c create mode 100644 src/package/c/package_info.h diff --git a/.editorconfig b/.editorconfig index e23a3c7..e9bac80 100644 --- a/.editorconfig +++ b/.editorconfig @@ -5,6 +5,6 @@ root = true end_of_line = lf insert_final_newline = true -[*.v] +[*.{v,c,h}] # vfmt wants it :( indent_style = tab diff --git a/.gitignore b/.gitignore index aaec9ef..daeb3d3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -*.c +vieter.c /data/ # Build artifacts diff --git a/src/package/c/dynarray.c b/src/package/c/dynarray.c new file mode 100644 index 0000000..a70feaf --- /dev/null +++ b/src/package/c/dynarray.c @@ -0,0 +1,43 @@ +#include "dynarray.h" + +struct dyn_array { + char **array; + size_t size; + size_t capacity; +}; + +DynArray *dynarray_init(size_t initial_capacity) { + DynArray *da = malloc(sizeof(DynArray)); + da->size = 0; + da->capacity = initial_capacity; + + return da; +} + +void dynarray_add(DynArray *da, const char *s) { + // An empty dynarray does not have an allocated internal array yet + if (da->size == 0) { + da->array = malloc(sizeof(char*) * da->capacity); + } + // Double array size if it's full + else if (da->size == da->capacity) { + da->array = realloc(da->array, da->capacity * 2); + da->capacity *= 2; + } + + da->array[da->size] = strdup(s); + da->size++; +} + +void dynarray_free(DynArray **ptp) { + DynArray *da = *ptp; + + for (size_t i = 0; i < da->size; i++) { + free(da->array[i]); + } + + free(da->array); + free(da); + + *ptp = NULL; +} diff --git a/src/package/c/dynarray.h b/src/package/c/dynarray.h new file mode 100644 index 0000000..73f5a0a --- /dev/null +++ b/src/package/c/dynarray.h @@ -0,0 +1,14 @@ +#ifndef VIETER_DYNARRAY +#define VIETER_DYNARRAY + +#include +#include + +typedef struct dyn_array DynArray; + +DynArray *dynarray_init(size_t initial_capacity); +void dynarray_add(DynArray *da, const char * s); +char ** dynarray_get_array(DynArray *da); +void dynarray_free(DynArray **ptp); + +#endif diff --git a/src/package/c/package.c b/src/package/c/package.c new file mode 100644 index 0000000..a248c92 --- /dev/null +++ b/src/package/c/package.c @@ -0,0 +1,94 @@ +#include "package.h" + +static char *ignored_names[5] = { + ".BUILDINFO", + ".INSTALL", + ".MTREE", + ".PKGINFO", + ".CHANGELOG" +}; +static int ignored_words_len = sizeof(ignored_names) / sizeof(char *); + +inline Pkg *package_init() { + return calloc(sizeof(PkgInfo), 1); +} + +Pkg *package_read_archive(const char *pkg_path) { + struct archive *a = archive_read_new(); + struct archive_entry *entry = archive_entry_new(); + + // These three are the most commonly used compression methods + archive_read_support_filter_zstd(a); + archive_read_support_filter_gzip(a); + archive_read_support_filter_xz(a); + + // Contents should always be a tarball + archive_read_support_format_tar(a); + + // TODO where does this 10240 come from? + int r = archive_read_open_filename(a, pkg_path, 10240); + + // Exit early if we weren't able to successfully open the archive for reading + if (r != ARCHIVE_OK) { + return NULL; + } + + int compression_code = archive_filter_code(a, 0); + const char *path_name; + + PkgInfo *pkg_info; + DynArray *files = dynarray_init(16); + + while (archive_read_next_header(a, &entry) == ARCHIVE_OK) { + path_name = archive_entry_pathname(entry); + + bool ignore = false; + + for (size_t i = 0; i < ignored_words_len; i++) { + if (strcmp(path_name, ignored_names[i]) == 0) { + ignore = true; + break; + } + } + + if (!ignore) { + dynarray_add(files, path_name); + } + + if (strcmp(path_name, ".PKGINFO") == 0) { + // Read data of file into memory buffer + int size = archive_entry_size(entry); + char *buf = malloc(size); + archive_read_data(a, buf, size); + + // Parse package info string into a struct + pkg_info = package_info_init(); + package_info_parse(pkg_info, buf); + + free(buf); + } else { + archive_read_data_skip(a); + } + } + + // Get size of file + struct stat stats; + + if (stat(pkg_path, &stats) != 0) { + return NULL; + } + + pkg_info->csize = stats.st_size; + + archive_read_free(a); + archive_entry_free(entry); + + // Create final return value + Pkg *pkg = package_init(); + pkg->path = strdup(pkg_path); + pkg->info = pkg_info; + pkg->files = files; + pkg->compression = compression_code; + + return pkg; +} diff --git a/src/package/c/package.h b/src/package/c/package.h new file mode 100644 index 0000000..76ec5ac --- /dev/null +++ b/src/package/c/package.h @@ -0,0 +1,25 @@ +#ifndef VIETER_PACKAGE +#define VIETER_PACKAGE + +#include +#include +#include +#include + +#include "archive.h" +#include "archive_entry.h" + +#include "package_info.h" +#include "dynarray.h" + +typedef struct pkg { + char *path; + PkgInfo *info; + DynArray *files; + int compression; +} Pkg; + +Pkg *package_read_archive(const char *pkg_path); +void package_free(Pkg ** ptp); + +#endif diff --git a/src/package/c/package_info.c b/src/package/c/package_info.c new file mode 100644 index 0000000..a8959ff --- /dev/null +++ b/src/package/c/package_info.c @@ -0,0 +1,46 @@ +#include "package_info.h" + +PkgInfo *package_info_init() { + PkgInfo *pkg_info = calloc(1, sizeof(PkgInfo)); + + pkg_info->groups = dynarray_init(4); + pkg_info->licenses = dynarray_init(4); + pkg_info->replaces = dynarray_init(4); + pkg_info->depends = dynarray_init(4); + pkg_info->conflicts = dynarray_init(4); + pkg_info->provides = dynarray_init(4); + pkg_info->optdepends = dynarray_init(4); + pkg_info->makedepends = dynarray_init(4); + pkg_info->checkdepends = dynarray_init(4); + + return pkg_info; +} + +void package_info_free(PkgInfo **ptp) { + PkgInfo *pkg_info = *ptp; + + FREE_STRING(pkg_info->name); + FREE_STRING(pkg_info->base); + FREE_STRING(pkg_info->version); + FREE_STRING(pkg_info->description); + FREE_STRING(pkg_info->url); + FREE_STRING(pkg_info->arch); + FREE_STRING(pkg_info->packager); + FREE_STRING(pkg_info->pgpsig); + + dynarray_free(&pkg_info->groups); + dynarray_free(&pkg_info->licenses); + dynarray_free(&pkg_info->replaces); + dynarray_free(&pkg_info->depends); + dynarray_free(&pkg_info->conflicts); + dynarray_free(&pkg_info->provides); + dynarray_free(&pkg_info->optdepends); + dynarray_free(&pkg_info->makedepends); + dynarray_free(&pkg_info->checkdepends); + + *ptp = NULL; +} + +void package_info_parse(PkgInfo *pkg_info, const char *pkg_info_str) { + +} diff --git a/src/package/c/package_info.h b/src/package/c/package_info.h new file mode 100644 index 0000000..7e16f4b --- /dev/null +++ b/src/package/c/package_info.h @@ -0,0 +1,39 @@ +#ifndef VIETER_PACKAGE_INFO +#define VIETER_PACKAGE_INFO + +#define FREE_STRING(sp) if (sp != NULL) free(sp) + +#include + +#include "dynarray.h" + +typedef struct pkg_info { + char *name; + char *base; + char *version; + char *description; + int64_t size; + int64_t csize; + char *url; + char *arch; + int64_t build_date; + char *packager; + char *pgpsig; + int64_t pgpsigsize; + + DynArray *groups; + DynArray *licenses; + DynArray *replaces; + DynArray *depends; + DynArray *conflicts; + DynArray *provides; + DynArray *optdepends; + DynArray *makedepends; + DynArray *checkdepends; +} PkgInfo; + +PkgInfo *package_info_init(); +void package_info_parse(PkgInfo *pkg_info, const char *pkg_info_str); +void package_info_free(PkgInfo **ptp); + +#endif From 32ff1206000f4371fde32597be72d6ab5cf964e6 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sat, 19 Nov 2022 23:53:42 +0100 Subject: [PATCH 2/5] chore: figure out how to compile everything with C --- Makefile | 3 ++- src/package/c/package.c | 2 +- src/package/package.c.v | 13 +++++++++++++ src/package/v.mod | 3 +++ src/{package => util}/c/dynarray.c | 0 src/{package => util}/c/dynarray.h | 0 src/util/util.c.v | 7 +++++++ src/util/v.mod | 3 +++ 8 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 src/package/package.c.v create mode 100644 src/package/v.mod rename src/{package => util}/c/dynarray.c (100%) rename src/{package => util}/c/dynarray.h (100%) create mode 100644 src/util/util.c.v create mode 100644 src/util/v.mod diff --git a/Makefile b/Makefile index e716807..5927d41 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,8 @@ SRC_DIR := src SOURCES != find '$(SRC_DIR)' -iname '*.v' V_PATH ?= v -V := $(V_PATH) -showcc -gc boehm -W -d use_openssl +# We need to use GCC because TCC doesn't like the way we use C bindings +V := $(V_PATH) -showcc -gc boehm -W -d use_openssl -cc gcc all: vieter diff --git a/src/package/c/package.c b/src/package/c/package.c index a248c92..d2e3c94 100644 --- a/src/package/c/package.c +++ b/src/package/c/package.c @@ -9,7 +9,7 @@ static char *ignored_names[5] = { }; static int ignored_words_len = sizeof(ignored_names) / sizeof(char *); -inline Pkg *package_init() { +Pkg *package_init() { return calloc(sizeof(PkgInfo), 1); } diff --git a/src/package/package.c.v b/src/package/package.c.v new file mode 100644 index 0000000..a9c4784 --- /dev/null +++ b/src/package/package.c.v @@ -0,0 +1,13 @@ +module package + +#flag -I @VMODROOT/c + +// We need to specify *every* C file here. Otherwise, Vieter doesn't compile. +#flag @VMODROOT/c/package.o +#flag @VMODROOT/c/package_info.o + +#include "package.h" + +struct C.Pkg{} + +fn C.package_read_archive(pkg_path &char) &C.pkg diff --git a/src/package/v.mod b/src/package/v.mod new file mode 100644 index 0000000..dc06e78 --- /dev/null +++ b/src/package/v.mod @@ -0,0 +1,3 @@ +Module{ + name: 'package' +} diff --git a/src/package/c/dynarray.c b/src/util/c/dynarray.c similarity index 100% rename from src/package/c/dynarray.c rename to src/util/c/dynarray.c diff --git a/src/package/c/dynarray.h b/src/util/c/dynarray.h similarity index 100% rename from src/package/c/dynarray.h rename to src/util/c/dynarray.h diff --git a/src/util/util.c.v b/src/util/util.c.v new file mode 100644 index 0000000..997a18d --- /dev/null +++ b/src/util/util.c.v @@ -0,0 +1,7 @@ +module util + +#flag -I @VMODROOT/c + +// This makes the V compiler include this object file when linking, allowing +// all other C parts of the codebase to use it as well. +#flag @VMODROOT/c/dynarray.o diff --git a/src/util/v.mod b/src/util/v.mod new file mode 100644 index 0000000..39a57af --- /dev/null +++ b/src/util/v.mod @@ -0,0 +1,3 @@ +Module{ + name: 'util' +} From 65a756da48942f4052ad2c8f515b82115f7870ff Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Sun, 20 Nov 2022 16:32:46 +0100 Subject: [PATCH 3/5] refactor: moved dynarray back to package model --- src/{util => package}/c/dynarray.c | 0 src/{util => package}/c/dynarray.h | 0 src/package/package.c.v | 1 + src/util/util.c.v | 7 ------- src/util/v.mod | 3 --- 5 files changed, 1 insertion(+), 10 deletions(-) rename src/{util => package}/c/dynarray.c (100%) rename src/{util => package}/c/dynarray.h (100%) delete mode 100644 src/util/util.c.v delete mode 100644 src/util/v.mod diff --git a/src/util/c/dynarray.c b/src/package/c/dynarray.c similarity index 100% rename from src/util/c/dynarray.c rename to src/package/c/dynarray.c diff --git a/src/util/c/dynarray.h b/src/package/c/dynarray.h similarity index 100% rename from src/util/c/dynarray.h rename to src/package/c/dynarray.h diff --git a/src/package/package.c.v b/src/package/package.c.v index a9c4784..25272f8 100644 --- a/src/package/package.c.v +++ b/src/package/package.c.v @@ -5,6 +5,7 @@ module package // We need to specify *every* C file here. Otherwise, Vieter doesn't compile. #flag @VMODROOT/c/package.o #flag @VMODROOT/c/package_info.o +#flag @VMODROOT/c/dynarray.o #include "package.h" diff --git a/src/util/util.c.v b/src/util/util.c.v deleted file mode 100644 index 997a18d..0000000 --- a/src/util/util.c.v +++ /dev/null @@ -1,7 +0,0 @@ -module util - -#flag -I @VMODROOT/c - -// This makes the V compiler include this object file when linking, allowing -// all other C parts of the codebase to use it as well. -#flag @VMODROOT/c/dynarray.o diff --git a/src/util/v.mod b/src/util/v.mod deleted file mode 100644 index 39a57af..0000000 --- a/src/util/v.mod +++ /dev/null @@ -1,3 +0,0 @@ -Module{ - name: 'util' -} From 3c0422b998b73227f4eed3f5d6f4390bd2c827bc Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Sun, 20 Nov 2022 18:00:13 +0100 Subject: [PATCH 4/5] feat(package): first version of parse function in C --- src/package/c/package_info.c | 106 ++++++++++++++++++++++++++++++++++- src/package/c/package_info.h | 2 +- 2 files changed, 106 insertions(+), 2 deletions(-) diff --git a/src/package/c/package_info.c b/src/package/c/package_info.c index a8959ff..79d8720 100644 --- a/src/package/c/package_info.c +++ b/src/package/c/package_info.c @@ -1,3 +1,5 @@ +#include + #include "package_info.h" PkgInfo *package_info_init() { @@ -41,6 +43,108 @@ void package_info_free(PkgInfo **ptp) { *ptp = NULL; } -void package_info_parse(PkgInfo *pkg_info, const char *pkg_info_str) { +/** + * Advance the pointer until all spaces are skipped. + */ +static inline char *trim_spaces_front(char *ptr) { + while (ptr[0] == ' ') { + ptr++; + } + return ptr; +} + +/** + * Given a string pointer in the middle of a string, move over all spaces in the + * given direction. The final space is replaced with a NULL-byte. + */ +static inline void trim_spaces_back(char *ptr) { + if (ptr[0] != ' ') { + return; + } + + while (ptr[-1] == ' ') { + ptr--; + } + + ptr[0] = '\0'; +} + +#define PKG_INFO_STRING(key, field) if (strcmp(key_ptr, key) == 0) { pkg_info->field = strdup(value_ptr); goto advance; } +#define PKG_INFO_INT(key, field) if (strcmp(key_ptr, key) == 0) { pkg_info->field = atoi(value_ptr); goto advance; } +#define PKG_INFO_ARRAY(key, field) if (strcmp(key_ptr, key) == 0) { dynarray_add(pkg_info->field, value_ptr); goto advance; } + +int package_info_parse(PkgInfo *pkg_info, char *pkg_info_str) { + char *offset_ptr, *equals_ptr, *key_ptr, *value_ptr; + + bool end = false; + + // Iterate over all lines in file + while (!end) { + // This pointer will always point to the final character of the + // current line, be it the position of a newline or the NULL byte at + // the end of the entire string + offset_ptr = strchr(pkg_info_str, '\n'); + + // We replace the newline with a NULL byte. Now we know the line runs + // until the next NULL byte. + if (offset_ptr != NULL) { + offset_ptr[0] = '\0'; + } else { + // Advance pointer to the NULL byte of the string + offset_ptr = pkg_info_str + 1; + + while (*offset_ptr != '\0') { + offset_ptr++; + } + + end = true; + } + + // Skip comment lines + if (pkg_info_str[0] == '#') { + goto advance; + } + + equals_ptr = strchr(pkg_info_str, '='); + + // If a line doesn't contain an equals sign, the file is invalid + if (equals_ptr == NULL) { + return 1; + } + + // Trim whitespace from key + key_ptr = trim_spaces_front(pkg_info_str); + trim_spaces_back(equals_ptr - 1); + + // Trim spaces from value + value_ptr = trim_spaces_front(equals_ptr + 1); + trim_spaces_back(offset_ptr - 1); + + // Match key + PKG_INFO_STRING("pkgname", name); + PKG_INFO_STRING("pkgbase", base); + PKG_INFO_STRING("pkgver", version); + PKG_INFO_STRING("pkgdesc", description); + PKG_INFO_INT("size", size); + PKG_INFO_STRING("url", url); + PKG_INFO_STRING("arch", arch); + PKG_INFO_INT("builddate", build_date); + PKG_INFO_STRING("packager", packager); + PKG_INFO_STRING("pgpsig", pgpsig); + PKG_INFO_INT("pgpsigsize", pgpsigsize); + PKG_INFO_ARRAY("group", groups); + PKG_INFO_ARRAY("license", licenses); + PKG_INFO_ARRAY("replaces", replaces); + PKG_INFO_ARRAY("depend", depends); + PKG_INFO_ARRAY("optdepend", optdepends); + PKG_INFO_ARRAY("makedepend", makedepends); + PKG_INFO_ARRAY("checkdepend", checkdepends); + +advance: + pkg_info_str = offset_ptr + 1; + continue; + } + + return 0; } diff --git a/src/package/c/package_info.h b/src/package/c/package_info.h index 7e16f4b..c3df790 100644 --- a/src/package/c/package_info.h +++ b/src/package/c/package_info.h @@ -33,7 +33,7 @@ typedef struct pkg_info { } PkgInfo; PkgInfo *package_info_init(); -void package_info_parse(PkgInfo *pkg_info, const char *pkg_info_str); +int package_info_parse(PkgInfo *pkg_info, char *pkg_info_str); void package_info_free(PkgInfo **ptp); #endif From 640e2914bf42b58faabd6b837f69c1378bd38dd4 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sun, 20 Nov 2022 19:58:25 +0100 Subject: [PATCH 5/5] feat(package.c): some cleanup --- Makefile | 2 +- src/package/c/dynarray.c | 28 ++++++++++++++++------- src/package/c/dynarray.h | 9 ++++++-- src/package/c/package.c | 4 ++++ src/package/c/package.h | 1 + src/package/c/package_info.c | 43 ++++++++++++++---------------------- src/package/c/package_info.h | 2 +- 7 files changed, 50 insertions(+), 39 deletions(-) diff --git a/Makefile b/Makefile index 5927d41..fbcabfe 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ # =====CONFIG===== SRC_DIR := src -SOURCES != find '$(SRC_DIR)' -iname '*.v' +SOURCES != find '$(SRC_DIR)' -type f \( -iname '*.v' -or -iname '*.c' -or -iname '*.h' \) V_PATH ?= v # We need to use GCC because TCC doesn't like the way we use C bindings diff --git a/src/package/c/dynarray.c b/src/package/c/dynarray.c index a70feaf..480c08f 100644 --- a/src/package/c/dynarray.c +++ b/src/package/c/dynarray.c @@ -29,15 +29,27 @@ void dynarray_add(DynArray *da, const char *s) { da->size++; } -void dynarray_free(DynArray **ptp) { - DynArray *da = *ptp; - - for (size_t i = 0; i < da->size; i++) { - free(da->array[i]); +void dynarray_free(DynArray *da) { + if (da == NULL) { + return; } - free(da->array); - free(da); + if (da->array != NULL) { + for (size_t i = 0; i < da->size; i++) { + free(da->array[i]); + } - *ptp = NULL; + free(da->array); + } + + free(da); +} + +char **dynarray_convert(DynArray *da) { + char **array = da->array; + + da->array = NULL; + dynarray_free(da); + + return array; } diff --git a/src/package/c/dynarray.h b/src/package/c/dynarray.h index 73f5a0a..e552ec4 100644 --- a/src/package/c/dynarray.h +++ b/src/package/c/dynarray.h @@ -8,7 +8,12 @@ typedef struct dyn_array DynArray; DynArray *dynarray_init(size_t initial_capacity); void dynarray_add(DynArray *da, const char * s); -char ** dynarray_get_array(DynArray *da); -void dynarray_free(DynArray **ptp); +void dynarray_free(DynArray *da); + +/** + * Convert a DynArray into an array by freeing all its surrounding components + * and returning the underlying array pointer. + */ +char **dynarray_convert(DynArray *da); #endif diff --git a/src/package/c/package.c b/src/package/c/package.c index d2e3c94..a098abb 100644 --- a/src/package/c/package.c +++ b/src/package/c/package.c @@ -92,3 +92,7 @@ Pkg *package_read_archive(const char *pkg_path) { return pkg; } + +char *package_to_description(Pkg *pkg) { + +} diff --git a/src/package/c/package.h b/src/package/c/package.h index 76ec5ac..09e91bd 100644 --- a/src/package/c/package.h +++ b/src/package/c/package.h @@ -21,5 +21,6 @@ typedef struct pkg { Pkg *package_read_archive(const char *pkg_path); void package_free(Pkg ** ptp); +char *package_to_description(Pkg *pkg); #endif diff --git a/src/package/c/package_info.c b/src/package/c/package_info.c index 79d8720..1202485 100644 --- a/src/package/c/package_info.c +++ b/src/package/c/package_info.c @@ -3,24 +3,10 @@ #include "package_info.h" PkgInfo *package_info_init() { - PkgInfo *pkg_info = calloc(1, sizeof(PkgInfo)); - - pkg_info->groups = dynarray_init(4); - pkg_info->licenses = dynarray_init(4); - pkg_info->replaces = dynarray_init(4); - pkg_info->depends = dynarray_init(4); - pkg_info->conflicts = dynarray_init(4); - pkg_info->provides = dynarray_init(4); - pkg_info->optdepends = dynarray_init(4); - pkg_info->makedepends = dynarray_init(4); - pkg_info->checkdepends = dynarray_init(4); - - return pkg_info; + return calloc(1, sizeof(PkgInfo)); } -void package_info_free(PkgInfo **ptp) { - PkgInfo *pkg_info = *ptp; - +void package_info_free(PkgInfo *pkg_info) { FREE_STRING(pkg_info->name); FREE_STRING(pkg_info->base); FREE_STRING(pkg_info->version); @@ -30,17 +16,17 @@ void package_info_free(PkgInfo **ptp) { FREE_STRING(pkg_info->packager); FREE_STRING(pkg_info->pgpsig); - dynarray_free(&pkg_info->groups); - dynarray_free(&pkg_info->licenses); - dynarray_free(&pkg_info->replaces); - dynarray_free(&pkg_info->depends); - dynarray_free(&pkg_info->conflicts); - dynarray_free(&pkg_info->provides); - dynarray_free(&pkg_info->optdepends); - dynarray_free(&pkg_info->makedepends); - dynarray_free(&pkg_info->checkdepends); + dynarray_free(pkg_info->groups); + dynarray_free(pkg_info->licenses); + dynarray_free(pkg_info->replaces); + dynarray_free(pkg_info->depends); + dynarray_free(pkg_info->conflicts); + dynarray_free(pkg_info->provides); + dynarray_free(pkg_info->optdepends); + dynarray_free(pkg_info->makedepends); + dynarray_free(pkg_info->checkdepends); - *ptp = NULL; + free(pkg_info); } /** @@ -72,7 +58,10 @@ static inline void trim_spaces_back(char *ptr) { #define PKG_INFO_STRING(key, field) if (strcmp(key_ptr, key) == 0) { pkg_info->field = strdup(value_ptr); goto advance; } #define PKG_INFO_INT(key, field) if (strcmp(key_ptr, key) == 0) { pkg_info->field = atoi(value_ptr); goto advance; } -#define PKG_INFO_ARRAY(key, field) if (strcmp(key_ptr, key) == 0) { dynarray_add(pkg_info->field, value_ptr); goto advance; } +#define PKG_INFO_ARRAY(key, field) if (strcmp(key_ptr, key) == 0) { \ + if (pkg_info->field == NULL) { pkg_info->field = dynarray_init(4); } \ + dynarray_add(pkg_info->field, value_ptr); goto advance; \ +} int package_info_parse(PkgInfo *pkg_info, char *pkg_info_str) { char *offset_ptr, *equals_ptr, *key_ptr, *value_ptr; diff --git a/src/package/c/package_info.h b/src/package/c/package_info.h index c3df790..d71386e 100644 --- a/src/package/c/package_info.h +++ b/src/package/c/package_info.h @@ -34,6 +34,6 @@ typedef struct pkg_info { PkgInfo *package_info_init(); int package_info_parse(PkgInfo *pkg_info, char *pkg_info_str); -void package_info_free(PkgInfo **ptp); +void package_info_free(PkgInfo *pkg_info); #endif