commit 99e92c6fe137a7bbb2b69efb811b586ade8605d0
parent d8454ec8719d7fa7b234c5452e82867af6a33c06
Author: aabacchus <ben@bvnf.space>
Date: Sat, 22 Apr 2023 18:46:59 +0100
split array functions into array.c
Diffstat:
6 files changed, 125 insertions(+), 95 deletions(-)
diff --git a/src/Makefile b/src/Makefile
@@ -2,7 +2,7 @@
XCFLAGS = $(CFLAGS) -Wall -Wextra -Wshadow -pedantic -D_XOPEN_SOURCE=700 -Og -g
-OBJS = utils.o list.o search.o
+OBJS = utils.o list.o search.o array.o
all: ckiss
@@ -26,8 +26,9 @@ clean:
.PHONY: clean test all
-utils.o: ckiss.h
+utils.o: ckiss.h array.h
test.o: ckiss.h
list.o: ckiss.h
-search.o: ckiss.h
+search.o: ckiss.h array.h
+array.o: ckiss.h array.h
main.o: ckiss.h
diff --git a/src/array.c b/src/array.c
@@ -0,0 +1,74 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "ckiss.h"
+#include "array.h"
+
+size_t
+arr_len(array_t arr) {
+ size_t n = 0;
+ if (arr) {
+ while (*arr != NULL) {
+ arr++;
+ n++;
+ }
+ }
+ return n;
+}
+
+array_t
+arr_append(array_t *arr, char *s, int n, bool dup) {
+ if (n < 0) {
+ n = arr_len(*arr);
+ }
+ array_t tmp = realloc(*arr, sizeof(char *) * (++n + 1));
+ if (tmp == NULL) {
+ free(*arr);
+ die_perror("realloc");
+ }
+ *arr = tmp;
+ (*arr)[n - 1] = dup ? strdup(s) : s;
+ (*arr)[n] = NULL;
+ return *arr;
+}
+
+array_t
+arr_copy(array_t arr) {
+ size_t n = arr_len(arr);
+ array_t s = malloc(sizeof(char *) * (n + 1));
+ if (s == NULL)
+ die_perror("malloc");
+ for (size_t i = 0; i < n; i++)
+ s[i] = strdup(arr[i]);
+ s[n] = NULL;
+ return s;
+}
+
+void
+arr_free(array_t arr) {
+ array_t t = arr;
+ if (t) {
+ while (*t) {
+ free(*t);
+ t++;
+ }
+ free(arr);
+ }
+}
+
+array_t
+split(char *s, char *sep) {
+ if (s == NULL)
+ return NULL;
+
+ array_t res = NULL;
+ char *p = strtok(s, sep);
+ int n = 0;
+
+ while (p) {
+ arr_append(&res, p, n++, true);
+ p = strtok(NULL, sep);
+ }
+
+ return res;
+}
diff --git a/src/array.h b/src/array.h
@@ -0,0 +1,29 @@
+#ifndef _CKISS_ARRAY_H
+#define _CKISS_ARRAY_H
+
+#include <stdbool.h>
+
+/* Array convenience functions. Arrays are lists of strings with a terminating
+ * NULL. */
+
+typedef char ** array_t;
+
+/* Walk an array to find its length, excluding the terminating NULL record. */
+size_t arr_len(array_t arr);
+
+/* Appends to *arr (allocs if NULL). If you don't know the length of arr but it
+ * has a terminating NULL, supply an n < 0. If s should be strdup'd then set dup
+ * to true. */
+array_t arr_append(array_t *arr, char *s, int n, bool dup);
+
+/* Make a deep copy of an array. */
+array_t arr_copy(array_t arr);
+
+/* Free each element of arr and arr. */
+void arr_free(array_t arr);
+
+/* splits s by any delimiters in sep into an array of strings. Each string and
+ * the array must be freed by the caller. */
+array_t split(char *s, char *sep);
+
+#endif
diff --git a/src/ckiss.h b/src/ckiss.h
@@ -7,16 +7,14 @@
#include <stdnoreturn.h>
#include <sys/stat.h>
+#include "array.h"
+
#ifndef noreturn
#define noreturn
#endif
#define KISS_VERSION "0.1.0 (compat 5.6.4)"
-struct cmd {
- char **args;
-};
-
struct env {
bool color;
bool debug;
@@ -53,32 +51,17 @@ noreturn void die_perror(const char *s);
* terminated with a NULL. Returned string must be freed by caller.*/
char *concat(char *s, ...);
-/* Walk an array to find its length, excluding the terminating NULL record. */
-size_t arr_len(char **arr);
-
-/* Appends to *arr (allocs if NULL). If you don't know the length of arr but it
- * has a terminating NULL, supply an n < 0. If s should be strdup'd then set dup
- * to true. */
-char **append_to_array(char ***arr, char *s, int n, bool dup);
-
-/* Make a deep copy of an array. */
-char ** arr_copy(char **arr);
-
-/* splits s by any delimiters in sep into an array of strings. Each string and
- * the array must be freed by the caller. */
-char **split(char *s, char *sep);
-
/* Goes through the path array looking for a file in each directory with the
* given name. Returns the first one. The returned string must be freed by the
* caller. If limit is true, only return the first result found in path,
* otherwise return an array of all results found in path. If isglob is true,
* treat name as a glob. test_flags is OR'd with the file's mode (from stat(3))
* to check if it matches a criterion (eg. executable, directory). */
-char **find_in_path(char *name, char **path, mode_t test_flags, bool limit, bool isglob);
+array_t find_in_path(char *name, array_t path, mode_t test_flags, bool limit, bool isglob);
/* Checks for the first cmd which may be found in path. Returns the index of the
* cmd (0, 1, 2, ...). Arg list must be terminated with a NULL */
-int available_cmd(char **path, char *cmd, ...);
+int available_cmd(array_t path, char *cmd, ...);
/* setup internal colours used by the logging functions. */
void setup_colors(struct env *e);
diff --git a/src/search.c b/src/search.c
@@ -5,11 +5,11 @@
int
search(int argc, char **argv, struct env *e) {
/* make a copy of kiss_path and append sys_db to it */
- char **p = arr_copy(e->kiss_path);
- append_to_array(&p, e->sys_db, -1, true);
+ array_t p = arr_copy(e->kiss_path);
+ arr_append(&p, e->sys_db, -1, true);
for (int i = 1; i < argc; i++) {
- char **s = find_in_path(argv[i], p, S_IFDIR, false, true);
+ array_t s = find_in_path(argv[i], p, S_IFDIR, false, true);
if (s == NULL)
die2(argv[i], "not found");
@@ -21,5 +21,6 @@ search(int argc, char **argv, struct env *e) {
free(s);
}
+ arr_free(p);
return 0;
}
diff --git a/src/utils.c b/src/utils.c
@@ -7,6 +7,7 @@
#include <sys/stat.h>
#include <time.h>
+#include "array.h"
#include "ckiss.h"
static char *c1 = "", *c2 = "", *c3 = "";
@@ -92,74 +93,15 @@ concat(char *s, ...) {
return c;
}
-size_t
-arr_len(char **arr) {
- size_t n = 0;
- if (arr) {
- while (*arr != NULL) {
- arr++;
- n++;
- }
- }
- return n;
-}
-
-char **
-append_to_array(char ***arr, char *s, int n, bool dup) {
- if (n < 0) {
- n = arr_len(*arr);
- }
- char **tmp = realloc(*arr, sizeof(char *) * ++n);
- if (tmp == NULL) {
- free(*arr);
- die_perror("realloc");
- }
- *arr = tmp;
- (*arr)[n - 1] = dup ? strdup(s) : s;
- return *arr;
-}
-
-char **
-arr_copy(char **arr) {
- size_t n = arr_len(arr);
- char **s = malloc(sizeof(char *) * (n + 1));
- if (s == NULL)
- die_perror("malloc");
- for (size_t i = 0; i < n; i++)
- s[i] = strdup(arr[i]);
- s[n] = NULL;
- return s;
-}
-
-char **
-split(char *s, char *sep) {
- if (s == NULL)
- return NULL;
-
- char **res = NULL;
- char *p = strtok(s, sep);
- int n = 0;
-
- while (p) {
- append_to_array(&res, p, n++, true);
- p = strtok(NULL, sep);
- }
-
- /* add a NULL terminator */
- append_to_array(&res, NULL, n, false);
-
- return res;
-}
-
-char **
-find_in_path(char *name, char **path, mode_t test_flags, bool limit, bool isglob) {
- char **s = NULL;
+array_t
+find_in_path(char *name, array_t path, mode_t test_flags, bool limit, bool isglob) {
+ array_t s = NULL;
int n = 0;
if (path == NULL || name == NULL)
return s;
for (int i = 0; path[i] != NULL; i++) {
char *file = concat(path[i], "/", name, NULL);
- char **list = NULL;
+ array_t list = NULL;
if (isglob) {
glob_t pglob;
int r = glob(file, GLOB_ERR, NULL, &pglob);
@@ -191,10 +133,10 @@ find_in_path(char *name, char **path, mode_t test_flags, bool limit, bool isglob
free(list[j]);
} else {
char *found = list[j];
- append_to_array(&s, found, n++, false);
+ arr_append(&s, found, n++, false);
if (limit) {
free(list);
- append_to_array(&s, NULL, n, false);
+ arr_append(&s, NULL, n, false);
return s;
}
}
@@ -203,18 +145,18 @@ find_in_path(char *name, char **path, mode_t test_flags, bool limit, bool isglob
}
if (s != NULL) {
/* add terminating NULL */
- append_to_array(&s, NULL, n, false);
+ arr_append(&s, NULL, n, false);
}
return s;
}
int
-available_cmd(char **path, char *cmd, ...) {
+available_cmd(array_t path, char *cmd, ...) {
va_list ap;
int n = 0;
va_start(ap, cmd);
while (cmd != NULL) {
- char **s = find_in_path(cmd, path, S_IXUSR | S_IXGRP | S_IXOTH, true, false);
+ array_t s = find_in_path(cmd, path, S_IXUSR | S_IXGRP | S_IXOTH, true, false);
if (s != NULL) {
free(*s);
free(s);