~ubuntu-branches/ubuntu/utopic/golang/utopic

« back to all changes in this revision

Viewing changes to src/lib9/flag.c

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2013-08-20 14:06:23 UTC
  • mfrom: (14.1.23 saucy-proposed)
  • Revision ID: package-import@ubuntu.com-20130820140623-b414jfxi3m0qkmrq
Tags: 2:1.1.2-2ubuntu1
* Merge from Debian unstable (LP: #1211749, #1202027). Remaining changes:
  - 016-armhf-elf-header.patch: Use correct ELF header for armhf binaries.
  - d/control,control.cross: Update Breaks/Replaces for Ubuntu
    versions to ensure smooth upgrades, regenerate control file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2012 The Go Authors.  All rights reserved.
 
2
// Use of this source code is governed by a BSD-style
 
3
// license that can be found in the LICENSE file.
 
4
 
 
5
#include <u.h>
 
6
#include <libc.h>
 
7
 
 
8
// Flag hash.
 
9
typedef struct Flag Flag;
 
10
 
 
11
struct Flag
 
12
{
 
13
        char *name;
 
14
        int namelen;
 
15
        char *desc;
 
16
        int iscount;
 
17
        void (*set)(char*, void*);
 
18
        void (*set2)(char*, char*, void*);
 
19
        void *arg;
 
20
        Flag *next;
 
21
        Flag *allnext;
 
22
};
 
23
 
 
24
static Flag *curflag;
 
25
 
 
26
static Flag *fhash[512];
 
27
static Flag *first, *last;
 
28
 
 
29
char *argv0;
 
30
 
 
31
/*
 
32
 * Mac OS can't deal with files that only declare data.
 
33
 * ARGBEGIN mentions this function so that this file gets pulled in.
 
34
 */
 
35
void __fixargv0(void) { }
 
36
 
 
37
// FNV-1 hash. http://isthe.com/chongo/tech/comp/fnv/
 
38
static uint32
 
39
fnv(char *p, int n)
 
40
{
 
41
        uint32 h;
 
42
        
 
43
        h = 2166136261U;
 
44
        while(n-- > 0)
 
45
                h = (h*16777619) ^ (uchar)*p++;
 
46
        return h;
 
47
}
 
48
 
 
49
static Flag*
 
50
lookflag(char *name, int namelen, int creat)
 
51
{
 
52
        uint32 h;
 
53
        Flag *f;
 
54
 
 
55
        h = fnv(name, namelen) & (nelem(fhash)-1);
 
56
        for(f=fhash[h]; f; f=f->next) {
 
57
                if(f->namelen == namelen && memcmp(f->name, name, namelen) == 0) {
 
58
                        if(creat)
 
59
                                sysfatal("multiple definitions of flag -%s", name);
 
60
                        return f;
 
61
                }
 
62
        }
 
63
        
 
64
        if(!creat)
 
65
                return nil;
 
66
 
 
67
        f = malloc(sizeof *f);
 
68
        if(f == nil)
 
69
                sysfatal("out of memory");
 
70
        memset(f, 0, sizeof *f);
 
71
        f->name = name;
 
72
        f->namelen = namelen;
 
73
        f->next = fhash[h];
 
74
        if(first == nil)
 
75
                first = f;
 
76
        else
 
77
                last->allnext = f;
 
78
        last = f;
 
79
        fhash[h] = f;
 
80
        return f;
 
81
}
 
82
 
 
83
static void
 
84
count(char *arg, void *p)
 
85
{
 
86
        int *ip;
 
87
        
 
88
        ip = p;
 
89
        if(arg != nil)
 
90
                *ip = atoi(arg);
 
91
        else
 
92
                (*ip)++;
 
93
}
 
94
 
 
95
void
 
96
flagcount(char *name, char *desc, int *p)
 
97
{
 
98
        Flag *f;
 
99
        
 
100
        f = lookflag(name, strlen(name), 1);
 
101
        f->desc = desc;
 
102
        f->iscount = 1;
 
103
        f->set = count;
 
104
        f->arg = p;
 
105
}
 
106
 
 
107
static void
 
108
atollwhex(char *s, void *p)
 
109
{
 
110
        char *t;
 
111
 
 
112
        *(int64*)p = strtoll(s, &t, 0);
 
113
        if(*s == '\0' || *t != '\0')
 
114
                sysfatal("invalid numeric argument -%s=%s", curflag->name, s);
 
115
}
 
116
 
 
117
void
 
118
flagint64(char *name, char *desc, int64 *p)
 
119
{
 
120
        Flag *f;
 
121
        
 
122
        f = lookflag(name, strlen(name), 1);
 
123
        f->desc = desc;
 
124
        f->set = atollwhex;
 
125
        f->arg = p;
 
126
}
 
127
 
 
128
static void
 
129
atolwhex(char *s, void *p)
 
130
{
 
131
        char *t;
 
132
 
 
133
        *(int32*)p = strtol(s, &t, 0);
 
134
        if(*s == '\0' || *t != '\0')
 
135
                sysfatal("invalid numeric argument -%s=%s", curflag->name, s);
 
136
}
 
137
 
 
138
void
 
139
flagint32(char *name, char *desc, int32 *p)
 
140
{
 
141
        Flag *f;
 
142
        
 
143
        f = lookflag(name, strlen(name), 1);
 
144
        f->desc = desc;
 
145
        f->set = atolwhex;
 
146
        f->arg = p;
 
147
}
 
148
 
 
149
static void
 
150
string(char *s, void *p)
 
151
{
 
152
        *(char**)p = s;
 
153
}
 
154
 
 
155
void
 
156
flagstr(char *name, char *desc, char **p)
 
157
{
 
158
 
 
159
        Flag *f;
 
160
        
 
161
        f = lookflag(name, strlen(name), 1);
 
162
        f->desc = desc;
 
163
        f->set = string;
 
164
        f->arg = p;
 
165
}       
 
166
 
 
167
static void
 
168
fn0(char *s, void *p)
 
169
{
 
170
        USED(s);
 
171
        ((void(*)(void))p)();
 
172
}
 
173
 
 
174
void
 
175
flagfn0(char *name, char *desc, void (*fn)(void))
 
176
{
 
177
        Flag *f;
 
178
        
 
179
        f = lookflag(name, strlen(name), 1);
 
180
        f->desc = desc;
 
181
        f->set = fn0;
 
182
        f->arg = fn;
 
183
        f->iscount = 1;
 
184
}
 
185
 
 
186
static void
 
187
fn1(char *s, void *p)
 
188
{
 
189
        ((void(*)(char*))p)(s);
 
190
}
 
191
 
 
192
void
 
193
flagfn1(char *name, char *desc, void (*fn)(char*))
 
194
{
 
195
        Flag *f;
 
196
        
 
197
        f = lookflag(name, strlen(name), 1);
 
198
        f->desc = desc;
 
199
        f->set = fn1;
 
200
        f->arg = fn;
 
201
}
 
202
 
 
203
static void
 
204
fn2(char *s, char *t, void *p)
 
205
{
 
206
        ((void(*)(char*, char*))p)(s, t);
 
207
}
 
208
 
 
209
void
 
210
flagfn2(char *name, char *desc, void (*fn)(char*, char*))
 
211
{
 
212
        Flag *f;
 
213
        
 
214
        f = lookflag(name, strlen(name), 1);
 
215
        f->desc = desc;
 
216
        f->set2 = fn2;
 
217
        f->arg = fn;
 
218
}
 
219
 
 
220
void
 
221
flagparse(int *argcp, char ***argvp, void (*usage)(void))
 
222
{
 
223
        int argc;
 
224
        char **argv, *p, *q;
 
225
        char *name;
 
226
        int namelen;
 
227
        Flag *f;
 
228
        
 
229
        argc = *argcp;
 
230
        argv = *argvp;
 
231
 
 
232
        argv0 = argv[0];
 
233
        argc--;
 
234
        argv++;
 
235
        
 
236
        while(argc > 0) {
 
237
                p = *argv;
 
238
                // stop before non-flag or -
 
239
                if(*p != '-' || p[1] == '\0')
 
240
                        break;
 
241
                argc--;
 
242
                argv++;
 
243
                // stop after --
 
244
                if(p[1] == '-' && p[2] == '\0') {
 
245
                        break;
 
246
                }
 
247
                
 
248
                // turn --foo into -foo
 
249
                if(p[1] == '-' && p[2] != '-')
 
250
                        p++;
 
251
                
 
252
                // allow -flag=arg if present
 
253
                name = p+1;
 
254
                q = strchr(name, '=');
 
255
                if(q != nil)
 
256
                        namelen = q++ - name;
 
257
                else
 
258
                        namelen = strlen(name);
 
259
                f = lookflag(name, namelen, 0);
 
260
                if(f == nil) {
 
261
                        if(strcmp(p, "-h") == 0 || strcmp(p, "-help") == 0 || strcmp(p, "-?") == 0)
 
262
                                usage();
 
263
                        sysfatal("unknown flag %s", p);
 
264
                }
 
265
                curflag = f;
 
266
 
 
267
                // otherwise consume next argument if non-boolean
 
268
                if(!f->iscount && q == nil) {
 
269
                        if(argc-- == 0)
 
270
                                sysfatal("missing argument to flag %s", p);
 
271
                        q = *argv++;
 
272
                }
 
273
                
 
274
                // and another if we need two
 
275
                if(f->set2 != nil) {
 
276
                        if(argc-- == 0)
 
277
                                sysfatal("missing second argument to flag %s", p);
 
278
                        f->set2(q, *argv++, f->arg);
 
279
                        continue;
 
280
                }
 
281
 
 
282
                f->set(q, f->arg);                      
 
283
        }
 
284
        
 
285
        *argcp = argc;
 
286
        *argvp = argv;          
 
287
}
 
288
 
 
289
void
 
290
flagprint(int fd)
 
291
{
 
292
        Flag *f;
 
293
        char *p, *q;
 
294
        
 
295
        for(f=first; f; f=f->allnext) {
 
296
                p = f->desc;
 
297
                if(p == nil || *p == '\0') // undocumented flag
 
298
                        continue;
 
299
                q = strstr(p, ": ");
 
300
                if(q)
 
301
                        fprint(fd, "  -%s %.*s\n    \t%s\n", f->name, utfnlen(p, q-p), p, q+2);
 
302
                else if(f->namelen > 1)
 
303
                        fprint(fd, "  -%s\n    \t%s\n", f->name, p);
 
304
                else
 
305
                        fprint(fd, "  -%s\t%s\n", f->name, p);
 
306
        }
 
307
}