ckiss

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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:
Msrc/Makefile | 7++++---
Asrc/array.c | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/array.h | 29+++++++++++++++++++++++++++++
Msrc/ckiss.h | 25++++---------------------
Msrc/search.c | 7++++---
Msrc/utils.c | 78++++++++++--------------------------------------------------------------------
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);