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 <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 {
92 if (wp)
93 free(wp);
94 return -1;
95 }
96 }
97 if (wp)
98 free(wp);
99 }
100 else
101 while(cp = bp = sfgetr(in,'\n',0))
102 {
103 ep = bp + (n=sfvalue(in)) -1;
104 while(ep > bp)
105 {
106 c = *--ep;
107 *ep = *bp;
108 *bp++ = c;
109 }
110 if(sfwrite(out,cp,n)<0)
111 return(-1);
112 }
113 return(0);
114 }
115
116 int
b_rev(int argc,register char ** argv,Shbltin_t * context)117 b_rev(int argc, register char** argv, Shbltin_t* context)
118 {
119 register Sfio_t *fp;
120 register char *cp;
121 register int n, line=0;
122 NOT_USED(argc);
123
124 cmdinit(argc, argv, context, ERROR_CATALOG, 0);
125 for (;;)
126 {
127 switch (optget(argv, usage))
128 {
129 case 'l':
130 line=1;
131 continue;
132 case ':':
133 error(2, "%s", opt_info.arg);
134 break;
135 case '?':
136 error(ERROR_usage(2), "%s", opt_info.arg);
137 break;
138 }
139 break;
140 }
141 argv += opt_info.index;
142 if(error_info.errors)
143 error(ERROR_usage(2),"%s",optusage((char*)0));
144 n=0;
145 if(cp = *argv)
146 argv++;
147 do
148 {
149 if(!cp || streq(cp,"-"))
150 fp = sfstdin;
151 else if(!(fp = sfopen((Sfio_t*)0,cp,"r")))
152 {
153 error(ERROR_system(0),"%s: cannot open",cp);
154 n=1;
155 continue;
156 }
157 if(line)
158 line = rev_line(fp,sfstdout,sftell(fp));
159 else
160 line = rev_char(fp,sfstdout);
161 if(fp!=sfstdin)
162 sfclose(fp);
163 if(line < 0)
164 error(ERROR_system(1),"write failed");
165 }
166 while(cp= *argv++);
167 return(n);
168 }
169