xref: /onnv-gate/usr/src/lib/libast/common/misc/optjoin.c (revision 12068:08a39a083754)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1985-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 *                   Phong Vo <kpv@research.att.com>                    *
204887Schin *                                                                      *
214887Schin ***********************************************************************/
224887Schin #pragma prototyped
234887Schin /*
244887Schin  * Glenn Fowler
254887Schin  * AT&T Research
264887Schin  *
274887Schin  * multi-pass commmand line option parse assist
284887Schin  *
294887Schin  *	int fun(char** argv, int last)
304887Schin  *
314887Schin  * each fun() argument parses as much of argv as
324887Schin  * possible starting at (opt_info.index,opt_info.offset) using
334887Schin  * optget()
344887Schin  *
354887Schin  * if last!=0 then fun is the last pass to view
364887Schin  * the current arg, otherwise fun sets opt_info.again=1
374887Schin  * and another pass will get a crack at it
384887Schin  *
394887Schin  * 0 fun() return causes immediate optjoin() 0 return
404887Schin  *
414887Schin  * optjoin() returns non-zero if more args remain
424887Schin  * to be parsed at opt_info.index
434887Schin  */
444887Schin 
454887Schin #include <optlib.h>
464887Schin 
474887Schin typedef int (*Optpass_f)(char**, int);
484887Schin 
494887Schin int
optjoin(char ** argv,...)504887Schin optjoin(char** argv, ...)
514887Schin {
524887Schin 	va_list			ap;
534887Schin 	register Optpass_f	fun;
544887Schin 	register Optpass_f	rep;
554887Schin 	Optpass_f		err;
564887Schin 	int			more;
574887Schin 	int			user;
584887Schin 	int			last_index;
594887Schin 	int			last_offset;
604887Schin 	int			err_index;
614887Schin 	int			err_offset;
624887Schin 
634887Schin 	if (!opt_info.state)
644887Schin 		optget(NiL, NiL);
654887Schin 	err = rep = 0;
664887Schin 	for (;;)
674887Schin 	{
684887Schin 		va_start(ap, argv);
694887Schin 		opt_info.state->join = 0;
704887Schin 		while (fun = va_arg(ap, Optpass_f))
714887Schin 		{
724887Schin 			last_index = opt_info.index;
734887Schin 			last_offset = opt_info.offset;
744887Schin 			opt_info.state->join++;
754887Schin 			user = (*fun)(argv, 0);
764887Schin 			more = argv[opt_info.index] != 0;
774887Schin 			if (!opt_info.again)
784887Schin 			{
794887Schin 				if (!more)
804887Schin 				{
814887Schin 					opt_info.state->join = 0;
824887Schin 					return 0;
834887Schin 				}
844887Schin 				if (!user)
854887Schin 				{
864887Schin 					if (*argv[opt_info.index] != '+')
874887Schin 					{
884887Schin 						opt_info.state->join = 0;
894887Schin 						return 1;
904887Schin 					}
914887Schin 					opt_info.again = -1;
924887Schin 				}
934887Schin 				else
944887Schin 					err = 0;
954887Schin 			}
964887Schin 			if (opt_info.again)
974887Schin 			{
984887Schin 				if (opt_info.again > 0 && (!err || err_index < opt_info.index || err_index == opt_info.index && err_offset < opt_info.offset))
994887Schin 				{
1004887Schin 					err = fun;
1014887Schin 					err_index = opt_info.index;
1024887Schin 					err_offset = opt_info.offset;
1034887Schin 				}
1044887Schin 				opt_info.again = 0;
1054887Schin 				opt_info.index = opt_info.state->pindex ? opt_info.state->pindex : 1;
1064887Schin 				opt_info.offset = opt_info.state->poffset;
1074887Schin 			}
1084887Schin 			if (!rep || opt_info.index != last_index || opt_info.offset != last_offset)
1094887Schin 				rep = fun;
1104887Schin 			else if (fun == rep)
1114887Schin 			{
1124887Schin 				if (!err)
1134887Schin 				{
1144887Schin 					opt_info.state->join = 0;
1154887Schin 					return 1;
1164887Schin 				}
1174887Schin 				(*err)(argv, 1);
1184887Schin 				opt_info.offset = 0;
1194887Schin 			}
1204887Schin 		}
1214887Schin 		va_end(ap);
1224887Schin 	}
1234887Schin }
124