1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 1985-2011 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 *                   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
optjoin(char ** argv,...)50 optjoin(char** argv, ...)
51 {
52 	va_list			ap;
53 	register Optpass_f	fun;
54 	register Optpass_f	rep;
55 	Optpass_f		err;
56 	Optstate_t*		state;
57 	int			r;
58 	int			more;
59 	int			user;
60 	int			last_index;
61 	int			last_offset;
62 	int			err_index;
63 	int			err_offset;
64 
65 	state = optstate(&opt_info);
66 	err = rep = 0;
67 	r = -1;
68 	while (r < 0)
69 	{
70 		va_start(ap, argv);
71 		state->join = 0;
72 		while (fun = va_arg(ap, Optpass_f))
73 		{
74 			last_index = opt_info.index;
75 			last_offset = opt_info.offset;
76 			state->join++;
77 			user = (*fun)(argv, 0);
78 			more = argv[opt_info.index] != 0;
79 			if (!opt_info.again)
80 			{
81 				if (!more)
82 				{
83 					state->join = 0;
84 					r = 0;
85 					break;
86 				}
87 				if (!user)
88 				{
89 					if (*argv[opt_info.index] != '+')
90 					{
91 						state->join = 0;
92 						r = 1;
93 						break;
94 					}
95 					opt_info.again = -1;
96 				}
97 				else
98 					err = 0;
99 			}
100 			if (opt_info.again)
101 			{
102 				if (opt_info.again > 0 && (!err || err_index < opt_info.index || err_index == opt_info.index && err_offset < opt_info.offset))
103 				{
104 					err = fun;
105 					err_index = opt_info.index;
106 					err_offset = opt_info.offset;
107 				}
108 				opt_info.again = 0;
109 				opt_info.index = state->pindex ? state->pindex : 1;
110 				opt_info.offset = state->poffset;
111 			}
112 			if (!rep || opt_info.index != last_index || opt_info.offset != last_offset)
113 				rep = fun;
114 			else if (fun == rep)
115 			{
116 				if (!err)
117 				{
118 					state->join = 0;
119 					r = 1;
120 					break;
121 				}
122 				(*err)(argv, 1);
123 				opt_info.offset = 0;
124 			}
125 		}
126 		va_end(ap);
127 	}
128 	return r;
129 }
130