enhanced the constant value handling

This commit is contained in:
2017-12-14 10:02:44 +00:00
parent 1f56b6cf93
commit 2172fa59a5
4 changed files with 329 additions and 197 deletions

View File

@ -56,10 +56,6 @@
#include <qse/si/sio.h>
#include <stdarg.h>
#include <stdio.h>
#define fr_strerror_printf printf
typedef struct const_fixup_t const_fixup_t;
struct const_fixup_t
@ -98,95 +94,82 @@ struct name_id_t
{
const qse_char_t* name;
int id;
int length;
};
static const name_id_t type_table[] =
{
{ QSE_T("string"), QSE_RADDIC_ATTR_TYPE_STRING },
{ QSE_T("octets"), QSE_RADDIC_ATTR_TYPE_OCTETS },
{ QSE_T("string"), QSE_RADDIC_ATTR_TYPE_STRING, -1 },
{ QSE_T("octets"), QSE_RADDIC_ATTR_TYPE_OCTETS, -1 },
{ QSE_T("ipaddr"), QSE_RADDIC_ATTR_TYPE_IPV4_ADDR },
{ QSE_T("ipv4prefix"), QSE_RADDIC_ATTR_TYPE_IPV4_PREFIX },
{ QSE_T("ipv6addr"), QSE_RADDIC_ATTR_TYPE_IPV6_ADDR },
{ QSE_T("ipv6prefix"), QSE_RADDIC_ATTR_TYPE_IPV6_PREFIX },
{ QSE_T("ifid"), QSE_RADDIC_ATTR_TYPE_IFID },
{ QSE_T("combo-ip"), QSE_RADDIC_ATTR_TYPE_COMBO_IP_ADDR },
{ QSE_T("combo-prefix"), QSE_RADDIC_ATTR_TYPE_COMBO_IP_PREFIX },
{ QSE_T("ether"), QSE_RADDIC_ATTR_TYPE_ETHERNET },
{ QSE_T("ipaddr"), QSE_RADDIC_ATTR_TYPE_IPV4_ADDR, 4 },
{ QSE_T("ipv4prefix"), QSE_RADDIC_ATTR_TYPE_IPV4_PREFIX, -1 },
{ QSE_T("ipv6addr"), QSE_RADDIC_ATTR_TYPE_IPV6_ADDR, 16 },
{ QSE_T("ipv6prefix"), QSE_RADDIC_ATTR_TYPE_IPV6_PREFIX, -1 },
{ QSE_T("ifid"), QSE_RADDIC_ATTR_TYPE_IFID, 8 },
{ QSE_T("combo-ip"), QSE_RADDIC_ATTR_TYPE_COMBO_IP_ADDR, -1 },
{ QSE_T("combo-prefix"), QSE_RADDIC_ATTR_TYPE_COMBO_IP_PREFIX, -1 },
{ QSE_T("ether"), QSE_RADDIC_ATTR_TYPE_ETHERNET, 6 },
{ QSE_T("bool"), QSE_RADDIC_ATTR_TYPE_BOOL },
{ QSE_T("bool"), QSE_RADDIC_ATTR_TYPE_BOOL, 1 },
{ QSE_T("uint8"), QSE_RADDIC_ATTR_TYPE_UINT8 },
{ QSE_T("uint16"), QSE_RADDIC_ATTR_TYPE_UINT16 },
{ QSE_T("uint32"), QSE_RADDIC_ATTR_TYPE_UINT32 },
{ QSE_T("uint64"), QSE_RADDIC_ATTR_TYPE_UINT64 },
{ QSE_T("uint8"), QSE_RADDIC_ATTR_TYPE_UINT8, 1 },
{ QSE_T("uint16"), QSE_RADDIC_ATTR_TYPE_UINT16, 2 },
{ QSE_T("uint32"), QSE_RADDIC_ATTR_TYPE_UINT32, 4 },
{ QSE_T("uint64"), QSE_RADDIC_ATTR_TYPE_UINT64, 8 },
{ QSE_T("int8"), QSE_RADDIC_ATTR_TYPE_INT8 },
{ QSE_T("int16"), QSE_RADDIC_ATTR_TYPE_INT16 },
{ QSE_T("int32"), QSE_RADDIC_ATTR_TYPE_INT32 },
{ QSE_T("int64"), QSE_RADDIC_ATTR_TYPE_INT64 },
{ QSE_T("int8"), QSE_RADDIC_ATTR_TYPE_INT8, 1 },
{ QSE_T("int16"), QSE_RADDIC_ATTR_TYPE_INT16, 2 },
{ QSE_T("int32"), QSE_RADDIC_ATTR_TYPE_INT32, 4 },
{ QSE_T("int64"), QSE_RADDIC_ATTR_TYPE_INT64, 8 },
{ QSE_T("float32"), QSE_RADDIC_ATTR_TYPE_FLOAT32 },
{ QSE_T("float64"), QSE_RADDIC_ATTR_TYPE_FLOAT64 },
{ QSE_T("float32"), QSE_RADDIC_ATTR_TYPE_FLOAT32, 4 },
{ QSE_T("float64"), QSE_RADDIC_ATTR_TYPE_FLOAT64, 8 },
{ QSE_T("timeval"), QSE_RADDIC_ATTR_TYPE_TIMEVAL },
{ QSE_T("date"), QSE_RADDIC_ATTR_TYPE_DATE },
{ QSE_T("date_milliseconds"), QSE_RADDIC_ATTR_TYPE_DATE_MILLISECONDS },
{ QSE_T("date_microseconds"), QSE_RADDIC_ATTR_TYPE_DATE_MICROSECONDS },
{ QSE_T("date_nanoseconds"), QSE_RADDIC_ATTR_TYPE_DATE_NANOSECONDS },
{ QSE_T("timeval"), QSE_RADDIC_ATTR_TYPE_TIMEVAL, -1 },
{ QSE_T("date"), QSE_RADDIC_ATTR_TYPE_DATE, 4 },
{ QSE_T("date_milliseconds"), QSE_RADDIC_ATTR_TYPE_DATE_MILLISECONDS, -1 },
{ QSE_T("date_microseconds"), QSE_RADDIC_ATTR_TYPE_DATE_MICROSECONDS, -1 },
{ QSE_T("date_nanoseconds"), QSE_RADDIC_ATTR_TYPE_DATE_NANOSECONDS, -1 },
{ QSE_T("abinary"), QSE_RADDIC_ATTR_TYPE_ABINARY },
{ QSE_T("abinary"), QSE_RADDIC_ATTR_TYPE_ABINARY, -1 },
{ QSE_T("size"), QSE_RADDIC_ATTR_TYPE_SIZE },
{ QSE_T("size"), QSE_RADDIC_ATTR_TYPE_SIZE, 8 },
{ QSE_T("tlv"), QSE_RADDIC_ATTR_TYPE_TLV },
{ QSE_T("struct"), QSE_RADDIC_ATTR_TYPE_STRUCT },
{ QSE_T("tlv"), QSE_RADDIC_ATTR_TYPE_TLV, -1 },
{ QSE_T("struct"), QSE_RADDIC_ATTR_TYPE_STRUCT, -1 },
{ QSE_T("extended"), QSE_RADDIC_ATTR_TYPE_EXTENDED },
{ QSE_T("long-extended"), QSE_RADDIC_ATTR_TYPE_LONG_EXTENDED },
{ QSE_T("extended"), QSE_RADDIC_ATTR_TYPE_EXTENDED, 0 },
{ QSE_T("long-extended"), QSE_RADDIC_ATTR_TYPE_LONG_EXTENDED, 0 },
{ QSE_T("vsa"), QSE_RADDIC_ATTR_TYPE_VSA },
{ QSE_T("evs"), QSE_RADDIC_ATTR_TYPE_EVS },
{ QSE_T("vendor"), QSE_RADDIC_ATTR_TYPE_VENDOR },
{ QSE_T("vsa"), QSE_RADDIC_ATTR_TYPE_VSA, -1 },
{ QSE_T("evs"), QSE_RADDIC_ATTR_TYPE_EVS, -1 },
{ QSE_T("vendor"), QSE_RADDIC_ATTR_TYPE_VENDOR, -1 },
/*
* Alternative names
*/
{ QSE_T("cidr"), QSE_RADDIC_ATTR_TYPE_IPV4_PREFIX },
{ QSE_T("byte"), QSE_RADDIC_ATTR_TYPE_UINT8 },
{ QSE_T("short"), QSE_RADDIC_ATTR_TYPE_UINT16 },
{ QSE_T("integer"), QSE_RADDIC_ATTR_TYPE_UINT32 },
{ QSE_T("integer64"), QSE_RADDIC_ATTR_TYPE_UINT64 },
{ QSE_T("decimal"), QSE_RADDIC_ATTR_TYPE_FLOAT64 },
{ QSE_T("signed"), QSE_RADDIC_ATTR_TYPE_INT32 },
#if 0
{ QSE_T("integer"), QSE_RADDIC_ATTR_TYPE_INTEGER },
{ QSE_T("string"), QSE_RADDIC_ATTR_TYPE_STRING },
{ QSE_T("ipaddr"), QSE_RADDIC_ATTR_TYPE_IPADDR },
{ QSE_T("date"), QSE_RADDIC_ATTR_TYPE_DATE },
{ QSE_T("abinary"), QSE_RADDIC_ATTR_TYPE_ABINARY },
{ QSE_T("octets"), QSE_RADDIC_ATTR_TYPE_OCTETS },
{ QSE_T("ifid"), QSE_RADDIC_ATTR_TYPE_IFID },
{ QSE_T("ipv6addr"), QSE_RADDIC_ATTR_TYPE_IPV6ADDR },
{ QSE_T("ipv6prefix"), QSE_RADDIC_ATTR_TYPE_IPV6PREFIX },
{ QSE_T("byte"), QSE_RADDIC_ATTR_TYPE_BYTE },
{ QSE_T("short"), QSE_RADDIC_ATTR_TYPE_SHORT },
{ QSE_T("ether"), QSE_RADDIC_ATTR_TYPE_ETHERNET },
{ QSE_T("combo-ip"), QSE_RADDIC_ATTR_TYPE_COMBO_IP },
{ QSE_T("tlv"), QSE_RADDIC_ATTR_TYPE_TLV },
{ QSE_T("signed"), QSE_RADDIC_ATTR_TYPE_SIGNED },
#endif
{ QSE_T("cidr"), QSE_RADDIC_ATTR_TYPE_IPV4_PREFIX, -1 },
{ QSE_T("byte"), QSE_RADDIC_ATTR_TYPE_UINT8, 1 },
{ QSE_T("short"), QSE_RADDIC_ATTR_TYPE_UINT16, 2 },
{ QSE_T("integer"), QSE_RADDIC_ATTR_TYPE_UINT32, 4 },
{ QSE_T("integer64"), QSE_RADDIC_ATTR_TYPE_UINT64, 8 },
{ QSE_T("decimal"), QSE_RADDIC_ATTR_TYPE_FLOAT64, 8 },
{ QSE_T("signed"), QSE_RADDIC_ATTR_TYPE_INT32, 4 }
};
/* -------------------------------------------------------------------------- */
static int str_to_type (qse_raddic_t* dic, const qse_char_t* name)
static int str_to_type (qse_raddic_t* dic, const qse_char_t* name, int* length)
{
int i;
for (i = 0; i < QSE_COUNTOF(type_table); i++)
{
if (qse_strcmp(name, type_table[i].name) == 0) return type_table[i].id;
if (qse_strcmp(name, type_table[i].name) == 0)
{
if (length) *length = type_table[i].length;
return type_table[i].id;
}
}
dic->errnum = QSE_RADDIC_EINVAL;
@ -281,7 +264,10 @@ static int dict_attr_value_cmp (qse_htl_t* htl, const void* one, const void* two
if (a->vendor < b->vendor) return -1;
if (a->vendor > b->vendor) return 1;
return a->attr - b->attr;
if (a->attr < b->attr) return -1;
if (a->attr > b->attr) return 1;
return 0;
}
/* -------------------------------------------------------------------------- */
@ -355,23 +341,34 @@ static int dict_const_value_cmp (qse_htl_t* htl, const void* one, const void* tw
if (a->attr < b->attr) return -1;
if (a->attr > b->attr) return 1;
return a->value - b->value;
if (a->value.type != b->value.type) return -2; /* cannot really compare */
/* this function actuall requires to check equality.
* it doesn't have to return greaterness or lessness.
* it also assumes that the unused space in the 'value'
* union field is all initialized to zero */
return QSE_MEMCMP(&a->value, &b->value, QSE_SIZEOF(a->value));
}
/* -------------------------------------------------------------------------- */
int qse_raddic_init (qse_raddic_t* dic, qse_mmgr_t* mmgr)
{
int count = 0;
QSE_MEMSET (dic, 0, QSE_SIZEOF(*dic));
dic->mmgr = mmgr;
qse_raddic_seterrnum (dic, QSE_RADDIC_ENOERR);
qse_htl_init (&dic->vendors_byname, mmgr, 1);
qse_htl_init (&dic->vendors_byvalue, mmgr, 1);
qse_htl_init (&dic->attrs_byname, mmgr, 1);
qse_htl_init (&dic->attrs_byvalue, mmgr, 1);
qse_htl_init (&dic->consts_byname, mmgr, 1);
qse_htl_init (&dic->consts_byvalue, mmgr, 1);
if (qse_htl_init(&dic->vendors_byname, mmgr, 1) <= -1 || (++count == 0) ||
qse_htl_init(&dic->vendors_byvalue, mmgr, 1) <= -1 || (++count == 0) ||
qse_htl_init(&dic->attrs_byname, mmgr, 1) <= -1 || (++count == 0) ||
qse_htl_init(&dic->attrs_byvalue, mmgr, 1) <= -1 ||(++count == 0) ||
qse_htl_init(&dic->consts_byname, mmgr, 1) <= -1 || (++count == 0) ||
qse_htl_init(&dic->consts_byvalue, mmgr, 1) <= -1 || (++count == 0))
{
goto oops;
}
qse_htl_sethasher (&dic->vendors_byname, dict_vendor_name_hash);
qse_htl_setcomper (&dic->vendors_byname, dict_vendor_name_cmp);
@ -398,18 +395,28 @@ int qse_raddic_init (qse_raddic_t* dic, qse_mmgr_t* mmgr)
/* no freeer for dic->consts_byvalue */
return 0;
oops:
if (count >= 6) qse_htl_fini (&dic->consts_byvalue);
if (count >= 5) qse_htl_fini (&dic->consts_byname);
if (count >= 4) qse_htl_fini (&dic->attrs_byvalue);
if (count >= 3) qse_htl_fini (&dic->attrs_byname);
if (count >= 2) qse_htl_fini (&dic->vendors_byvalue);
if (count >= 1) qse_htl_fini (&dic->vendors_byname);
return -1;
}
void qse_raddic_fini (qse_raddic_t* dic)
{
qse_raddic_clear (dic);
qse_htl_fini (&dic->vendors_byname);
qse_htl_fini (&dic->vendors_byvalue);
qse_htl_fini (&dic->attrs_byname);
qse_htl_fini (&dic->attrs_byvalue);
qse_htl_fini (&dic->consts_byvalue);
qse_htl_fini (&dic->consts_byname);
qse_htl_fini (&dic->attrs_byvalue);
qse_htl_fini (&dic->attrs_byname);
qse_htl_fini (&dic->vendors_byvalue);
qse_htl_fini (&dic->vendors_byname);
}
qse_raddic_t* qse_raddic_open (qse_mmgr_t* mmgr, qse_size_t xtnsize)
@ -727,7 +734,7 @@ qse_raddic_attr_t* qse_raddic_findattrbyvalue (qse_raddic_t* dic, qse_uint32_t a
return (qse_raddic_attr_t*)np->data;
}
qse_raddic_attr_t* qse_raddic_addattr (qse_raddic_t* dic, const qse_char_t* name, int vendor, int type, int value, const qse_raddic_attr_flags_t* flags)
qse_raddic_attr_t* qse_raddic_addattr (qse_raddic_t* dic, const qse_char_t* name, int vendor, qse_raddic_attr_type_t type, int value, const qse_raddic_attr_flags_t* flags)
{
qse_size_t length;
qse_raddic_attr_t* dv, * old_dv;
@ -857,7 +864,7 @@ int qse_raddic_deleteattrbyname (qse_raddic_t* dic, const qse_char_t* name)
return 0;
}
int qse_raddic_deleteattrbyvalue (qse_raddic_t* dic, int attr)
int qse_raddic_deleteattrbyvalue (qse_raddic_t* dic, qse_uint32_t attr)
{
qse_raddic_attr_t* dv;
@ -908,13 +915,13 @@ qse_raddic_const_t* qse_raddic_findconstbyname (qse_raddic_t* dic, qse_uint32_t
return (qse_raddic_const_t*)np->data;
}
qse_raddic_const_t* qse_raddic_findconstbyvalue (qse_raddic_t* dic, qse_uint32_t attr, int value)
qse_raddic_const_t* qse_raddic_findconstbyvalue (qse_raddic_t* dic, qse_uint32_t attr, const qse_raddic_const_value_t* value)
{
qse_htl_node_t* np;
qse_raddic_const_t dval;
dval.attr = attr;
dval.value = value;
dval.value = *value;
np = qse_htl_search (&dic->consts_byvalue, &dval);
if (!np)
{
@ -924,7 +931,7 @@ qse_raddic_const_t* qse_raddic_findconstbyvalue (qse_raddic_t* dic, qse_uint32_t
return (qse_raddic_const_t*)np->data;
}
qse_raddic_const_t* qse_raddic_addconst (qse_raddic_t* dic, const qse_char_t* name, const qse_char_t* attrstr, int value)
qse_raddic_const_t* qse_raddic_addconst (qse_raddic_t* dic, const qse_char_t* name, const qse_char_t* attrstr, const qse_raddic_const_value_t* value)
{
qse_size_t length;
qse_raddic_const_t* dval, * old_dval;
@ -942,7 +949,7 @@ qse_raddic_const_t* qse_raddic_addconst (qse_raddic_t* dic, const qse_char_t* na
}
qse_strcpy(dval->name, name);
dval->value = value;
dval->value = *value;
dval->nextc = QSE_NULL;
/*
@ -965,9 +972,9 @@ qse_raddic_const_t* qse_raddic_addconst (qse_raddic_t* dic, const qse_char_t* na
*/
if (dattr)
{
if (dattr->flags.has_value_alias)
if (dattr->type != value->type)
{
/* cannot add a VALUE for an attribute having a VALUE_ALIAS */
qse_raddic_seterrfmt (dic, QSE_RADDIC_EINVAL, QSE_T("conflicts between attribute type and constant value"));
return QSE_NULL;
}
@ -1046,7 +1053,8 @@ qse_raddic_const_t* qse_raddic_addconst (qse_raddic_t* dic, const qse_char_t* na
}
else
{
if ((dic->opt.trait & QSE_RADDIC_ALLOW_DUPLICATE_CONST) && ((qse_raddic_const_t*)np->data)->value == dval->value)
if ((dic->opt.trait & QSE_RADDIC_ALLOW_DUPLICATE_CONST) &&
QSE_MEMCMP(&((qse_raddic_const_t*)np->data)->value, &dval->value, QSE_SIZEOF(dval->value)) == 0)
{
QSE_MMGR_FREE (dic->mmgr, dval);
return np->data;
@ -1065,7 +1073,7 @@ qse_raddic_const_t* qse_raddic_addconst (qse_raddic_t* dic, const qse_char_t* na
/* updated the existing item successfully.
* link the old item to the current item */
QSE_ASSERT (np->data == dval);
QSE_ASSERT (dval->value == old_dval->value);
QSE_ASSERT (QSE_MEMCMP(&dval->value, &old_dval->value, QSE_SIZEOF(dval->value)) == 0);
dval->nextc = old_dval;
}
else
@ -1090,7 +1098,7 @@ int qse_raddic_deleteconstbyname (qse_raddic_t* dic, qse_uint32_t attr, const qs
if (!dv) return -1;
QSE_ASSERT (attr == dv->attr);
dv2 = qse_raddic_findconstbyvalue(dic, attr, dv->value);
dv2 = qse_raddic_findconstbyvalue(dic, attr, &dv->value);
QSE_ASSERT (dv2 != QSE_NULL);
if (dv != dv2)
@ -1098,7 +1106,7 @@ int qse_raddic_deleteconstbyname (qse_raddic_t* dic, qse_uint32_t attr, const qs
qse_raddic_const_t* x, * y;
QSE_ASSERT (qse_strcasecmp(dv->name, dv2->name) != 0);
QSE_ASSERT (dv->value == dv2->value);
QSE_ASSERT (QSE_MEMCMP (&dv->value, &dv2->value, QSE_SIZEOF(dv->value)) == 0);
QSE_ASSERT (dv->attr == dv2->attr);
/* when the constibute of the given name is not the first one
@ -1130,7 +1138,7 @@ int qse_raddic_deleteconstbyname (qse_raddic_t* dic, qse_uint32_t attr, const qs
return 0;
}
int qse_raddic_deleteconstbyvalue (qse_raddic_t* dic, qse_uint32_t attr, int value)
int qse_raddic_deleteconstbyvalue (qse_raddic_t* dic, qse_uint32_t attr, const qse_raddic_const_value_t* value)
{
qse_raddic_const_t* dv;
@ -1178,6 +1186,7 @@ static int sscanf_i (qse_raddic_t* dic, const qse_char_t* str, int* pvalue)
{
qse_long_t v;
const qse_char_t* end;
QSE_STRTONUM (v, str, &end, 0);
if (*end != '\0')
{
@ -1188,6 +1197,41 @@ static int sscanf_i (qse_raddic_t* dic, const qse_char_t* str, int* pvalue)
return 0;
}
static int sscanf_ui32 (qse_raddic_t* dic, const qse_char_t* str, qse_uint32_t* pvalue, qse_uint32_t* pvalue2)
{
qse_long_t v, v2;
const qse_char_t* end;
const qse_char_t* start2 = QSE_NULL;
if (!QSE_ISDIGIT(*str) && *str != QSE_T('+'))
{
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("invalid unsigned number - %s"), str);
return -1;
}
QSE_STRTONUM (v, str, &end, 0);
if (pvalue2 && *end == '.')
{
start2 = end + 1;
QSE_STRTONUM (v2, start2, &end, 0);
}
if (*end != '\0')
{
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("invalid unsigned number - %s"), str);
return -1;
}
*pvalue = v;
if (start2)
{
*pvalue2 = v2;
return (int)(end - start2); /* the value must not be very long. so i cast it to 'int' */
}
return 0;
}
/*
* Process the ATTRIBUTE command
*/
@ -1196,9 +1240,11 @@ static int process_attribute (
int block_vendor, qse_raddic_attr_t* block_tlv, qse_char_t** argv, int argc)
{
int vendor = 0;
int value;
unsigned int value;
int type;
qse_raddic_attr_flags_t flags;
qse_char_t* p;
int typelen = -1;
if ((argc < 3) || (argc > 4))
{
@ -1206,33 +1252,62 @@ static int process_attribute (
return -1;
}
QSE_MEMSET (&flags, 0, QSE_SIZEOF(flags));
/*
* Validate all entries
*/
if (sscanf_i(dic, argv[1], &value) <= -1)
{
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd]: invalid value %s"), fn, line, argv[1]);
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd]: invalid attribute value %s"), fn, line, argv[1]);
return -1;
}
/*
* find the type of the attribute.
*/
type = str_to_type(dic, argv[2]);
p = qse_strchr(argv[2], QSE_T('[')); /* for instance, octets[20] */
if (p)
{
qse_char_t* q;
*p = QSE_T('\0');
q = qse_strchr(p + 1, QSE_T(']'));
if (!q || q[1] != QSE_T('\0'))
{
*p = QSE_T('[');
goto invalid_type;
}
*q = QSE_T('\0');
if (sscanf_i(dic, p + 1, &typelen) <= -1 || typelen <= 0 || typelen > 253)
{
*p = QSE_T('[');
*q = QSE_T(']');
goto invalid_type;
}
flags.length = typelen;
}
type = str_to_type(dic, argv[2], &typelen);
if (type < 0)
{
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd]: invalid type \"%s\""), fn, line, argv[2]);
invalid_type:
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd]: invalid attribute type \"%s\""), fn, line, argv[2]);
return -1;
}
if (flags.length <= 0 && typelen >= 0) flags.length = typelen;
/*
* Only look up the vendor if the string
* is non-empty.
*/
QSE_MEMSET (&flags, 0, QSE_SIZEOF(flags));
if (argc == 4)
if (argc >= 4)
{
qse_char_t* key, * next, * last;
qse_char_t* key, * next;
key = argv[3];
do
@ -1240,49 +1315,40 @@ static int process_attribute (
next = qse_strchr(key, QSE_T(','));
if (next) *(next++) = QSE_T('\0');
if (qse_strcmp(key, QSE_T("has_tag")) == 0 ||
qse_strcmp(key, QSE_T("has_tag=1")) == 0)
if (qse_strcasecmp(key, QSE_T("has_tag")) == 0 ||
qse_strcasecmp(key, QSE_T("has_tag=1")) == 0)
{
/* Boolean flag, means this is a
tagged attribute */
flags.has_tag = 1;
}
else if (qse_strzcmp(key, QSE_T("encrypt="), 8) == 0)
else if (qse_strzcasecmp(key, QSE_T("encrypt="), 8) == 0)
{
/* Encryption method, defaults to 0 (none).
Currently valid is just type 2,
Tunnel-Password style, which can only
be applied to strings. */
flags.encrypt = qse_strtol(key + 8, 0);
#if 0
if (*last)
unsigned int ev;
if (sscanf_i(dic, key + 8, &ev) <= -1 || ev < QSE_RADDIC_ATTR_FLAG_ENCRYPT_NONE || ev > QSE_RADDIC_ATTR_FLAG_ENCRYPT_OTHER)
{
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd] invalid option %s"), fn, line, key);
return -1;
}
#endif
flags.encrypt = ev;
}
else if (qse_strcmp(key, QSE_T("array")) == 0)
else if (qse_strcasecmp(key, QSE_T("array")) == 0)
{
flags.array = 1;
/* TODO: ... */
switch (type)
{
case QSE_RADDIC_ATTR_TYPE_IPV4_ADDR:
case QSE_RADDIC_ATTR_TYPE_UINT8:
case QSE_RADDIC_ATTR_TYPE_UINT16:
case QSE_RADDIC_ATTR_TYPE_UINT32:
case QSE_RADDIC_ATTR_TYPE_DATE:
break;
default:
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd] Only IP addresses can have the \"array\" flag set."), fn, line);
return -1;
}
} else {
}
else if (qse_strcasecmp(key, QSE_T("concat")) == 0)
{
flags.concat = 1;
}
else if (qse_strcasecmp(key, QSE_T("internal")) == 0)
{
flags.internal = 1;
}
else
{
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd]: unknown option \"%s\""), fn, line, key);
return -1;
}
@ -1361,7 +1427,9 @@ static int process_attribute (
static int process_constant(qse_raddic_t* dic, const qse_char_t* fn, const qse_size_t line, qse_char_t** argv, int argc)
{
int value;
qse_raddic_const_value_t value;
int n;
qse_uint32_t v1, v2;
if (argc != 3)
{
@ -1377,14 +1445,25 @@ static int process_constant(qse_raddic_t* dic, const qse_char_t* fn, const qse_s
/*
* Validate all entries
*/
if (sscanf_i(dic, argv[2], &value) <= -1)
if ((n = sscanf_ui32(dic, argv[2], &v1, &v2)) <= -1)
{
qse_strcpy (dic->errmsg2, dic->errmsg);
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd]: invalid constant value - %s"), fn, line, dic->errmsg2);
return -1;
}
if (qse_raddic_addconst(dic, argv[1], argv[0], value) == QSE_NULL)
QSE_MEMSET (&value, 0, QSE_SIZEOF(value));
value.type = QSE_RADDIC_ATTR_TYPE_UINT32;
value.u.ui32 = v1;
if (n >= 1)
{
value.type = QSE_RADDIC_ATTR_TYPE_FLOAT64;
value.u.f64 = (qse_flt_t)v1 + ((qse_flt_t)v2 / (pow(10, n))); /* TOOD: XXXXXXXXXXXXX device a way to prepresent this */
}
value.type = (n == 0)? QSE_RADDIC_ATTR_TYPE_UINT32: QSE_RADDIC_ATTR_TYPE_FLOAT64;
if (qse_raddic_addconst(dic, argv[1], argv[0], &value) == QSE_NULL)
{
qse_strcpy (dic->errmsg2, dic->errmsg);
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd]: cannot add a constant - %s"), fn, line, dic->errmsg2);
@ -1508,7 +1587,7 @@ static int process_vendor (qse_raddic_t* dic, const qse_char_t* fn, const qse_si
return 0;
}
static int load_file (qse_raddic_t* dic, const qse_char_t* dir, const qse_char_t* fn, const qse_char_t* src_file, qse_size_t src_line)
static int load_file (qse_raddic_t* dic, const qse_char_t* fn, const qse_char_t* src_file, qse_size_t src_line)
{
qse_sio_t* sio = QSE_NULL;
qse_char_t buf[256]; /* TODO: is this a good size? */
@ -1543,7 +1622,7 @@ static int load_file (qse_raddic_t* dic, const qse_char_t* dir, const qse_char_t
if (src_file)
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd]: cannot open %s"), src_file, src_line, fname);
else
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("cannot open %s"), fname);
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("cannot open \"%s\""), fname);
goto oops;
}
@ -1568,7 +1647,7 @@ static int load_file (qse_raddic_t* dic, const qse_char_t* dir, const qse_char_t
if (argc == 1)
{
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd] invalid entry"), fname, line);
qse_raddic_seterrfmt (dic, QSE_RADDIC_ESYNERR, QSE_T("%s[%zd] invalid entry \"%s\""), fname, line, argv[0]);
goto oops;
}
@ -1595,7 +1674,7 @@ static int load_file (qse_raddic_t* dic, const qse_char_t* dir, const qse_char_t
*/
if (qse_strcasecmp(argv[0], QSE_T("$INCLUDE")) == 0)
{
if (load_file(dic, dir, argv[1], fname, line) < 0) goto oops;
if (load_file(dic, argv[1], fname, line) < 0) goto oops;
continue;
} /* $INCLUDE */
@ -1720,5 +1799,5 @@ oops:
int qse_raddic_load (qse_raddic_t* dic, const qse_char_t* file)
{
return load_file (dic, QSE_NULL, file, QSE_NULL, 0);
return load_file (dic, file, QSE_NULL, 0);
}