Attached is a first shot at seq(1) for sbase. I do not like having to
juggle data around to play games with sprintf, so if someone has a
cleaner approach to this program, please speak up.
Specifically: everything inside the if(wflag){} block is truly awful.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#include "util.h"
int
main(int argc, char *argv[])
{
char c;
char *fmtin;
char fmt[4096];
char *sep;
char tmp[4096];
char *d;
int maxl = 0;
int maxr = 0;
bool wflag = false;
double end = 1.0;
double start = 1.0;
double step = 1.0;
double out = start;
sep = "\n";
fmtin = "%G";
while((c = getopt(argc, argv, "f:s:w")) != -1)
switch(c) {
case 'f':
fmtin = optarg;
/* TODO: validate this (freebsd does this ok) */
break;
case 's':
sep = optarg;
break;
case 'w':
wflag = true;
break;
}
switch(argc-optind) {
case 3:
start=atof(argv[optind++]);
step=atof(argv[optind++]);
end=atof(argv[optind]);
break;
case 2:
start=atof(argv[optind++]);
step=1.0;
end=atof(argv[optind]);
break;
case 1:
start=1.0;
step=1.0;
end=atof(argv[optind]);
break;
default:
eprintf("usage: seq [-f'fmt'] [-s'separator'] [-w] [start [step]] end\n");
}
if (step==0) eprintf("increment value can't be zero\n");
sprintf(fmt, "%s", fmtin);
if (wflag) {
sprintf(tmp, fmt, end);
d = strchr(tmp, '.');
if (d) {
maxl = d-tmp;
maxr = strlen(strchr(tmp, '.')+1);
} else {
maxl = strlen(tmp);
}
sprintf(fmt,"%%0%d.%df", maxl+maxr+1, maxr);
printf("%s\n", fmt);
}
for (out = start; out <= end; out += step) {
printf(fmt, out);
printf("%s", sep);
}
return EXIT_SUCCESS;
}