V10/cmd/fmt.c

Compare this file to the similar file:
Show the results in this format:

/*% cyntax % && cc -go # %
 * block up paragraphs, possibly with indentation
 */
#include <libc.h>
#include <stdio.h>
#include <ctype.h>
int indent=0;		/* how many spaces to indent */
int length=70;		/* how many columns per output line */
main(argc, argv)
char *argv[];
{
	register i;
	register FILE *f;
	for(i=1;i!=argc && argv[i][0]=='-';i++){
		switch(argv[i][1]){
		case 'i':
			if(argv[i][2])
				indent=atoi(argv[i]+2);
			else if(i+1<argc){
				indent=atoi(argv[i+1]);
				i++;
			}
			else
				goto Usage;
			break;
		case 'w':
		case 'l':
			if(argv[i][2])
				length=atoi(argv[i]+2);
			else if(i+1<argc){
				length=atoi(argv[i+1]);
				i++;
			}
			else
				goto Usage;
			break;
		default:
		Usage:
			fprintf(stderr,
				"Usage: %s [-i number] [-l number] [file ...]\n",
				argv[0]);
			exit(1);
		}
	}
	if(length<=indent){
		fprintf(stderr, "%s: line length<=indentation\n", argv[0]);
		exit(1);
	}
	if(i==argc)
		fmt(stdin);
	else{
		for(;i!=argc;i++){
			f=fopen(argv[i], "r");
			if(f==0)
				perror(argv[i]);
			else{
				fmt(f);
				fclose(f);
				if(i!=argc-1)
					putchar('\n');
			}
		}
	}
	exit(0);
}
fmt(f)
register FILE *f;
{
	register c;
	while((c=getc(f))!=EOF)
		outchar(c);
	flush();
}
#define TAB 8
#define	NWORD	(TAB*32)
char word[NWORD+1];
char *wp=word;
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(1) or init space(2) */
outchar(c){
	switch(c){
	case '\0':
		break;
	case '\n':
		switch(newline){
		case 0:
			outword();
			break;
		case 1:
			flush();
		case 2:
			putchar('\n');
			wp=word;
		}
		newline=1;
		break;
	case ' ':
	case '\t':
		switch(newline) {
		case 0:
			outword();
			break;
		case 1:
			flush();
			newline=2;
		case 2:
			do {
				addchar(' ');
			} while(c=='\t' && (wp-word)%TAB);
		}
		break;
	default:
		addchar(c);
		newline=0;
	}
}
addchar(c)
{
	if(wp==&word[NWORD]) {
		if(strchr(" \t",wp[-1]))
			wp=word;
		outword();
	}
	*wp++=c;
}
outword(){
	register i;
	if(wp==word)
		return;
	if(wp-word+col+(bol?0:punct?2:1)>length){
		putchar('\n');
		col=0;
		bol=1;
	}
	if(col==0){
		for(i=0;i+8<=indent;i+=8)
			putchar('\t');
		while(i++<indent)
			putchar(' ');
		col=indent;
	}
	if(bol)
		bol=0;
	else{
		if(punct){
			putchar(' ');
			col++;
		}
		putchar(' ');
		col++;
	}
	*wp='\0';
	puncttest();
	printf("%s", word);
	col+=wp-word;
	wp=word;
}
/* is the word followed by major punctuation, .?:! */
/* disregard short things followed by periods; they are probably
   initials or titles like Mrs. and Dr. */
puncttest()
{
	char *ep;
	punct = 0;
	for(ep=wp; --ep>=word; ) {
		switch(*ep) {
		case ')': case '\'': case '"':
			continue;
		case '.':
			if(isupper(*word)&&ep-word<=3)
				return;
		case '?': case ':': case '!':
			punct = 1;
		default:
			return;
		}
	}
}
flush(){
	outword();
	if(col!=0){
		putchar('\n');
		col=0;
		bol=1;
	}
}