1 /***********************************************************************
3 * This software is part of the ast package *
4 * Copyright (c) 1992-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
20 ***********************************************************************/
24 * AT&T Bell Laboratories
29 static const char usage
[] =
30 "[-?\n@(#)$Id: fold (AT&T Research) 2004-11-18 $\n]"
32 "[+NAME?fold - fold lines]"
33 "[+DESCRIPTION?\bfold\b is a filter that folds lines from its input, "
34 "breaking the lines to have a maximum of \awidth\a column "
35 "positions (or bytes if the \b-b\b option is specified). Lines "
36 "are broken by the insertion of a newline character such that "
37 "each output line is the maximum width possible that does not "
38 "exceed the specified number of column positions, (or bytes). A line "
39 "will not be broken in the middle of a character.] "
40 "[+?Unless the \b-b\b option is specified, the following will be treated "
42 "[+carriage-return?The current count of line width will be set "
43 "to zero. \bfold\b will not insert a newline immediately "
44 "before or after a carriage-return.]"
45 "[+backspace?If positive, the current count of line width will be "
46 "decremented by one. \bfold\b will not insert a newline "
47 "immediately before or after a backspace.]"
48 "[+tab?Each tab character encountered will advance the column "
49 "position to the next tab stop. Tab stops are at each "
50 "column position \an\a, where \an\a modulo 8 equals 1.]"
52 "[+?If no \afile\a is given, or if the \afile\a is \b-\b, \bfold\b "
53 "reads from standard input. The start of the file is defined "
54 "as the current offset.]"
56 "[b:bytes?Count bytes rather than columns so that each carriage-return, "
57 "backspace, and tab counts as 1.]"
58 "[c:continue?Emit \atext\a at line splits.]:[text:='\\n']"
59 "[d:delimiter?Break at \adelim\a boundaries.]:[delim]"
60 "[s:spaces?Break at word boundaries. If the line contains any blanks, "
61 "(spaces or tabs), within the first \awidth\a column positions or "
62 "bytes, the line is broken after the last blank meeting the "
63 "\awidth\a constraint.]"
64 "[w:width]#[width:=80?Use a maximum line length of \awidth\a columns "
65 "instead of the default.]"
70 "[+0?All files processed successfully.]"
71 "[+>0?An error occurred.]"
73 "[+SEE ALSO?\bpaste\b(1)]"
89 static void fold(Sfio_t
*in
, Sfio_t
*out
, register int width
, const char *cont
, size_t contsize
, char *cols
)
91 register char *cp
, *first
;
92 register int n
, col
=0, x
=0;
93 register char *last_space
=0;
97 if (!(cp
= sfgetr(in
,'\n',0)))
99 if (!(cp
= sfgetr(in
,'\n',-1)) || (n
= sfvalue(in
)) <= 0)
104 /* special case -b since no column adjustment is needed */
105 if(cols
['\b']==0 && (n
=sfvalue(in
))<=width
)
115 while((n
=cols
[*(unsigned char*)cp
++])==0);
116 while((cp
-first
) > (width
-col
))
119 col
= last_space
- first
;
122 sfwrite(out
,first
,col
);
126 if(cp
>first
+1 || (n
!=T_NL
&& n
!=T_BS
))
127 sfwrite(out
, cont
, contsize
);
139 if((cp
+(--col
)-first
)>0)
143 n
= (TABSIZE
-1) - (cp
+col
-1-first
)&(TABSIZE
-1);
145 if((cp
-first
) > (width
-col
))
147 sfwrite(out
,first
,(--cp
)-first
);
148 sfwrite(out
, cont
, contsize
);
165 sfwrite(out
,first
,cp
-first
);
170 b_fold(int argc
, char *argv
[], void* context
)
172 register int n
, width
=WIDTH
;
177 char cols
[1<<CHAR_BIT
];
179 cmdinit(argc
, argv
, context
, ERROR_CATALOG
, 0);
180 memset(cols
, 0, sizeof(cols
));
187 switch (optget(argv
, usage
))
192 cols
['\r'] = cols
['\b'] = 0;
193 cols
['\t'] = cols
[' '];
196 contsize
= stresc(cont
= strdup(opt_info
.arg
));
199 if (n
= *opt_info
.arg
)
208 if ((width
= opt_info
.num
) <= 0)
209 error(2, "%d: width must be positive", opt_info
.num
);
212 error(2, "%s", opt_info
.arg
);
215 error(ERROR_usage(2), "%s", opt_info
.arg
);
220 argv
+= opt_info
.index
;
221 argc
-= opt_info
.index
;
222 if(error_info
.errors
)
223 error(ERROR_usage(2),"%s", optusage(NiL
));
228 if(!cp
|| streq(cp
,"-"))
230 else if(!(fp
= sfopen(NiL
,cp
,"r")))
232 error(ERROR_system(0),"%s: cannot open",cp
);
233 error_info
.errors
= 1;
236 fold(fp
,sfstdout
,width
,cont
,contsize
,cols
);
241 return(error_info
.errors
);