logo

utils-std

Collection of commonly available Unix tools
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:

Mcmd/seq.c63+++++++++++++++++++++++++++++++++++++++++++++++++++------------
Mtest-cmd/seq16++++++++++++++++
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 }