Adding seq command.

This commit is contained in:
Christoph Lohmann 2012-04-10 17:33:19 +02:00
parent ff96728bdd
commit e8d6e30106
3 changed files with 170 additions and 0 deletions

View File

@ -8,6 +8,8 @@ MIT/X Consortium License
© 2011 pancake <pancake@youterm.com> © 2011 pancake <pancake@youterm.com>
© 2011 Random832 <random832@fastmail.us> © 2011 Random832 <random832@fastmail.us>
© 2012 William Haddon <william@haddonthethird.net> © 2012 William Haddon <william@haddonthethird.net>
© 2012 Kurt H. Maier <khm@intma.in>
© 2012 Christoph Lohmann <20h@r-36.net>
Permission is hereby granted, free of charge, to any person obtaining a Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"), copy of this software and associated documentation files (the "Software"),

View File

@ -51,6 +51,7 @@ SRC = \
true.c \ true.c \
tty.c \ tty.c \
uname.c \ uname.c \
seq.c \
wc.c wc.c
OBJ = $(SRC:.c=.o) $(LIB) OBJ = $(SRC:.c=.o) $(LIB)

167
seq.c Normal file
View File

@ -0,0 +1,167 @@
/* See LICENSE file for copyright and license details. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#include <libgen.h>
#include "util.h"
char afmt[4096];
char *
getalignedwidthfmt(char *fmt, char *starts, char *steps, char *ends)
{
char starttmp[4096], steptmp[4096], endtmp[4096];
char *startdelim, *stepdelim, *enddelim;
int startl, startr, stepr, endl, endr;
int maxl, maxr;
/*
* 1.) Get a temp buffer we can work in.
* 2.) Calculate the *r(ight) and *l(eft) size.
*/
memmove(starttmp, starts, strlen(starts)+1);
startdelim = strchr(starttmp, '.');
if (startdelim != NULL) {
startdelim[0] = '\0';
startr = strlen(startdelim+1);
} else {
startr = 0;
}
startl = strlen(starttmp);
if (starttmp[0] == '+')
startl--;
memmove(endtmp, ends, strlen(ends)+1);
enddelim = strchr(endtmp, '.');
if (enddelim != NULL) {
enddelim[0] = '\0';
endr = strlen(enddelim+1);
} else {
endr = 0;
}
endl = strlen(endtmp);
if (endtmp[0] == '+')
endl--;
/*
* We do not care for the left length of the step, because it
* will never be displayed.
*/
memmove(steptmp, steps, strlen(steps)+1);
stepdelim = strchr(steptmp, '.');
if (stepdelim != NULL) {
stepdelim[0] = '\0';
stepr = strlen(stepdelim+1);
} else {
stepr = 0;
}
maxl = (startl > endl)? startl : endl;
maxr = (startl > endr)? startr : endr;
if (stepr > maxr)
maxr = stepr;
if (maxl <= 1) {
snprintf(afmt, sizeof(afmt), "%%.%df", maxr);
} else if (maxr == 0) {
snprintf(afmt, sizeof(afmt), "%%0%d.f", maxl);
} else {
snprintf(afmt, sizeof(afmt), "%%0%d.%df", maxl+maxr+1, maxr);
}
return afmt;
}
int
main(int argc, char *argv[])
{
char c, *fmt, *sep, *starts, *steps, *ends;
bool wflag = false;
double start, step, end, out;
sep = "\n";
fmt = "%G";
starts = "1";
steps = "1";
ends = "1";
while((c = getopt(argc, argv, "f:s:w")) != -1) {
switch(c) {
case 'f':
fmt = optarg;
break;
case 's':
sep = optarg;
break;
case 'w':
wflag = true;
break;
}
}
switch(argc-optind) {
case 3:
starts = argv[optind++];
steps = argv[optind++];
ends = argv[optind++];
break;
case 2:
starts = argv[optind++];
ends = argv[optind++];
break;
case 1:
ends = argv[optind++];
break;
default:
eprintf("usage: %s [-f fmt] [-s separator] [-w] [start [step]]"
" end\n", basename(argv[0]));
}
start = atof(starts);
step = atof(steps);
end = atof(ends);
if (step == 0)
return EXIT_FAILURE;
if (start > end) {
if (step > 0)
return EXIT_FAILURE;
} else if (start < end) {
if (step < 0)
return EXIT_FAILURE;
}
if (wflag)
fmt = getalignedwidthfmt(fmt, starts, steps, ends);
printf("%s\n", fmt);
for (out = start;;) {
printf(fmt, out);
out += step;
if (start > end) {
if (out >= end) {
printf("%s", sep);
} else {
break;
}
} else if (start < end) {
if (out <= end) {
printf("%s", sep);
} else {
break;
}
} else {
break;
}
}
printf("\n");
return EXIT_SUCCESS;
}