#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFSIZE 1000000

int main(int argc,char *argv[]){
	int Si,N,Sr,i,k,l,v,s;
	FILE *in,*out;
	char dump[BUFSIZE+1];
	
	if ((argc<2)||(3!=sscanf(argv[1],"%d,%d,%d",&Si,&N,&Sr))) {
		fprintf(stderr,"\n  usage: catranges RANGE_EXPRESSION [INFILE [OUTFILE]]\n\n  catranges echoes ranges of lines. RANGE_EXPRESSION has syntax 'Si,N,Sr',\n  where initially Si lines are skipped, and then repeatedly N lines are\n  echoed and Sr lines are skipped until the end of the stream is reached.\n  If given, data are read from INFILE and echoed to OUTFILE, otherwise\n  STDIN and STDOUT is used, which can also be specified by the character '-'.\n  To effect an equivalent action for record separators different from\n  newlines, consider chaining with the tool tr.\n\n");
		exit(EXIT_FAILURE);
	}
	
	if ((argc>2)&&((strlen(argv[2])>1)||(argv[2][0]!='-'))) {
		if ((in=fopen(argv[2],"rt"))==NULL) {
			fprintf(stderr,"Could not open %s for reading.\n",argv[2]);
			exit(EXIT_FAILURE);
		}
	} else in=stdin;
	
	if ((argc>3)&&((strlen(argv[3])>1)||(argv[3][0]!='-'))) {
		if ((out=fopen(argv[3],"wt"))==NULL) {
			fprintf(stderr,"Could not open %s for writing.\n",argv[3]);
			exit(EXIT_FAILURE);
		}
	} else out=stdout;
	
	if (Si>0) {
		l=Si;	//number of lines left to read
		v=0;		//now skipping
	} else {
		l=N;
		v=1;
	}
READ:
	k=fread(dump,1,BUFSIZE,in);	//end of dump
	if (k==0) return 0;
	dump[k]='\n';				//dummy for breaking loop
	i=0;						//position in dump
	s=0;						//start here when writing out
	while (1) if (dump[i++]=='\n') {
		if (i==k+1) {	//dummy is hit
			if (v==1) fwrite(dump+s,1,k-s,out);
			goto READ;
		}
		--l;
		if (l==0) {
			if (v==1) {
				fwrite(dump+s,1,i-s,out);
				v=0;
				l=Sr;
			} else {
				v=1;
				s=i;
				l=N;
			}
		}
	}
}
