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 #include <ast.h>
25 #include <ast_getopt.h>
26
27 #undef _BLD_ast /* enable ast imports since we're user static */
28
29 #include <error.h>
30 #include <option.h>
31 #include <getopt.h>
32 #include <ctype.h>
33
34 static const char* lastoptstring;
35 static const struct option* lastlongopts;
36 static char* usage;
37 static Sfio_t* up;
38
39 static int lastoptind;
40
41 static int
golly(int argc,char * const * argv,const char * optstring,const struct option * longopts,int * longindex,int flags)42 golly(int argc, char* const* argv, const char* optstring, const struct option* longopts, int* longindex, int flags)
43 {
44 register char* s;
45 register const struct option* o;
46 register int c;
47 char* t;
48
49 if (!up || optstring != lastoptstring || longopts != lastlongopts)
50 {
51 if (!up && !(up = sfstropen()))
52 return -1;
53 sfprintf(up, "[-1p%d]", flags);
54 t = strdup(optstring);
55 for (o = longopts; o->name; o++)
56 {
57 if (o->flag || o->val <= 0 || o->val > UCHAR_MAX || !isalnum(o->val))
58 sfprintf(up, "\n[%d:%s]", UCHAR_MAX + 1 + (o - longopts), o->name);
59 else
60 {
61 sfprintf(up, "\n[%c:%s]", o->val, o->name);
62 if (s = strchr(t, o->val))
63 {
64 *s++ = ' ';
65 if (*s == ':')
66 {
67 *s++ = ' ';
68 if (*s == ':')
69 *s = ' ';
70 }
71 }
72 }
73 if (o->has_arg)
74 {
75 sfputc(up, ':');
76 if (o->has_arg == optional_argument)
77 sfputc(up, '?');
78 sfprintf(up, "[string]");
79 }
80 }
81 s = t;
82 while (c = *s++)
83 if (c != ' ')
84 {
85 sfprintf(up, "\n[%c]", c);
86 if (*s == ':')
87 {
88 sfputc(up, *s);
89 if (*++s == ':')
90 {
91 sfputc(up, '?');
92 s++;
93 }
94 sfputc(up, '[');
95 sfputc(up, ']');
96 }
97 }
98 sfputc(up, '\n');
99 if (!(usage = sfstruse(up)))
100 return -1;
101 lastoptstring = optstring;
102 lastlongopts = longopts;
103 }
104 opt_info.index = (optind > 1 || optind == lastoptind) ? optind : 0;
105 if (opt_info.index >= argc || !(c = optget((char**)argv, usage)))
106 {
107 sfstrclose(up);
108 up = 0;
109 c = -1;
110 }
111 else
112 {
113 if (c == ':' || c == '?')
114 {
115 if (opterr && (!optstring || *optstring != ':'))
116 {
117 if (!error_info.id)
118 error_info.id = argv[0];
119 errormsg(NiL, c == '?' ? (ERROR_USAGE|4) : 2, "%s", opt_info.arg);
120 }
121 optopt = opt_info.option[1];
122 c = '?';
123 }
124 optarg = opt_info.arg;
125 if (c < 0)
126 {
127 o = longopts - c - UCHAR_MAX - 1;
128 if (o->flag)
129 {
130 *o->flag = o->val;
131 c = 0;
132 }
133 else
134 c = o->val;
135 }
136 }
137 lastoptind = optind = opt_info.index;
138 return c;
139 }
140
141 extern int
getopt_long(int argc,char * const * argv,const char * optstring,const struct option * longopts,int * longindex)142 getopt_long(int argc, char* const* argv, const char* optstring, const struct option* longopts, int* longindex)
143 {
144 return golly(argc, argv, optstring, longopts, longindex, 2);
145 }
146
147 extern int
getopt_long_only(int argc,char * const * argv,const char * optstring,const struct option * longopts,int * longindex)148 getopt_long_only(int argc, char* const* argv, const char* optstring, const struct option* longopts, int* longindex)
149 {
150 return golly(argc, argv, optstring, longopts, longindex, 1);
151 }
152