ZOOM: throw present request out of range again YAZ-739
[yaz-moved-to-github.git] / src / options.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) Index Data
3  * See the file LICENSE for details.
4  */
5 /**
6  * \file options.c
7  * \brief Implements command line options parsing
8  */
9 #if HAVE_CONFIG_H
10 #include <config.h>
11 #endif
12
13 #include <stdlib.h>
14 #include <string.h>
15 #include <yaz/options.h>
16
17 static int arg_no = 1;
18 static size_t arg_off = 0;
19 static int eof_options = 0;
20
21 int options(const char *desc, char **argv, int argc, char **arg)
22 {
23     const char *opt_buf = 0;
24     size_t i = 0;
25     int ch = 0;
26
27     if (arg_no >= argc)
28         return YAZ_OPTIONS_EOF;
29     if (arg_off == 0)
30     {
31         while (argv[arg_no][0] == '\0')
32         {
33             arg_no++;
34             if (arg_no >= argc)
35                 return YAZ_OPTIONS_EOF;
36         }
37         if (argv[arg_no][0] != '-' || argv[arg_no][1] == '\0' || eof_options)
38         {
39             *arg = argv[arg_no++];
40             return 0;
41         }
42         arg_off++; /* skip - */
43     }
44     /* we're in option mode */
45     if (argv[arg_no][1] == '-')
46     {   /* long opt */
47         if (argv[arg_no][2] == '\0') /* -- : end of options */
48         {
49             eof_options = 1;
50             arg_off = 0;
51             ++arg_no;
52             if (arg_no >= argc)
53                 return YAZ_OPTIONS_EOF;
54             *arg = argv[arg_no++];
55             return 0;
56         }
57         opt_buf = argv[arg_no]+2;
58         arg_off = strlen(argv[arg_no]);
59     }
60     else
61     {   /* single char opt */
62         ch = argv[arg_no][arg_off++];
63     }
64     while (desc[i])
65     {
66         int desc_char = desc[i++];
67         int type = 0;
68         while (desc[i] == '{')
69         {
70             size_t i0 = ++i;
71             while (desc[i] && desc[i] != '}')
72                 i++;
73             if (opt_buf && (i - i0) == strlen(opt_buf) &&
74                 memcmp(opt_buf, desc+i0, i - i0) == 0)
75                 ch = desc_char;
76             if (desc[i])
77                 i++;
78         }
79         if (desc[i] == ':')
80         {       /* option with string argument */
81             type = desc[i++];
82         }
83         if (desc_char == ch)
84         {
85             if (type) /* option with argument */
86             {
87                 if (argv[arg_no][arg_off])
88                 {
89                     *arg = argv[arg_no]+arg_off;
90                     arg_no++;
91                     arg_off = 0;
92                 }
93                 else
94                 {
95                     arg_no++;
96                     arg_off = 0;
97                     if (arg_no < argc)
98                         *arg = argv[arg_no++];
99                     else
100                         *arg = "";
101                 }
102             }
103             else /* option with no argument */
104             {
105                 if (!argv[arg_no][arg_off])
106                 {
107                     arg_off = 0;
108                     arg_no++;
109                 }
110             }
111             return ch;
112         }
113     }
114     *arg = argv[arg_no]+arg_off-1;
115     arg_no = arg_no + 1;
116     arg_off = 0;
117     return YAZ_OPTIONS_ERROR;
118 }
119 /*
120  * Local variables:
121  * c-basic-offset: 4
122  * c-file-style: "Stroustrup"
123  * indent-tabs-mode: nil
124  * End:
125  * vim: shiftwidth=4 tabstop=8 expandtab
126  */
127