henesyinit from p9fd787fda5 years agoHistory
259 lines · 3.9 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <bio.h>#include <ctype.h> /* * block up paragraphs, possibly with indentation */ void	fmt(Biobuf*);void	outchar(Rune);void	addrune(Rune);void	outword(void);void	puncttest(void);void	flush(void);void nextline(void); int join = 1;			/* can input lines be joined? */int indent = 0;			/* how many spaces to indent */int tindent = 0;		/* temporary extra indent */int length = 70;		/* how many columns per output line */int maxtab = 8;Biobuf bin;Biobuf bout; voidusage(void){	fprint(2, "usage: %s [-j] [-i indent] [-l length] [file...]\n", argv0);	exits("usage");} voidmain(int argc, char **argv){	int i, f;	char *s, *err; 	ARGBEGIN{	case 'i':		indent = atoi(EARGF(usage()));		break;	case 'j':		join = 0;		break;	case 'w':	case 'l':		length = atoi(EARGF(usage()));		break;	default:		usage();	}ARGEND 	if(length <= indent){		fprint(2, "%s: line length<=indentation\n", argv0);		exits("length");	} 	s=getenv("tabstop");	if(s!=nil && atoi(s)>0)		maxtab=atoi(s);	err = nil;	Binit(&bout, 1, OWRITE);	if(argc <= 0){		Binit(&bin, 0, OREAD);		fmt(&bin);	}else{		for(i=0; i<argc; i++){			f = open(argv[i], OREAD);			if(f < 0){				fprint(2, "%s: can't open %s: %r\n", argv0, argv[i]);				err = "open";			}else{				Binit(&bin, f, OREAD);				fmt(&bin);				Bterm(&bin);				if(i != argc-1)					Bputc(&bout, '\n');			}		}	}	exits(err);}voidfmt(Biobuf *f){	long c; 	while((c = Bgetrune(f)) >= 0)		outchar((Rune) c);	flush();} #define	NWORD	(maxtab*32) Rune *word;int mword;int wp; int col = 0;		/* output column number */int bol = 1;		/* at beginning of output line? */int punct = 0;		/* last character out was punctuation? */int newline = 1;	/* last char read was newline */int nspace = 0;		/* number of spaces beginning this line */ intaddspace(int nspace, Rune c){	if(c == ' ')		return nspace+1;	/* else tab */	nspace = ((nspace/maxtab)+1)*maxtab;	return nspace;} voidoutchar(Rune c){	switch(c){	case '\0':		break;	case '\n':		switch(newline){		case 0:			if(join)				outword();			else				flush();			break;		case 1:			flush();		case 2:			tindent = 0;			Bputc(&bout, '\n');			wp = 0;		}		newline = 1;		break;	case ' ':	case '\t':		switch(newline) {		case 0:			outword();			break;		case 1:			nspace = addspace(nspace, c);			outword();			break;		}		break;	default:		if(nspace > 0){			if(!newline && tindent != nspace){				nextline();				newline = 1;			}			tindent = nspace;			nspace = 0;		}else			if(newline){				if(tindent)					nextline();				tindent = 0;			}		addrune(c);		newline = 0;	}} voidaddrune(Rune c){	if(wp==mword) {		if(mword == 0)			mword = 10;		else			mword *= 2;		word = realloc(word, sizeof(Rune)*mword);		if(word == nil) {			fprint(2, "fmt: out of memory\n");			exits("out of memory");		}	}	word[wp++] = c;} voidoutword(void){	int i; 	if(wp == 0)		return;	if(wp+col+(bol?0:punct?2:1) > length){		Bputc(&bout, '\n');		col = 0;		bol = 1;	}	if(col == 0){		for(i=0; i+maxtab <= indent+tindent; i+=maxtab)			Bputc(&bout, '\t');		while(i++ < indent+tindent)			Bputc(&bout, ' ');		col = indent+tindent;	}	if(bol)		bol = 0;	else{		if(punct){			Bputc(&bout, ' ');			col++;		}		Bputc(&bout, ' ');		col++;	}	puncttest();	for (i = 0; i < wp; i++)		Bputrune(&bout, word[i]);	col += i;	wp = 0;} /* is the word followed by major punctuation, .?:! *//* disregard short things followed by periods; they are probably   initials or titles like Mrs. and Dr. */voidpuncttest(void){	int rp; 	punct = 0;	for(rp=wp; --rp>=0; ) {		switch(word[rp]) {		case ')': case '\'': case '"':			continue;		case '.':			if(isupper(*word)&&rp<=3)				return;		case '?': case '!': /*case ':':*/			punct = 1;		default:			return;		}	}}voidnextline(void){	Bputc(&bout, '\n');	col = 0;	bol = 1;}voidflush(void){	outword();	if(col != 0)		nextline();}