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 */ 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 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