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*                  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
47typedef int (*Optpass_f)(char**, int);
48
49int
50optjoin(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			more;
58	int			user;
59	int			last_index;
60	int			last_offset;
61	int			err_index;
62	int			err_offset;
63
64	state = optstate(&opt_info);
65	err = rep = 0;
66	for (;;)
67	{
68		va_start(ap, argv);
69		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			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					state->join = 0;
82					return 0;
83				}
84				if (!user)
85				{
86					if (*argv[opt_info.index] != '+')
87					{
88						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 = state->pindex ? state->pindex : 1;
106				opt_info.offset = 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					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