xref: /titanic_50/usr/src/lib/libast/common/misc/optjoin.c (revision dea05b66b1fa2d0242e78345542e72df4f14a55f)
1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 1985-2010 AT&T Intellectual Property          *
5 *                      and is licensed under the                       *
6 *                  Common Public License, Version 1.0                  *
7 *                    by AT&T Intellectual Property                     *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *            http://www.opensource.org/licenses/cpl1.0.txt             *
11 *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
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 *                   Phong Vo <kpv@research.att.com>                    *
20 *                                                                      *
21 ***********************************************************************/
22 #pragma prototyped
23 /*
24  * Glenn Fowler
25  * AT&T Research
26  *
27  * multi-pass commmand line option parse assist
28  *
29  *	int fun(char** argv, int last)
30  *
31  * each fun() argument parses as much of argv as
32  * possible starting at (opt_info.index,opt_info.offset) using
33  * optget()
34  *
35  * if last!=0 then fun is the last pass to view
36  * the current arg, otherwise fun sets opt_info.again=1
37  * and another pass will get a crack at it
38  *
39  * 0 fun() return causes immediate optjoin() 0 return
40  *
41  * optjoin() returns non-zero if more args remain
42  * to be parsed at opt_info.index
43  */
44 
45 #include <optlib.h>
46 
47 typedef int (*Optpass_f)(char**, int);
48 
49 int
50 optjoin(char** argv, ...)
51 {
52 	va_list			ap;
53 	register Optpass_f	fun;
54 	register Optpass_f	rep;
55 	Optpass_f		err;
56 	int			more;
57 	int			user;
58 	int			last_index;
59 	int			last_offset;
60 	int			err_index;
61 	int			err_offset;
62 
63 	if (!opt_info.state)
64 		optget(NiL, NiL);
65 	err = rep = 0;
66 	for (;;)
67 	{
68 		va_start(ap, argv);
69 		opt_info.state->join = 0;
70 		while (fun = va_arg(ap, Optpass_f))
71 		{
72 			last_index = opt_info.index;
73 			last_offset = opt_info.offset;
74 			opt_info.state->join++;
75 			user = (*fun)(argv, 0);
76 			more = argv[opt_info.index] != 0;
77 			if (!opt_info.again)
78 			{
79 				if (!more)
80 				{
81 					opt_info.state->join = 0;
82 					return 0;
83 				}
84 				if (!user)
85 				{
86 					if (*argv[opt_info.index] != '+')
87 					{
88 						opt_info.state->join = 0;
89 						return 1;
90 					}
91 					opt_info.again = -1;
92 				}
93 				else
94 					err = 0;
95 			}
96 			if (opt_info.again)
97 			{
98 				if (opt_info.again > 0 && (!err || err_index < opt_info.index || err_index == opt_info.index && err_offset < opt_info.offset))
99 				{
100 					err = fun;
101 					err_index = opt_info.index;
102 					err_offset = opt_info.offset;
103 				}
104 				opt_info.again = 0;
105 				opt_info.index = opt_info.state->pindex ? opt_info.state->pindex : 1;
106 				opt_info.offset = opt_info.state->poffset;
107 			}
108 			if (!rep || opt_info.index != last_index || opt_info.offset != last_offset)
109 				rep = fun;
110 			else if (fun == rep)
111 			{
112 				if (!err)
113 				{
114 					opt_info.state->join = 0;
115 					return 1;
116 				}
117 				(*err)(argv, 1);
118 				opt_info.offset = 0;
119 			}
120 		}
121 		va_end(ap);
122 	}
123 }
124