77dd6a2dc73429d7841432713febc0b03c139986 — Simon Ser 26 days ago 37e7c07
shell/word: expose word_to_pattern

We need to convert words to patterns in several places, not only when
performing pathname expansion.
2 files changed, 25 insertions(+), 12 deletions(-)

M include/shell/word.h
M shell/word.c
M include/shell/word.h => include/shell/word.h +5 -0
@@ 16,6 16,11 @@ const char *ifs);
  void get_fields_str(struct mrsh_array *strs, const struct mrsh_array *fields);
  /**
+  * Convert a word to a pattern. Returns NULL if word doesn't contain any
+  * special pattern character (ie. requires an exact match).
+  */
+ char *word_to_pattern(const struct mrsh_word *word);
+ /**
   * Performs pathname expansion on each item in `fields`.
   */
  bool expand_pathnames(struct mrsh_array *expanded,

M shell/word.c => shell/word.c +20 -12
@@ 295,7 295,7 @@   }
  
- static void get_word_pathname_pattern(struct mrsh_buffer *buf,
+ static void _word_to_pattern(struct mrsh_buffer *buf,
  		const struct mrsh_word *word, bool quoted) {
  	switch (word->type) {
  	case MRSH_WORD_STRING:;


@@ 315,7 315,7 @@   		for (size_t i = 0; i < wl->children.len; i++) {
  			const struct mrsh_word *child = wl->children.data[i];
- 			get_word_pathname_pattern(buf, child, quoted || wl->double_quoted);
+ 			_word_to_pattern(buf, child, quoted || wl->double_quoted);
  		}
  		break;
  	default:


@@ 323,24 323,30 @@ }
  }
  
- bool expand_pathnames(struct mrsh_array *expanded,
- 		const struct mrsh_array *fields) {
+ char *word_to_pattern(const struct mrsh_word *word) {
+ 	if (!needs_pathname_expansion(word)) {
+ 		return NULL;
+ 	}
+ 
  	struct mrsh_buffer buf = {0};
+ 	_word_to_pattern(&buf, word, false);
+ 	mrsh_buffer_append_char(&buf, '\0');
+ 	return mrsh_buffer_steal(&buf);
+ }
  
+ bool expand_pathnames(struct mrsh_array *expanded,
+ 		const struct mrsh_array *fields) {
  	for (size_t i = 0; i < fields->len; ++i) {
  		const struct mrsh_word *field = fields->data[i];
  
- 		if (!needs_pathname_expansion(field)) {
+ 		char *pattern = word_to_pattern(field);
+ 		if (pattern == NULL) {
  			mrsh_array_add(expanded, mrsh_word_str(field));
  			continue;
  		}
  
- 		buf.len = 0;
- 		get_word_pathname_pattern(&buf, field, false);
- 		mrsh_buffer_append_char(&buf, '\0');
- 
  		glob_t glob_buf;
- 		int ret = glob(buf.data, GLOB_NOSORT, NULL, &glob_buf);
+ 		int ret = glob(pattern, GLOB_NOSORT, NULL, &glob_buf);
  		if (ret == 0) {
  			for (size_t i = 0; i < glob_buf.gl_pathc; ++i) {
  				mrsh_array_add(expanded, strdup(glob_buf.gl_pathv[i]));


@@ 349,11 355,13 @@ } else if (ret == GLOB_NOMATCH) {
  			mrsh_array_add(expanded, mrsh_word_str(field));
  		} else {
- 			fprintf(stderr, "glob() failed\n");
+ 			fprintf(stderr, "glob failed: %d\n", ret);
+ 			free(pattern);
  			return false;
  		}
+ 
+ 		free(pattern);
  	}
  
- 	mrsh_buffer_finish(&buf);
  	return true;
  }