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
33 static const char usage[] =
34 "[-?\n@(#)$Id: rev (AT&T Research) 2007-11-29 $\n]"
35 USAGE_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 */
rev_char(Sfio_t * in,Sfio_t * out)60 static 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
112 int
b_rev(int argc,register char ** argv,void * context)113 b_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