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


Reply via email to