1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*3e14f97fSRoger A. Faulkner * Copyright (c) 1992-2010 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6da2e3ebdSchin * Common Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt *
11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12da2e3ebdSchin * *
13da2e3ebdSchin * Information and Software Systems Research *
14da2e3ebdSchin * AT&T Research *
15da2e3ebdSchin * Florham Park NJ *
16da2e3ebdSchin * *
17da2e3ebdSchin * Glenn Fowler <gsf@research.att.com> *
18da2e3ebdSchin * David Korn <dgk@research.att.com> *
19da2e3ebdSchin * *
20da2e3ebdSchin ***********************************************************************/
21da2e3ebdSchin #pragma prototyped
22da2e3ebdSchin /*
23da2e3ebdSchin * David Korn
24da2e3ebdSchin * Glenn Fowler
25da2e3ebdSchin * AT&T Bell Laboratories
26da2e3ebdSchin *
27da2e3ebdSchin * cat
28da2e3ebdSchin */
29da2e3ebdSchin
30da2e3ebdSchin #include <cmd.h>
31da2e3ebdSchin #include <fcntl.h>
32da2e3ebdSchin
33da2e3ebdSchin static const char usage[] =
3434f9b3eeSRoland Mainz "[-?\n@(#)$Id: cat (AT&T Research) 2009-03-31 $\n]"
35da2e3ebdSchin USAGE_LICENSE
36da2e3ebdSchin "[+NAME?cat - concatenate files]"
37da2e3ebdSchin "[+DESCRIPTION?\bcat\b copies each \afile\a in sequence to the standard"
38da2e3ebdSchin " output. If no \afile\a is given, or if the \afile\a is \b-\b,"
39da2e3ebdSchin " \bcat\b copies from standard input starting at the current location.]"
40da2e3ebdSchin
41da2e3ebdSchin "[b:number-nonblank?Number lines as with \b-n\b but omit line numbers from"
42da2e3ebdSchin " blank lines.]"
43da2e3ebdSchin "[d:dos-input?Input files are opened in \atext\amode which removes carriage"
44da2e3ebdSchin " returns in front of new-lines on some systems.]"
45da2e3ebdSchin "[e?Equivalent to \b-vE\b.]"
46da2e3ebdSchin "[n:number?Causes a line number to be inserted at the beginning of each line.]"
47da2e3ebdSchin "[s?Equivalent to \b-S\b for \aatt\a universe and \b-B\b otherwise.]"
48da2e3ebdSchin "[t?Equivalent to \b-vT\b.]"
49da2e3ebdSchin "[u:unbuffer?The output is not delayed by buffering.]"
50da2e3ebdSchin "[v:show-nonprinting?Causes non-printing characters (whith the exception of"
51da2e3ebdSchin " tabs, new-lines, and form-feeds) to be output as printable charater"
52da2e3ebdSchin " sequences. ASCII control characters are printed as \b^\b\an\a,"
53da2e3ebdSchin " where \an\a is the corresponding ASCII character in the range"
54da2e3ebdSchin " octal 100-137. The DEL character (octal 0177) is copied"
55da2e3ebdSchin " as \b^?\b. Other non-printable characters are copied as \bM-\b\ax\a"
56da2e3ebdSchin " where \ax\a is the ASCII character specified by the low-order seven"
57da2e3ebdSchin " bits. Multibyte characters in the current locale are treated as"
58da2e3ebdSchin " printable characters.]"
59da2e3ebdSchin "[A:show-all?Equivalent to \b-vET\b.]"
60da2e3ebdSchin "[B:squeeze-blank?Multiple adjacent new-line characters are replace by one"
61da2e3ebdSchin " new-line.]"
62da2e3ebdSchin "[D:dos-output?Output files are opened in \atext\amode which inserts carriage"
63da2e3ebdSchin " returns in front of new-lines on some systems.]"
64da2e3ebdSchin "[E:show-ends?Causes a \b$\b to be inserted before each new-line.]"
6534f9b3eeSRoland Mainz "[R:regress?Regression test defaults: \b-v\b buffer size 4.]"
66da2e3ebdSchin "[S:silent?\bcat\b is silent about non-existent files.]"
67da2e3ebdSchin "[T:show-blank?Causes tabs to be copied as \b^I\b and formfeeds as \b^L\b.]"
68da2e3ebdSchin
69da2e3ebdSchin "\n"
70da2e3ebdSchin "\n[file ...]\n"
71da2e3ebdSchin "\n"
72da2e3ebdSchin
73da2e3ebdSchin "[+SEE ALSO?\bcp\b(1), \bgetconf\b(1), \bpr\b(1)]"
74da2e3ebdSchin ;
75da2e3ebdSchin
76da2e3ebdSchin #define RUBOUT 0177
77da2e3ebdSchin
78da2e3ebdSchin /* control flags */
79da2e3ebdSchin #define B_FLAG (1<<0)
80da2e3ebdSchin #define E_FLAG (1<<1)
81da2e3ebdSchin #define F_FLAG (1<<2)
82da2e3ebdSchin #define N_FLAG (1<<3)
83da2e3ebdSchin #define S_FLAG (1<<4)
84da2e3ebdSchin #define T_FLAG (1<<5)
85da2e3ebdSchin #define U_FLAG (1<<6)
86da2e3ebdSchin #define V_FLAG (1<<7)
87da2e3ebdSchin #define D_FLAG (1<<8)
88da2e3ebdSchin #define d_FLAG (1<<9)
89da2e3ebdSchin
90da2e3ebdSchin /* character types */
9134f9b3eeSRoland Mainz #define T_ERROR 1
9234f9b3eeSRoland Mainz #define T_EOF 2
9334f9b3eeSRoland Mainz #define T_ENDBUF 3
9434f9b3eeSRoland Mainz #define T_NEWLINE 4
9534f9b3eeSRoland Mainz #define T_CONTROL 5
9634f9b3eeSRoland Mainz #define T_EIGHTBIT 6
9734f9b3eeSRoland Mainz #define T_CNTL8BIT 7
98da2e3ebdSchin
99da2e3ebdSchin #define printof(c) ((c)^0100)
100da2e3ebdSchin
10134f9b3eeSRoland Mainz typedef void* (*Reserve_f)(Sfio_t*, ssize_t, int);
10234f9b3eeSRoland Mainz
10334f9b3eeSRoland Mainz #ifndef sfvalue
10434f9b3eeSRoland Mainz #define sfvalue(f) ((f)->_val)
10534f9b3eeSRoland Mainz #endif
10634f9b3eeSRoland Mainz
10734f9b3eeSRoland Mainz static void*
regress(Sfio_t * sp,ssize_t n,int f)10834f9b3eeSRoland Mainz regress(Sfio_t* sp, ssize_t n, int f)
10934f9b3eeSRoland Mainz {
11034f9b3eeSRoland Mainz void* r;
11134f9b3eeSRoland Mainz
11234f9b3eeSRoland Mainz if (!(r = sfreserve(sp, 4, f)))
11334f9b3eeSRoland Mainz r = sfreserve(sp, n, f);
11434f9b3eeSRoland Mainz else if (sfvalue(sp) > 4)
11534f9b3eeSRoland Mainz sfvalue(sp) = 4;
11634f9b3eeSRoland Mainz return r;
11734f9b3eeSRoland Mainz }
11834f9b3eeSRoland Mainz
119da2e3ebdSchin /*
120da2e3ebdSchin * called for any special output processing
121da2e3ebdSchin */
122da2e3ebdSchin
123da2e3ebdSchin static int
vcat(register char * states,Sfio_t * ip,Sfio_t * op,Reserve_f reserve,int flags)12434f9b3eeSRoland Mainz vcat(register char* states, Sfio_t* ip, Sfio_t* op, Reserve_f reserve, int flags)
125da2e3ebdSchin {
126da2e3ebdSchin register unsigned char* cp;
12734f9b3eeSRoland Mainz register unsigned char* pp;
12834f9b3eeSRoland Mainz unsigned char* cur;
12934f9b3eeSRoland Mainz unsigned char* end;
13034f9b3eeSRoland Mainz unsigned char* buf;
13134f9b3eeSRoland Mainz unsigned char* nxt;
132da2e3ebdSchin register int n;
13334f9b3eeSRoland Mainz register int line;
13434f9b3eeSRoland Mainz register int raw;
13534f9b3eeSRoland Mainz int last;
13634f9b3eeSRoland Mainz int c;
13734f9b3eeSRoland Mainz int m;
13834f9b3eeSRoland Mainz int any;
13934f9b3eeSRoland Mainz int header;
140da2e3ebdSchin
141da2e3ebdSchin unsigned char meta[4];
14234f9b3eeSRoland Mainz unsigned char tmp[32];
143da2e3ebdSchin
144da2e3ebdSchin meta[0] = 'M';
145da2e3ebdSchin meta[1] = '-';
14634f9b3eeSRoland Mainz last = -1;
14734f9b3eeSRoland Mainz *(cp = buf = end = tmp) = 0;
14834f9b3eeSRoland Mainz any = 0;
14934f9b3eeSRoland Mainz header = flags & (B_FLAG|N_FLAG);
15034f9b3eeSRoland Mainz line = 1;
15134f9b3eeSRoland Mainz states[0] = T_ENDBUF;
15234f9b3eeSRoland Mainz raw = !mbwide();
153da2e3ebdSchin for (;;)
154da2e3ebdSchin {
15534f9b3eeSRoland Mainz cur = cp;
15634f9b3eeSRoland Mainz if (raw)
15734f9b3eeSRoland Mainz while (!(n = states[*cp++]));
158da2e3ebdSchin else
15934f9b3eeSRoland Mainz for (;;)
160da2e3ebdSchin {
16134f9b3eeSRoland Mainz while (!(n = states[*cp++]));
16234f9b3eeSRoland Mainz if (n < T_CONTROL)
16334f9b3eeSRoland Mainz break;
16434f9b3eeSRoland Mainz if ((m = mbsize(pp = cp - 1)) > 1)
16534f9b3eeSRoland Mainz cp += m - 1;
16634f9b3eeSRoland Mainz else
167da2e3ebdSchin {
16834f9b3eeSRoland Mainz if (m <= 0)
169da2e3ebdSchin {
17034f9b3eeSRoland Mainz if (cur == pp)
17134f9b3eeSRoland Mainz {
17234f9b3eeSRoland Mainz if (last > 0)
17334f9b3eeSRoland Mainz {
17434f9b3eeSRoland Mainz *end = last;
17534f9b3eeSRoland Mainz last = -1;
17634f9b3eeSRoland Mainz c = end - pp + 1;
17734f9b3eeSRoland Mainz if ((m = mbsize(pp)) == c)
17834f9b3eeSRoland Mainz {
17934f9b3eeSRoland Mainz any = 1;
18034f9b3eeSRoland Mainz if (header)
18134f9b3eeSRoland Mainz {
18234f9b3eeSRoland Mainz header = 0;
18334f9b3eeSRoland Mainz sfprintf(op, "%6d\t", line);
18434f9b3eeSRoland Mainz }
18534f9b3eeSRoland Mainz sfwrite(op, cur, m);
18634f9b3eeSRoland Mainz *(cp = cur = end) = 0;
187da2e3ebdSchin }
188da2e3ebdSchin else
189da2e3ebdSchin {
19034f9b3eeSRoland Mainz memcpy(tmp, pp, c);
19134f9b3eeSRoland Mainz if (!(nxt = (unsigned char*)(*reserve)(ip, SF_UNBOUND, 0)))
19234f9b3eeSRoland Mainz {
19334f9b3eeSRoland Mainz states[0] = sfvalue(ip) ? T_ERROR : T_EOF;
19434f9b3eeSRoland Mainz *(cp = end = tmp + sizeof(tmp) - 1) = 0;
19534f9b3eeSRoland Mainz last = -1;
196da2e3ebdSchin }
19734f9b3eeSRoland Mainz else if ((n = sfvalue(ip)) <= 0)
19834f9b3eeSRoland Mainz {
19934f9b3eeSRoland Mainz states[0] = n ? T_ERROR : T_EOF;
20034f9b3eeSRoland Mainz *(cp = end = tmp + sizeof(tmp) - 1) = 0;
20134f9b3eeSRoland Mainz last = -1;
202da2e3ebdSchin }
20334f9b3eeSRoland Mainz else
20434f9b3eeSRoland Mainz {
20534f9b3eeSRoland Mainz cp = buf = nxt;
20634f9b3eeSRoland Mainz end = buf + n - 1;
20734f9b3eeSRoland Mainz last = *end;
20834f9b3eeSRoland Mainz *end = 0;
209da2e3ebdSchin }
21034f9b3eeSRoland Mainz mb:
21134f9b3eeSRoland Mainz if ((n = end - cp + 1) >= (sizeof(tmp) - c))
21234f9b3eeSRoland Mainz n = sizeof(tmp) - c - 1;
21334f9b3eeSRoland Mainz memcpy(tmp + c, cp, n);
21434f9b3eeSRoland Mainz if ((m = mbsize(tmp)) >= c)
21534f9b3eeSRoland Mainz {
21634f9b3eeSRoland Mainz any = 1;
21734f9b3eeSRoland Mainz if (header)
21834f9b3eeSRoland Mainz {
21934f9b3eeSRoland Mainz header = 0;
22034f9b3eeSRoland Mainz sfprintf(op, "%6d\t", line);
22134f9b3eeSRoland Mainz }
22234f9b3eeSRoland Mainz sfwrite(op, tmp, m);
22334f9b3eeSRoland Mainz cur = cp += m - c;
22434f9b3eeSRoland Mainz }
22534f9b3eeSRoland Mainz }
22634f9b3eeSRoland Mainz continue;
22734f9b3eeSRoland Mainz }
22834f9b3eeSRoland Mainz }
22934f9b3eeSRoland Mainz else
23034f9b3eeSRoland Mainz {
23134f9b3eeSRoland Mainz cp = pp + 1;
23234f9b3eeSRoland Mainz n = 0;
23334f9b3eeSRoland Mainz }
23434f9b3eeSRoland Mainz }
23534f9b3eeSRoland Mainz break;
23634f9b3eeSRoland Mainz }
23734f9b3eeSRoland Mainz }
23834f9b3eeSRoland Mainz c = *--cp;
23934f9b3eeSRoland Mainz if ((m = cp - cur) || n >= T_CONTROL)
24034f9b3eeSRoland Mainz {
24134f9b3eeSRoland Mainz flush:
24234f9b3eeSRoland Mainz any = 1;
24334f9b3eeSRoland Mainz if (header)
24434f9b3eeSRoland Mainz {
24534f9b3eeSRoland Mainz header = 0;
24634f9b3eeSRoland Mainz sfprintf(op, "%6d\t", line);
24734f9b3eeSRoland Mainz }
24834f9b3eeSRoland Mainz if (m)
24934f9b3eeSRoland Mainz sfwrite(op, cur, m);
25034f9b3eeSRoland Mainz }
25134f9b3eeSRoland Mainz special:
252da2e3ebdSchin switch (n)
253da2e3ebdSchin {
25434f9b3eeSRoland Mainz case T_ERROR:
25534f9b3eeSRoland Mainz if (cp != end)
256da2e3ebdSchin {
25734f9b3eeSRoland Mainz n = T_CONTROL;
25834f9b3eeSRoland Mainz goto flush;
259da2e3ebdSchin }
26034f9b3eeSRoland Mainz return -1;
26134f9b3eeSRoland Mainz case T_EOF:
26234f9b3eeSRoland Mainz if (cp != end)
263da2e3ebdSchin {
26434f9b3eeSRoland Mainz n = T_CONTROL;
26534f9b3eeSRoland Mainz goto flush;
266da2e3ebdSchin }
26734f9b3eeSRoland Mainz return 0;
26834f9b3eeSRoland Mainz case T_ENDBUF:
26934f9b3eeSRoland Mainz if (cp != end)
27034f9b3eeSRoland Mainz {
27134f9b3eeSRoland Mainz n = T_CONTROL;
27234f9b3eeSRoland Mainz goto flush;
27334f9b3eeSRoland Mainz }
27434f9b3eeSRoland Mainz c = last;
27534f9b3eeSRoland Mainz if (!(nxt = (unsigned char*)(*reserve)(ip, SF_UNBOUND, 0)))
27634f9b3eeSRoland Mainz {
27734f9b3eeSRoland Mainz *(cp = end = tmp) = 0;
27834f9b3eeSRoland Mainz states[0] = sfvalue(ip) ? T_ERROR : T_EOF;
27934f9b3eeSRoland Mainz last = -1;
28034f9b3eeSRoland Mainz }
28134f9b3eeSRoland Mainz else if ((m = sfvalue(ip)) <= 0)
28234f9b3eeSRoland Mainz {
28334f9b3eeSRoland Mainz *(cp = end = tmp) = 0;
28434f9b3eeSRoland Mainz states[0] = m ? T_ERROR : T_EOF;
28534f9b3eeSRoland Mainz last = -1;
28634f9b3eeSRoland Mainz }
28734f9b3eeSRoland Mainz else
28834f9b3eeSRoland Mainz {
28934f9b3eeSRoland Mainz buf = nxt;
29034f9b3eeSRoland Mainz end = buf + m - 1;
29134f9b3eeSRoland Mainz last = *end;
29234f9b3eeSRoland Mainz *end = 0;
29334f9b3eeSRoland Mainz cp = buf;
29434f9b3eeSRoland Mainz }
29534f9b3eeSRoland Mainz if (c >= 0)
29634f9b3eeSRoland Mainz {
29734f9b3eeSRoland Mainz if (!(n = states[c]))
29834f9b3eeSRoland Mainz {
29934f9b3eeSRoland Mainz *(cur = tmp) = c;
30034f9b3eeSRoland Mainz m = 1;
30134f9b3eeSRoland Mainz goto flush;
30234f9b3eeSRoland Mainz }
30334f9b3eeSRoland Mainz if (raw || n < T_CONTROL)
30434f9b3eeSRoland Mainz {
30534f9b3eeSRoland Mainz cp--;
30634f9b3eeSRoland Mainz goto special;
30734f9b3eeSRoland Mainz }
30834f9b3eeSRoland Mainz tmp[0] = c;
30934f9b3eeSRoland Mainz c = 1;
31034f9b3eeSRoland Mainz goto mb;
31134f9b3eeSRoland Mainz }
312da2e3ebdSchin break;
313da2e3ebdSchin case T_CONTROL:
314da2e3ebdSchin do
315da2e3ebdSchin {
31634f9b3eeSRoland Mainz sfputc(op, '^');
31734f9b3eeSRoland Mainz sfputc(op, printof(c));
31834f9b3eeSRoland Mainz } while (states[c = *++cp] == T_CONTROL);
319da2e3ebdSchin break;
32034f9b3eeSRoland Mainz case T_CNTL8BIT:
32134f9b3eeSRoland Mainz meta[2] = '^';
322da2e3ebdSchin do
323da2e3ebdSchin {
32434f9b3eeSRoland Mainz n = c & ~0200;
32534f9b3eeSRoland Mainz meta[3] = printof(n);
32634f9b3eeSRoland Mainz sfwrite(op, (char*)meta, 4);
32734f9b3eeSRoland Mainz } while (states[c = *++cp] == T_CNTL8BIT && raw);
328da2e3ebdSchin break;
32934f9b3eeSRoland Mainz case T_EIGHTBIT:
33034f9b3eeSRoland Mainz do
33134f9b3eeSRoland Mainz {
33234f9b3eeSRoland Mainz meta[2] = c & ~0200;
33334f9b3eeSRoland Mainz sfwrite(op, (char*)meta, 3);
33434f9b3eeSRoland Mainz } while (states[c = *++cp] == T_EIGHTBIT && raw);
33534f9b3eeSRoland Mainz break;
33634f9b3eeSRoland Mainz case T_NEWLINE:
33734f9b3eeSRoland Mainz if (header && !(flags & B_FLAG))
33834f9b3eeSRoland Mainz sfprintf(op, "%6d\t", line);
33934f9b3eeSRoland Mainz if (flags & E_FLAG)
34034f9b3eeSRoland Mainz sfputc(op, '$');
34134f9b3eeSRoland Mainz sfputc(op, '\n');
34234f9b3eeSRoland Mainz if (!header || !(flags & B_FLAG))
34334f9b3eeSRoland Mainz line++;
34434f9b3eeSRoland Mainz header = !(flags & S_FLAG);
34534f9b3eeSRoland Mainz for (;;)
34634f9b3eeSRoland Mainz {
34734f9b3eeSRoland Mainz if ((n = states[*++cp]) == T_ENDBUF)
34834f9b3eeSRoland Mainz {
34934f9b3eeSRoland Mainz if (cp != end || last != '\n')
35034f9b3eeSRoland Mainz break;
35134f9b3eeSRoland Mainz if (!(nxt = (unsigned char*)(*reserve)(ip, SF_UNBOUND, 0)))
35234f9b3eeSRoland Mainz {
35334f9b3eeSRoland Mainz states[0] = sfvalue(ip) ? T_ERROR : T_EOF;
35434f9b3eeSRoland Mainz cp = end = tmp;
35534f9b3eeSRoland Mainz *cp-- = 0;
35634f9b3eeSRoland Mainz last = -1;
357da2e3ebdSchin }
35834f9b3eeSRoland Mainz else if ((n = sfvalue(ip)) <= 0)
35934f9b3eeSRoland Mainz {
36034f9b3eeSRoland Mainz states[0] = n ? T_ERROR : T_EOF;
36134f9b3eeSRoland Mainz cp = end = tmp;
36234f9b3eeSRoland Mainz *cp-- = 0;
36334f9b3eeSRoland Mainz last = -1;
36434f9b3eeSRoland Mainz }
36534f9b3eeSRoland Mainz else
36634f9b3eeSRoland Mainz {
36734f9b3eeSRoland Mainz buf = nxt;
36834f9b3eeSRoland Mainz end = buf + n - 1;
36934f9b3eeSRoland Mainz last = *end;
37034f9b3eeSRoland Mainz *end = 0;
37134f9b3eeSRoland Mainz cp = buf - 1;
37234f9b3eeSRoland Mainz }
37334f9b3eeSRoland Mainz }
37434f9b3eeSRoland Mainz else if (n != T_NEWLINE)
37534f9b3eeSRoland Mainz break;
37634f9b3eeSRoland Mainz if (!(flags & S_FLAG) || any || header)
37734f9b3eeSRoland Mainz {
37834f9b3eeSRoland Mainz any = 0;
37934f9b3eeSRoland Mainz header = 0;
38034f9b3eeSRoland Mainz if ((flags & (B_FLAG|N_FLAG)) == N_FLAG)
38134f9b3eeSRoland Mainz sfprintf(op, "%6d\t", line);
38234f9b3eeSRoland Mainz if (flags & E_FLAG)
38334f9b3eeSRoland Mainz sfputc(op, '$');
38434f9b3eeSRoland Mainz sfputc(op, '\n');
38534f9b3eeSRoland Mainz }
38634f9b3eeSRoland Mainz if (!(flags & B_FLAG))
38734f9b3eeSRoland Mainz line++;
38834f9b3eeSRoland Mainz }
38934f9b3eeSRoland Mainz header = flags & (B_FLAG|N_FLAG);
39034f9b3eeSRoland Mainz break;
391da2e3ebdSchin }
392da2e3ebdSchin }
393da2e3ebdSchin }
394da2e3ebdSchin
395da2e3ebdSchin int
b_cat(int argc,char ** argv,void * context)396da2e3ebdSchin b_cat(int argc, char** argv, void* context)
397da2e3ebdSchin {
398da2e3ebdSchin register int n;
399da2e3ebdSchin register int flags = 0;
400da2e3ebdSchin register char* cp;
401da2e3ebdSchin register Sfio_t* fp;
402da2e3ebdSchin char* mode;
40334f9b3eeSRoland Mainz Reserve_f reserve = sfreserve;
404da2e3ebdSchin int att;
405da2e3ebdSchin int dovcat = 0;
406da2e3ebdSchin char states[UCHAR_MAX+1];
407da2e3ebdSchin
408da2e3ebdSchin cmdinit(argc, argv, context, ERROR_CATALOG, 0);
409da2e3ebdSchin att = !strcmp(astconf("UNIVERSE", NiL, NiL), "att");
410da2e3ebdSchin mode = "r";
411da2e3ebdSchin for (;;)
412da2e3ebdSchin {
41334f9b3eeSRoland Mainz n = 0;
414da2e3ebdSchin switch (optget(argv, usage))
415da2e3ebdSchin {
416da2e3ebdSchin case 'A':
41734f9b3eeSRoland Mainz n = T_FLAG|E_FLAG|V_FLAG;
41834f9b3eeSRoland Mainz break;
419da2e3ebdSchin case 'B':
42034f9b3eeSRoland Mainz n = S_FLAG;
42134f9b3eeSRoland Mainz break;
422da2e3ebdSchin case 'b':
42334f9b3eeSRoland Mainz n = B_FLAG;
42434f9b3eeSRoland Mainz break;
425da2e3ebdSchin case 'd':
42634f9b3eeSRoland Mainz mode = opt_info.num ? "rt" : "r";
427da2e3ebdSchin continue;
428da2e3ebdSchin case 'D':
42934f9b3eeSRoland Mainz n = d_FLAG;
43034f9b3eeSRoland Mainz break;
43134f9b3eeSRoland Mainz case 'E':
43234f9b3eeSRoland Mainz n = E_FLAG;
43334f9b3eeSRoland Mainz break;
43434f9b3eeSRoland Mainz case 'e':
43534f9b3eeSRoland Mainz n = E_FLAG|V_FLAG;
43634f9b3eeSRoland Mainz break;
43734f9b3eeSRoland Mainz case 'n':
43834f9b3eeSRoland Mainz n = N_FLAG;
43934f9b3eeSRoland Mainz break;
44034f9b3eeSRoland Mainz case 'R':
44134f9b3eeSRoland Mainz reserve = opt_info.num ? regress : sfreserve;
442da2e3ebdSchin continue;
44334f9b3eeSRoland Mainz case 's':
44434f9b3eeSRoland Mainz n = att ? F_FLAG : S_FLAG;
44534f9b3eeSRoland Mainz break;
44634f9b3eeSRoland Mainz case 'S':
44734f9b3eeSRoland Mainz n = F_FLAG;
44834f9b3eeSRoland Mainz break;
44934f9b3eeSRoland Mainz case 'T':
45034f9b3eeSRoland Mainz n = T_FLAG;
45134f9b3eeSRoland Mainz break;
45234f9b3eeSRoland Mainz case 't':
45334f9b3eeSRoland Mainz n = T_FLAG|V_FLAG;
45434f9b3eeSRoland Mainz break;
45534f9b3eeSRoland Mainz case 'u':
45634f9b3eeSRoland Mainz n = U_FLAG;
45734f9b3eeSRoland Mainz break;
45834f9b3eeSRoland Mainz case 'v':
45934f9b3eeSRoland Mainz n = V_FLAG;
46034f9b3eeSRoland Mainz break;
461da2e3ebdSchin case ':':
462da2e3ebdSchin error(2, "%s", opt_info.arg);
463da2e3ebdSchin break;
464da2e3ebdSchin case '?':
465da2e3ebdSchin error(ERROR_usage(2), "%s", opt_info.arg);
466da2e3ebdSchin break;
467da2e3ebdSchin }
46834f9b3eeSRoland Mainz if (!n)
469da2e3ebdSchin break;
47034f9b3eeSRoland Mainz if (opt_info.num)
47134f9b3eeSRoland Mainz flags |= n;
47234f9b3eeSRoland Mainz else
47334f9b3eeSRoland Mainz flags &= ~n;
474da2e3ebdSchin }
475da2e3ebdSchin argv += opt_info.index;
476da2e3ebdSchin if (error_info.errors)
477da2e3ebdSchin error(ERROR_usage(2), "%s", optusage(NiL));
478da2e3ebdSchin memset(states, 0, sizeof(states));
479da2e3ebdSchin if (flags&V_FLAG)
480da2e3ebdSchin {
481da2e3ebdSchin memset(states, T_CONTROL, ' ');
482da2e3ebdSchin states[RUBOUT] = T_CONTROL;
483da2e3ebdSchin memset(states+0200, T_EIGHTBIT, 0200);
484da2e3ebdSchin memset(states+0200, T_CNTL8BIT, ' ');
485da2e3ebdSchin states[RUBOUT|0200] = T_CNTL8BIT;
486da2e3ebdSchin states['\n'] = 0;
487da2e3ebdSchin }
488da2e3ebdSchin if (flags&T_FLAG)
489da2e3ebdSchin states['\t'] = T_CONTROL;
490da2e3ebdSchin states[0] = T_ENDBUF;
491da2e3ebdSchin if (att)
492da2e3ebdSchin {
493da2e3ebdSchin if (flags&V_FLAG)
494da2e3ebdSchin {
495da2e3ebdSchin states['\n'|0200] = T_EIGHTBIT;
496da2e3ebdSchin if (!(flags&T_FLAG))
497da2e3ebdSchin {
498da2e3ebdSchin states['\t'] = states['\f'] = 0;
499da2e3ebdSchin states['\t'|0200] = states['\f'|0200] = T_EIGHTBIT;
500da2e3ebdSchin }
501da2e3ebdSchin }
502da2e3ebdSchin }
503da2e3ebdSchin else if (flags)
504da2e3ebdSchin {
505da2e3ebdSchin if (!(flags&T_FLAG))
506da2e3ebdSchin states['\t'] = 0;
507da2e3ebdSchin }
5087c2fbfb3SApril Chin if (flags&(V_FLAG|T_FLAG|N_FLAG|E_FLAG|B_FLAG|S_FLAG))
509da2e3ebdSchin {
510da2e3ebdSchin states['\n'] = T_NEWLINE;
511da2e3ebdSchin dovcat = 1;
512da2e3ebdSchin }
513da2e3ebdSchin if (flags&d_FLAG)
514da2e3ebdSchin sfopen(sfstdout, NiL, "wt");
515da2e3ebdSchin if (cp = *argv)
516da2e3ebdSchin argv++;
517da2e3ebdSchin do
518da2e3ebdSchin {
519da2e3ebdSchin if (!cp || streq(cp, "-"))
520da2e3ebdSchin {
521da2e3ebdSchin fp = sfstdin;
522da2e3ebdSchin if (flags&D_FLAG)
523da2e3ebdSchin sfopen(fp, NiL, mode);
524da2e3ebdSchin }
525da2e3ebdSchin else if (!(fp = sfopen(NiL, cp, mode)))
526da2e3ebdSchin {
527da2e3ebdSchin if (!(flags&F_FLAG))
528da2e3ebdSchin error(ERROR_system(0), "%s: cannot open", cp);
529da2e3ebdSchin error_info.errors = 1;
530da2e3ebdSchin continue;
531da2e3ebdSchin }
532da2e3ebdSchin if (flags&U_FLAG)
533da2e3ebdSchin sfsetbuf(fp, (void*)fp, -1);
534da2e3ebdSchin if (dovcat)
53534f9b3eeSRoland Mainz n = vcat(states, fp, sfstdout, reserve, flags);
536da2e3ebdSchin else if (sfmove(fp, sfstdout, SF_UNBOUND, -1) >= 0 && sfeof(fp))
537da2e3ebdSchin n = 0;
538da2e3ebdSchin else
539da2e3ebdSchin n = -1;
540da2e3ebdSchin if (fp != sfstdin)
541da2e3ebdSchin sfclose(fp);
542da2e3ebdSchin if (n < 0 && errno != EPIPE)
543da2e3ebdSchin {
544da2e3ebdSchin if (cp)
545da2e3ebdSchin error(ERROR_system(0), "%s: read error", cp);
546da2e3ebdSchin else
547da2e3ebdSchin error(ERROR_system(0), "read error");
548da2e3ebdSchin }
549da2e3ebdSchin if (sferror(sfstdout))
550da2e3ebdSchin break;
551da2e3ebdSchin } while (cp = *argv++);
552da2e3ebdSchin if (sfsync(sfstdout))
553da2e3ebdSchin error(ERROR_system(0), "write error");
554da2e3ebdSchin if (flags&d_FLAG)
555da2e3ebdSchin sfopen(sfstdout, NiL, "w");
556da2e3ebdSchin return error_info.errors;
557da2e3ebdSchin }
558