1 /*
2 ** OSSP l2 - Flexible Logging
3 ** Copyright (c) 2001-2005 Cable & Wireless <http://www.cw.com/>
4 ** Copyright (c) 2001-2005 The OSSP Project <http://www.ossp.org/>
5 ** Copyright (c) 2001-2005 Ralf S. Engelschall <rse@engelschall.com>
6 **
7 ** This file is part of OSSP l2, a flexible logging library which
8 ** can be found at http://www.ossp.org/pkg/lib/l2/.
9 **
10 ** Permission to use, copy, modify, and distribute this software for
11 ** any purpose with or without fee is hereby granted, provided that
12 ** the above copyright notice and this permission notice appear in all
13 ** copies.
14 **
15 ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
16 ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17 ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 ** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
19 ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
22 ** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 ** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 ** SUCH DAMAGE.
27 **
28 ** l2_ut_param.c: parameter parsing support
29 */
30
31 #include "l2.h"
32 #include "l2_p.h"
33
34 #include <stdlib.h>
35 #include <string.h>
36 #include <limits.h>
37 #include <math.h>
38 #include <ctype.h>
39
l2_util_setparams(l2_env_t * env,l2_param_t pa[],const char * fmt,va_list * ap)40 l2_result_t l2_util_setparams(l2_env_t *env, l2_param_t pa[], const char *fmt, va_list *ap)
41 {
42 char *cpB, *cpE;
43 char *spec;
44 int ok;
45 int i;
46 int n;
47
48 /* argument sanity check */
49 if (env == NULL || pa == NULL || fmt == NULL)
50 return L2_ERR_ARG;
51
52 /* on-the-fly create or just take over parameter specification string */
53 spec = l2_util_vasprintf(fmt, ap);
54
55 /* enter the parsing loop */
56 cpE = spec;
57 while (*cpE != '\0') {
58 /* determine begin of parameter name */
59 cpB = cpE;
60 if ((n = strspn(cpB, " \t\r\n")) > 0)
61 cpB += n;
62
63 /* determine end of parameter name */
64 cpE = cpB;
65 if (!isalpha((int)*cpE)) {
66 l2_env_errorinfo(env, L2_ERR_ARG,
67 "expected alpha-numerical parameter "
68 "start character, got '%c'", *cpE);
69 return L2_ERR_ARG;
70 }
71 cpE++;
72 while (isalnum((int)*cpE))
73 cpE++;
74 if (*cpE != '=') {
75 l2_env_errorinfo(env, L2_ERR_ARG,
76 "expected assignment operator ('='), "
77 "got '%c'", *cpE);
78 return L2_ERR_ARG;
79 }
80 *cpE++ = '\0';
81
82 /* try to match with configured parameters */
83 ok = FALSE;
84 for (i = 0; pa[i].name != NULL; i++) {
85 if (strcmp(pa[i].name, cpB) == 0) {
86 ok = TRUE;
87 break;
88 }
89 }
90 if (!ok) {
91 l2_env_errorinfo(env, L2_ERR_ARG, "unknown parameter name '%s'", cpB);
92 return L2_ERR_ARG;
93 }
94
95 /* determine parameter value */
96 cpB = cpE;
97 if ((n = strspn(cpB, " \t\r\n")) > 0)
98 cpB += n;
99 if (*cpB == '"') {
100 cpB++;
101 while (1) {
102 cpE = cpB;
103 if ((cpE = strchr(cpE+1, '"')) == NULL) {
104 l2_env_errorinfo(env, L2_ERR_ARG, "closing quote ('\"') not found");
105 return L2_ERR_ARG;
106 }
107 if (*(cpE-1) != '\\')
108 break;
109 }
110 }
111 else {
112 cpE = cpB;
113 while (1) {
114 if ((n = strcspn(cpE, " \t\r\n,")) > 0) {
115 cpE += n;
116 if (*(cpE-1) == '\\') {
117 cpE++;
118 continue;
119 }
120 }
121 break;
122 }
123 }
124 *cpE++ = '\0';
125
126 /* store parameter value */
127 switch (pa[i].type) {
128 case L2_TYPE_INT: {
129 /* integer parameter */
130 long val;
131 if (strlen(cpB) > 2 && cpB[0] == '0' && cpB[1] == 'x')
132 val = strtol(cpB+2, &cpE, 16);
133 else if (strlen(cpB) > 1 && cpB[0] == '0')
134 val = strtol(cpB+1, &cpE, 8);
135 else
136 val = strtol(cpB, &cpE, 10);
137 if ((val == LONG_MIN || val == LONG_MAX) && errno == ERANGE) {
138 l2_env_errorinfo(env, L2_ERR_ARG,
139 "numerical parameter value out of range "
140 "('%s')", cpB);
141 return L2_ERR_ARG;
142 }
143 if (*cpE != '\0') {
144 l2_env_errorinfo(env, L2_ERR_ARG,
145 "expected valid numerical parameter value, "
146 "got '%c' character", *cpE);
147 return L2_ERR_ARG;
148 }
149 *(int *)(pa[i].store) = (int)val;
150 break;
151 }
152 case L2_TYPE_FLT: {
153 /* floating point parameter */
154 double val = strtod(cpB, &cpE);
155 if (val == HUGE_VAL && errno == ERANGE) {
156 l2_env_errorinfo(env, L2_ERR_ARG,
157 "floating point parameter value too huge "
158 "('%s')", cpB);
159 return L2_ERR_ARG;
160 }
161 if (val == 0 && cpE == cpB) {
162 l2_env_errorinfo(env, L2_ERR_ARG,
163 "floating point parameter value conversion failed "
164 "('%s')", cpB);
165 }
166 if (*cpE != '\0') {
167 l2_env_errorinfo(env, L2_ERR_ARG,
168 "expected valid floating point parameter value, "
169 "got '%c' character", *cpE);
170 return L2_ERR_ARG;
171 }
172 *(float *)(pa[i].store) = (float)val;
173 break;
174 }
175 case L2_TYPE_STR: {
176 /* string parameter */
177 if (*(char **)(pa[i].store) != NULL)
178 free(*(char **)(pa[i].store));
179 *(char **)(pa[i].store) = strdup(cpB);
180 break;
181 }
182 }
183
184 /* skip delimiter */
185 if ((n = strspn(cpE, " \t\r\n,")) > 0)
186 cpE += n;
187 }
188
189 free(spec);
190
191 return L2_OK;
192 }
193
194