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