commit: 730f9471a08eb080b7972d07562fa6173d14c84e
parent 96743d0fd0b33e04b4bcceccffef33dff6219c5c
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Sat, 24 Aug 2024 05:12:52 +0200
cmd/cut: Fix non-stop range support
Diffstat:
2 files changed, 52 insertions(+), 8 deletions(-)
diff --git a/cmd/cut.c b/cmd/cut.c
@@ -6,6 +6,7 @@
#include "../lib/reallocarray.h"
+#include <ctype.h>
#include <errno.h>
#include <locale.h>
#include <stdbool.h>
@@ -31,6 +32,7 @@ bool opt_n = false, opt_s = false;
enum cut_mode mode = CUT_MODE_NONE;
bool *list = NULL;
size_t list_len = 0;
+bool nostop = false;
static ssize_t
parse_list_num(char **s)
@@ -83,13 +85,21 @@ parse_list(char *s)
if(s && *s == '-')
{
s++;
- max = parse_list_num(&s);
- if(max < 0) return -1;
- if(max < min)
+ if(!isdigit(*s))
{
- fprintf(stderr, "cut: Error: decreasing range: %zu-%zu\n", min, max);
- return -1;
+ nostop = true;
+ }
+ else
+ {
+ max = parse_list_num(&s);
+ if(max < 0) return -1;
+
+ if(max < min)
+ {
+ fprintf(stderr, "cut: Error: decreasing range: %zu-%zu\n", min, max);
+ return -1;
+ }
}
}
@@ -98,7 +108,7 @@ parse_list(char *s)
if((size_t)max > list_len)
{
- list = reallocarray(list, max, sizeof(*list));
+ list = reallocarray(list, (size_t)max, sizeof(*list));
if(list == NULL)
{
fprintf(stderr, "cut: Memory allocation error: %s\n", strerror(errno));
@@ -153,9 +163,13 @@ cut_b(FILE *in, const char *filename)
continue;
}
+ if(line[nread - 1] == '\n') line[nread--] = '\0';
+
for(size_t i = 0; i < MIN(list_len, (size_t)nread); i++)
if(list[i]) fputc(line[i], stdout);
+ if(nostop && (size_t)nread > list_len) fwrite(line + list_len, nread - list_len, 1, stdout);
+
fputc('\n', stdout);
}
@@ -194,6 +208,8 @@ cut_c(FILE *in, const char *filename)
continue;
}
+ if(line[nread - 1] == '\n') line[nread--] = '\0';
+
if(nread > line_wsz)
{
line_w = reallocarray(line_w, nread, sizeof(*line_w));
@@ -218,9 +234,16 @@ cut_c(FILE *in, const char *filename)
//DEBUG fprintf(stderr, "cut: mbstowcs(_, _, %zu) => %zu\n", nread, wcread);
- for(size_t i = 0; i < MIN(list_len, wcread); i++)
+ size_t i = 0;
+ for(; i < MIN(list_len, wcread); i++)
if(list[i]) fputwc(line_w[i], stdout);
+ if(nostop && wcread > list_len)
+ {
+ for(; i < wcread; i++)
+ fputwc(line_w[i], stdout);
+ }
+
fputc('\n', stdout);
}
@@ -266,6 +289,17 @@ cut_f(FILE *in, const char *filename)
char *toks = NULL;
for(char *c = strtok_r(line, &delim, &toks); c != NULL; c = strtok_r(NULL, &delim, &toks), i++)
{
+ if(i >= list_len)
+ {
+ if(!nostop) break;
+
+ if(need_sep) fputc(delim, stdout);
+
+ fputs(c, stdout);
+ need_sep = true;
+ continue;
+ }
+
if(list[i])
{
if(need_sep) fputc(delim, stdout);
diff --git a/test-cmd/cut.sh b/test-cmd/cut.sh
@@ -4,18 +4,23 @@
WD="$(dirname "$0")/../"
target="${WD}/cmd/cut"
-plans=6
+plans=9
. "${WD}/test-cmd/tap.sh"
. "${WD}/test-cmd/init_env.sh"
t 'bytes:2-3,10-20,4,12' "-b 2-3,10-20,4,12 ${WD}/test-cmd/inputs/alnum" '1239ABCDEFGHIJ
'
+t 'bytes:11-' "-b 11- ${WD}/test-cmd/inputs/alnum" 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+'
t --exit=1 'bytes:,' "-b , ${WD}/test-cmd/inputs/alnum" 'cut: Error: empty list element
'
# Example taken from POSIX cut(1)
t --input='abcdefghi' 'chars:6,2,4-7,1' '-c 6,2,4-7,1' 'abdefg
'
+t 'chars:11-' "-c 11- ${WD}/test-cmd/inputs/alnum" 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+'
+
t --input='aéb' 'widechar' '-c2' 'é
'
@@ -31,3 +36,8 @@ b
t --input="$fields" s_f2 '-s -f2' '2
b
'
+
+t --input="$fields" f2- '-f2-' '2 3 4
+
+b c
+'