xaizek / vifm (License: GPLv2+) (since 2018-12-07)
Vifm is a file manager with curses interface, which provides Vi[m]-like environment for managing objects within file systems, extended with some useful ideas from mutt.
Commit f6dc735636f05dc6d24bc0edbdf6e4ff56eeff91

Extract utils/matchers.c:matchers_init() helper
This somewhat improves handling of errors but is also needed to
introduce a second constructor for the type later.

While at it, update how reallocarray() is done and move declarations
next to their uses..
Author: xaizek
Author date (UTC): 2026-07-17 17:21
Committer name: xaizek
Committer date (UTC): 2026-07-17 17:21
Parent(s): cc27237907f26554885f99e7d0491496bdac6958
Signing key: 99DC5E4DB05F6BE2
Tree: a0c8d69210f922ff0e1ddba3c92ea3698781a450
File Lines added Lines deleted
src/utils/matchers.c 28 16
File src/utils/matchers.c changed (mode: 100644) (index 26f619414..fd75f2a90)
... ... typedef struct
64 64 } }
65 65 parsing_state_t; parsing_state_t;
66 66
67 static matchers_t * matchers_init(const char expr[], char *subs[], int nsubs,
68 int cs_by_def, MatcherExpr expr_kind, const char on_empty_re[],
69 char **error);
67 70 TSTATIC char ** break_into_matchers(const char concat[], int *count, TSTATIC char ** break_into_matchers(const char concat[], int *count,
68 71 int is_list); int is_list);
69 72 static int find_patterns(parsing_state_t *state); static int find_patterns(parsing_state_t *state);
 
... ... static void load_token(parsing_state_t *state, int single_char);
75 78 static int get_token_width(TokenType tok); static int get_token_width(TokenType tok);
76 79
77 80 matchers_t * matchers_t *
78 matchers_alloc(const char list[], int cs_by_def, int glob_by_def,
81 matchers_alloc(const char expr[], int cs_by_def, int glob_by_def,
79 82 const char on_empty_re[], char **error) const char on_empty_re[], char **error)
80 83 { {
81 char **exprs;
82 int nexprs;
83 int i;
84 int nsubs;
85 char **subs = break_into_matchers(expr, &nsubs, /*is_list=*/0);
84 86
85 matchers_t *const matchers = malloc(sizeof(*matchers));
87 MatcherExpr expr_kind = (glob_by_def ? ME_DEF_GLOB : ME_DEF_REGEX);
88 matchers_t *matchers = matchers_init(expr, subs, nsubs, cs_by_def,
89 expr_kind, on_empty_re, error);
90
91 free_string_array(subs, nsubs);
86 92
93 return matchers;
94 }
95
96 /* Allocates and initializes an instance of matchers. Returns a newly
97 * allocated instance or NULL. */
98 static matchers_t *
99 matchers_init(const char expr[], char *subs[], int nsubs, int cs_by_def,
100 MatcherExpr expr_kind, const char on_empty_re[], char **error)
101 {
87 102 *error = NULL; *error = NULL;
88 103
89 exprs = break_into_matchers(list, &nexprs, 0);
90 matchers->count = nexprs;
91 matchers->list = reallocarray(NULL, nexprs, sizeof(matcher_t *));
92 matchers->expr = strdup(list);
104 matchers_t *const matchers = malloc(sizeof(*matchers));
105 matchers->count = nsubs;
106 matchers->list = reallocarray(NULL, nsubs, sizeof(*matchers->list));
107 matchers->expr = strdup(expr);
93 108 if(matchers->list == NULL || matchers->expr == NULL) if(matchers->list == NULL || matchers->expr == NULL)
94 109 { {
95 110 matchers->count = 0; matchers->count = 0;
96 111 matchers_free(matchers); matchers_free(matchers);
97 free_string_array(exprs, nexprs);
98 112 return NULL; return NULL;
99 113 } }
100 114
101 const MatcherExpr expr_kind = (glob_by_def ? ME_DEF_GLOB : ME_DEF_REGEX);
102 for(i = 0; i < nexprs; ++i)
115 int i;
116 for(i = 0; i < nsubs; ++i)
103 117 { {
104 matchers->list[i] = matcher_alloc(exprs[i], cs_by_def, expr_kind,
118 matchers->list[i] = matcher_alloc(subs[i], cs_by_def, expr_kind,
105 119 on_empty_re, error); on_empty_re, error);
106 120 if(matchers->list[i] == NULL) if(matchers->list[i] == NULL)
107 121 { {
108 char *const err = format_str("%s: %s", exprs[i], *error);
122 char *const err = format_str("%s: %s", subs[i], *error);
109 123
110 124 matchers->count = i; matchers->count = i;
111 125 matchers_free(matchers); matchers_free(matchers);
112 free_string_array(exprs, nexprs);
113 126
114 127 free(*error); free(*error);
115 128 *error = err; *error = err;
 
... ... matchers_alloc(const char list[], int cs_by_def, int glob_by_def,
117 130 } }
118 131 } }
119 132
120 free_string_array(exprs, nexprs);
121 133 return matchers; return matchers;
122 134 } }
123 135
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/vifm

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/vifm

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master