commit: 7c1fea1925ff2dfe5e7e51584984f2d31896fd83
parent d25112bfeffcb4d0a2fbc3f3fb2bb6ca6e21fcc4
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Thu, 14 Mar 2024 20:10:24 +0100
cmd/seq: implement -w option
Diffstat:
M | cmd/seq.c | 63 | +++++++++++++++++++++++++++++++++++++++++++++++++++------------ |
M | test-cmd/seq | 16 | ++++++++++++++++ |
2 files changed, 67 insertions(+), 12 deletions(-)
diff --git a/cmd/seq.c b/cmd/seq.c
@@ -5,39 +5,41 @@
#define _POSIX_C_SOURCE 200809L
#include "../lib/absu.h"
+#include <ctype.h> // isdigit
#include <errno.h> // errno
#include <stdbool.h> // bool, true, false
#include <stdio.h> // puts, fprintf
#include <stdlib.h> // atoi, exit
+#include <string.h> // strlen
#include <unistd.h> // getopt, optarg, optind
-char *separator = "\n";
-bool zero_pad = false;
+char *sep = "\n";
+int len = 0;
-void
+static void
seq(long i, unsigned long step, long last)
{
if(i == last)
{
- printf("%li\n", i);
+ printf("%0*li\n", len, i);
}
else if(i < last)
{
for(; i < last; i += step)
- printf("%li%s", i, separator);
+ printf("%0*li%s", len, i, sep);
- if(i <= last) printf("%li\n", i);
+ if(i <= last) printf("%0*li\n", len, i);
}
else if(i > last)
{
for(; i > last; i -= step)
- printf("%li%s", i, separator);
+ printf("%0*li%s", len, i, sep);
- if(i >= last) printf("%li\n", i);
+ if(i >= last) printf("%0*li\n", len, i);
}
}
-long
+static long
get_num(char *str)
{
errno = 0;
@@ -53,7 +55,20 @@ get_num(char *str)
return num;
}
-void
+static size_t
+digits(char *s)
+{
+ size_t c = 0;
+
+ if(*s == '-') s++, c++;
+
+ for(; *s != 0; s++)
+ if(isdigit(*s)) c++;
+
+ return c;
+}
+
+static void
usage(void)
{
fprintf(stderr, "usage: seq [-w] [-s separator] [first [step]] last\n");
@@ -63,6 +78,7 @@ int
main(int argc, char *argv[])
{
int c;
+ bool opt_w = false;
/* flawfinder: ignore. Old implementations of getopt should fix themselves */
while((c = getopt(argc, argv, ":ws:")) != -1)
@@ -70,16 +86,23 @@ main(int argc, char *argv[])
switch(c)
{
case 'w':
- zero_pad = true;
+ opt_w = true;
break;
case 's':
- separator = optarg;
+ sep = optarg;
break;
case '?':
+ if(isdigit(optopt))
+ {
+ fprintf(stderr, "seq: Warning: Pass -- if the first non-option argument starts with a dash(-)\n");
+ optind--;
+ goto getopt_end;
+ }
usage();
return 1;
}
}
+getopt_end:
argc -= optind;
argv += optind;
@@ -92,15 +115,31 @@ main(int argc, char *argv[])
{
case 1:
last = get_num(argv[0]);
+
+ if(opt_w) len = digits(argv[0]);
break;
case 2:
first = get_num(argv[0]);
last = get_num(argv[1]);
+
+ if(opt_w)
+ {
+ size_t f_len = digits(argv[0]);
+ size_t l_len = digits(argv[1]);
+ len = f_len > l_len ? f_len : l_len;
+ }
break;
case 3:
first = get_num(argv[0]);
step = labsu(get_num(argv[1]));
last = get_num(argv[2]);
+
+ if(opt_w)
+ {
+ size_t f_len = digits(argv[0]);
+ size_t l_len = digits(argv[2]);
+ len = f_len > l_len ? f_len : l_len;
+ }
break;
default:
usage();
diff --git a/test-cmd/seq b/test-cmd/seq
@@ -67,6 +67,18 @@ limits_body() {
atf_check -s exit:1 ../cmd/seq -- -9223372036854775807 -9223372036854775809
}
+atf_test_case initial_d
+initial_d_body() {
+ atf_check -e "inline:seq: Warning: Pass -- if the first non-option argument starts with a dash(-)\n" -o "inline:-3\n-2\n-1\n0\n" ../cmd/seq -3 0
+}
+
+atf_test_case width
+width_body() {
+ atf_check -o "inline:-1\n04\n09\n14\n" ../cmd/seq -w -- -1 5 15
+ atf_check -o "inline:-3\n-2\n-1\n00\n" ../cmd/seq -w -- -3 1 0
+ atf_check -o "inline:-10\n-11\n-12\n-13\n-14\n-15\n" ../cmd/seq -w -- -10 1 -15
+}
+
atf_init_test_cases() {
cd "$(atf_get_srcdir)" || exit 1
@@ -79,4 +91,8 @@ atf_init_test_cases() {
atf_add_test_case noarg
atf_add_test_case badflag
#atf_add_test_case limits
+
+ atf_add_test_case initial_d
+
+ atf_add_test_case width
}