--- l2_ut_param.c 2001/09/08 22:06:09 1.5
+++ l2_ut_param.c 2001/11/07 13:05:20 1.6
@@ -30,82 +30,157 @@
#include "l2.h"
#include "l2_p.h"
+#include <stdlib.h>
#include <string.h>
+#include <limits.h>
+#include <math.h>
+#include <ctype.h>
-l2_result_t l2_util_setparams(l2_param_t pa[], const char *fmt, va_list ap)
+l2_result_t l2_util_setparams(l2_env_t *env, l2_param_t pa[], const char *fmt, va_list ap)
{
- const char *cpB, *cpE;
- const char *cpC, *cpG;
+ char *cpB, *cpE;
+ char *spec;
int ok;
int i;
+ int n;
- if (pa == NULL || fmt == NULL || ap == NULL)
+ /* argument sanity check */
+ if (env == NULL || pa == NULL || fmt == NULL || ap == NULL)
return L2_ERR_ARG;
- cpE = fmt;
+
+ /* on-the-fly create or just take over parameter specification string */
+ spec = l2_util_vasprintf(fmt, ap);
+
+ /* enter the parsing loop */
+ cpE = spec;
while (*cpE != '\0') {
/* determine begin of parameter name */
cpB = cpE;
- while (*cpB == ',')
- cpB++;
+ if ((n = strspn(cpB, " \t\r\n")) > 0)
+ cpB += n;
/* determine end of parameter name */
cpE = cpB;
- while (*cpE != ',' && *cpE != '\0')
+ if (!isalpha((int)*cpE)) {
+ l2_env_errorinfo(env, L2_ERR_ARG,
+ "expected alpha-numerical parameter "
+ "start character, got '%c'", *cpE);
+ return L2_ERR_ARG;
+ }
+ cpE++;
+ while (isalnum((int)*cpE))
cpE++;
+ if (*cpE != '=') {
+ l2_env_errorinfo(env, L2_ERR_ARG,
+ "expected assignment operator ('='), "
+ "got '%c'", *cpE);
+ return L2_ERR_ARG;
+ }
+ *cpE++ = '\0';
/* try to match with configured parameters */
ok = FALSE;
for (i = 0; pa[i].name != NULL; i++) {
- cpC = pa[i].name;
- cpG = cpB;
- while (*cpC != '\0' && cpG < cpE) {
- if (*cpC != *cpG)
+ if (strcmp(pa[i].name, cpB) == 0) {
+ ok = TRUE;
+ break;
+ }
+ }
+ if (!ok) {
+ l2_env_errorinfo(env, L2_ERR_ARG, "unknown parameter name '%s'", cpB);
+ return L2_ERR_ARG;
+ }
+
+ /* determine parameter value */
+ cpB = cpE;
+ if ((n = strspn(cpB, " \t\r\n")) > 0)
+ cpB += n;
+ if (*cpB == '"') {
+ cpB++;
+ while (1) {
+ cpE = cpB;
+ if ((cpE = strchr(cpE+1, '"')) == NULL) {
+ l2_env_errorinfo(env, L2_ERR_ARG, "closing quote ('\"') not found");
+ return L2_ERR_ARG;
+ }
+ if (*(cpE-1) != '\\')
break;
- cpC++;
- cpG++;
}
- if (*cpC == '\0' && cpG == cpE) {
- /* parameter matched, so store value */
- switch (pa[i].type) {
- case L2_TYPE_CHAR:
- *(char *)(pa[i].store) = va_get(ap, char);
- break;
- case L2_TYPE_SHORT:
- *(short *)(pa[i].store) = va_get(ap, short);
- break;
- case L2_TYPE_INT:
- *(int *)(pa[i].store) = va_get(ap, int);
- break;
- case L2_TYPE_LONG:
- *(long *)(pa[i].store) = va_get(ap, long);
- break;
- case L2_TYPE_FLOAT:
- *(float *)(pa[i].store) = va_get(ap, float);
- break;
- case L2_TYPE_DOUBLE:
- *(double *)(pa[i].store) = va_get(ap, double);
- break;
- case L2_TYPE_STRING:
- if (*(char **)(pa[i].store) != NULL)
- free(*(char **)(pa[i].store));
- *(char **)(pa[i].store) = va_get(ap, charptr);
- if (*(char **)(pa[i].store) != NULL)
- *(char **)(pa[i].store) = strdup(*(char **)(pa[i].store));
- break;
- case L2_TYPE_CHARPTR:
- *(char **)(pa[i].store) = va_get(ap, charptr);
- break;
- case L2_TYPE_VOIDPTR:
- *(void **)(pa[i].store) = va_get(ap, voidptr);
- break;
+ }
+ else {
+ cpE = cpB;
+ while (1) {
+ if ((n = strcspn(cpE, " \t\r\n,")) > 0) {
+ cpE += n;
+ if (*(cpE-1) == '\\') {
+ cpE++;
+ continue;
+ }
}
- ok = TRUE;
break;
}
}
- if (!ok)
- return L2_ERR_USE;
+ *cpE++ = '\0';
+
+ /* store parameter value */
+ switch (pa[i].type) {
+ case L2_TYPE_INT: {
+ /* integer parameter */
+ long val = strtol(cpB, &cpE, 10);
+ if ((val == LONG_MIN || val == LONG_MAX) && errno == ERANGE) {
+ l2_env_errorinfo(env, L2_ERR_ARG,
+ "numerical parameter value out of range "
+ "('%s')", cpB);
+ return L2_ERR_ARG;
+ }
+ if (*cpE != '\0') {
+ l2_env_errorinfo(env, L2_ERR_ARG,
+ "expected valid numerical parameter value, "
+ "got '%c' character", *cpE);
+ return L2_ERR_ARG;
+ }
+ *(int *)(pa[i].store) = (int)val;
+ break;
+ }
+ case L2_TYPE_FLT: {
+ /* floating point parameter */
+ double val = strtod(cpB, &cpE);
+ if (val == HUGE_VAL && errno == ERANGE) {
+ l2_env_errorinfo(env, L2_ERR_ARG,
+ "floating point parameter value too huge "
+ "('%s')", cpB);
+ return L2_ERR_ARG;
+ }
+ if (val == 0 && cpE == cpB) {
+ l2_env_errorinfo(env, L2_ERR_ARG,
+ "floating point parameter value conversion failed "
+ "('%s')", cpB);
+ }
+ if (*cpE != '\0') {
+ l2_env_errorinfo(env, L2_ERR_ARG,
+ "expected valid floating point parameter value, "
+ "got '%c' character", *cpE);
+ return L2_ERR_ARG;
+ }
+ *(float *)(pa[i].store) = (float)val;
+ break;
+ }
+ case L2_TYPE_STR: {
+ /* string parameter */
+ if (*(char **)(pa[i].store) != NULL)
+ free(*(char **)(pa[i].store));
+ *(char **)(pa[i].store) = strdup(cpB);
+ break;
+ }
+ }
+
+ /* skip delimiter */
+ if ((n = strspn(cpE, " \t\r\n,")) > 0)
+ cpE += n;
}
+
+ free(spec);
+
return L2_OK;
}
|