Added SILC Thread Queue API
[silc.git] / lib / silcutil / silcgetopt.c
1 /*
2
3   silcgetopt.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2007 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19
20 #include "silc.h"
21
22 /* Getopt, like getopt(3). */
23
24 int silc_getopt(int argc, char **argv, const char *optstring, SilcGetOpt op)
25 {
26   register int c;
27   register char *cp;
28   SilcBool optional = FALSE, optional_found = FALSE;
29
30   SILC_VERIFY(op);
31
32   op->opt_arg = NULL;
33
34   if (op->opt_sp == 1) {
35     if (op->opt_index >= argc ||
36         argv[op->opt_index][0] != '-' || argv[op->opt_index][1] == '\0') {
37       return -1;
38     } else if (strcmp(argv[op->opt_index], "--") == 0) {
39       op->opt_index++;
40       return -1;
41     }
42   }
43   op->opt_option = c = argv[op->opt_index][op->opt_sp];
44
45   if (c == ':' || (cp = strchr(optstring, c)) == NULL) {
46     if (op->opt_error)
47       fprintf(stderr, "%s: illegal option -- %c\n", argv[0], c);
48     if (argv[op->opt_index][++op->opt_sp] == '\0') {
49       op->opt_index++;
50       op->opt_sp = 1;
51     }
52     return '?';
53   }
54
55   if (*++cp == ':') {
56     /* Check for optional argument (::), must be written -oarg, not -o arg. */
57     if (strlen(cp) && *(cp + 1) == ':') {
58       optional = TRUE;
59       if (argv[op->opt_index][op->opt_sp + 1] != '\0')
60         optional_found = TRUE;
61     }
62
63     if (argv[op->opt_index][op->opt_sp + 1] != '\0')
64       op->opt_arg = &argv[op->opt_index++][op->opt_sp + 1];
65     else if (++op->opt_index >= argc) {
66       if (!optional && !optional_found) {
67         if (op->opt_error)
68           fprintf(stderr, "%s: option requires an argument -- %c\n",
69                   argv[0], c);
70         op->opt_sp = 1;
71         return ':';
72       }
73     } else if (!optional || optional_found)
74       op->opt_arg = argv[op->opt_index++];
75     op->opt_sp = 1;
76   } else {
77     if (argv[op->opt_index][++op->opt_sp] == '\0') {
78       op->opt_sp = 1;
79       op->opt_index++;
80     }
81     op->opt_arg = NULL;
82   }
83
84   return c;
85 }