|
@@ -22,7 +22,6 @@
|
|
|
# define NULL ((void *) 0)
|
|
# define NULL ((void *) 0)
|
|
|
# endif /* NULL */
|
|
# endif /* NULL */
|
|
|
|
|
|
|
|
-
|
|
|
|
|
# ifndef _STDBOOL_H
|
|
# ifndef _STDBOOL_H
|
|
|
# define LIB_H_STDBOOL
|
|
# define LIB_H_STDBOOL
|
|
|
|
|
|
|
@@ -61,6 +60,9 @@ enum err {
|
|
|
ERR_FAILED_WRITE,
|
|
ERR_FAILED_WRITE,
|
|
|
ERR_FAILED_FORK,
|
|
ERR_FAILED_FORK,
|
|
|
ERR_FAILED_WAITPID,
|
|
ERR_FAILED_WAITPID,
|
|
|
|
|
+ ERR_FAILED_STAT,
|
|
|
|
|
+ ERR_FAILED_OPENDIR,
|
|
|
|
|
+ ERR_FAILED_READDIR,
|
|
|
ERR_WROTE_WRONG_AMOUNT,
|
|
ERR_WROTE_WRONG_AMOUNT,
|
|
|
ERR_FAILED_ALLOC,
|
|
ERR_FAILED_ALLOC,
|
|
|
ERR_FAILED_REALLOC,
|
|
ERR_FAILED_REALLOC,
|
|
@@ -75,34 +77,48 @@ enum err {
|
|
|
ERR_SGFX_POS_OUTSIDE_CANVAS
|
|
ERR_SGFX_POS_OUTSIDE_CANVAS
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
-const char *err_to_name[] = {
|
|
|
|
|
- "ERR_GENERAL_ERROR",
|
|
|
|
|
- "ERR_OK",
|
|
|
|
|
- "ERR_NOT_INT",
|
|
|
|
|
- "ERR_TOO_BIG",
|
|
|
|
|
- "ERR_NULL_ARG",
|
|
|
|
|
- "ERR_INVALID_ARG",
|
|
|
|
|
- "ERR_NOT_FOUND",
|
|
|
|
|
- "ERR_INDEX_TOO_LARGE",
|
|
|
|
|
- "ERR_FAILED_OPEN",
|
|
|
|
|
- "ERR_FAILED_CLOSE",
|
|
|
|
|
- "ERR_FAILED_READ",
|
|
|
|
|
- "ERR_FAILED_WRITE",
|
|
|
|
|
- "ERR_FAILED_FORK",
|
|
|
|
|
- "ERR_FAILED_WAITPID",
|
|
|
|
|
- "ERR_WROTE_WRONG_AMOUNT",
|
|
|
|
|
- "ERR_FAILED_ALLOC",
|
|
|
|
|
- "ERR_FAILED_REALLOC",
|
|
|
|
|
- "ERR_MKDIR_FAILED",
|
|
|
|
|
- "ERR_FAILED_HASHING",
|
|
|
|
|
- "ERR_STR_EMPTY",
|
|
|
|
|
- "ERR_PATH_EMPTY",
|
|
|
|
|
- "ERR_PATH_INVALID",
|
|
|
|
|
- "ERR_PATH_FILE_EMPTY",
|
|
|
|
|
- "ERR_PATH_FILE_FAILED_SEEK",
|
|
|
|
|
- "ERR_CMD_NON_ZERO_EXIT_CODE",
|
|
|
|
|
- "ERR_SGFX_POS_OUTSIDE_CANVAS",
|
|
|
|
|
-};
|
|
|
|
|
|
|
+const char *err2cstr(enum err err);
|
|
|
|
|
+
|
|
|
|
|
+# if defined(IMP) || defined(IMP_LIB)
|
|
|
|
|
+
|
|
|
|
|
+const char *
|
|
|
|
|
+err2cstr(enum err err)
|
|
|
|
|
+{
|
|
|
|
|
+ switch ( err ) {
|
|
|
|
|
+ case ERR_GENERAL_ERROR: return "ERR_GENERAL_ERROR";
|
|
|
|
|
+ case ERR_OK: return "ERR_OK";
|
|
|
|
|
+ case ERR_NOT_INT: return "ERR_NOT_INT";
|
|
|
|
|
+ case ERR_TOO_BIG: return "ERR_TOO_BIG";
|
|
|
|
|
+ case ERR_NULL_ARG: return "ERR_NULL_ARG";
|
|
|
|
|
+ case ERR_INVALID_ARG: return "ERR_INVALID_ARG";
|
|
|
|
|
+ case ERR_NOT_FOUND: return "ERR_NOT_FOUND";
|
|
|
|
|
+ case ERR_INDEX_TOO_LARGE: return "ERR_INDEX_TOO_LARGE";
|
|
|
|
|
+ case ERR_FAILED_OPEN: return "ERR_FAILED_OPEN";
|
|
|
|
|
+ case ERR_FAILED_CLOSE: return "ERR_FAILED_CLOSE";
|
|
|
|
|
+ case ERR_FAILED_READ: return "ERR_FAILED_READ";
|
|
|
|
|
+ case ERR_FAILED_WRITE: return "ERR_FAILED_WRITE";
|
|
|
|
|
+ case ERR_FAILED_FORK: return "ERR_FAILED_FORK";
|
|
|
|
|
+ case ERR_FAILED_WAITPID: return "ERR_FAILED_WAITPID";
|
|
|
|
|
+ case ERR_FAILED_STAT: return "ERR_FAILED_STAT";
|
|
|
|
|
+ case ERR_FAILED_OPENDIR: return "ERR_FAILED_OPENDIR";
|
|
|
|
|
+ case ERR_FAILED_READDIR: return "ERR_FAILED_READDIR";
|
|
|
|
|
+ case ERR_WROTE_WRONG_AMOUNT: return "ERR_WROTE_WRONG_AMOUNT";
|
|
|
|
|
+ case ERR_FAILED_ALLOC: return "ERR_FAILED_ALLOC";
|
|
|
|
|
+ case ERR_FAILED_REALLOC: return "ERR_FAILED_REALLOC";
|
|
|
|
|
+ case ERR_MKDIR_FAILED: return "ERR_MKDIR_FAILED";
|
|
|
|
|
+ case ERR_FAILED_HASHING: return "ERR_FAILED_HASHING";
|
|
|
|
|
+ case ERR_STR_EMPTY: return "ERR_STR_EMPTY";
|
|
|
|
|
+ case ERR_PATH_EMPTY: return "ERR_PATH_EMPTY";
|
|
|
|
|
+ case ERR_PATH_INVALID: return "ERR_PATH_INVALID";
|
|
|
|
|
+ case ERR_PATH_FILE_EMPTY: return "ERR_PATH_FILE_EMPTY";
|
|
|
|
|
+ case ERR_PATH_FILE_FAILED_SEEK: return "ERR_PATH_FILE_FAILED_SEEK";
|
|
|
|
|
+ case ERR_CMD_NON_ZERO_EXIT_CODE: return "ERR_CMD_NON_ZERO_EXIT_CODE";
|
|
|
|
|
+ case ERR_SGFX_POS_OUTSIDE_CANVAS: return "ERR_SGFX_POS_OUTSIDE_CANVAS";
|
|
|
|
|
+ default: return "UNKNOWN_ERR";
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+# endif /* defined(IMP) || defined(IMP_LIB) */
|
|
|
|
|
|
|
|
/* ---------------------------- END GLOBAL DEF ----------------------------- */
|
|
/* ---------------------------- END GLOBAL DEF ----------------------------- */
|
|
|
|
|
|
|
@@ -146,6 +162,14 @@ int fork(void);
|
|
|
# error "Must import <stdarg.h> before lib.h!"
|
|
# error "Must import <stdarg.h> before lib.h!"
|
|
|
# endif
|
|
# endif
|
|
|
|
|
|
|
|
|
|
+# ifndef _DIRENT_H
|
|
|
|
|
+# error "Must import <dirent.h> before lib.h!"
|
|
|
|
|
+# endif
|
|
|
|
|
+
|
|
|
|
|
+# ifndef _ERRNO_H
|
|
|
|
|
+# error "Must import <errno.h> before lib.h!"
|
|
|
|
|
+# endif
|
|
|
|
|
+
|
|
|
/* ----------------------------- START LIB DEF ----------------------------- */
|
|
/* ----------------------------- START LIB DEF ----------------------------- */
|
|
|
|
|
|
|
|
# define TODO(msg) \
|
|
# define TODO(msg) \
|
|
@@ -279,9 +303,167 @@ _VEC2_STRUCT_DEF(u8);
|
|
|
|
|
|
|
|
# if defined(WANT_CSTR) || defined(WANT_ALL)
|
|
# if defined(WANT_CSTR) || defined(WANT_ALL)
|
|
|
|
|
|
|
|
|
|
+# ifndef CSTR_SIZE_LIMIT
|
|
|
|
|
+# define CSTR_SIZE_LIMIT 1028
|
|
|
|
|
+# endif /* CSTR_SIZE_LIMIT */
|
|
|
|
|
+
|
|
|
|
|
+# define CSTR_ARRAY(...) (const char *[]){__VA_ARGS__, NULL}
|
|
|
|
|
+
|
|
|
u64 cstr_len_max(const char *cstr, u64 max, bool *out_hit_max,
|
|
u64 cstr_len_max(const char *cstr, u64 max, bool *out_hit_max,
|
|
|
enum err *out_err);
|
|
enum err *out_err);
|
|
|
|
|
|
|
|
|
|
+struct __cstr_len_args {
|
|
|
|
|
+ bool has_max;
|
|
|
|
|
+ u64 max;
|
|
|
|
|
+ bool *out_hit_max;
|
|
|
|
|
+};
|
|
|
|
|
+# define cstr_len(Cstr, OutErr, ...) \
|
|
|
|
|
+ _cstr_len( \
|
|
|
|
|
+ (Cstr), \
|
|
|
|
|
+ (struct __cstr_len_args) { \
|
|
|
|
|
+ .has_max=false, \
|
|
|
|
|
+ __VA_ARGS__ \
|
|
|
|
|
+ }, \
|
|
|
|
|
+ (OutErr) \
|
|
|
|
|
+ )
|
|
|
|
|
+u64 _cstr_len(const char *cstr, struct __cstr_len_args args,
|
|
|
|
|
+ enum err *out_err);
|
|
|
|
|
+
|
|
|
|
|
+const char *cstr_dup(const char *cstr, enum err *out_err);
|
|
|
|
|
+
|
|
|
|
|
+# define CSTR_WITH_SIZE(Cstr, OutErr, ...) \
|
|
|
|
|
+ (Cstr), cstr_len((Cstr), (OutErr), __VA_ARGS__)
|
|
|
|
|
+
|
|
|
|
|
+bool cstr_eq(const char *_r_ cstr1, u64 size1,
|
|
|
|
|
+ const char *_r_ cstr2, u64 size2, enum err *_r_ out_err);
|
|
|
|
|
+
|
|
|
|
|
+bool cstr_endswith(const char *_r_ cstr, u64 size,
|
|
|
|
|
+ const char *_r_ end, u64 end_size, enum err *_r_ out_err);
|
|
|
|
|
+
|
|
|
|
|
+# if defined(IMP_CSTR) || defined(IMP)
|
|
|
|
|
+
|
|
|
|
|
+u64
|
|
|
|
|
+cstr_len_max(const char *cstr, u64 max, bool *out_hit_max, enum err *out_err)
|
|
|
|
|
+{
|
|
|
|
|
+ u64 ret = 0;
|
|
|
|
|
+
|
|
|
|
|
+ LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, 0);
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL(cstr, out_err, 0);
|
|
|
|
|
+
|
|
|
|
|
+_loop:
|
|
|
|
|
+ if ( ret >= max ) {
|
|
|
|
|
+ LIB_SET_IF_NOT_NULL(out_hit_max, true);
|
|
|
|
|
+ goto _loop_end;
|
|
|
|
|
+ }
|
|
|
|
|
+ if ( cstr[ret] == '\0' ) {
|
|
|
|
|
+ LIB_SET_IF_NOT_NULL(out_hit_max, false);
|
|
|
|
|
+ goto _loop_end;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ ++ret;
|
|
|
|
|
+ goto _loop;
|
|
|
|
|
+_loop_end:
|
|
|
|
|
+
|
|
|
|
|
+ LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
|
|
|
|
|
+ return ret;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+u64
|
|
|
|
|
+_cstr_len(const char *cstr, struct __cstr_len_args args, enum err *out_err)
|
|
|
|
|
+{
|
|
|
|
|
+ u64 ret = 0;
|
|
|
|
|
+
|
|
|
|
|
+ LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, 0);
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL(cstr, out_err, 0);
|
|
|
|
|
+
|
|
|
|
|
+_loop:
|
|
|
|
|
+ if ( args.has_max == true && ret >= args.max ) {
|
|
|
|
|
+ LIB_SET_IF_NOT_NULL(args.out_hit_max, true);
|
|
|
|
|
+ goto _loop_end;
|
|
|
|
|
+ }
|
|
|
|
|
+ if ( cstr[ret] == '\0' ) {
|
|
|
|
|
+ LIB_SET_IF_NOT_NULL(args.out_hit_max, false);
|
|
|
|
|
+ goto _loop_end;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ ++ret;
|
|
|
|
|
+ goto _loop;
|
|
|
|
|
+_loop_end:
|
|
|
|
|
+
|
|
|
|
|
+ LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
|
|
|
|
|
+ return ret;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const char *
|
|
|
|
|
+cstr_dup(const char *cstr, enum err *out_err)
|
|
|
|
|
+{
|
|
|
|
|
+ char *ret = NULL;
|
|
|
|
|
+ u64 size = 0;
|
|
|
|
|
+ bool hit_limit = false;
|
|
|
|
|
+
|
|
|
|
|
+ LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, NULL);
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL(cstr, out_err, NULL);
|
|
|
|
|
+
|
|
|
|
|
+ size = cstr_len_max(cstr, CSTR_SIZE_LIMIT, &hit_limit, NULL);
|
|
|
|
|
+ if ( hit_limit == true ) {
|
|
|
|
|
+ LIB_SET_IF_NOT_NULL(out_err, ERR_TOO_BIG);
|
|
|
|
|
+ goto exit_err;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ ret = malloc(size + 1);
|
|
|
|
|
+ if ( ret == NULL ) {
|
|
|
|
|
+ LIB_SET_IF_NOT_NULL(out_err, ERR_FAILED_ALLOC);
|
|
|
|
|
+ goto exit_err;
|
|
|
|
|
+ }
|
|
|
|
|
+ memset(ret, 0, size + 1);
|
|
|
|
|
+
|
|
|
|
|
+ memcpy(ret, cstr, size);
|
|
|
|
|
+
|
|
|
|
|
+ return (const char *) ret;
|
|
|
|
|
+exit_err:
|
|
|
|
|
+ LIB_FREE(ret);
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+bool
|
|
|
|
|
+cstr_eq(const char *_r_ cstr1, u64 size1,
|
|
|
|
|
+ const char *_r_ cstr2, u64 size2, enum err *_r_ out_err)
|
|
|
|
|
+{
|
|
|
|
|
+ LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, false);
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL(cstr1, out_err, false);
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL(cstr2, out_err, false);
|
|
|
|
|
+
|
|
|
|
|
+ if ( size1 != size2 ) return false;
|
|
|
|
|
+
|
|
|
|
|
+ for ( u64 i = 0; i < size1; ++i ) {
|
|
|
|
|
+ if ( cstr1[i] != cstr2[i] ) return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return true;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+bool
|
|
|
|
|
+cstr_endswith(const char *_r_ cstr, u64 size,
|
|
|
|
|
+ const char *_r_ end, u64 end_size, enum err *_r_ out_err)
|
|
|
|
|
+{
|
|
|
|
|
+ LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, false);
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL(cstr, out_err, false);
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL(end, out_err, false);
|
|
|
|
|
+
|
|
|
|
|
+ if ( size < end_size ) return false;
|
|
|
|
|
+
|
|
|
|
|
+ u64 i = size - 1;
|
|
|
|
|
+ u64 j = end_size - 1;
|
|
|
|
|
+_loop:
|
|
|
|
|
+ if ( cstr[i] != end[j] ) return false;
|
|
|
|
|
+ if ( j == 0 ) return true;
|
|
|
|
|
+ --i;
|
|
|
|
|
+ --j;
|
|
|
|
|
+ goto _loop;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+# endif /* defined(IMP_CSTR) || defined(IMP) */
|
|
|
|
|
+
|
|
|
# endif /* defined(WANT_CSTR) || defined(WANT_ALL) */
|
|
# endif /* defined(WANT_CSTR) || defined(WANT_ALL) */
|
|
|
|
|
|
|
|
/* ----------------------------- END CSTR DEF ------------------------------ */
|
|
/* ----------------------------- END CSTR DEF ------------------------------ */
|
|
@@ -1224,8 +1406,6 @@ bool path_mkdir(struct path path, u32 mode, bool do_create_parents,
|
|
|
bool path_touch(struct path path, int (*open)(const char *, int),
|
|
bool path_touch(struct path path, int (*open)(const char *, int),
|
|
|
enum err *out_err);
|
|
enum err *out_err);
|
|
|
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
struct file {
|
|
struct file {
|
|
|
u8 *data;
|
|
u8 *data;
|
|
|
u64 size;
|
|
u64 size;
|
|
@@ -1235,8 +1415,136 @@ struct file path_file_read_all(const struct path *path, enum err *out_err);
|
|
|
enum err path_file_save(const struct path *path, const struct file *file,
|
|
enum err path_file_save(const struct path *path, const struct file *file,
|
|
|
enum err *out_err);
|
|
enum err *out_err);
|
|
|
|
|
|
|
|
|
|
+struct dir {
|
|
|
|
|
+ const char *path;
|
|
|
|
|
+ struct stat stat;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+struct dirs {
|
|
|
|
|
+ struct dir *data;
|
|
|
|
|
+ u64 size;
|
|
|
|
|
+ u64 cap;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+struct __dir_list_args {
|
|
|
|
|
+ bool stat;
|
|
|
|
|
+ bool recurse;
|
|
|
|
|
+ bool with_self;
|
|
|
|
|
+ bool with_previous;
|
|
|
|
|
+};
|
|
|
|
|
+# define dir_list_cstr(Path, OutErr, ...) \
|
|
|
|
|
+ _dir_list_cstr( \
|
|
|
|
|
+ (Path), \
|
|
|
|
|
+ (struct __dir_list_args) {.stat=true, __VA_ARGS__}, \
|
|
|
|
|
+ (OutErr) \
|
|
|
|
|
+ )
|
|
|
|
|
+struct dirs _dir_list_cstr(const char *path, struct __dir_list_args args,
|
|
|
|
|
+ enum err *out_err);
|
|
|
|
|
+
|
|
|
|
|
+enum err dir_list_destroy(struct dirs *dirs, enum err *out_err);
|
|
|
|
|
+
|
|
|
# if defined(IMP_PATH) || defined(IMP)
|
|
# if defined(IMP_PATH) || defined(IMP)
|
|
|
|
|
|
|
|
|
|
+struct dirs
|
|
|
|
|
+_dir_list_cstr(const char *path, struct __dir_list_args args,
|
|
|
|
|
+ enum err *out_err)
|
|
|
|
|
+{
|
|
|
|
|
+ enum err err = ERR_OK;
|
|
|
|
|
+ enum err *perr = &err;
|
|
|
|
|
+
|
|
|
|
|
+ struct dirs empty = {0};
|
|
|
|
|
+ struct dirs dirs = {0};
|
|
|
|
|
+
|
|
|
|
|
+ DIR *d = NULL;
|
|
|
|
|
+ struct dirent *de = NULL;
|
|
|
|
|
+
|
|
|
|
|
+ LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, empty);
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL(path, out_err, empty);
|
|
|
|
|
+
|
|
|
|
|
+ if ( out_err != NULL ) perr = out_err;
|
|
|
|
|
+
|
|
|
|
|
+ d = opendir(path);
|
|
|
|
|
+ if ( d == NULL ) {
|
|
|
|
|
+ *perr = ERR_FAILED_OPENDIR;
|
|
|
|
|
+ goto exit_err;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ errno = 0;
|
|
|
|
|
+ de = readdir(d);
|
|
|
|
|
+ while ( de != NULL ) {
|
|
|
|
|
+ struct dir dir = {0};
|
|
|
|
|
+
|
|
|
|
|
+ if ( args.with_self == false ) {
|
|
|
|
|
+ if ( cstr_eq(CSTR_WITH_SIZE(de->d_name, perr), ".", 1, perr) ) {
|
|
|
|
|
+ goto _continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if ( args.with_previous == false ) {
|
|
|
|
|
+ if ( cstr_eq(CSTR_WITH_SIZE(de->d_name, perr), "..", 2, perr) ) {
|
|
|
|
|
+ goto _continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if ( args.recurse == true ) {
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ dir.path = cstr_dup(
|
|
|
|
|
+ temp_sprintf("%s/%s", path, de->d_name),
|
|
|
|
|
+ perr
|
|
|
|
|
+ );
|
|
|
|
|
+ if ( *perr != ERR_OK ) goto exit_err;
|
|
|
|
|
+
|
|
|
|
|
+ if ( args.stat == true ) {
|
|
|
|
|
+ *perr = stat(dir.path, &dir.stat);
|
|
|
|
|
+ if ( *perr != ERR_OK ) {
|
|
|
|
|
+ *perr = ERR_FAILED_STAT;
|
|
|
|
|
+ goto exit_err;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ DA_APPEND(dirs, dir, perr);
|
|
|
|
|
+ if ( *perr != ERR_OK ) goto exit_err;
|
|
|
|
|
+
|
|
|
|
|
+ _continue:
|
|
|
|
|
+ de = readdir(d);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if ( errno != 0 ) {
|
|
|
|
|
+ *perr = ERR_FAILED_READDIR;
|
|
|
|
|
+ goto exit_err;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ closedir(d);
|
|
|
|
|
+
|
|
|
|
|
+ *perr = ERR_OK;
|
|
|
|
|
+ return dirs;
|
|
|
|
|
+exit_err:
|
|
|
|
|
+ if ( d != NULL ) closedir(d);
|
|
|
|
|
+ dir_list_destroy(&dirs, NULL);
|
|
|
|
|
+ return empty;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+enum err
|
|
|
|
|
+dir_list_destroy(struct dirs *_r_ dirs, enum err *_r_ out_err)
|
|
|
|
|
+{
|
|
|
|
|
+ LIB_ARG_IF_NOT_NULL_MUST_BE_RET_IT(out_err, ERR_OK);
|
|
|
|
|
+ LIB_ARG_MUST_NOT_BE_NULL_SET_RET_ERR(dirs, out_err);
|
|
|
|
|
+
|
|
|
|
|
+ if ( dirs->data != NULL ) {
|
|
|
|
|
+ DA_FOREACH(*dirs, it) {
|
|
|
|
|
+ LIB_FREE(it->path);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ LIB_FREE(dirs->data);
|
|
|
|
|
+
|
|
|
|
|
+ dirs->data = NULL;
|
|
|
|
|
+ dirs->size = 0;
|
|
|
|
|
+ dirs->cap = 0;
|
|
|
|
|
+
|
|
|
|
|
+ LIB_SET_IF_NOT_NULL(out_err, ERR_OK);
|
|
|
|
|
+ return ERR_OK;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
# endif /* defined(IMP_PATH) || defined(IMP) */
|
|
# endif /* defined(IMP_PATH) || defined(IMP) */
|
|
|
|
|
|
|
@@ -1960,6 +2268,12 @@ tokenizer_is_str_lit(struct tokenizer *tkn, struct str str)
|
|
|
|
|
|
|
|
# ifdef unix
|
|
# ifdef unix
|
|
|
# define CC "cc"
|
|
# define CC "cc"
|
|
|
|
|
+# define CC_FLAGS "-std=gnu99", "-m64", "-O2", "-pedantic", \
|
|
|
|
|
+ "-Wall", "-Wextra", "-Wshadow", "-Wcast-align", "-Wunused", \
|
|
|
|
|
+ "-Wconversion", "-Wmisleading-indentation", "-Wdouble-promotion", \
|
|
|
|
|
+ "-Wformat=2", "-Wbad-function-cast", "-Wmissing-declarations", \
|
|
|
|
|
+ "-Wmissing-prototypes", "-Wnested-externs", "-Werror", \
|
|
|
|
|
+ "-Wno-override-init"
|
|
|
# else
|
|
# else
|
|
|
# error "No CC for this platform"
|
|
# error "No CC for this platform"
|
|
|
# endif
|
|
# endif
|
|
@@ -2033,10 +2347,10 @@ enum err cmd_set_exe(struct cmd *_r_ cmd, struct str exe,
|
|
|
enum err cmd_append_arg(struct cmd *_r_ cmd, struct str arg,
|
|
enum err cmd_append_arg(struct cmd *_r_ cmd, struct str arg,
|
|
|
enum err *_r_ out_err);
|
|
enum err *_r_ out_err);
|
|
|
|
|
|
|
|
-# define cmd_append_args_cstrs(Cmd, OutErr, Arg, ...) \
|
|
|
|
|
|
|
+# define cmd_append_args_cstrs(Cmd, OutErr, ...) \
|
|
|
_cmd_append_args_cstrs( \
|
|
_cmd_append_args_cstrs( \
|
|
|
(Cmd), \
|
|
(Cmd), \
|
|
|
- (const char *[]){(Arg), __VA_ARGS__, NULL}, \
|
|
|
|
|
|
|
+ (const char *[]){__VA_ARGS__, NULL}, \
|
|
|
(OutErr) \
|
|
(OutErr) \
|
|
|
)
|
|
)
|
|
|
enum err _cmd_append_args_cstrs(struct cmd *_r_ cmd, const char **args,
|
|
enum err _cmd_append_args_cstrs(struct cmd *_r_ cmd, const char **args,
|
|
@@ -2075,8 +2389,20 @@ enum err _cmd_exec(struct cmd *_r_ cmd, struct __cmd_exec_args args,
|
|
|
enum err cmd_clear_args(struct cmd *cmd, enum err *out_err);
|
|
enum err cmd_clear_args(struct cmd *cmd, enum err *out_err);
|
|
|
enum err cmd_destroy(struct cmd *cmd, enum err *out_err);
|
|
enum err cmd_destroy(struct cmd *cmd, enum err *out_err);
|
|
|
|
|
|
|
|
-# define GO_REBUILD_YOURSELF() _cmd_go_rebuild_yourself(__FILE__, argv)
|
|
|
|
|
-void _cmd_go_rebuild_yourself(const char *src, char **argv);
|
|
|
|
|
|
|
+struct __cmd_go_rebuild_yourself_args {
|
|
|
|
|
+ const char **deps;
|
|
|
|
|
+ const char **opts;
|
|
|
|
|
+ bool debug;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+# define GO_REBUILD_YOURSELF(...) \
|
|
|
|
|
+ _cmd_go_rebuild_yourself( \
|
|
|
|
|
+ __FILE__, \
|
|
|
|
|
+ argv, \
|
|
|
|
|
+ (struct __cmd_go_rebuild_yourself_args){.debug=false, __VA_ARGS__} \
|
|
|
|
|
+ )
|
|
|
|
|
+void _cmd_go_rebuild_yourself(const char *src, char **argv,
|
|
|
|
|
+ struct __cmd_go_rebuild_yourself_args args);
|
|
|
|
|
|
|
|
|
|
|
|
|
# if defined(IMP_CMD) || defined(IMP)
|
|
# if defined(IMP_CMD) || defined(IMP)
|
|
@@ -2384,7 +2710,8 @@ cmd_destroy(struct cmd *cmd, enum err *out_err)
|
|
|
|
|
|
|
|
# ifdef _SYS_STAT_H
|
|
# ifdef _SYS_STAT_H
|
|
|
void
|
|
void
|
|
|
-_cmd_go_rebuild_yourself(const char *src, char **argv)
|
|
|
|
|
|
|
+_cmd_go_rebuild_yourself(const char *src, char **argv,
|
|
|
|
|
+ struct __cmd_go_rebuild_yourself_args args)
|
|
|
{
|
|
{
|
|
|
enum err err = ERR_OK;
|
|
enum err err = ERR_OK;
|
|
|
struct stat src_stat = {0};
|
|
struct stat src_stat = {0};
|
|
@@ -2393,16 +2720,43 @@ _cmd_go_rebuild_yourself(const char *src, char **argv)
|
|
|
if ( err == ERR_OK ) err = stat(src, &src_stat);
|
|
if ( err == ERR_OK ) err = stat(src, &src_stat);
|
|
|
if ( err == ERR_OK ) err = stat(argv[0] , &exec_stat);
|
|
if ( err == ERR_OK ) err = stat(argv[0] , &exec_stat);
|
|
|
|
|
|
|
|
|
|
+ if ( err == ERR_OK ) if ( args.deps != NULL ) {
|
|
|
|
|
+ while ( *args.deps != NULL ) {
|
|
|
|
|
+ struct stat tmp_stat = {0};
|
|
|
|
|
+ err = stat(*args.deps++, &tmp_stat);
|
|
|
|
|
+ if ( err != ERR_OK ) break;
|
|
|
|
|
+ if ( tmp_stat.st_mtime > src_stat.st_mtime ) {
|
|
|
|
|
+ src_stat = tmp_stat;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if ( err == ERR_OK ) do {
|
|
if ( err == ERR_OK ) do {
|
|
|
if ( src_stat.st_mtime > exec_stat.st_mtime ) {
|
|
if ( src_stat.st_mtime > exec_stat.st_mtime ) {
|
|
|
- err = rename(argv[0], temp_sprintf("%s.old", argv[0]));
|
|
|
|
|
-
|
|
|
|
|
struct cmd cmd = cmd_create_ns(CC, &err);
|
|
struct cmd cmd = cmd_create_ns(CC, &err);
|
|
|
- cmd_append_arg_ns(&cmd, src, &err);
|
|
|
|
|
- cmd_append_arg_ns(&cmd, "-o", &err);
|
|
|
|
|
- cmd_append_arg_ns(&cmd, argv[0], &err);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ cmd_append_args_cstrs(&cmd, &err, CC_FLAGS);
|
|
|
|
|
+
|
|
|
|
|
+ if ( args.debug == true ) {
|
|
|
|
|
+ cmd_append_args_cstrs(
|
|
|
|
|
+ &cmd, &err,
|
|
|
|
|
+ "-O0", "-ggdb", "-fsanitize=address"
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if ( args.opts != NULL ) {
|
|
|
|
|
+ _cmd_append_args_cstrs(&cmd, args.opts, &err);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ cmd_append_args_cstrs(
|
|
|
|
|
+ &cmd, &err,
|
|
|
|
|
+ src, "-o", temp_sprintf("%s.new", argv[0])
|
|
|
|
|
+ );
|
|
|
cmd_exec(&cmd, &err);
|
|
cmd_exec(&cmd, &err);
|
|
|
cmd_destroy(&cmd, &err);
|
|
cmd_destroy(&cmd, &err);
|
|
|
|
|
+ if ( err == ERR_OK ) err = rename(
|
|
|
|
|
+ temp_sprintf("%s.new", argv[0]), argv[0]
|
|
|
|
|
+ );
|
|
|
|
|
|
|
|
if ( err == ERR_OK ) execv(argv[0], argv);
|
|
if ( err == ERR_OK ) execv(argv[0], argv);
|
|
|
if ( err == ERR_OK ) exit(0);
|
|
if ( err == ERR_OK ) exit(0);
|
|
@@ -2410,7 +2764,7 @@ _cmd_go_rebuild_yourself(const char *src, char **argv)
|
|
|
} while(0);
|
|
} while(0);
|
|
|
|
|
|
|
|
if ( err != ERR_OK ) {
|
|
if ( err != ERR_OK ) {
|
|
|
- fprintf(stderr, "Failed recompiling myself: %s\n", err_to_name[err]);
|
|
|
|
|
|
|
+ fprintf(stderr, "Failed recompiling myself: %s\n", err2cstr(err));
|
|
|
exit(1);
|
|
exit(1);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -2760,43 +3114,6 @@ _str_memcpy(void *dest, const void *src, u64 n)
|
|
|
|
|
|
|
|
/* ------------------------------ END LIB IMP ------------------------------ */
|
|
/* ------------------------------ END LIB IMP ------------------------------ */
|
|
|
|
|
|
|
|
-/* ---------------------------- START CSTR IMP ----------------------------- */
|
|
|
|
|
-
|
|
|
|
|
-# if defined(WANT_CSTR) || defined(WANT_ALL)
|
|
|
|
|
-
|
|
|
|
|
-u64
|
|
|
|
|
-cstr_len_max(const char *cstr, u64 max, bool *out_hit_max, enum err *out_err)
|
|
|
|
|
-{
|
|
|
|
|
- u64 ret = 0;
|
|
|
|
|
-
|
|
|
|
|
- _ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, 0);
|
|
|
|
|
-
|
|
|
|
|
- if ( cstr == NULL ) {
|
|
|
|
|
- _SET_IF_NOT_NULL(out_err, ERR_NULL_ARG);
|
|
|
|
|
- return 0;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-_loop:
|
|
|
|
|
- if ( ret >= max ) {
|
|
|
|
|
- _SET_IF_NOT_NULL(out_hit_max, true);
|
|
|
|
|
- goto _loop_end;
|
|
|
|
|
- }
|
|
|
|
|
- if ( cstr[ret] == '\0' ) {
|
|
|
|
|
- goto _loop_end;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- ++ret;
|
|
|
|
|
- goto _loop;
|
|
|
|
|
-_loop_end:
|
|
|
|
|
-
|
|
|
|
|
- _SET_IF_NOT_NULL(out_err, ERR_OK);
|
|
|
|
|
- return ret;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-# endif /* defined(WANT_CSTR) || defined(WANT_ALL) */
|
|
|
|
|
-
|
|
|
|
|
-/* ----------------------------- END CSTR IMP ------------------------------ */
|
|
|
|
|
-
|
|
|
|
|
/* ---------------------------- START STR DEF ------------------------------ */
|
|
/* ---------------------------- START STR DEF ------------------------------ */
|
|
|
|
|
|
|
|
# if defined(WANT_STR) || defined(WANT_ALL)
|
|
# if defined(WANT_STR) || defined(WANT_ALL)
|
|
@@ -2942,7 +3259,8 @@ str_dup(struct str str)
|
|
|
{
|
|
{
|
|
|
struct str ret = str;
|
|
struct str ret = str;
|
|
|
|
|
|
|
|
- ret.data = malloc(ret.size * sizeof(*ret.data));
|
|
|
|
|
|
|
+ ret.data = malloc((ret.size * sizeof(*ret.data)) + 1);
|
|
|
|
|
+ memset((void *)ret.data, 0, (ret.size * sizeof(*ret.data)) + 1);
|
|
|
|
|
|
|
|
memcpy((char *)ret.data, str.data, str.size);
|
|
memcpy((char *)ret.data, str.data, str.size);
|
|
|
|
|
|
|
@@ -3263,7 +3581,7 @@ getenv_as_path(const char *name, enum err *out_err)
|
|
|
{
|
|
{
|
|
|
struct path empty = {0};
|
|
struct path empty = {0};
|
|
|
struct str str = {0};
|
|
struct str str = {0};
|
|
|
- enum err err;
|
|
|
|
|
|
|
+ enum err err = ERR_OK;
|
|
|
|
|
|
|
|
LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, empty);
|
|
LIB_ARG_IF_NOT_NULL_MUST_BE(out_err, ERR_OK, empty);
|
|
|
|
|
|
|
@@ -3307,7 +3625,7 @@ path_from_str(struct str str, enum err *out_err)
|
|
|
struct path
|
|
struct path
|
|
|
path_from_cstr(const char *cstr, u64 cstr_size, enum err *out_err)
|
|
path_from_cstr(const char *cstr, u64 cstr_size, enum err *out_err)
|
|
|
{
|
|
{
|
|
|
- enum err err;
|
|
|
|
|
|
|
+ enum err err = ERR_OK;
|
|
|
struct str str;
|
|
struct str str;
|
|
|
struct path path = {0};
|
|
struct path path = {0};
|
|
|
|
|
|