xref: /onnv-gate/usr/src/lib/libcmd/common/rev.c (revision 12068:08a39a083754)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1992-2010 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                 Glenn Fowler <gsf@research.att.com>                  *
184887Schin *                  David Korn <dgk@research.att.com>                   *
194887Schin *                                                                      *
204887Schin ***********************************************************************/
214887Schin #pragma prototyped
224887Schin /*
234887Schin  * rev [-l] [file ...]
244887Schin  *
254887Schin  * reverse the characters or lines of one or more files
264887Schin  *
274887Schin  *   David Korn
284887Schin  *   AT&T Laboratories
294887Schin  *   dgk@research.att.com
304887Schin  *
314887Schin  */
324887Schin 
334887Schin static const char usage[] =
348462SApril.Chin@Sun.COM "[-?\n@(#)$Id: rev (AT&T Research) 2007-11-29 $\n]"
354887Schin USAGE_LICENSE
364887Schin "[+NAME?rev - reverse the characters or lines of one or more files]"
374887Schin "[+DESCRIPTION?\brev\b copies one or more files to standard output "
384887Schin 	"reversing the order of characters on every line of the file "
394887Schin 	"or reversing the order of lines of the file if \b-l\b is specified.]"
404887Schin "[+?If no \afile\a is given, or if the \afile\a is \b-\b, \brev\b "
414887Schin         "copies from standard input starting at the current offset.]"
424887Schin "[l:line?Reverse the lines of the file.]"
434887Schin 
444887Schin "\n"
454887Schin "\n[file ...]\n"
464887Schin "\n"
474887Schin "[+EXIT STATUS?]{"
484887Schin         "[+0?All files copied successfully.]"
494887Schin         "[+>0?One or more files did not copy.]"
504887Schin "}"
514887Schin "[+SEE ALSO?\bcat\b(1), \btail\b(1)]"
524887Schin ;
534887Schin 
544887Schin #include	<cmd.h>
554887Schin #include	<rev.h>
564887Schin 
574887Schin /*
584887Schin  * reverse the characters within a line
594887Schin  */
rev_char(Sfio_t * in,Sfio_t * out)604887Schin static int rev_char(Sfio_t *in, Sfio_t *out)
614887Schin {
624887Schin 	register int c;
634887Schin 	register char *ep, *bp, *cp;
648462SApril.Chin@Sun.COM 	register wchar_t *wp, *xp;
658462SApril.Chin@Sun.COM 	register size_t n;
668462SApril.Chin@Sun.COM 	register size_t w;
678462SApril.Chin@Sun.COM 	if (mbwide())
684887Schin 	{
698462SApril.Chin@Sun.COM 		wp = 0;
708462SApril.Chin@Sun.COM 		w = 0;
718462SApril.Chin@Sun.COM 		while(cp = bp = sfgetr(in,'\n',0))
724887Schin 		{
738462SApril.Chin@Sun.COM 			ep = bp + (n=sfvalue(in)) - 1;
748462SApril.Chin@Sun.COM 			if (n > w)
758462SApril.Chin@Sun.COM 			{
768462SApril.Chin@Sun.COM 				w = roundof(n + 1, 1024);
778462SApril.Chin@Sun.COM 				if (!(wp = newof(wp, wchar_t, w, 0)))
788462SApril.Chin@Sun.COM 				{
798462SApril.Chin@Sun.COM 					error(ERROR_SYSTEM|2, "out of space");
808462SApril.Chin@Sun.COM 					return 0;
818462SApril.Chin@Sun.COM 				}
828462SApril.Chin@Sun.COM 			}
838462SApril.Chin@Sun.COM 			xp = wp;
848462SApril.Chin@Sun.COM 			while (cp < ep)
858462SApril.Chin@Sun.COM 				*xp++ = mbchar(cp);
868462SApril.Chin@Sun.COM 			cp = bp;
878462SApril.Chin@Sun.COM 			while (xp > wp)
888462SApril.Chin@Sun.COM 				cp += mbconv(cp, *--xp);
898462SApril.Chin@Sun.COM 			*cp++ = '\n';
908462SApril.Chin@Sun.COM 			if (sfwrite(out, bp, cp - bp) < 0)
918462SApril.Chin@Sun.COM 				return -1;
924887Schin 		}
938462SApril.Chin@Sun.COM 		if (wp)
948462SApril.Chin@Sun.COM 			free(wp);
954887Schin 	}
968462SApril.Chin@Sun.COM 	else
978462SApril.Chin@Sun.COM 		while(cp = bp = sfgetr(in,'\n',0))
988462SApril.Chin@Sun.COM 		{
998462SApril.Chin@Sun.COM 			ep = bp + (n=sfvalue(in)) -1;
1008462SApril.Chin@Sun.COM 			while(ep > bp)
1018462SApril.Chin@Sun.COM 			{
1028462SApril.Chin@Sun.COM 				c = *--ep;
1038462SApril.Chin@Sun.COM 				*ep = *bp;
1048462SApril.Chin@Sun.COM 				*bp++ = c;
1058462SApril.Chin@Sun.COM 			}
1068462SApril.Chin@Sun.COM 			if(sfwrite(out,cp,n)<0)
1078462SApril.Chin@Sun.COM 				return(-1);
1088462SApril.Chin@Sun.COM 		}
1094887Schin 	return(0);
1104887Schin }
1114887Schin 
1124887Schin int
b_rev(int argc,register char ** argv,void * context)1134887Schin b_rev(int argc, register char** argv, void* context)
1144887Schin {
1154887Schin 	register Sfio_t *fp;
1164887Schin 	register char *cp;
1174887Schin 	register int n, line=0;
1184887Schin 	NOT_USED(argc);
1194887Schin 
1204887Schin 	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
1214887Schin 	while (n = optget(argv, usage)) switch (n)
1224887Schin 	{
1234887Schin 	    case 'l':
1244887Schin 		line=1;
1254887Schin 		break;
1264887Schin 	    case ':':
1274887Schin 		error(2, "%s", opt_info.arg);
1284887Schin 		break;
1294887Schin 	    case '?':
1304887Schin 		error(ERROR_usage(2), "%s", opt_info.arg);
1314887Schin 		break;
1324887Schin 	}
1334887Schin 	argv += opt_info.index;
1344887Schin 	if(error_info.errors)
1354887Schin 		error(ERROR_usage(2),"%s",optusage((char*)0));
1364887Schin 	n=0;
1374887Schin 	if(cp = *argv)
1384887Schin 		argv++;
1394887Schin 	do
1404887Schin 	{
1414887Schin 		if(!cp || streq(cp,"-"))
1424887Schin 			fp = sfstdin;
1434887Schin 		else if(!(fp = sfopen((Sfio_t*)0,cp,"r")))
1444887Schin 		{
1454887Schin 			error(ERROR_system(0),"%s: cannot open",cp);
1464887Schin 			n=1;
1474887Schin 			continue;
1484887Schin 		}
1494887Schin 		if(line)
1504887Schin 			line = rev_line(fp,sfstdout,sftell(fp));
1514887Schin 		else
1524887Schin 			line = rev_char(fp,sfstdout);
1534887Schin 		if(fp!=sfstdin)
1544887Schin 			sfclose(fp);
1554887Schin 		if(line < 0)
1564887Schin 			error(ERROR_system(1),"write failed");
1574887Schin 	}
1584887Schin 	while(cp= *argv++);
1594887Schin 	return(n);
1604887Schin }
161