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