1/***********************************************************************
2*                                                                      *
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                     *
8*                                                                      *
9*                A copy of the License is available at                 *
10*            http://www.opensource.org/licenses/cpl1.0.txt             *
11*         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12*                                                                      *
13*              Information and Software Systems Research               *
14*                            AT&T Research                             *
15*                           Florham Park NJ                            *
16*                                                                      *
17*                 Glenn Fowler <gsf@research.att.com>                  *
18*                  David Korn <dgk@research.att.com>                   *
19*                                                                      *
20***********************************************************************/
21#pragma prototyped
22/*
23 * rev [-l] [file ...]
24 *
25 * reverse the characters or lines of one or more files
26 *
27 *   David Korn
28 *   AT&T Laboratories
29 *   dgk@research.att.com
30 *
31 */
32
33static const char usage[] =
34"[-?\n@(#)$Id: rev (AT&T Research) 2007-11-29 $\n]"
35USAGE_LICENSE
36"[+NAME?rev - reverse the characters or lines of one or more files]"
37"[+DESCRIPTION?\brev\b copies one or more files to standard output "
38	"reversing the order of characters on every line of the file "
39	"or reversing the order of lines of the file if \b-l\b is specified.]"
40"[+?If no \afile\a is given, or if the \afile\a is \b-\b, \brev\b "
41        "copies from standard input starting at the current offset.]"
42"[l:line?Reverse the lines of the file.]"
43
44"\n"
45"\n[file ...]\n"
46"\n"
47"[+EXIT STATUS?]{"
48        "[+0?All files copied successfully.]"
49        "[+>0?One or more files did not copy.]"
50"}"
51"[+SEE ALSO?\bcat\b(1), \btail\b(1)]"
52;
53
54#include	<cmd.h>
55#include	<rev.h>
56
57/*
58 * reverse the characters within a line
59 */
60static int rev_char(Sfio_t *in, Sfio_t *out)
61{
62	register int c;
63	register char *ep, *bp, *cp;
64	register wchar_t *wp, *xp;
65	register size_t n;
66	register size_t w;
67	if (mbwide())
68	{
69		wp = 0;
70		w = 0;
71		while(cp = bp = sfgetr(in,'\n',0))
72		{
73			ep = bp + (n=sfvalue(in)) - 1;
74			if (n > w)
75			{
76				w = roundof(n + 1, 1024);
77				if (!(wp = newof(wp, wchar_t, w, 0)))
78				{
79					error(ERROR_SYSTEM|2, "out of space");
80					return 0;
81				}
82			}
83			xp = wp;
84			while (cp < ep)
85				*xp++ = mbchar(cp);
86			cp = bp;
87			while (xp > wp)
88				cp += mbconv(cp, *--xp);
89			*cp++ = '\n';
90			if (sfwrite(out, bp, cp - bp) < 0)
91				return -1;
92		}
93		if (wp)
94			free(wp);
95	}
96	else
97		while(cp = bp = sfgetr(in,'\n',0))
98		{
99			ep = bp + (n=sfvalue(in)) -1;
100			while(ep > bp)
101			{
102				c = *--ep;
103				*ep = *bp;
104				*bp++ = c;
105			}
106			if(sfwrite(out,cp,n)<0)
107				return(-1);
108		}
109	return(0);
110}
111
112int
113b_rev(int argc, register char** argv, void* context)
114{
115	register Sfio_t *fp;
116	register char *cp;
117	register int n, line=0;
118	NOT_USED(argc);
119
120	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
121	while (n = optget(argv, usage)) switch (n)
122	{
123	    case 'l':
124		line=1;
125		break;
126	    case ':':
127		error(2, "%s", opt_info.arg);
128		break;
129	    case '?':
130		error(ERROR_usage(2), "%s", opt_info.arg);
131		break;
132	}
133	argv += opt_info.index;
134	if(error_info.errors)
135		error(ERROR_usage(2),"%s",optusage((char*)0));
136	n=0;
137	if(cp = *argv)
138		argv++;
139	do
140	{
141		if(!cp || streq(cp,"-"))
142			fp = sfstdin;
143		else if(!(fp = sfopen((Sfio_t*)0,cp,"r")))
144		{
145			error(ERROR_system(0),"%s: cannot open",cp);
146			n=1;
147			continue;
148		}
149		if(line)
150			line = rev_line(fp,sfstdout,sftell(fp));
151		else
152			line = rev_char(fp,sfstdout);
153		if(fp!=sfstdin)
154			sfclose(fp);
155		if(line < 0)
156			error(ERROR_system(1),"write failed");
157	}
158	while(cp= *argv++);
159	return(n);
160}
161