summaryrefslogtreecommitdiff
path: root/lib/isccfg/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/isccfg/parser.c')
-rw-r--r--lib/isccfg/parser.c86
1 files changed, 81 insertions, 5 deletions
diff --git a/lib/isccfg/parser.c b/lib/isccfg/parser.c
index f14c5d6221f6..7c969961f4ca 100644
--- a/lib/isccfg/parser.c
+++ b/lib/isccfg/parser.c
@@ -15,12 +15,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id$ */
-
/*! \file */
#include <config.h>
+#include <stdlib.h>
+
#include <isc/buffer.h>
#include <isc/dir.h>
#include <isc/formatcheck.h>
@@ -122,6 +122,7 @@ cfg_rep_t cfg_rep_tuple = { "tuple", free_tuple };
cfg_rep_t cfg_rep_sockaddr = { "sockaddr", free_noop };
cfg_rep_t cfg_rep_netprefix = { "netprefix", free_noop };
cfg_rep_t cfg_rep_void = { "void", free_noop };
+cfg_rep_t cfg_rep_fixedpoint = { "fixedpoint", free_noop };
/*
* Configuration type definitions.
@@ -601,6 +602,79 @@ cfg_type_t cfg_type_void = {
"void", cfg_parse_void, cfg_print_void, cfg_doc_void, &cfg_rep_void,
NULL };
+/*
+ * Fixed point
+ */
+isc_result_t
+cfg_parse_fixedpoint(cfg_parser_t *pctx, const cfg_type_t *type,
+ cfg_obj_t **ret)
+{
+ isc_result_t result;
+ cfg_obj_t *obj = NULL;
+ size_t n1, n2, n3, l;
+ const char *p;
+
+ UNUSED(type);
+
+ CHECK(cfg_gettoken(pctx, 0));
+ if (pctx->token.type != isc_tokentype_string) {
+ cfg_parser_error(pctx, CFG_LOG_NEAR,
+ "expected fixed point number");
+ return (ISC_R_UNEXPECTEDTOKEN);
+ }
+
+
+ p = TOKEN_STRING(pctx);
+ l = strlen(p);
+ n1 = strspn(p, "0123456789");
+ n2 = strspn(p + n1, ".");
+ n3 = strspn(p + n1 + n2, "0123456789");
+
+ if ((n1 + n2 + n3 != l) || (n1 + n3 == 0) ||
+ n1 > 5 || n2 > 1 || n3 > 2) {
+ cfg_parser_error(pctx, CFG_LOG_NEAR,
+ "expected fixed point number");
+ return (ISC_R_UNEXPECTEDTOKEN);
+ }
+
+ CHECK(cfg_create_obj(pctx, &cfg_type_fixedpoint, &obj));
+
+ obj->value.uint32 = strtoul(p, NULL, 10) * 100;
+ switch (n3) {
+ case 2:
+ obj->value.uint32 += strtoul(p + n1 + n2, NULL, 10);
+ break;
+ case 1:
+ obj->value.uint32 += strtoul(p + n1 + n2, NULL, 10) * 10;
+ break;
+ }
+ *ret = obj;
+
+ cleanup:
+ return (result);
+}
+
+void
+cfg_print_fixedpoint(cfg_printer_t *pctx, const cfg_obj_t *obj) {
+ char buf[64];
+ int n;
+
+ n = snprintf(buf, sizeof(buf), "%u.%02u",
+ obj->value.uint32/100, obj->value.uint32%100);
+ INSIST(n > 0 && (size_t)n < sizeof(buf));
+ cfg_print_chars(pctx, buf, strlen(buf));
+}
+
+isc_uint32_t
+cfg_obj_asfixedpoint(const cfg_obj_t *obj) {
+ REQUIRE(obj != NULL && obj->type->rep == &cfg_rep_fixedpoint);
+ return (obj->value.uint32);
+}
+
+cfg_type_t cfg_type_fixedpoint = {
+ "fixedpoint", cfg_parse_fixedpoint, cfg_print_fixedpoint,
+ cfg_doc_terminal, &cfg_rep_fixedpoint, NULL
+};
/*
* uint32
@@ -1442,10 +1516,11 @@ parse_any_named_map(cfg_parser_t *pctx, cfg_type_t *nametype, const cfg_type_t *
CHECK(cfg_parse_obj(pctx, nametype, &idobj));
CHECK(cfg_parse_map(pctx, type, &mapobj));
mapobj->value.map.id = idobj;
- idobj = NULL;
*ret = mapobj;
+ return (result);
cleanup:
CLEANUP_OBJ(idobj);
+ CLEANUP_OBJ(mapobj);
return (result);
}
@@ -2332,9 +2407,10 @@ parser_complain(cfg_parser_t *pctx, isc_boolean_t is_warning,
current_file(pctx), pctx->line);
len = vsnprintf(message, sizeof(message), format, args);
+#define ELIPSIS " ... "
if (len >= sizeof(message))
- FATAL_ERROR(__FILE__, __LINE__,
- "error message would overflow");
+ strcpy(message + sizeof(message) - sizeof(ELIPSIS) - 1,
+ ELIPSIS);
if ((flags & (CFG_LOG_NEAR|CFG_LOG_BEFORE|CFG_LOG_NOPREP)) != 0) {
isc_region_t r;