From 519e60e15ab52f887b87a5474fdebbd45063b567 Mon Sep 17 00:00:00 2001 From: Yahya Civelek Date: Mon, 27 Apr 2026 19:02:00 +0300 Subject: T8587: add u64 type support Mirror existing u32 handling to introduce a new u64 integer type: - Add INT64_TYPE to vtw_type_e enum - Register 'u64' type name and extend template lexer to classify integer literals as INT64_TYPE when they exceed UINT_MAX - Accept full u64 range in value lexer (strtoull / ULLONG_MAX) - Add %llu cond_formats slot and INT64_TYPE comparison path in val_cmp; map INT64_TYPE in type_to_name - Add u64 / u64:* cases to bash completion value formatter --- etc/bash_completion.d/vyatta-cfg | 6 ++++++ src/cli_cstore.h | 1 + src/cli_def.l | 22 +++++++++++++++++++--- src/cli_new.c | 16 ++++++++++++++-- src/cli_val.l | 16 ++++++++++------ 5 files changed, 50 insertions(+), 11 deletions(-) diff --git a/etc/bash_completion.d/vyatta-cfg b/etc/bash_completion.d/vyatta-cfg index bbb6d12..8961af2 100644 --- a/etc/bash_completion.d/vyatta-cfg +++ b/etc/bash_completion.d/vyatta-cfg @@ -550,6 +550,12 @@ get_value_format_string () u32:*) echo -n "<${vtype##u32:}>" ;; + u64) + echo -n '<0-18446744073709551615>' + ;; + u64:*) + echo -n "<${vtype##u64:}>" + ;; range) echo -n "-" ;; diff --git a/src/cli_cstore.h b/src/cli_cstore.h index 3ef7f72..1e82bd8 100644 --- a/src/cli_cstore.h +++ b/src/cli_cstore.h @@ -35,6 +35,7 @@ typedef enum { IPV6_TYPE, IPV6NET_TYPE, MACADDR_TYPE, + INT64_TYPE, DOMAIN_TYPE, /*end of addr types */ TEXT_TYPE, BOOL_TYPE, diff --git a/src/cli_def.l b/src/cli_def.l index 820a7a4..b9e379b 100644 --- a/src/cli_def.l +++ b/src/cli_def.l @@ -3,6 +3,9 @@ %x str %option noyywrap %{ +#include +#include +#include #include "cli_val.h" #include "cli_parse.h" @@ -43,9 +46,11 @@ static int act_types[] = { -1, -1, -1, static char *type_names[] = { "txt", "u32", "ipv4", "ipv4net", "ipv6", "ipv6net", "bool", "macaddr", + "u64", NULL }; static int type_t[] = { TEXT_TYPE, INT_TYPE, IPV4_TYPE, IPV4NET_TYPE, - IPV6_TYPE, IPV6NET_TYPE, BOOL_TYPE, MACADDR_TYPE, 0 }; + IPV6_TYPE, IPV6NET_TYPE, BOOL_TYPE, MACADDR_TYPE, + INT64_TYPE, 0 }; static char *op_cond_strs[] = { "in", "==", "!=", "<", ">", "<=", ">=", NULL }; static int op_cond_types[] = { IN_COND, EQ_COND, NE_COND, LT_COND, @@ -256,7 +261,7 @@ RE_URL_DIGITS {RE_URL_DIGIT}{1,} RE_URL_SUBDELIMS "!"|"$"|"&"|"'"|"("|")"|"*"|"+"|","|";"|"=" /* type names */ -RE_TYPE_NAME (txt|u32|ipv4|ipv4net|ipv6|ipv6net|bool|macaddr) +RE_TYPE_NAME (txt|u32|u64|ipv4|ipv4net|ipv6|ipv6net|bool|macaddr) /* values */ RE_VAL_U32 [0-9]+ @@ -450,7 +455,18 @@ RE_ACT_FIELD (help|syntax|commit|delete|update|activate|create|begin|end|enumera } {RE_VAL_PRIORITY} { return return_value(PRIORITY_TYPE); } -{RE_VAL_U32} { return return_value(INT_TYPE); } +{RE_VAL_U32} { + /* classify integer literal as u32 if it fits in unsigned int, + * otherwise as u64 (cli_parse.y / validators may further range-check). */ + unsigned long long ullv = 0; + char *endp = NULL; + errno = 0; + ullv = strtoull(yy_cli_def_text, &endp, 10); + if (errno == 0 && endp && *endp == '\0' && ullv > (unsigned long long)UINT_MAX) { + return return_value(INT64_TYPE); + } + return return_value(INT_TYPE); + } {RE_IPV4} { return return_value(IPV4_TYPE); } {RE_IPV4NET} { return return_value(IPV4NET_TYPE); } {RE_IPV6} { return return_value(IPV6_TYPE); } diff --git a/src/cli_new.c b/src/cli_new.c index f045ba5..1b47d44 100644 --- a/src/cli_new.c +++ b/src/cli_new.c @@ -63,7 +63,8 @@ static char const *cond_formats[DOMAIN_TYPE] = "%u.%u.%u.%u/%u", /* IPV4NET_TYPE */ "%x:%x:%x:%x:%x:%x:%x:%x", /* IPV6NET */ "%x:%x:%x:%x:%x:%x:%x:%x/%u", /* IPV6NET_TYPE */ - "%x:%x:%x:%x:%x:%x" /* MACADDR_TYPE */ + "%x:%x:%x:%x:%x:%x", /* MACADDR_TYPE */ + "%llu" /* INT64_TYPE */ }; static int cond_format_lens[DOMAIN_TYPE] = @@ -74,7 +75,8 @@ static int cond_format_lens[DOMAIN_TYPE] = 5, /* IPV4NET_TYPE */ 16, /* IPV6_TYPE */ 17, /* IPV6NET_TYPE */ - 6 /* MACADDR_TYPE */ + 6, /* MACADDR_TYPE */ + 1 /* INT64_TYPE */ }; static int cli_val_len; @@ -787,6 +789,15 @@ val_cmp(const valstruct *left, const valstruct *right, vtw_cond_e cond) right_parts+2, right_parts+3, right_parts+4, right_parts+5); break; + case INT64_TYPE: { + unsigned long long lv = 0, rv = 0; + (void) sscanf(lval, "%llu", &lv); + (void) sscanf(rval, "%llu", &rv); + if (lv > rv) res = 1; + else if (lv < rv) res = -1; + else res = 0; + goto done_comp; + } case TEXT_TYPE: case BOOL_TYPE: res = strcmp(lval, rval); @@ -1972,6 +1983,7 @@ touch(void) const char *type_to_name(vtw_type_e type) { switch(type) { case INT_TYPE: return("u32"); + case INT64_TYPE: return("u64"); case IPV4_TYPE: return("ipv4"); case IPV4NET_TYPE: return("ipv4net"); case IPV6_TYPE: return("ipv6"); diff --git a/src/cli_val.l b/src/cli_val.l index d568de6..b8cb459 100644 --- a/src/cli_val.l +++ b/src/cli_val.l @@ -228,16 +228,20 @@ false { } [0-9]+ { - long long int cval = 0; + unsigned long long ucval = 0; char *endp = NULL; errno = 0; - cval = strtoll(yytext, &endp, 10); - if ((errno == ERANGE && (cval == LLONG_MAX || cval == LLONG_MIN)) - || (errno != 0 && cval == 0) - || (*endp != '\0') || (cval < 0) || (cval > UINT_MAX)) { + ucval = strtoull(yytext, &endp, 10); + if ((errno == ERANGE && ucval == ULLONG_MAX) + || (errno != 0 && ucval == 0) + || (*endp != '\0')) { return SYNTAX_ERROR; } - make_val_value(INT_TYPE); + if (ucval > (unsigned long long)UINT_MAX) { + make_val_value(INT64_TYPE); + } else { + make_val_value(INT_TYPE); + } return VALUE; } -- cgit v1.2.3 From fc06449dd9a255353cf21e369d5e3f1e74e8188d Mon Sep 17 00:00:00 2001 From: Yahya Civelek Date: Wed, 29 Apr 2026 13:51:48 +0300 Subject: T8587: address review feedback for u64 type support - cli_def.l: reject out-of-range integer literals (errno==ERANGE) as a syntax error instead of silently classifying them as u32. - cli_new.c (val_cmp): unify u32/u64 comparison through strtoull() with errno/end-pointer validation so unparseable operands are skipped instead of silently compared as 0, and so mixed u32/u64 operands are evaluated correctly via the 64-bit path. - cli_new.c (cond_formats/cond_format_lens): replace the unused INT64_TYPE entries with NULL/0 sentinels and a comment, since INT64_TYPE is handled via its own branch in val_cmp(); this removes a latent foot-gun where '%llu' would write 8 bytes into a 4-byte unsigned int slot of left_parts[] if a future refactor routed INT64_TYPE through the generic path. - cli_new.c: introduce type compatibility helpers and apply them so that a u32-magnitude value is accepted in a u64 (INT64_TYPE) context (validate_value, char2val_notext) and so that comparisons between u32 and u64 operands proceed (check_comp, val_cmp). The reverse direction (u64-magnitude value into a u32 field) remains rejected to preserve u32 range enforcement. --- src/cli_cstore.h | 5 ++-- src/cli_def.l | 11 +++++--- src/cli_new.c | 81 +++++++++++++++++++++++++++++++++++++++++++++----------- src/cli_parse.y | 14 +++++++++- 4 files changed, 90 insertions(+), 21 deletions(-) diff --git a/src/cli_cstore.h b/src/cli_cstore.h index 1e82bd8..62903ab 100644 --- a/src/cli_cstore.h +++ b/src/cli_cstore.h @@ -35,11 +35,12 @@ typedef enum { IPV6_TYPE, IPV6NET_TYPE, MACADDR_TYPE, - INT64_TYPE, DOMAIN_TYPE, /*end of addr types */ TEXT_TYPE, BOOL_TYPE, - PRIORITY_TYPE + PRIORITY_TYPE, + INT64_TYPE /* u64; appended last to preserve ABI stability + against out-of-tree consumers. */ } vtw_type_e; typedef struct { diff --git a/src/cli_def.l b/src/cli_def.l index b9e379b..3a905e7 100644 --- a/src/cli_def.l +++ b/src/cli_def.l @@ -456,13 +456,18 @@ RE_ACT_FIELD (help|syntax|commit|delete|update|activate|create|begin|end|enumera {RE_VAL_PRIORITY} { return return_value(PRIORITY_TYPE); } {RE_VAL_U32} { - /* classify integer literal as u32 if it fits in unsigned int, - * otherwise as u64 (cli_parse.y / validators may further range-check). */ + /* Classify integer literal as u32 if it fits in unsigned int, + * as u64 if it exceeds UINT_MAX but fits in unsigned long long, + * otherwise reject as a syntax error so out-of-range constants + * don't silently get treated as u32. */ unsigned long long ullv = 0; char *endp = NULL; errno = 0; ullv = strtoull(yy_cli_def_text, &endp, 10); - if (errno == 0 && endp && *endp == '\0' && ullv > (unsigned long long)UINT_MAX) { + if (errno == ERANGE || endp == yy_cli_def_text || (endp && *endp != '\0')) { + return SYNTAX_ERROR; + } + if (ullv > (unsigned long long)UINT_MAX) { return return_value(INT64_TYPE); } return return_value(INT_TYPE); diff --git a/src/cli_new.c b/src/cli_new.c index 1b47d44..fdd4131 100644 --- a/src/cli_new.c +++ b/src/cli_new.c @@ -55,6 +55,9 @@ void *var_ref_handle = NULL; static vtw_node *vtw_free_nodes; /* linked via left */ static int cond1[TOP_COND] ={5, 0,-1,-1, 0, 1, 0, 0}; static int cond2[TOP_COND] ={5, 0, 1,-1,-1, 1, 1, 0}; +/* Indexed by vtw_type_e for types <= MACADDR_TYPE only. INT64_TYPE sits + * past DOMAIN_TYPE in the enum and is handled via its own branch in + * val_cmp(); it must never be used as an index into these tables. */ static char const *cond_formats[DOMAIN_TYPE] = { 0, @@ -63,8 +66,7 @@ static char const *cond_formats[DOMAIN_TYPE] = "%u.%u.%u.%u/%u", /* IPV4NET_TYPE */ "%x:%x:%x:%x:%x:%x:%x:%x", /* IPV6NET */ "%x:%x:%x:%x:%x:%x:%x:%x/%u", /* IPV6NET_TYPE */ - "%x:%x:%x:%x:%x:%x", /* MACADDR_TYPE */ - "%llu" /* INT64_TYPE */ + "%x:%x:%x:%x:%x:%x" /* MACADDR_TYPE */ }; static int cond_format_lens[DOMAIN_TYPE] = @@ -75,8 +77,7 @@ static int cond_format_lens[DOMAIN_TYPE] = 5, /* IPV4NET_TYPE */ 16, /* IPV6_TYPE */ 17, /* IPV6NET_TYPE */ - 6, /* MACADDR_TYPE */ - 1 /* INT64_TYPE */ + 6 /* MACADDR_TYPE */ }; static int cli_val_len; @@ -111,6 +112,38 @@ static int set_reference_environment(const char* var_reference, clind_path_ref *n_cmd_path, int active); +/* Integer type helpers: u32 values are a subset of u64 values, so allow + * using an INT_TYPE literal where an INT64_TYPE is expected, and permit + * comparisons between u32 and u64 operands. The reverse (INT64_TYPE + * value in an INT_TYPE context) is rejected because it would exceed + * u32 range. */ +static inline boolean +is_int_like(vtw_type_e t) +{ + return (t == INT_TYPE || t == INT64_TYPE); +} + +/* Returns TRUE if a value of type `val_type` is acceptable in a context + * declaring `expected`. Strict equality, except a u32 value is accepted + * in a u64 context. */ +static inline boolean +type_accepts_val(vtw_type_e expected, vtw_type_e val_type) +{ + if (expected == val_type) return TRUE; + if (expected == INT64_TYPE && val_type == INT_TYPE) return TRUE; + return FALSE; +} + +/* Returns TRUE if two types may be meaningfully compared: equal types, or + * any pair among {u32, u64}. */ +static inline boolean +types_comparable(vtw_type_e a, vtw_type_e b) +{ + if (a == b) return TRUE; + if (is_int_like(a) && is_int_like(b)) return TRUE; + return FALSE; +} + /************************************************* GLOBAL FUNCTIONS ***************************************************/ @@ -606,8 +639,9 @@ int char2val_notext(const vtw_def *def, int my_type, int my_type2, } return 0; } - if (my_type != get_cli_value_ptr()->val_type && - (my_type2 != ERROR_TYPE && my_type2 != get_cli_value_ptr()->val_type)) { + if (!type_accepts_val(my_type, get_cli_value_ptr()->val_type) && + (my_type2 == ERROR_TYPE + || !type_accepts_val(my_type2, get_cli_value_ptr()->val_type))) { if (def->def_type_help){ set_at_string(value); (void)expand_string(def->def_type_help); @@ -751,10 +785,14 @@ val_cmp(const valstruct *left, const valstruct *right, vtw_cond_e cond) rval = right->vals[rcur]; //don't bother comparing if these are different types. - if ((rcur || right->cnt) + if ((rcur || right->cnt) && right->val_types != NULL && right->val_types[rcur] != ERROR_TYPE) { - if (right->val_types[rcur] != val_type) { + /* Skip if the per-element right type is incompatible with the + * left type. u32 and u64 are treated as mutually compatible so + * mixed integer comparisons (e.g. u32 value vs u64 literal) are + * evaluated correctly via the 64-bit path below. */ + if (!types_comparable(val_type, right->val_types[rcur])) { continue; } } @@ -773,7 +811,6 @@ val_cmp(const valstruct *left, const valstruct *right, vtw_cond_e cond) case IPV4_TYPE: case IPV4NET_TYPE: case MACADDR_TYPE: - case INT_TYPE: format = cond_formats[val_type]; parts_num = cond_format_lens[val_type]; (void) sscanf(lval, format, left_parts, left_parts+1, @@ -789,10 +826,24 @@ val_cmp(const valstruct *left, const valstruct *right, vtw_cond_e cond) right_parts+2, right_parts+3, right_parts+4, right_parts+5); break; + case INT_TYPE: case INT64_TYPE: { + /* Unified integer comparison: parse both sides as unsigned long + * long so that u32 and u64 operands can be mixed without loss. */ unsigned long long lv = 0, rv = 0; - (void) sscanf(lval, "%llu", &lv); - (void) sscanf(rval, "%llu", &rv); + char *endp = NULL; + errno = 0; + lv = strtoull(lval, &endp, 10); + if (errno != 0 || endp == lval || (endp && *endp != '\0')) { + /* unparseable left operand: skip this comparison */ + continue; + } + errno = 0; + rv = strtoull(rval, &endp, 10); + if (errno != 0 || endp == rval || (endp && *endp != '\0')) { + /* unparseable right operand: skip this comparison */ + continue; + } if (lv > rv) res = 1; else if (lv < rv) res = -1; else res = 0; @@ -870,7 +921,7 @@ static boolean check_comp(vtw_node *cur) status, right.val_type, right.cnt, right.val); if (status) goto free_and_return; - if(left.val_type != right.val_type) { + if (!types_comparable(left.val_type, right.val_type)) { printf("Different types in comparison\n"); goto free_and_return; } @@ -1917,9 +1968,9 @@ boolean validate_value(const vtw_def *def, char *cp) if (status != VTWERR_OK) { return FALSE; } - if ((def->def_type!=ERROR_TYPE) && - ((validate_value_val.val_type != def->def_type) && - (validate_value_val.val_type != def->def_type2))) { + if ((def->def_type!=ERROR_TYPE) && + !type_accepts_val(def->def_type, validate_value_val.val_type) && + !type_accepts_val(def->def_type2, validate_value_val.val_type)) { if (def->def_type_help){ (void)expand_string(def->def_type_help); OUTPUT_USER("%s\n", exe_string); diff --git a/src/cli_parse.y b/src/cli_parse.y index f871894..794a388 100644 --- a/src/cli_parse.y +++ b/src/cli_parse.y @@ -170,7 +170,19 @@ help_cause: HELP STRING default_cause: DEFAULT VALUE { - if ($2.val_type != parse_defp->def_type) + /* Accept the default if its type matches either declared + * type. Additionally, a u32 literal is accepted in a u64 + * context (u32 values are a subset of u64), mirroring the + * runtime check in validate_value(). */ + vtw_type_e vt = $2.val_type; + vtw_type_e dt1 = parse_defp->def_type; + vtw_type_e dt2 = parse_defp->def_type2; + int ok = (vt == dt1) + || (dt1 == INT64_TYPE && vt == INT_TYPE) + || (dt2 != ERROR_TYPE + && (vt == dt2 + || (dt2 == INT64_TYPE && vt == INT_TYPE))); + if (!ok) yy_cli_parse_error((const char *)"Bad default\n"); parse_defp->def_default = $2.val; } -- cgit v1.2.3 From 66241a3b73b9df71aaae1d4a57b0d5987dfa47a0 Mon Sep 17 00:00:00 2001 From: Yahya Civelek Date: Thu, 30 Apr 2026 09:19:48 +0300 Subject: Revert "T8587: address review feedback for u64 type support" This reverts commit fc06449dd9a255353cf21e369d5e3f1e74e8188d. --- src/cli_cstore.h | 5 ++-- src/cli_def.l | 11 +++----- src/cli_new.c | 81 +++++++++++--------------------------------------------- src/cli_parse.y | 14 +--------- 4 files changed, 21 insertions(+), 90 deletions(-) diff --git a/src/cli_cstore.h b/src/cli_cstore.h index 62903ab..1e82bd8 100644 --- a/src/cli_cstore.h +++ b/src/cli_cstore.h @@ -35,12 +35,11 @@ typedef enum { IPV6_TYPE, IPV6NET_TYPE, MACADDR_TYPE, + INT64_TYPE, DOMAIN_TYPE, /*end of addr types */ TEXT_TYPE, BOOL_TYPE, - PRIORITY_TYPE, - INT64_TYPE /* u64; appended last to preserve ABI stability - against out-of-tree consumers. */ + PRIORITY_TYPE } vtw_type_e; typedef struct { diff --git a/src/cli_def.l b/src/cli_def.l index 3a905e7..b9e379b 100644 --- a/src/cli_def.l +++ b/src/cli_def.l @@ -456,18 +456,13 @@ RE_ACT_FIELD (help|syntax|commit|delete|update|activate|create|begin|end|enumera {RE_VAL_PRIORITY} { return return_value(PRIORITY_TYPE); } {RE_VAL_U32} { - /* Classify integer literal as u32 if it fits in unsigned int, - * as u64 if it exceeds UINT_MAX but fits in unsigned long long, - * otherwise reject as a syntax error so out-of-range constants - * don't silently get treated as u32. */ + /* classify integer literal as u32 if it fits in unsigned int, + * otherwise as u64 (cli_parse.y / validators may further range-check). */ unsigned long long ullv = 0; char *endp = NULL; errno = 0; ullv = strtoull(yy_cli_def_text, &endp, 10); - if (errno == ERANGE || endp == yy_cli_def_text || (endp && *endp != '\0')) { - return SYNTAX_ERROR; - } - if (ullv > (unsigned long long)UINT_MAX) { + if (errno == 0 && endp && *endp == '\0' && ullv > (unsigned long long)UINT_MAX) { return return_value(INT64_TYPE); } return return_value(INT_TYPE); diff --git a/src/cli_new.c b/src/cli_new.c index fdd4131..1b47d44 100644 --- a/src/cli_new.c +++ b/src/cli_new.c @@ -55,9 +55,6 @@ void *var_ref_handle = NULL; static vtw_node *vtw_free_nodes; /* linked via left */ static int cond1[TOP_COND] ={5, 0,-1,-1, 0, 1, 0, 0}; static int cond2[TOP_COND] ={5, 0, 1,-1,-1, 1, 1, 0}; -/* Indexed by vtw_type_e for types <= MACADDR_TYPE only. INT64_TYPE sits - * past DOMAIN_TYPE in the enum and is handled via its own branch in - * val_cmp(); it must never be used as an index into these tables. */ static char const *cond_formats[DOMAIN_TYPE] = { 0, @@ -66,7 +63,8 @@ static char const *cond_formats[DOMAIN_TYPE] = "%u.%u.%u.%u/%u", /* IPV4NET_TYPE */ "%x:%x:%x:%x:%x:%x:%x:%x", /* IPV6NET */ "%x:%x:%x:%x:%x:%x:%x:%x/%u", /* IPV6NET_TYPE */ - "%x:%x:%x:%x:%x:%x" /* MACADDR_TYPE */ + "%x:%x:%x:%x:%x:%x", /* MACADDR_TYPE */ + "%llu" /* INT64_TYPE */ }; static int cond_format_lens[DOMAIN_TYPE] = @@ -77,7 +75,8 @@ static int cond_format_lens[DOMAIN_TYPE] = 5, /* IPV4NET_TYPE */ 16, /* IPV6_TYPE */ 17, /* IPV6NET_TYPE */ - 6 /* MACADDR_TYPE */ + 6, /* MACADDR_TYPE */ + 1 /* INT64_TYPE */ }; static int cli_val_len; @@ -112,38 +111,6 @@ static int set_reference_environment(const char* var_reference, clind_path_ref *n_cmd_path, int active); -/* Integer type helpers: u32 values are a subset of u64 values, so allow - * using an INT_TYPE literal where an INT64_TYPE is expected, and permit - * comparisons between u32 and u64 operands. The reverse (INT64_TYPE - * value in an INT_TYPE context) is rejected because it would exceed - * u32 range. */ -static inline boolean -is_int_like(vtw_type_e t) -{ - return (t == INT_TYPE || t == INT64_TYPE); -} - -/* Returns TRUE if a value of type `val_type` is acceptable in a context - * declaring `expected`. Strict equality, except a u32 value is accepted - * in a u64 context. */ -static inline boolean -type_accepts_val(vtw_type_e expected, vtw_type_e val_type) -{ - if (expected == val_type) return TRUE; - if (expected == INT64_TYPE && val_type == INT_TYPE) return TRUE; - return FALSE; -} - -/* Returns TRUE if two types may be meaningfully compared: equal types, or - * any pair among {u32, u64}. */ -static inline boolean -types_comparable(vtw_type_e a, vtw_type_e b) -{ - if (a == b) return TRUE; - if (is_int_like(a) && is_int_like(b)) return TRUE; - return FALSE; -} - /************************************************* GLOBAL FUNCTIONS ***************************************************/ @@ -639,9 +606,8 @@ int char2val_notext(const vtw_def *def, int my_type, int my_type2, } return 0; } - if (!type_accepts_val(my_type, get_cli_value_ptr()->val_type) && - (my_type2 == ERROR_TYPE - || !type_accepts_val(my_type2, get_cli_value_ptr()->val_type))) { + if (my_type != get_cli_value_ptr()->val_type && + (my_type2 != ERROR_TYPE && my_type2 != get_cli_value_ptr()->val_type)) { if (def->def_type_help){ set_at_string(value); (void)expand_string(def->def_type_help); @@ -785,14 +751,10 @@ val_cmp(const valstruct *left, const valstruct *right, vtw_cond_e cond) rval = right->vals[rcur]; //don't bother comparing if these are different types. - if ((rcur || right->cnt) + if ((rcur || right->cnt) && right->val_types != NULL && right->val_types[rcur] != ERROR_TYPE) { - /* Skip if the per-element right type is incompatible with the - * left type. u32 and u64 are treated as mutually compatible so - * mixed integer comparisons (e.g. u32 value vs u64 literal) are - * evaluated correctly via the 64-bit path below. */ - if (!types_comparable(val_type, right->val_types[rcur])) { + if (right->val_types[rcur] != val_type) { continue; } } @@ -811,6 +773,7 @@ val_cmp(const valstruct *left, const valstruct *right, vtw_cond_e cond) case IPV4_TYPE: case IPV4NET_TYPE: case MACADDR_TYPE: + case INT_TYPE: format = cond_formats[val_type]; parts_num = cond_format_lens[val_type]; (void) sscanf(lval, format, left_parts, left_parts+1, @@ -826,24 +789,10 @@ val_cmp(const valstruct *left, const valstruct *right, vtw_cond_e cond) right_parts+2, right_parts+3, right_parts+4, right_parts+5); break; - case INT_TYPE: case INT64_TYPE: { - /* Unified integer comparison: parse both sides as unsigned long - * long so that u32 and u64 operands can be mixed without loss. */ unsigned long long lv = 0, rv = 0; - char *endp = NULL; - errno = 0; - lv = strtoull(lval, &endp, 10); - if (errno != 0 || endp == lval || (endp && *endp != '\0')) { - /* unparseable left operand: skip this comparison */ - continue; - } - errno = 0; - rv = strtoull(rval, &endp, 10); - if (errno != 0 || endp == rval || (endp && *endp != '\0')) { - /* unparseable right operand: skip this comparison */ - continue; - } + (void) sscanf(lval, "%llu", &lv); + (void) sscanf(rval, "%llu", &rv); if (lv > rv) res = 1; else if (lv < rv) res = -1; else res = 0; @@ -921,7 +870,7 @@ static boolean check_comp(vtw_node *cur) status, right.val_type, right.cnt, right.val); if (status) goto free_and_return; - if (!types_comparable(left.val_type, right.val_type)) { + if(left.val_type != right.val_type) { printf("Different types in comparison\n"); goto free_and_return; } @@ -1968,9 +1917,9 @@ boolean validate_value(const vtw_def *def, char *cp) if (status != VTWERR_OK) { return FALSE; } - if ((def->def_type!=ERROR_TYPE) && - !type_accepts_val(def->def_type, validate_value_val.val_type) && - !type_accepts_val(def->def_type2, validate_value_val.val_type)) { + if ((def->def_type!=ERROR_TYPE) && + ((validate_value_val.val_type != def->def_type) && + (validate_value_val.val_type != def->def_type2))) { if (def->def_type_help){ (void)expand_string(def->def_type_help); OUTPUT_USER("%s\n", exe_string); diff --git a/src/cli_parse.y b/src/cli_parse.y index 794a388..f871894 100644 --- a/src/cli_parse.y +++ b/src/cli_parse.y @@ -170,19 +170,7 @@ help_cause: HELP STRING default_cause: DEFAULT VALUE { - /* Accept the default if its type matches either declared - * type. Additionally, a u32 literal is accepted in a u64 - * context (u32 values are a subset of u64), mirroring the - * runtime check in validate_value(). */ - vtw_type_e vt = $2.val_type; - vtw_type_e dt1 = parse_defp->def_type; - vtw_type_e dt2 = parse_defp->def_type2; - int ok = (vt == dt1) - || (dt1 == INT64_TYPE && vt == INT_TYPE) - || (dt2 != ERROR_TYPE - && (vt == dt2 - || (dt2 == INT64_TYPE && vt == INT_TYPE))); - if (!ok) + if ($2.val_type != parse_defp->def_type) yy_cli_parse_error((const char *)"Bad default\n"); parse_defp->def_default = $2.val; } -- cgit v1.2.3 From 9422a9297c5e851feb70ec8483c22ab4f5412996 Mon Sep 17 00:00:00 2001 From: Yahya Civelek Date: Thu, 30 Apr 2026 09:20:10 +0300 Subject: Revert "T8587: add u64 type support" This reverts commit 519e60e15ab52f887b87a5474fdebbd45063b567. --- etc/bash_completion.d/vyatta-cfg | 6 ------ src/cli_cstore.h | 1 - src/cli_def.l | 22 +++------------------- src/cli_new.c | 16 ++-------------- src/cli_val.l | 16 ++++++---------- 5 files changed, 11 insertions(+), 50 deletions(-) diff --git a/etc/bash_completion.d/vyatta-cfg b/etc/bash_completion.d/vyatta-cfg index 8961af2..bbb6d12 100644 --- a/etc/bash_completion.d/vyatta-cfg +++ b/etc/bash_completion.d/vyatta-cfg @@ -550,12 +550,6 @@ get_value_format_string () u32:*) echo -n "<${vtype##u32:}>" ;; - u64) - echo -n '<0-18446744073709551615>' - ;; - u64:*) - echo -n "<${vtype##u64:}>" - ;; range) echo -n "-" ;; diff --git a/src/cli_cstore.h b/src/cli_cstore.h index 1e82bd8..3ef7f72 100644 --- a/src/cli_cstore.h +++ b/src/cli_cstore.h @@ -35,7 +35,6 @@ typedef enum { IPV6_TYPE, IPV6NET_TYPE, MACADDR_TYPE, - INT64_TYPE, DOMAIN_TYPE, /*end of addr types */ TEXT_TYPE, BOOL_TYPE, diff --git a/src/cli_def.l b/src/cli_def.l index b9e379b..820a7a4 100644 --- a/src/cli_def.l +++ b/src/cli_def.l @@ -3,9 +3,6 @@ %x str %option noyywrap %{ -#include -#include -#include #include "cli_val.h" #include "cli_parse.h" @@ -46,11 +43,9 @@ static int act_types[] = { -1, -1, -1, static char *type_names[] = { "txt", "u32", "ipv4", "ipv4net", "ipv6", "ipv6net", "bool", "macaddr", - "u64", NULL }; static int type_t[] = { TEXT_TYPE, INT_TYPE, IPV4_TYPE, IPV4NET_TYPE, - IPV6_TYPE, IPV6NET_TYPE, BOOL_TYPE, MACADDR_TYPE, - INT64_TYPE, 0 }; + IPV6_TYPE, IPV6NET_TYPE, BOOL_TYPE, MACADDR_TYPE, 0 }; static char *op_cond_strs[] = { "in", "==", "!=", "<", ">", "<=", ">=", NULL }; static int op_cond_types[] = { IN_COND, EQ_COND, NE_COND, LT_COND, @@ -261,7 +256,7 @@ RE_URL_DIGITS {RE_URL_DIGIT}{1,} RE_URL_SUBDELIMS "!"|"$"|"&"|"'"|"("|")"|"*"|"+"|","|";"|"=" /* type names */ -RE_TYPE_NAME (txt|u32|u64|ipv4|ipv4net|ipv6|ipv6net|bool|macaddr) +RE_TYPE_NAME (txt|u32|ipv4|ipv4net|ipv6|ipv6net|bool|macaddr) /* values */ RE_VAL_U32 [0-9]+ @@ -455,18 +450,7 @@ RE_ACT_FIELD (help|syntax|commit|delete|update|activate|create|begin|end|enumera } {RE_VAL_PRIORITY} { return return_value(PRIORITY_TYPE); } -{RE_VAL_U32} { - /* classify integer literal as u32 if it fits in unsigned int, - * otherwise as u64 (cli_parse.y / validators may further range-check). */ - unsigned long long ullv = 0; - char *endp = NULL; - errno = 0; - ullv = strtoull(yy_cli_def_text, &endp, 10); - if (errno == 0 && endp && *endp == '\0' && ullv > (unsigned long long)UINT_MAX) { - return return_value(INT64_TYPE); - } - return return_value(INT_TYPE); - } +{RE_VAL_U32} { return return_value(INT_TYPE); } {RE_IPV4} { return return_value(IPV4_TYPE); } {RE_IPV4NET} { return return_value(IPV4NET_TYPE); } {RE_IPV6} { return return_value(IPV6_TYPE); } diff --git a/src/cli_new.c b/src/cli_new.c index 1b47d44..f045ba5 100644 --- a/src/cli_new.c +++ b/src/cli_new.c @@ -63,8 +63,7 @@ static char const *cond_formats[DOMAIN_TYPE] = "%u.%u.%u.%u/%u", /* IPV4NET_TYPE */ "%x:%x:%x:%x:%x:%x:%x:%x", /* IPV6NET */ "%x:%x:%x:%x:%x:%x:%x:%x/%u", /* IPV6NET_TYPE */ - "%x:%x:%x:%x:%x:%x", /* MACADDR_TYPE */ - "%llu" /* INT64_TYPE */ + "%x:%x:%x:%x:%x:%x" /* MACADDR_TYPE */ }; static int cond_format_lens[DOMAIN_TYPE] = @@ -75,8 +74,7 @@ static int cond_format_lens[DOMAIN_TYPE] = 5, /* IPV4NET_TYPE */ 16, /* IPV6_TYPE */ 17, /* IPV6NET_TYPE */ - 6, /* MACADDR_TYPE */ - 1 /* INT64_TYPE */ + 6 /* MACADDR_TYPE */ }; static int cli_val_len; @@ -789,15 +787,6 @@ val_cmp(const valstruct *left, const valstruct *right, vtw_cond_e cond) right_parts+2, right_parts+3, right_parts+4, right_parts+5); break; - case INT64_TYPE: { - unsigned long long lv = 0, rv = 0; - (void) sscanf(lval, "%llu", &lv); - (void) sscanf(rval, "%llu", &rv); - if (lv > rv) res = 1; - else if (lv < rv) res = -1; - else res = 0; - goto done_comp; - } case TEXT_TYPE: case BOOL_TYPE: res = strcmp(lval, rval); @@ -1983,7 +1972,6 @@ touch(void) const char *type_to_name(vtw_type_e type) { switch(type) { case INT_TYPE: return("u32"); - case INT64_TYPE: return("u64"); case IPV4_TYPE: return("ipv4"); case IPV4NET_TYPE: return("ipv4net"); case IPV6_TYPE: return("ipv6"); diff --git a/src/cli_val.l b/src/cli_val.l index b8cb459..d568de6 100644 --- a/src/cli_val.l +++ b/src/cli_val.l @@ -228,20 +228,16 @@ false { } [0-9]+ { - unsigned long long ucval = 0; + long long int cval = 0; char *endp = NULL; errno = 0; - ucval = strtoull(yytext, &endp, 10); - if ((errno == ERANGE && ucval == ULLONG_MAX) - || (errno != 0 && ucval == 0) - || (*endp != '\0')) { + cval = strtoll(yytext, &endp, 10); + if ((errno == ERANGE && (cval == LLONG_MAX || cval == LLONG_MIN)) + || (errno != 0 && cval == 0) + || (*endp != '\0') || (cval < 0) || (cval > UINT_MAX)) { return SYNTAX_ERROR; } - if (ucval > (unsigned long long)UINT_MAX) { - make_val_value(INT64_TYPE); - } else { - make_val_value(INT_TYPE); - } + make_val_value(INT_TYPE); return VALUE; } -- cgit v1.2.3 From 5250133e6a075358d7cf1f439c03ef60682c587f Mon Sep 17 00:00:00 2001 From: Yahya Civelek Date: Thu, 30 Apr 2026 09:24:23 +0300 Subject: T8587: support u64 type in bash completion value formatting --- etc/bash_completion.d/vyatta-cfg | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/etc/bash_completion.d/vyatta-cfg b/etc/bash_completion.d/vyatta-cfg index bbb6d12..8961af2 100644 --- a/etc/bash_completion.d/vyatta-cfg +++ b/etc/bash_completion.d/vyatta-cfg @@ -550,6 +550,12 @@ get_value_format_string () u32:*) echo -n "<${vtype##u32:}>" ;; + u64) + echo -n '<0-18446744073709551615>' + ;; + u64:*) + echo -n "<${vtype##u64:}>" + ;; range) echo -n "-" ;; -- cgit v1.2.3