Avoid printf %.*s for arbitrary strings
[yaz-moved-to-github.git] / src / options.c
1 /* This file is part of the YAZ toolkit.
2  * Copyright (C) 1995-2011 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
20 int options (const char *desc, char **argv, int argc, char **arg)
21 {
22     const char *opt_buf = 0;
23     size_t i = 0;
24     int ch = 0;
25     
26     if (arg_no >= argc)
27         return YAZ_OPTIONS_EOF;
28     if (arg_off == 0)
29     {
30         while (argv[arg_no][0] == '\0')
31         {
32             arg_no++;
33             if (arg_no >= argc)
34                 return YAZ_OPTIONS_EOF;
35         }
36         if (argv[arg_no][0] != '-' || argv[arg_no][1] == '\0')
37         {
38             *arg = argv[arg_no++];
39             return 0;
40         }
41         arg_off++; /* skip - */
42     }
43     if (argv[arg_no][1] == '-')
44     {   /* long opt */
45         opt_buf = argv[arg_no]+2;
46         arg_off = strlen(argv[arg_no]);
47     }
48     else
49     {   /* single char opt */
50         ch = argv[arg_no][arg_off++];
51     }
52     while (desc[i])
53     {
54         int desc_char = desc[i++];
55         int type = 0;
56         while (desc[i] == '{')
57         {
58             size_t i0 = ++i;
59             while (desc[i] && desc[i] != '}')
60                 i++;
61             if (opt_buf && (i - i0) == strlen(opt_buf) &&
62                 memcmp(opt_buf, desc+i0, i - i0) == 0)
63                 ch = desc_char;
64             if (desc[i])
65                 i++;
66         }
67         if (desc[i] == ':')
68         {       /* option with string argument */
69             type = desc[i++];
70         }
71         if (desc_char == ch)
72         { 
73             if (type) /* option with argument */
74             {
75                 if (argv[arg_no][arg_off])
76                 {
77                     *arg = argv[arg_no]+arg_off;
78                     arg_no++;
79                     arg_off = 0;
80                 }
81                 else
82                 {
83                     arg_no++;
84                     arg_off = 0;
85                     if (arg_no < argc)
86                         *arg = argv[arg_no++];
87                     else
88                         *arg = "";
89                 }
90             }
91             else /* option with no argument */
92             {
93                 if (!argv[arg_no][arg_off])
94                 {
95                     arg_off = 0;
96                     arg_no++;
97                 }
98             }
99             return ch;
100         }               
101     }
102     *arg = argv[arg_no]+arg_off-1;
103     arg_no = arg_no + 1;
104     arg_off = 0;
105     return YAZ_OPTIONS_ERROR;
106 }
107 /*
108  * Local variables:
109  * c-basic-offset: 4
110  * c-file-style: "Stroustrup"
111  * indent-tabs-mode: nil
112  * End:
113  * vim: shiftwidth=4 tabstop=8 expandtab
114  */
115