/*********************************************************************** * * * This software is part of the ast package * * Copyright (c) 1992-2007 AT&T Intellectual Property * * and is licensed under the * * Common Public License, Version 1.0 * * by AT&T Intellectual Property * * * * A copy of the License is available at * * http://www.opensource.org/licenses/cpl1.0.txt * * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * * * * Information and Software Systems Research * * AT&T Research * * Florham Park NJ * * * * Glenn Fowler * * David Korn * * * ***********************************************************************/ #pragma prototyped /* * David Korn * AT&T Bell Laboratories * * fold */ static const char usage[] = "[-?\n@(#)$Id: fold (AT&T Research) 2004-11-18 $\n]" USAGE_LICENSE "[+NAME?fold - fold lines]" "[+DESCRIPTION?\bfold\b is a filter that folds lines from its input, " "breaking the lines to have a maximum of \awidth\a column " "positions (or bytes if the \b-b\b option is specified). Lines " "are broken by the insertion of a newline character such that " "each output line is the maximum width possible that does not " "exceed the specified number of column positions, (or bytes). A line " "will not be broken in the middle of a character.] " "[+?Unless the \b-b\b option is specified, the following will be treated " "specially:]{" "[+carriage-return?The current count of line width will be set " "to zero. \bfold\b will not insert a newline immediately " "before or after a carriage-return.]" "[+backspace?If positive, the current count of line width will be " "decremented by one. \bfold\b will not insert a newline " "immediately before or after a backspace.]" "[+tab?Each tab character encountered will advance the column " "position to the next tab stop. Tab stops are at each " "column position \an\a, where \an\a modulo 8 equals 1.]" "}" "[+?If no \afile\a is given, or if the \afile\a is \b-\b, \bfold\b " "reads from standard input. The start of the file is defined " "as the current offset.]" "[b:bytes?Count bytes rather than columns so that each carriage-return, " "backspace, and tab counts as 1.]" "[c:continue?Emit \atext\a at line splits.]:[text:='\\n']" "[d:delimiter?Break at \adelim\a boundaries.]:[delim]" "[s:spaces?Break at word boundaries. If the line contains any blanks, " "(spaces or tabs), within the first \awidth\a column positions or " "bytes, the line is broken after the last blank meeting the " "\awidth\a constraint.]" "[w:width]#[width:=80?Use a maximum line length of \awidth\a columns " "instead of the default.]" "\n" "\n[file ...]\n" "\n" "[+EXIT STATUS?]{" "[+0?All files processed successfully.]" "[+>0?An error occurred.]" "}" "[+SEE ALSO?\bpaste\b(1)]" ; #include #define WIDTH 80 #define TABSIZE 8 #define T_EOF 1 #define T_NL 2 #define T_BS 3 #define T_TAB 4 #define T_SP 5 #define T_RET 6 static void fold(Sfio_t *in, Sfio_t *out, register int width, const char *cont, size_t contsize, char *cols) { register char *cp, *first; register int n, col=0, x=0; register char *last_space=0; cols[0] = 0; for (;;) { if (!(cp = sfgetr(in,'\n',0))) { if (!(cp = sfgetr(in,'\n',-1)) || (n = sfvalue(in)) <= 0) break; x = cp[--n]; cp[n] = '\n'; } /* special case -b since no column adjustment is needed */ if(cols['\b']==0 && (n=sfvalue(in))<=width) { sfwrite(out,cp,n); continue; } first = cp; col = 0; last_space = 0; for(;;) { while((n=cols[*(unsigned char*)cp++])==0); while((cp-first) > (width-col)) { if(last_space) col = last_space - first; else col = width-col; sfwrite(out,first,col); first += col; col = 0; last_space = 0; if(cp>first+1 || (n!=T_NL && n!=T_BS)) sfwrite(out, cont, contsize); } switch(n) { case T_NL: if(x) *(cp-1) = x; break; case T_RET: col = 0; continue; case T_BS: if((cp+(--col)-first)>0) col--; continue; case T_TAB: n = (TABSIZE-1) - (cp+col-1-first)&(TABSIZE-1); col +=n; if((cp-first) > (width-col)) { sfwrite(out,first,(--cp)-first); sfwrite(out, cont, contsize); first = cp; col = TABSIZE-1; last_space = 0; continue; } if(cols[' ']) last_space = cp; continue; case T_SP: last_space = cp; continue; default: continue; } break; } sfwrite(out,first,cp-first); } } int b_fold(int argc, char *argv[], void* context) { register int n, width=WIDTH; register Sfio_t *fp; register char *cp; char *cont="\n"; size_t contsize = 1; char cols[1<