logo

utils

~/.local/bin tools and git-hooks git clone https://hacktivis.me/git/utils.git
commit: 0207b4eb7ba7228bd84e24207d2ab1c55a6663af
parent 2a84b987813114a0e325fd3fed7c178d87103dc4
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Wed,  2 Mar 2022 14:32:34 +0100

bin/range: Transform into bin/seq

Diffstat:

Dbin/range.c54------------------------------------------------------
Abin/seq.c104+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtest-bin/Kyuafile1+
Atest-bin/seq54++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 159 insertions(+), 54 deletions(-)

diff --git a/bin/range.c b/bin/range.c @@ -1,54 +0,0 @@ -// Collection of Unix tools, comparable to coreutils -// Copyright 2017-2022 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> -// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only - -#define _POSIX_C_SOURCE 200809L -#include <stdio.h> -#include <stdlib.h> - -char *IFS; -int a, b; - -void -usage(char *a0) -{ - printf("usage: %s [ini <max>]\n", a0); -} - -void -range(int initial, int maximum) -{ - printf("%i", initial); - if(initial < maximum) - { - for(initial++; initial <= maximum; initial++) - printf("%s%i", IFS, initial); - } - else if(initial > maximum) - { - for(initial--; initial >= maximum; initial--) - printf("%s%i", IFS, initial); - } -} - -int -main(int argc, char *argv[]) -{ - if(!(IFS = getenv("IFS"))) - { - IFS = " "; - } - - if(argc == 2) - { - range(0, atoi(argv[1])); - } - else if(argc == 3) - { - range(atoi(argv[1]), atoi(argv[2])); - } - else - { - usage(argv[0]); - } -} diff --git a/bin/seq.c b/bin/seq.c @@ -0,0 +1,104 @@ +// Collection of Unix tools, comparable to coreutils +// Copyright 2017-2022 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> +// SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only + +#define _POSIX_C_SOURCE 200809L +#include <errno.h> // errno +#include <stdbool.h> // bool, true, false +#include <stdio.h> // puts, fprintf +#include <stdlib.h> // atoi, exit +#include <unistd.h> // getopt, optarg, optind + +char *separator = "\n"; +bool zero_pad = false; + +void +seq(long i, long step, long last) +{ + if(i == last) + { + printf("%li%s", i, separator); + } + else if(i < last) + { + for(;i <= last; i += step) + printf("%li%s", i, separator); + } + else if(i > last) + { + for(;i >= last; i -= step) + printf("%li%s", i, separator); + } +} + +long +get_num(char *str) +{ + errno = 0; + + long num = strtol(str, NULL, 10); + + if(errno != 0) + { + perror("seq: strtol:"); + exit(1); + } + + return num; +} + +void +usage(void) +{ + fprintf(stderr, "usage: seq [-w] [-s separator] [first [step]] last\n"); +} + +int +main(int argc, char *argv[]) +{ + int c; + + /* flawfinder: ignore. Old implementations of getopt should fix themselves */ + while((c = getopt(argc, argv, ":ws:")) != -1) + { + switch(c) + { + case 'w': + zero_pad = true; + break; + case 's': + separator = optarg; + break; + } + } + + argc -= optind; + argv += optind; + + long first = 1; + long step = 1; + long last = 1; + + switch(argc) + { + case 1: + last = get_num(argv[0]); + break; + case 2: + first = get_num(argv[0]); + last = get_num(argv[1]); + break; + case 3: + first = get_num(argv[0]); + step = get_num(argv[1]); + last = get_num(argv[2]); + break; + default: + usage(); + return 1; + } + + seq(first, step, last); + + return 0; +} diff --git a/test-bin/Kyuafile b/test-bin/Kyuafile @@ -18,6 +18,7 @@ atf_test_program{name="false", required_files=basedir.."/bin/false"} atf_test_program{name="humanize", required_files=basedir.."/bin/humanize"} atf_test_program{name="mdate", required_files=basedir.."/bin/mdate"} atf_test_program{name="pwd", required_files=basedir.."/bin/pwd"} +atf_test_program{name="seq", required_files=basedir.."/bin/seq"} atf_test_program{name="sname", required_files=basedir.."/bin/sname"} atf_test_program{name="strings", required_files=basedir.."/bin/strings"} atf_test_program{name="tee", required_files=basedir.."/bin/tee"} diff --git a/test-bin/seq b/test-bin/seq @@ -0,0 +1,54 @@ +#!/usr/bin/env atf-sh +atf_test_case one +one_body() { + atf_check -o "inline:1\n" ../bin/seq 1 + atf_check -o "inline:1\n2\n3\n4\n5\n" ../bin/seq 5 +} + +atf_test_case two +two_body() { + atf_check -o "inline:0\n1\n" ../bin/seq 0 1 + atf_check -o "inline:0\n1\n2\n3\n4\n5\n" ../bin/seq 0 5 + atf_check -o "inline:10\n11\n12\n13\n14\n15\n" ../bin/seq 10 15 +} + +atf_test_case three +three_body() { + atf_check -o "inline:0\n1\n" ../bin/seq 0 1 1 + atf_check -o "inline:0\n1\n2\n3\n4\n5\n" ../bin/seq 0 1 5 + atf_check -o "inline:10\n11\n12\n13\n14\n15\n" ../bin/seq 10 1 15 + + atf_check -o "inline:0\n2\n4\n" ../bin/seq 0 2 5 + atf_check -o "inline:10\n12\n14\n" ../bin/seq 10 2 15 +} + +atf_test_case noarg +noarg_body() { + atf_check -s exit:1 -e 'inline:usage: seq [-w] [-s separator] [first [step]] last\n' ../bin/seq +} + +atf_test_case badflag +badflag_body() { + atf_check -s exit:1 -e 'inline:usage: seq [-w] [-s separator] [first [step]] last\n' ../bin/seq -f +} + +atf_test_case limits +limits_body() { + atf_check ../bin/seq 9223372036854775806 9223372036854775807 + atf_check -s exit:1 ../bin/seq 9223372036854775806 9223372036854775808 + + atf_check ../bin/seq -- -9223372036854775807 -9223372036854775808 + atf_check -s exit:1 ../bin/seq -- -9223372036854775807 -9223372036854775809 +} + +atf_init_test_cases() { + cd "$(atf_get_srcdir)" || exit 1 + + atf_add_test_case one + atf_add_test_case two + atf_add_test_case three + + atf_add_test_case noarg + atf_add_test_case badflag + #atf_add_test_case limits +}