diff options
Diffstat (limited to 'usr/src/lib/libcmd/common/fold.c')
-rw-r--r-- | usr/src/lib/libcmd/common/fold.c | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/usr/src/lib/libcmd/common/fold.c b/usr/src/lib/libcmd/common/fold.c new file mode 100644 index 0000000000..459ad35850 --- /dev/null +++ b/usr/src/lib/libcmd/common/fold.c @@ -0,0 +1,242 @@ +/*********************************************************************** +* * +* This software is part of the ast package * +* Copyright (c) 1992-2007 AT&T Knowledge Ventures * +* and is licensed under the * +* Common Public License, Version 1.0 * +* by AT&T Knowledge Ventures * +* * +* 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 <gsf@research.att.com> * +* David Korn <dgk@research.att.com> * +* * +***********************************************************************/ +#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 <cmd.h> + +#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<<CHAR_BIT]; + + cmdinit(argc, argv, context, ERROR_CATALOG, 0); + memset(cols, 0, sizeof(cols)); + cols['\t'] = T_TAB; + cols['\b'] = T_BS; + cols['\n'] = T_NL; + cols['\r'] = T_RET; + for (;;) + { + switch (optget(argv, usage)) + { + case 0: + break; + case 'b': + cols['\r'] = cols['\b'] = 0; + cols['\t'] = cols[' ']; + continue; + case 'c': + contsize = stresc(cont = strdup(opt_info.arg)); + continue; + case 'd': + if (n = *opt_info.arg) + cols[n] = T_SP; + continue; + case 's': + cols[' '] = T_SP; + if(cols['\t']==0) + cols['\t'] = T_SP; + continue; + case 'w': + if ((width = opt_info.num) <= 0) + error(2, "%d: width must be positive", opt_info.num); + continue; + case ':': + error(2, "%s", opt_info.arg); + continue; + case '?': + error(ERROR_usage(2), "%s", opt_info.arg); + continue; + } + break; + } + argv += opt_info.index; + argc -= opt_info.index; + if(error_info.errors) + error(ERROR_usage(2),"%s", optusage(NiL)); + if(cp = *argv) + argv++; + do + { + if(!cp || streq(cp,"-")) + fp = sfstdin; + else if(!(fp = sfopen(NiL,cp,"r"))) + { + error(ERROR_system(0),"%s: cannot open",cp); + error_info.errors = 1; + continue; + } + fold(fp,sfstdout,width,cont,contsize,cols); + if(fp!=sfstdin) + sfclose(fp); + } + while(cp= *argv++); + return(error_info.errors); +} |