pkarashchenko commented on a change in pull request #5690: URL: https://github.com/apache/incubator-nuttx/pull/5690#discussion_r821407979
########## File path: libs/libc/locale/lib_gettext.c ########## @@ -195,6 +213,262 @@ static FAR char *molookup(FAR char *p, size_t size, FAR const char *s) return NULL; } +static FAR const char *skipspace(FAR const char *s) +{ + while (isspace(*s)) + { + s++; + } + + return s; +} + +/* Grammar: + * + * Start = Expr ';' + * Expr = Or | Or '?' Expr ':' Expr + * Or = And | Or '||' And + * And = Eq | And '&&' Eq + * Eq = Rel | Eq '==' Rel | Eq '!=' Rel + * Rel = Add | Rel '<=' Add | Rel '>=' Add | Rel '<' Add | Rel '>' Add + * Add = Mul | Add '+' Mul | Add '-' Mul + * Mul = Prim | Mul '*' Prim | Mul '/' Prim | Mul '%' Prim + * Prim = '(' Expr ')' | '!' Prim | decimal | 'n' + * + * Internals: + * + * Recursive descent expression evaluator with stack depth limit. + * for binary operators an operator-precedence parser is used. + * eval* functions store the result of the parsed subexpression + * and return a pointer to the next non-space character. + */ + +static FAR const char *evalprim(FAR struct eval_s *ev, + FAR const char *s, int d) +{ + FAR char *e; + + if (--d < 0) + { + return ""; + } + + s = skipspace(s); + if (isdigit(*s)) + { + ev->r = strtoul(s, &e, 10); + if (e == s || ev->r == -1) + { + return ""; + } + + return skipspace(e); + } + + if (*s == 'n') + { + ev->r = ev->n; + return skipspace(s + 1); + } + + if (*s == '(') + { + s = evalexpr(ev, s + 1, d); + if (*s != ')') + { + return ""; + } + + return skipspace(s + 1); + } + + if (*s == '!') + { + s = evalprim(ev, s + 1, d); + ev->r = !ev->r; + return s; + } + + return ""; +} + +static int binop(FAR struct eval_s *ev, int op, unsigned long left) +{ + unsigned long a = left; + unsigned long b = ev->r; + + switch (op) + { + case 0: + ev->r = a || b; + return 0; + + case 1: + ev->r = a && b; + return 0; + + case 2: + ev->r = a == b; + return 0; + + case 3: + ev->r = a != b; + return 0; + + case 4: + ev->r = a >= b; + return 0; + + case 5: + ev->r = a <= b; + return 0; + + case 6: + ev->r = a > b; + return 0; + + case 7: + ev->r = a < b; + return 0; + + case 8: + ev->r = a + b; + return 0; + + case 9: + ev->r = a - b; + return 0; + + case 10: + ev->r = a * b; + return 0; + + case 11: + if (b) + { + ev->r = a % b; + return 0; + } Review comment: Do we need to set `ev->r` to predefined value in `else` case or `return 1;` covers that case? ########## File path: libs/libc/locale/lib_gettext.c ########## @@ -119,7 +136,8 @@ static FAR void *momap(FAR const char *path, FAR size_t *size) { *size = st.st_size; map = mmap(NULL, *size, PROT_READ, MAP_SHARED, fd, 0); - if (map[0] != MO_MAGIC && map[0] != __swap_uint32(MO_MAGIC)) + if (map != MAP_FAILED && + map[0] != MO_MAGIC && map[0] != __swap_uint32(MO_MAGIC)) Review comment: Not related to this change, but just for my understanding: Do we swap always not depending on `BYTE_ORDER`? I mean do we have files in different format for LE and BE systems? ########## File path: libs/libc/locale/lib_gettext.c ########## @@ -195,6 +213,262 @@ static FAR char *molookup(FAR char *p, size_t size, FAR const char *s) return NULL; } +static FAR const char *skipspace(FAR const char *s) +{ + while (isspace(*s)) + { + s++; + } + + return s; +} + +/* Grammar: + * + * Start = Expr ';' + * Expr = Or | Or '?' Expr ':' Expr + * Or = And | Or '||' And + * And = Eq | And '&&' Eq + * Eq = Rel | Eq '==' Rel | Eq '!=' Rel + * Rel = Add | Rel '<=' Add | Rel '>=' Add | Rel '<' Add | Rel '>' Add + * Add = Mul | Add '+' Mul | Add '-' Mul + * Mul = Prim | Mul '*' Prim | Mul '/' Prim | Mul '%' Prim + * Prim = '(' Expr ')' | '!' Prim | decimal | 'n' + * + * Internals: + * + * Recursive descent expression evaluator with stack depth limit. + * for binary operators an operator-precedence parser is used. + * eval* functions store the result of the parsed subexpression + * and return a pointer to the next non-space character. + */ + +static FAR const char *evalprim(FAR struct eval_s *ev, + FAR const char *s, int d) +{ + FAR char *e; + + if (--d < 0) + { + return ""; + } + + s = skipspace(s); + if (isdigit(*s)) + { + ev->r = strtoul(s, &e, 10); + if (e == s || ev->r == -1) + { + return ""; + } + + return skipspace(e); + } + + if (*s == 'n') + { + ev->r = ev->n; + return skipspace(s + 1); + } + + if (*s == '(') + { + s = evalexpr(ev, s + 1, d); + if (*s != ')') + { + return ""; + } + + return skipspace(s + 1); + } + + if (*s == '!') + { + s = evalprim(ev, s + 1, d); + ev->r = !ev->r; + return s; + } + + return ""; +} + +static int binop(FAR struct eval_s *ev, int op, unsigned long left) +{ + unsigned long a = left; + unsigned long b = ev->r; + + switch (op) + { + case 0: + ev->r = a || b; + return 0; + + case 1: + ev->r = a && b; + return 0; + + case 2: + ev->r = a == b; + return 0; + + case 3: + ev->r = a != b; + return 0; + + case 4: + ev->r = a >= b; + return 0; + + case 5: + ev->r = a <= b; + return 0; + + case 6: + ev->r = a > b; + return 0; + + case 7: + ev->r = a < b; + return 0; + + case 8: + ev->r = a + b; + return 0; + + case 9: + ev->r = a - b; + return 0; + + case 10: + ev->r = a * b; + return 0; + + case 11: + if (b) + { + ev->r = a % b; + return 0; + } + + return 1; + + case 12: + if (b) + { + ev->r = a / b; + return 0; + } + + return 1; + } + + return 1; +} + +static FAR const char *parseop(FAR struct eval_s *ev, FAR const char *s) +{ + static const char opch[11] = "|&=!><+-*%/"; + static const char opch2[6] = "|&===="; Review comment: same as above ########## File path: libs/libc/locale/lib_gettext.c ########## @@ -195,6 +213,262 @@ static FAR char *molookup(FAR char *p, size_t size, FAR const char *s) return NULL; } +static FAR const char *skipspace(FAR const char *s) +{ + while (isspace(*s)) + { + s++; + } + + return s; +} + +/* Grammar: + * + * Start = Expr ';' + * Expr = Or | Or '?' Expr ':' Expr + * Or = And | Or '||' And + * And = Eq | And '&&' Eq + * Eq = Rel | Eq '==' Rel | Eq '!=' Rel + * Rel = Add | Rel '<=' Add | Rel '>=' Add | Rel '<' Add | Rel '>' Add + * Add = Mul | Add '+' Mul | Add '-' Mul + * Mul = Prim | Mul '*' Prim | Mul '/' Prim | Mul '%' Prim + * Prim = '(' Expr ')' | '!' Prim | decimal | 'n' + * + * Internals: + * + * Recursive descent expression evaluator with stack depth limit. + * for binary operators an operator-precedence parser is used. + * eval* functions store the result of the parsed subexpression + * and return a pointer to the next non-space character. + */ + +static FAR const char *evalprim(FAR struct eval_s *ev, + FAR const char *s, int d) +{ + FAR char *e; + + if (--d < 0) + { + return ""; + } + + s = skipspace(s); + if (isdigit(*s)) + { + ev->r = strtoul(s, &e, 10); + if (e == s || ev->r == -1) + { + return ""; + } + + return skipspace(e); + } + + if (*s == 'n') + { + ev->r = ev->n; + return skipspace(s + 1); + } + + if (*s == '(') + { + s = evalexpr(ev, s + 1, d); + if (*s != ')') + { + return ""; + } + + return skipspace(s + 1); + } + + if (*s == '!') + { + s = evalprim(ev, s + 1, d); + ev->r = !ev->r; + return s; + } + + return ""; +} + +static int binop(FAR struct eval_s *ev, int op, unsigned long left) +{ + unsigned long a = left; + unsigned long b = ev->r; + + switch (op) + { + case 0: + ev->r = a || b; + return 0; + + case 1: + ev->r = a && b; + return 0; + + case 2: + ev->r = a == b; + return 0; + + case 3: + ev->r = a != b; + return 0; + + case 4: + ev->r = a >= b; + return 0; + + case 5: + ev->r = a <= b; + return 0; + + case 6: + ev->r = a > b; + return 0; + + case 7: + ev->r = a < b; + return 0; + + case 8: + ev->r = a + b; + return 0; + + case 9: + ev->r = a - b; + return 0; + + case 10: + ev->r = a * b; + return 0; + + case 11: + if (b) + { + ev->r = a % b; + return 0; + } + + return 1; + + case 12: + if (b) + { + ev->r = a / b; + return 0; + } + + return 1; + } + + return 1; +} + +static FAR const char *parseop(FAR struct eval_s *ev, FAR const char *s) +{ + static const char opch[11] = "|&=!><+-*%/"; + static const char opch2[6] = "|&===="; + int i; + + for (i = 0; i < 11; i++) + { + if (*s == opch[i]) + { + /* note: >,< are accepted with or without = */ + + if (i < 6 && s[1] == opch2[i]) Review comment: ```suggestion if (i < sizeof(opch2) && *(s + 1) == opch2[i]) ``` `*(s + 1)` -- just for style consistency ########## File path: libs/libc/locale/lib_gettext.c ########## @@ -195,6 +213,262 @@ static FAR char *molookup(FAR char *p, size_t size, FAR const char *s) return NULL; } +static FAR const char *skipspace(FAR const char *s) +{ + while (isspace(*s)) + { + s++; + } + + return s; +} + +/* Grammar: + * + * Start = Expr ';' + * Expr = Or | Or '?' Expr ':' Expr + * Or = And | Or '||' And + * And = Eq | And '&&' Eq + * Eq = Rel | Eq '==' Rel | Eq '!=' Rel + * Rel = Add | Rel '<=' Add | Rel '>=' Add | Rel '<' Add | Rel '>' Add + * Add = Mul | Add '+' Mul | Add '-' Mul + * Mul = Prim | Mul '*' Prim | Mul '/' Prim | Mul '%' Prim + * Prim = '(' Expr ')' | '!' Prim | decimal | 'n' + * + * Internals: + * + * Recursive descent expression evaluator with stack depth limit. + * for binary operators an operator-precedence parser is used. + * eval* functions store the result of the parsed subexpression + * and return a pointer to the next non-space character. + */ + +static FAR const char *evalprim(FAR struct eval_s *ev, + FAR const char *s, int d) +{ + FAR char *e; + + if (--d < 0) + { + return ""; + } + + s = skipspace(s); + if (isdigit(*s)) + { + ev->r = strtoul(s, &e, 10); + if (e == s || ev->r == -1) + { + return ""; + } + + return skipspace(e); + } + + if (*s == 'n') + { + ev->r = ev->n; + return skipspace(s + 1); + } + + if (*s == '(') + { + s = evalexpr(ev, s + 1, d); + if (*s != ')') + { + return ""; + } + + return skipspace(s + 1); + } + + if (*s == '!') + { + s = evalprim(ev, s + 1, d); + ev->r = !ev->r; + return s; + } + + return ""; +} + +static int binop(FAR struct eval_s *ev, int op, unsigned long left) +{ + unsigned long a = left; + unsigned long b = ev->r; + + switch (op) + { + case 0: + ev->r = a || b; + return 0; + + case 1: + ev->r = a && b; + return 0; + + case 2: + ev->r = a == b; + return 0; + + case 3: + ev->r = a != b; + return 0; + + case 4: + ev->r = a >= b; + return 0; + + case 5: + ev->r = a <= b; + return 0; + + case 6: + ev->r = a > b; + return 0; + + case 7: + ev->r = a < b; + return 0; + + case 8: + ev->r = a + b; + return 0; + + case 9: + ev->r = a - b; + return 0; + + case 10: + ev->r = a * b; + return 0; + + case 11: + if (b) + { + ev->r = a % b; + return 0; + } + + return 1; + + case 12: + if (b) + { + ev->r = a / b; + return 0; + } + + return 1; + } + + return 1; +} + +static FAR const char *parseop(FAR struct eval_s *ev, FAR const char *s) +{ + static const char opch[11] = "|&=!><+-*%/"; + static const char opch2[6] = "|&===="; + int i; + + for (i = 0; i < 11; i++) Review comment: ```suggestion for (i = 0; i < sizeof(opch); i++) ``` ########## File path: libs/libc/locale/lib_gettext.c ########## @@ -195,6 +213,262 @@ static FAR char *molookup(FAR char *p, size_t size, FAR const char *s) return NULL; } +static FAR const char *skipspace(FAR const char *s) +{ + while (isspace(*s)) + { + s++; + } + + return s; +} + +/* Grammar: + * + * Start = Expr ';' + * Expr = Or | Or '?' Expr ':' Expr + * Or = And | Or '||' And + * And = Eq | And '&&' Eq + * Eq = Rel | Eq '==' Rel | Eq '!=' Rel + * Rel = Add | Rel '<=' Add | Rel '>=' Add | Rel '<' Add | Rel '>' Add + * Add = Mul | Add '+' Mul | Add '-' Mul + * Mul = Prim | Mul '*' Prim | Mul '/' Prim | Mul '%' Prim + * Prim = '(' Expr ')' | '!' Prim | decimal | 'n' + * + * Internals: + * + * Recursive descent expression evaluator with stack depth limit. + * for binary operators an operator-precedence parser is used. + * eval* functions store the result of the parsed subexpression + * and return a pointer to the next non-space character. + */ + +static FAR const char *evalprim(FAR struct eval_s *ev, + FAR const char *s, int d) +{ + FAR char *e; + + if (--d < 0) + { + return ""; + } + + s = skipspace(s); + if (isdigit(*s)) + { + ev->r = strtoul(s, &e, 10); + if (e == s || ev->r == -1) + { + return ""; + } + + return skipspace(e); + } + + if (*s == 'n') + { + ev->r = ev->n; + return skipspace(s + 1); + } + + if (*s == '(') + { + s = evalexpr(ev, s + 1, d); + if (*s != ')') + { + return ""; + } + + return skipspace(s + 1); + } + + if (*s == '!') + { + s = evalprim(ev, s + 1, d); + ev->r = !ev->r; + return s; + } + + return ""; +} + +static int binop(FAR struct eval_s *ev, int op, unsigned long left) Review comment: ```suggestion static bool binop(FAR struct eval_s *ev, int op, unsigned long left) ``` ########## File path: libs/libc/locale/lib_gettext.c ########## @@ -321,14 +597,79 @@ FAR char *dcngettext(FAR const char *domainname, return notrans; } + /* Initialize the default plural rule */ + + mofile->plural_rule = "n!=1;"; + mofile->nplurals = 2; + + /* Parse the plural rule from the header entry(empty string) */ + + r = molookup(mofile->map, mofile->size, ""); + while (r && strncmp(r, "Plural-Forms:", 13)) Review comment: ```suggestion while ((r != NULL) && (strncmp(r, "Plural-Forms:", 13) != 0)) ``` ########## File path: libs/libc/locale/lib_gettext.c ########## @@ -195,6 +213,262 @@ static FAR char *molookup(FAR char *p, size_t size, FAR const char *s) return NULL; } +static FAR const char *skipspace(FAR const char *s) +{ + while (isspace(*s)) + { + s++; + } + + return s; +} + +/* Grammar: + * + * Start = Expr ';' + * Expr = Or | Or '?' Expr ':' Expr + * Or = And | Or '||' And + * And = Eq | And '&&' Eq + * Eq = Rel | Eq '==' Rel | Eq '!=' Rel + * Rel = Add | Rel '<=' Add | Rel '>=' Add | Rel '<' Add | Rel '>' Add + * Add = Mul | Add '+' Mul | Add '-' Mul + * Mul = Prim | Mul '*' Prim | Mul '/' Prim | Mul '%' Prim + * Prim = '(' Expr ')' | '!' Prim | decimal | 'n' + * + * Internals: + * + * Recursive descent expression evaluator with stack depth limit. + * for binary operators an operator-precedence parser is used. + * eval* functions store the result of the parsed subexpression + * and return a pointer to the next non-space character. + */ + +static FAR const char *evalprim(FAR struct eval_s *ev, + FAR const char *s, int d) +{ + FAR char *e; + + if (--d < 0) + { + return ""; + } + + s = skipspace(s); + if (isdigit(*s)) + { + ev->r = strtoul(s, &e, 10); + if (e == s || ev->r == -1) + { + return ""; + } + + return skipspace(e); + } + + if (*s == 'n') + { + ev->r = ev->n; + return skipspace(s + 1); + } + + if (*s == '(') + { + s = evalexpr(ev, s + 1, d); + if (*s != ')') + { + return ""; + } + + return skipspace(s + 1); + } + + if (*s == '!') + { + s = evalprim(ev, s + 1, d); + ev->r = !ev->r; + return s; + } + + return ""; +} + +static int binop(FAR struct eval_s *ev, int op, unsigned long left) +{ + unsigned long a = left; + unsigned long b = ev->r; + + switch (op) + { + case 0: + ev->r = a || b; + return 0; + + case 1: + ev->r = a && b; + return 0; + + case 2: + ev->r = a == b; + return 0; + + case 3: + ev->r = a != b; + return 0; + + case 4: + ev->r = a >= b; + return 0; + + case 5: + ev->r = a <= b; + return 0; + + case 6: + ev->r = a > b; + return 0; + + case 7: + ev->r = a < b; + return 0; + + case 8: + ev->r = a + b; + return 0; + + case 9: + ev->r = a - b; + return 0; + + case 10: + ev->r = a * b; + return 0; + + case 11: + if (b) + { + ev->r = a % b; + return 0; + } + + return 1; + + case 12: + if (b) + { + ev->r = a / b; + return 0; + } + + return 1; + } + + return 1; +} + +static FAR const char *parseop(FAR struct eval_s *ev, FAR const char *s) +{ + static const char opch[11] = "|&=!><+-*%/"; Review comment: either `static const char opch[11] = { '|', '&', '=', '!', '>', '<', '+', '-', '*', '%', '/' };` or `static const char opch[] = "|&=!><+-*%/";` because `|&=!><+-*%/` are 11 symbols and `opch[11]` does not include `'\0'`. ########## File path: libs/libc/locale/lib_gettext.c ########## @@ -321,14 +597,79 @@ FAR char *dcngettext(FAR const char *domainname, return notrans; } + /* Initialize the default plural rule */ + + mofile->plural_rule = "n!=1;"; + mofile->nplurals = 2; + + /* Parse the plural rule from the header entry(empty string) */ + + r = molookup(mofile->map, mofile->size, ""); + while (r && strncmp(r, "Plural-Forms:", 13)) + { + r = strchr(r, '\n'); + if (r != NULL) + { + r += 1; + } + } + + if (r != NULL) + { + r = skipspace(r + 13); + if (strncmp(r, "nplurals=", 9) == 0) + { + mofile->nplurals = strtoul(r + 9, (FAR char **)&r, 10); + } + + r = strchr(r, ';'); + if (r != NULL) + { + r = skipspace(r + 1); + if (strncmp(r, "plural=", 7) == 0) + { + mofile->plural_rule = r + 7; + } + } + } + mofile->next = g_mofile; g_mofile = mofile; } _SEM_POST(&g_sem); /* Leave look before search */ trans = molookup(mofile->map, mofile->size, msgid1); - return trans ? trans : notrans; + if (trans == NULL) + { + return notrans; + } + + /* Process the plural rule if request */ + + if (msgid2 && mofile->nplurals) + { + unsigned long plural = eval(mofile->plural_rule, n); + if (plural >= mofile->nplurals) + { + return notrans; + } + + while (plural--) Review comment: ```suggestion while (plural-- != 0) ``` or ``` for (; plural > 0; plural--) ``` -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: commits-unsubscr...@nuttx.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org