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;
}
    

Reply via email to