logo

utils

~/.local/bin tools and git-hooks git clone https://hacktivis.me/git/utils.git

seq.c (1886B)


  1. // Collection of Unix tools, comparable to coreutils
  2. // SPDX-FileCopyrightText: 2017-2022 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
  3. // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
  4. #define _POSIX_C_SOURCE 200809L
  5. #include <errno.h> // errno
  6. #include <stdbool.h> // bool, true, false
  7. #include <stdio.h> // puts, fprintf
  8. #include <stdlib.h> // atoi, exit
  9. #include <unistd.h> // getopt, optarg, optind
  10. char *separator = "\n";
  11. bool zero_pad = false;
  12. void
  13. seq(long i, long step, long last)
  14. {
  15. if(i == last)
  16. {
  17. printf("%li%s", i, separator);
  18. }
  19. else if(i < last)
  20. {
  21. for(; i <= last; i += step)
  22. printf("%li%s", i, separator);
  23. }
  24. else if(i > last)
  25. {
  26. for(; i >= last; i -= step)
  27. printf("%li%s", i, separator);
  28. }
  29. }
  30. static long unsigned int
  31. safe_labs(long int a)
  32. {
  33. if(a >= 0)
  34. {
  35. return (long unsigned int)a;
  36. }
  37. else
  38. {
  39. return (long unsigned int)-a;
  40. }
  41. }
  42. long
  43. get_num(char *str)
  44. {
  45. errno = 0;
  46. long num = strtol(str, NULL, 10);
  47. if(errno != 0)
  48. {
  49. perror("seq: strtol:");
  50. exit(1);
  51. }
  52. return num;
  53. }
  54. void
  55. usage(void)
  56. {
  57. fprintf(stderr, "usage: seq [-w] [-s separator] [first [step]] last\n");
  58. }
  59. int
  60. main(int argc, char *argv[])
  61. {
  62. int c;
  63. /* flawfinder: ignore. Old implementations of getopt should fix themselves */
  64. while((c = getopt(argc, argv, ":ws:")) != -1)
  65. {
  66. switch(c)
  67. {
  68. case 'w':
  69. zero_pad = true;
  70. break;
  71. case 's':
  72. separator = optarg;
  73. break;
  74. case '?':
  75. usage();
  76. return 1;
  77. }
  78. }
  79. argc -= optind;
  80. argv += optind;
  81. long first = 1;
  82. long step = 1;
  83. long last = 1;
  84. switch(argc)
  85. {
  86. case 1:
  87. last = get_num(argv[0]);
  88. break;
  89. case 2:
  90. first = get_num(argv[0]);
  91. last = get_num(argv[1]);
  92. break;
  93. case 3:
  94. first = get_num(argv[0]);
  95. step = (long)safe_labs(get_num(argv[1]));
  96. last = get_num(argv[2]);
  97. break;
  98. default:
  99. usage();
  100. return 1;
  101. }
  102. seq(first, step, last);
  103. return 0;
  104. }