Created
February 5, 2010 01:55
-
-
Save atr000/295400 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* A word wrapper | |
* Copyright (C) 2009 | |
* Andreas Harnack (ah8 at freenet dot de) | |
* This software is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* You should have received a copy of the GNU General Public License along | |
* with this library; see the file COPYING. If not, write to the Free | |
* Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, | |
* USA. | |
* As a special exception, you may use this file as part of a free software | |
* library without restriction. Specifically, if other files instantiate | |
* templates or use macros or inline functions from this file, or you compile | |
* this file and link it with other files to produce an executable, this | |
* file does not by itself cause the resulting executable to be covered by | |
* the GNU General Public License. This exception does not however | |
* invalidate any other reasons why the executable file might be covered by | |
* the GNU General Public License. | |
*/ | |
#include <ctype.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
char *progname; | |
int getint(const char* p) { return p ? atoi(p) : 0; } | |
int getval(int v, int d) { return v > 0 ? v : d; } | |
int ws(int ch) { | |
return isspace(ch); | |
} | |
void putb(char* buffer, char* end, FILE *out) { | |
while ( buffer < end ) putc(*buffer++, out); | |
} | |
int wordwrap(char *buffer, char *lineend, FILE *in, FILE *out) | |
{ | |
/* Note: the first character of a line is never being buffered, */ | |
/* the buffer is expected to be of size linelength - 1, */ | |
/* lineend is expected to point at buffer[sizeof(buffer)] */ | |
char *token; /* points to the first character of a buffered token */ | |
char *index; /* points to the position where the next character is */ | |
/* going to be buffered, the current line length is */ | |
/* given by (index-buffer) + 1 */ | |
int ch = 0; | |
state_0: | |
/* read white-spaces at the beginning of a line */ | |
/* i.e. before the first character of the first */ | |
/* token has been seen */ | |
if ( (ch = getc(in)) == EOF ) | |
/* line hasn't started yet, no need to terminate one */ | |
return 0; | |
else if ( ws(ch) ) | |
goto state_0; | |
else { | |
/* print first character of token */ | |
putc(ch, out); | |
/* index is used to count line length */ | |
/* buffer points to the second character in the line */ | |
index = buffer; | |
goto state_1; | |
} | |
state_1: | |
/* read the first token of a line, it is neither buffered */ | |
/* nor truncated but printed as it is read, only the length */ | |
/* is being counted; it might exceed the line length */ | |
if ( (ch = getc(in)) == EOF ) { | |
/* terminate line */ | |
putc('\n', out); | |
return 0; | |
} | |
else if ( ws(ch) ) { | |
/* reserve space for whitespace and check line length*/ | |
if ( ++index < lineend ) | |
/* some space left: continue line */ | |
goto state_2; | |
else { | |
/* no space left: terminate line */ | |
putc('\n', out); | |
goto state_0; | |
} | |
} | |
else { | |
/* print token character */ | |
putc(ch, out); | |
/* count line length, stop at line end */ | |
if ( index < lineend ) | |
++index; | |
goto state_1; | |
} | |
state_2: | |
/* read white-spaces between two tokens, it might be the */ | |
/* end of the line; the output is just behind the previous */ | |
/* token, the index at the beginning of the next (after a */ | |
/* potential separating white-space); there is guarantied */ | |
/* to be space for at least one more character on the */ | |
/* current line */ | |
if ( (ch = getc(in)) == EOF ) { | |
/* terminate line */ | |
putc('\n', out); | |
return 0; | |
} | |
else if ( ws(ch) ) | |
goto state_2; | |
else { | |
/* remember current index */ | |
token = index; | |
/* buffer token character */ | |
*index++ = ch; | |
goto state_3; | |
} | |
state_3: | |
/* read subsequent token on the line; the token is */ | |
/* buffered and checked for length, the buffered token */ | |
/* is guarantied to fit on the current line; if the token */ | |
/* exceeds he line length , the line is terminated and the */ | |
/* buffered part printed at the beginning of the next line */ | |
if ( (ch = getc(in)) == EOF ) { | |
/* print buffered token, terminate line */ | |
putc(' ', out); | |
putb(token, index, out); | |
putc('\n', out); | |
return 0; | |
} | |
else if ( ws(ch) ) { | |
/* print buffered token */ | |
putc(' ', out); | |
putb(token, index, out); | |
/* reserve space for whitespace and check line length*/ | |
if ( ++index < lineend ) | |
/* some space left: continue line */ | |
goto state_2; | |
else { | |
/* no space left: terminate line */ | |
putc('\n', out); | |
goto state_0; | |
} | |
} | |
else { | |
/* check line length */ | |
if ( index < lineend ) { | |
/* some space left: buffer token character */ | |
*index++ = ch; | |
goto state_3; | |
} | |
else { | |
/* no space left: terminate line, print token */ | |
putc('\n', out); | |
putb(token, index, out); | |
putc(ch, out); | |
/* adjust index to token length */ | |
index = buffer + (index-token); | |
goto state_1; | |
} | |
} | |
} | |
const char *helptext = | |
" -help: this text\n" | |
" -<num>: set line width to <num>\n" | |
; | |
int main(int argc, char *argv[]) | |
{ | |
char *buffer, *lineend; | |
int pagewidth = 72; | |
progname = *argv; | |
pagewidth = getval(getint(getenv("PAGEWIDTH")), pagewidth); | |
for( ++argv; *argv!=NULL && **argv=='-'; ++argv) { | |
if((*((*argv)+1))=='\0') | |
break; /* stdin */ | |
else if ( strcmp(*argv, "-help") == 0 ) { | |
fprintf(stdout, helptext); | |
exit(0); | |
} | |
else if ( (pagewidth=atoi(*argv+1)) > 0 ) | |
; | |
else { | |
fprintf(stderr, "%s: unknown option: %s\n" | |
" (see -help for details)\n", progname, *argv); | |
exit(1); | |
} | |
} | |
buffer = malloc(--pagewidth); | |
if ( ! buffer ) { | |
fprintf(stderr, "%s: can't allocate buffer\n", progname); | |
exit(2); | |
} | |
lineend = buffer+pagewidth; | |
if( *argv == NULL ) | |
return wordwrap(buffer, lineend, stdin, stdout); | |
else for(; *argv != NULL; argv++) { | |
int retcode = 0; | |
FILE *fp; | |
if ( strcmp(*argv, "-") == 0 ) | |
retcode = wordwrap(buffer, lineend, stdin, stdout); | |
else if( (fp=fopen(*argv, "r")) != NULL ) { | |
retcode = wordwrap(buffer, lineend, stdin, stdout); | |
fclose(fp); | |
} | |
else { | |
fprintf(stderr, "%s: can't open %s\n", progname, *argv); | |
exit(2); | |
} | |
if ( retcode ) | |
return retcode; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment