Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libcmd/fold.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1992-2012 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* David Korn <[email protected]> *
19
* *
20
***********************************************************************/
21
#pragma prototyped
22
/*
23
* David Korn
24
* AT&T Bell Laboratories
25
*
26
* fold
27
*/
28
29
static const char usage[] =
30
"[-?\n@(#)$Id: fold (AT&T Research) 2004-11-18 $\n]"
31
USAGE_LICENSE
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 "
41
"specially:]{"
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.]"
51
"}"
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.]"
55
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.]"
66
"\n"
67
"\n[file ...]\n"
68
"\n"
69
"[+EXIT STATUS?]{"
70
"[+0?All files processed successfully.]"
71
"[+>0?An error occurred.]"
72
"}"
73
"[+SEE ALSO?\bpaste\b(1)]"
74
;
75
76
77
#include <cmd.h>
78
79
#define WIDTH 80
80
#define TABSIZE 8
81
82
#define T_EOF 1
83
#define T_NL 2
84
#define T_BS 3
85
#define T_TAB 4
86
#define T_SP 5
87
#define T_RET 6
88
89
static void fold(Sfio_t *in, Sfio_t *out, register int width, const char *cont, size_t contsize, char *cols)
90
{
91
register char *cp, *first;
92
register int n, col=0, x=0;
93
register char *last_space=0;
94
cols[0] = 0;
95
for (;;)
96
{
97
if (!(cp = sfgetr(in,'\n',0)))
98
{
99
if (!(cp = sfgetr(in,'\n',-1)) || (n = sfvalue(in)) <= 0)
100
break;
101
x = cp[--n];
102
cp[n] = '\n';
103
}
104
/* special case -b since no column adjustment is needed */
105
if(cols['\b']==0 && (n=sfvalue(in))<=width)
106
{
107
sfwrite(out,cp,n);
108
continue;
109
}
110
first = cp;
111
col = 0;
112
last_space = 0;
113
for(;;)
114
{
115
while((n=cols[*(unsigned char*)cp++])==0);
116
while((cp-first) > (width-col))
117
{
118
if(last_space)
119
col = last_space - first;
120
else
121
col = width-col;
122
sfwrite(out,first,col);
123
first += col;
124
col = 0;
125
last_space = 0;
126
if(cp>first+1 || (n!=T_NL && n!=T_BS))
127
sfwrite(out, cont, contsize);
128
}
129
switch(n)
130
{
131
case T_NL:
132
if(x)
133
*(cp-1) = x;
134
break;
135
case T_RET:
136
col = 0;
137
continue;
138
case T_BS:
139
if((cp+(--col)-first)>0)
140
col--;
141
continue;
142
case T_TAB:
143
n = (TABSIZE-1) - (cp+col-1-first)&(TABSIZE-1);
144
col +=n;
145
if((cp-first) > (width-col))
146
{
147
sfwrite(out,first,(--cp)-first);
148
sfwrite(out, cont, contsize);
149
first = cp;
150
col = TABSIZE-1;
151
last_space = 0;
152
continue;
153
}
154
if(cols[' '])
155
last_space = cp;
156
continue;
157
case T_SP:
158
last_space = cp;
159
continue;
160
default:
161
continue;
162
}
163
break;
164
}
165
sfwrite(out,first,cp-first);
166
}
167
}
168
169
int
170
b_fold(int argc, char** argv, Shbltin_t* context)
171
{
172
register int n, width=WIDTH;
173
register Sfio_t *fp;
174
register char *cp;
175
char *cont="\n";
176
size_t contsize = 1;
177
char cols[1<<CHAR_BIT];
178
179
cmdinit(argc, argv, context, ERROR_CATALOG, 0);
180
memset(cols, 0, sizeof(cols));
181
cols['\t'] = T_TAB;
182
cols['\b'] = T_BS;
183
cols['\n'] = T_NL;
184
cols['\r'] = T_RET;
185
for (;;)
186
{
187
switch (optget(argv, usage))
188
{
189
case 'b':
190
cols['\r'] = cols['\b'] = 0;
191
cols['\t'] = cols[' '];
192
continue;
193
case 'c':
194
contsize = stresc(cont = strdup(opt_info.arg));
195
continue;
196
case 'd':
197
if (n = *opt_info.arg)
198
cols[n] = T_SP;
199
continue;
200
case 's':
201
cols[' '] = T_SP;
202
if(cols['\t']==0)
203
cols['\t'] = T_SP;
204
continue;
205
case 'w':
206
if ((width = opt_info.num) <= 0)
207
error(2, "%d: width must be positive", opt_info.num);
208
continue;
209
case ':':
210
error(2, "%s", opt_info.arg);
211
continue;
212
case '?':
213
error(ERROR_usage(2), "%s", opt_info.arg);
214
continue;
215
}
216
break;
217
}
218
argv += opt_info.index;
219
argc -= opt_info.index;
220
if(error_info.errors)
221
error(ERROR_usage(2),"%s", optusage(NiL));
222
if(cp = *argv)
223
argv++;
224
do
225
{
226
if(!cp || streq(cp,"-"))
227
fp = sfstdin;
228
else if(!(fp = sfopen(NiL,cp,"r")))
229
{
230
error(ERROR_system(0),"%s: cannot open",cp);
231
error_info.errors = 1;
232
continue;
233
}
234
fold(fp,sfstdout,width,cont,contsize,cols);
235
if(fp!=sfstdin)
236
sfclose(fp);
237
}
238
while(cp= *argv++);
239
return(error_info.errors);
240
}
241
242