Fixes and checks for seq. Thanks David Galos!
This commit is contained in:
parent
d512d7938e
commit
29ce2560a7
1
LICENSE
1
LICENSE
@ -10,6 +10,7 @@ MIT/X Consortium License
|
|||||||
© 2012 William Haddon <william@haddonthethird.net>
|
© 2012 William Haddon <william@haddonthethird.net>
|
||||||
© 2012 Kurt H. Maier <khm@intma.in>
|
© 2012 Kurt H. Maier <khm@intma.in>
|
||||||
© 2012 Christoph Lohmann <20h@r-36.net>
|
© 2012 Christoph Lohmann <20h@r-36.net>
|
||||||
|
© 2012 David Galos <galosd83@students.rowan.edu>
|
||||||
|
|
||||||
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"),
|
||||||
|
1
Makefile
1
Makefile
@ -52,6 +52,7 @@ SRC = \
|
|||||||
tty.c \
|
tty.c \
|
||||||
uname.c \
|
uname.c \
|
||||||
seq.c \
|
seq.c \
|
||||||
|
seq-test.c \
|
||||||
wc.c
|
wc.c
|
||||||
|
|
||||||
OBJ = $(SRC:.c=.o) $(LIB)
|
OBJ = $(SRC:.c=.o) $(LIB)
|
||||||
|
147
seq.c
147
seq.c
@ -5,85 +5,81 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
|
#include <regex.h>
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
char afmt[4096];
|
#define MAX(a, b) (((a) > (b))? (a):(b))
|
||||||
|
|
||||||
char *
|
int
|
||||||
getalignedwidthfmt(char *fmt, char *starts, char *steps, char *ends)
|
validfloat(char *fmt)
|
||||||
{
|
{
|
||||||
char starttmp[4096], steptmp[4096], endtmp[4096];
|
char *end;
|
||||||
char *startdelim, *stepdelim, *enddelim;
|
|
||||||
int startl, startr, stepr, endl, endr;
|
|
||||||
int maxl, maxr;
|
|
||||||
|
|
||||||
/*
|
fmt += strspn(fmt, " ");
|
||||||
* 1.) Get a temp buffer we can work in.
|
strtod(fmt, &end);
|
||||||
* 2.) Calculate the *r(ight) and *l(eft) size.
|
if (fmt == end || end != fmt + strlen(fmt))
|
||||||
*/
|
return 0;
|
||||||
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);
|
return 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;
|
int
|
||||||
maxr = (startl > endr)? startr : endr;
|
digitsleft(char *d)
|
||||||
if (stepr > maxr)
|
{
|
||||||
maxr = stepr;
|
char *exp;
|
||||||
|
int shift;
|
||||||
|
|
||||||
if (maxl <= 1) {
|
if (d[0] == '-' || d[0] == '+')
|
||||||
snprintf(afmt, sizeof(afmt), "%%.%df", maxr);
|
d++;
|
||||||
} else if (maxr == 0) {
|
exp = strpbrk(d, "eE");
|
||||||
snprintf(afmt, sizeof(afmt), "%%0%d.f", maxl);
|
shift = exp? atoi(exp+1) : 0;
|
||||||
} else {
|
|
||||||
snprintf(afmt, sizeof(afmt), "%%0%d.%df", maxl+maxr+1, maxr);
|
return MAX(0, strspn(d, "0123456789")+shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
return afmt;
|
int
|
||||||
|
digitsright(char *d)
|
||||||
|
{
|
||||||
|
char *exp;
|
||||||
|
int shift, after;
|
||||||
|
|
||||||
|
if (d[0] == '-' || d[0] == '+')
|
||||||
|
d++;
|
||||||
|
exp = strpbrk(d, "eE");
|
||||||
|
shift = exp ? atoi(exp+1) : 0;
|
||||||
|
after = (d = strchr(d, '.'))? strspn(d+1, "0123456789") : 0;
|
||||||
|
|
||||||
|
return MAX(0, after-shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
validfmt(char *fmt)
|
||||||
|
{
|
||||||
|
regex_t reg;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
regcomp(®, "\\([^%]|%%\\)*%[0-9]*\\.[0-9]*[fFgG]"
|
||||||
|
"\\([^%]|%%\\)*", REG_NOSUB);
|
||||||
|
ret = regexec(®, fmt, 0, NULL, 0);
|
||||||
|
regfree(®);
|
||||||
|
|
||||||
|
return (ret == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
char c, *fmt, *sep, *starts, *steps, *ends;
|
char c, *fmt, ftmp[4096], *sep, *starts, *steps, *ends;
|
||||||
bool wflag = false;
|
bool wflag, fflag;
|
||||||
double start, step, end, out;
|
double start, step, end, out;
|
||||||
|
int left, right;
|
||||||
|
|
||||||
sep = "\n";
|
sep = "\n";
|
||||||
fmt = "%G";
|
fmt = ftmp;
|
||||||
|
|
||||||
|
wflag = false;
|
||||||
|
fflag = false;
|
||||||
|
|
||||||
starts = "1";
|
starts = "1";
|
||||||
steps = "1";
|
steps = "1";
|
||||||
@ -92,7 +88,10 @@ main(int argc, char *argv[])
|
|||||||
while((c = getopt(argc, argv, "f:s:w")) != -1) {
|
while((c = getopt(argc, argv, "f:s:w")) != -1) {
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case 'f':
|
case 'f':
|
||||||
|
if (!validfmt(optarg))
|
||||||
|
eprintf("invalid format.\n");
|
||||||
fmt = optarg;
|
fmt = optarg;
|
||||||
|
fflag = true;
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
sep = optarg;
|
sep = optarg;
|
||||||
@ -103,6 +102,9 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wflag && fflag)
|
||||||
|
eprintf("-f and -w cannot be combined.\n");
|
||||||
|
|
||||||
switch(argc-optind) {
|
switch(argc-optind) {
|
||||||
case 3:
|
case 3:
|
||||||
starts = argv[optind++];
|
starts = argv[optind++];
|
||||||
@ -117,10 +119,18 @@ main(int argc, char *argv[])
|
|||||||
ends = argv[optind++];
|
ends = argv[optind++];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
eprintf("usage: %s [-w] [-f fmt] [-s separator] [start [step]]"
|
eprintf("usage: %s [-w] [-f fmt] [-s separator] "
|
||||||
" end\n", basename(argv[0]));
|
"[start [step]] end\n",
|
||||||
|
basename(argv[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!validfloat(starts))
|
||||||
|
eprintf("start is not a valid float.\n");
|
||||||
|
if (!validfloat(steps))
|
||||||
|
eprintf("step is not a valid float.\n");
|
||||||
|
if (!validfloat(ends))
|
||||||
|
eprintf("end is not a valid float.\n");
|
||||||
|
|
||||||
start = atof(starts);
|
start = atof(starts);
|
||||||
step = atof(steps);
|
step = atof(steps);
|
||||||
end = atof(ends);
|
end = atof(ends);
|
||||||
@ -136,9 +146,18 @@ main(int argc, char *argv[])
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wflag)
|
right = MAX(digitsright(starts),
|
||||||
fmt = getalignedwidthfmt(fmt, starts, steps, ends);
|
MAX(digitsright(ends),
|
||||||
printf("%s\n", fmt);
|
digitsright(steps)));
|
||||||
|
if (wflag) {
|
||||||
|
left = MAX(digitsleft(starts), digitsleft(ends));
|
||||||
|
|
||||||
|
snprintf(ftmp, sizeof(ftmp), "%%0%d.%df",
|
||||||
|
right+left+(right != 0),
|
||||||
|
right);
|
||||||
|
} else if (fmt == ftmp) {
|
||||||
|
snprintf(ftmp, sizeof(ftmp), "%%.%df", right);
|
||||||
|
}
|
||||||
|
|
||||||
for (out = start;;) {
|
for (out = start;;) {
|
||||||
printf(fmt, out);
|
printf(fmt, out);
|
||||||
|
Loading…
Reference in New Issue
Block a user