bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] regex: use C99-style array arg syntax


From: Paul Eggert
Subject: [PATCH] regex: use C99-style array arg syntax
Date: Thu, 26 Aug 2021 15:44:54 -0700

This should help with some static checking.
Derived from a suggestion by Martin Sebor in:
https://sourceware.org/pipermail/libc-alpha/2021-August/130336.html
This also ports recent and relevant Glibc changes to Gnulib
and prepares to copy back.
* lib/cdefs.h (__ARG_NELTS): New macro.
* lib/regex.c: Ignore -Wvla for the whole file.
* lib/regex.h (_ARG_NELTS_, _Attr_access_): New macros.
Ignore -Wvla when declaring regexec.
* lib/regex.h (re_compile_pattern, re_search, re_search_2)
(re_match, re_match_2, regcomp, regerror):
Use _Attr_access_ where that could help static checking.
* lib/regexec.c (regexec, __compat_regexec, re_copy_regs)
(re_search_internal, proceed_next_node, push_fail_stack)
(pop_fail_stack, set_regs, update_regs):
Use __ARG_NELTS for each array parameter whose size is another arg,
but which might be null.
---
 ChangeLog     | 15 ++++++++++
 lib/cdefs.h   |  9 ++++++
 lib/regex.c   |  1 +
 lib/regex.h   | 52 +++++++++++++++++++++++++++++-----
 lib/regexec.c | 78 +++++++++++++++++++++++++++++----------------------
 5 files changed, 114 insertions(+), 41 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 785fbc44b3..80c2b83846 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2021-08-26  Paul Eggert  <eggert@cs.ucla.edu>
+
+       regex: use C99-style array arg syntax
+       This should help with some static checking.
+       Derived from a suggestion by Martin Sebor in:
+       https://sourceware.org/pipermail/libc-alpha/2021-August/130336.html
+       * lib/cdefs.h (__ARG_NELTS): New macro.
+       * lib/regex.c: Ignore -Wvla for the whole file.
+       * lib/regex.h (_ARG_NELTS_): New macro.
+       Ignore -Wvla when declaring regexec.
+       * lib/regexec.c (regexec, __compat_regexec, re_copy_regs)
+       (re_search_internal, proceed_next_node, push_fail_stack)
+       (pop_fail_stack, set_regs, update_regs):
+       Use __ARG_NELTS for each array parameter whose size is another arg.
+
 2021-08-25  Bruno Haible  <bruno@clisp.org>
 
        execute tests: Fix test failure when libtool is in use.
diff --git a/lib/cdefs.h b/lib/cdefs.h
index 4dac9d264d..13c5542bfd 100644
--- a/lib/cdefs.h
+++ b/lib/cdefs.h
@@ -634,4 +634,13 @@ _Static_assert (0, "IEEE 128-bits long double requires 
redirection on this platf
 # define __attribute_returns_twice__ /* Ignore.  */
 #endif
 
+/* Specify the number of elements of a function's array parameter,
+   as in 'int f (int n, int a[__ARG_NELTS (n)]);'.  */
+#if (defined __STDC_VERSION__ && 199901L <= __STDC_VERSION__ \
+     && !defined __STDC_NO_VLA__)
+# define __ARG_NELTS(n) n
+#else
+# define __ARG_NELTS(n)
+#endif
+
 #endif  /* sys/cdefs.h */
diff --git a/lib/regex.c b/lib/regex.c
index 7296be0f08..d32863972c 100644
--- a/lib/regex.c
+++ b/lib/regex.c
@@ -24,6 +24,7 @@
 
 # if __GNUC_PREREQ (4, 6)
 #  pragma GCC diagnostic ignored "-Wsuggest-attribute=pure"
+#  pragma GCC diagnostic ignored "-Wvla"
 # endif
 # if __GNUC_PREREQ (4, 3)
 #  pragma GCC diagnostic ignored "-Wold-style-definition"
diff --git a/lib/regex.h b/lib/regex.h
index 8e4ef45578..540c323163 100644
--- a/lib/regex.h
+++ b/lib/regex.h
@@ -522,6 +522,32 @@ typedef struct
 
 /* Declarations for routines.  */
 
+#ifndef _ARG_NELTS_
+# ifdef __ARG_NELTS
+#  define _ARG_NELTS_(arg) __ARG_NELTS (arg)
+# elif (defined __STDC_VERSION__ && 199901L <= __STDC_VERSION__ \
+       && !defined __STDC_NO_VLA__)
+#  define _ARG_NELTS_(n) n
+# else
+#  define _ARG_NELTS_(n)
+# endif
+#endif
+
+#if defined __GNUC__ && 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wvla"
+#endif
+
+#ifndef _Attr_access_
+# ifdef __attr_access
+#  define _Attr_access_(arg) __attr_access (arg)
+# elif defined __GNUC__ && 10 <= __GNUC__
+#  define _Attr_access_(x) __attribute__ ((__access__ x))
+# else
+#  define _Attr_access_(x)
+# endif
+#endif
+
 #ifdef __USE_GNU
 /* Sets the current default syntax to SYNTAX, and return the old syntax.
    You can also simply assign to the 're_syntax_options' variable.  */
@@ -536,7 +562,8 @@ extern reg_syntax_t re_set_syntax (reg_syntax_t __syntax);
    'regcomp', with a malloc'ed value, or set to NULL before calling
    'regfree'.  */
 extern const char *re_compile_pattern (const char *__pattern, size_t __length,
-                                      struct re_pattern_buffer *__buffer);
+                                      struct re_pattern_buffer *__buffer)
+    _Attr_access_ ((__read_only__, 1, 2));
 
 
 /* Compile a fastmap for the compiled pattern in BUFFER; used to
@@ -553,7 +580,8 @@ extern int re_compile_fastmap (struct re_pattern_buffer 
*__buffer);
 extern regoff_t re_search (struct re_pattern_buffer *__buffer,
                           const char *__String, regoff_t __length,
                           regoff_t __start, regoff_t __range,
-                          struct re_registers *__regs);
+                          struct re_registers *__regs)
+    _Attr_access_ ((__read_only__, 2, 3));
 
 
 /* Like 're_search', but search in the concatenation of STRING1 and
@@ -563,14 +591,17 @@ extern regoff_t re_search_2 (struct re_pattern_buffer 
*__buffer,
                             const char *__string2, regoff_t __length2,
                             regoff_t __start, regoff_t __range,
                             struct re_registers *__regs,
-                            regoff_t __stop);
+                            regoff_t __stop)
+    _Attr_access_ ((__read_only__, 2, 3))
+    _Attr_access_ ((__read_only__, 4, 5));
 
 
 /* Like 're_search', but return how many characters in STRING the regexp
    in BUFFER matched, starting at position START.  */
 extern regoff_t re_match (struct re_pattern_buffer *__buffer,
                          const char *__String, regoff_t __length,
-                         regoff_t __start, struct re_registers *__regs);
+                         regoff_t __start, struct re_registers *__regs)
+    _Attr_access_ ((__read_only__, 2, 3));
 
 
 /* Relates to 're_match' as 're_search_2' relates to 're_search'.  */
@@ -578,7 +609,9 @@ extern regoff_t re_match_2 (struct re_pattern_buffer 
*__buffer,
                            const char *__string1, regoff_t __length1,
                            const char *__string2, regoff_t __length2,
                            regoff_t __start, struct re_registers *__regs,
-                           regoff_t __stop);
+                           regoff_t __stop)
+    _Attr_access_ ((__read_only__, 2, 3))
+    _Attr_access_ ((__read_only__, 4, 5));
 
 
 /* Set REGS to hold NUM_REGS registers, storing them in STARTS and
@@ -648,13 +681,18 @@ extern int regcomp (regex_t *_Restrict_ __preg,
 extern int regexec (const regex_t *_Restrict_ __preg,
                    const char *_Restrict_ __String, size_t __nmatch,
                    regmatch_t __pmatch[_Restrict_arr_],
-                   int __eflags);
+                   int __eflags)
+    _Attr_access_ ((__write_only__, 4, 3));
 
 extern size_t regerror (int __errcode, const regex_t *_Restrict_ __preg,
-                       char *_Restrict_ __errbuf, size_t __errbuf_size);
+                       char *_Restrict_ __errbuf, size_t __errbuf_size)
+    _Attr_access_ ((__write_only__, 3, 4));
 
 extern void regfree (regex_t *__preg);
 
+#if defined __GNUC__ && 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
+# pragma GCC diagnostic pop
+#endif
 
 #ifdef __cplusplus
 }
diff --git a/lib/regexec.c b/lib/regexec.c
index 5e4eb497a6..da1fb7fafa 100644
--- a/lib/regexec.c
+++ b/lib/regexec.c
@@ -31,11 +31,11 @@ static re_sub_match_last_t * match_ctx_add_sublast 
(re_sub_match_top_t *subtop,
 static void sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts,
                           re_dfastate_t **limited_sts, Idx last_node,
                           Idx last_str_idx);
-static reg_errcode_t re_search_internal (const regex_t *preg,
-                                        const char *string, Idx length,
-                                        Idx start, Idx last_start, Idx stop,
-                                        size_t nmatch, regmatch_t pmatch[],
-                                        int eflags);
+static reg_errcode_t
+re_search_internal (const regex_t *preg, const char *string, Idx length,
+                   Idx start, Idx last_start, Idx stop, size_t nmatch,
+                   regmatch_t pmatch[__ARG_NELTS (static nmatch)],
+                   int eflags);
 static regoff_t re_search_2_stub (struct re_pattern_buffer *bufp,
                                  const char *string1, Idx length1,
                                  const char *string2, Idx length2,
@@ -47,23 +47,29 @@ static regoff_t re_search_stub (struct re_pattern_buffer 
*bufp,
                                regoff_t range, Idx stop,
                                struct re_registers *regs,
                                bool ret_len);
-static unsigned re_copy_regs (struct re_registers *regs, regmatch_t *pmatch,
-                              Idx nregs, int regs_allocated);
+static unsigned re_copy_regs (struct re_registers *regs, Idx nregs,
+                             regmatch_t pmatch[__ARG_NELTS (static nregs)],
+                             int regs_allocated);
 static reg_errcode_t prune_impossible_nodes (re_match_context_t *mctx);
 static Idx check_matching (re_match_context_t *mctx, bool fl_longest_match,
                           Idx *p_match_first);
 static Idx check_halt_state_context (const re_match_context_t *mctx,
                                     const re_dfastate_t *state, Idx idx);
-static void update_regs (const re_dfa_t *dfa, regmatch_t *pmatch,
-                        regmatch_t *prev_idx_match, Idx cur_node,
-                        Idx cur_idx, Idx nmatch);
-static reg_errcode_t push_fail_stack (struct re_fail_stack_t *fs,
-                                     Idx str_idx, Idx dest_node, Idx nregs,
-                                     regmatch_t *regs, regmatch_t *prevregs,
-                                     re_node_set *eps_via_nodes);
+static void
+update_regs (const re_dfa_t *dfa, Idx nmatch,
+            regmatch_t pmatch[__ARG_NELTS (static nmatch)],
+            regmatch_t prev_idx_match[__ARG_NELTS (static nmatch)],
+            Idx cur_node, Idx cur_idx);
+static reg_errcode_t
+push_fail_stack (struct re_fail_stack_t *fs,
+                Idx str_idx, Idx dest_node, Idx nregs,
+                regmatch_t regs[__ARG_NELTS (static nregs)],
+                regmatch_t prevregs[__ARG_NELTS (static nregs)],
+                re_node_set *eps_via_nodes);
 static reg_errcode_t set_regs (const regex_t *preg,
                               const re_match_context_t *mctx,
-                              size_t nmatch, regmatch_t *pmatch,
+                              size_t nmatch,
+                              regmatch_t pmatch[__ARG_NELTS (static nmatch)],
                               bool fl_backtrack);
 static reg_errcode_t free_fail_stack_return (struct re_fail_stack_t *fs);
 
@@ -191,7 +197,7 @@ static reg_errcode_t extend_buffers (re_match_context_t 
*mctx, int min_len);
 
 int
 regexec (const regex_t *__restrict preg, const char *__restrict string,
-        size_t nmatch, regmatch_t pmatch[], int eflags)
+        size_t nmatch, regmatch_t pmatch[__ARG_NELTS (nmatch)], int eflags)
 {
   reg_errcode_t err;
   Idx start, length;
@@ -212,12 +218,8 @@ regexec (const regex_t *__restrict preg, const char 
*__restrict string,
     }
 
   lock_lock (dfa->lock);
-  if (preg->no_sub)
-    err = re_search_internal (preg, string, length, start, length,
-                             length, 0, NULL, eflags);
-  else
-    err = re_search_internal (preg, string, length, start, length,
-                             length, nmatch, pmatch, eflags);
+  err = re_search_internal (preg, string, length, start, length,
+                           length, preg->no_sub ? 0 : nmatch, pmatch, eflags);
   lock_unlock (dfa->lock);
   return err != REG_NOERROR;
 }
@@ -235,7 +237,7 @@ int
 attribute_compat_text_section
 __compat_regexec (const regex_t *__restrict preg,
                  const char *__restrict string, size_t nmatch,
-                 regmatch_t pmatch[], int eflags)
+                 regmatch_t pmatch[__ARG_NELTS (nmatch)], int eflags)
 {
   return regexec (preg, string, nmatch, pmatch,
                  eflags & (REG_NOTBOL | REG_NOTEOL));
@@ -434,7 +436,7 @@ re_search_stub (struct re_pattern_buffer *bufp, const char 
*string, Idx length,
   else if (regs != NULL)
     {
       /* If caller wants register contents data back, copy them.  */
-      bufp->regs_allocated = re_copy_regs (regs, pmatch, nregs,
+      bufp->regs_allocated = re_copy_regs (regs, nregs, pmatch,
                                           bufp->regs_allocated);
       if (__glibc_unlikely (bufp->regs_allocated == REGS_UNALLOCATED))
        rval = -2;
@@ -457,7 +459,8 @@ re_search_stub (struct re_pattern_buffer *bufp, const char 
*string, Idx length,
 }
 
 static unsigned
-re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, Idx nregs,
+re_copy_regs (struct re_registers *regs, Idx nregs,
+             regmatch_t pmatch[__ARG_NELTS (static nregs)],
              int regs_allocated)
 {
   int rval = REGS_REALLOCATE;
@@ -585,7 +588,8 @@ static reg_errcode_t
 __attribute_warn_unused_result__
 re_search_internal (const regex_t *preg, const char *string, Idx length,
                    Idx start, Idx last_start, Idx stop, size_t nmatch,
-                   regmatch_t pmatch[], int eflags)
+                   regmatch_t pmatch[__ARG_NELTS (static nmatch)],
+                   int eflags)
 {
   reg_errcode_t err;
   const re_dfa_t *dfa = preg->buffer;
@@ -1210,8 +1214,9 @@ check_halt_state_context (const re_match_context_t *mctx,
    return -1 on match failure, -2 on error.  */
 
 static Idx
-proceed_next_node (const re_match_context_t *mctx, Idx nregs, regmatch_t *regs,
-                  regmatch_t *prevregs,
+proceed_next_node (const re_match_context_t *mctx, Idx nregs,
+                  regmatch_t regs[__ARG_NELTS (static nregs)],
+                  regmatch_t prevregs[__ARG_NELTS (static nregs)],
                   Idx *pidx, Idx node, re_node_set *eps_via_nodes,
                   struct re_fail_stack_t *fs)
 {
@@ -1321,7 +1326,9 @@ proceed_next_node (const re_match_context_t *mctx, Idx 
nregs, regmatch_t *regs,
 static reg_errcode_t
 __attribute_warn_unused_result__
 push_fail_stack (struct re_fail_stack_t *fs, Idx str_idx, Idx dest_node,
-                Idx nregs, regmatch_t *regs, regmatch_t *prevregs,
+                Idx nregs,
+                regmatch_t regs[__ARG_NELTS (static nregs)],
+                regmatch_t prevregs[__ARG_NELTS (static nregs)],
                 re_node_set *eps_via_nodes)
 {
   reg_errcode_t err;
@@ -1349,7 +1356,8 @@ push_fail_stack (struct re_fail_stack_t *fs, Idx str_idx, 
Idx dest_node,
 
 static Idx
 pop_fail_stack (struct re_fail_stack_t *fs, Idx *pidx, Idx nregs,
-               regmatch_t *regs, regmatch_t *prevregs,
+               regmatch_t regs[__ARG_NELTS (static nregs)],
+               regmatch_t prevregs[__ARG_NELTS (static nregs)],
                re_node_set *eps_via_nodes)
 {
   if (fs == NULL || fs->num == 0)
@@ -1379,7 +1387,7 @@ pop_fail_stack (struct re_fail_stack_t *fs, Idx *pidx, 
Idx nregs,
 static reg_errcode_t
 __attribute_warn_unused_result__
 set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
-         regmatch_t *pmatch, bool fl_backtrack)
+         regmatch_t pmatch[__ARG_NELTS (static nmatch)], bool fl_backtrack)
 {
   const re_dfa_t *dfa = preg->buffer;
   Idx idx, cur_node;
@@ -1415,7 +1423,7 @@ set_regs (const regex_t *preg, const re_match_context_t 
*mctx, size_t nmatch,
 
   for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;)
     {
-      update_regs (dfa, pmatch, prev_idx_match, cur_node, idx, nmatch);
+      update_regs (dfa, nmatch, pmatch, prev_idx_match, cur_node, idx);
 
       if ((idx == pmatch[0].rm_eo && cur_node == mctx->last_node)
          || (fs && re_node_set_contains (&eps_via_nodes, cur_node)))
@@ -1487,8 +1495,10 @@ free_fail_stack_return (struct re_fail_stack_t *fs)
 }
 
 static void
-update_regs (const re_dfa_t *dfa, regmatch_t *pmatch,
-            regmatch_t *prev_idx_match, Idx cur_node, Idx cur_idx, Idx nmatch)
+update_regs (const re_dfa_t *dfa, Idx nmatch,
+            regmatch_t pmatch[__ARG_NELTS (static nmatch)],
+            regmatch_t prev_idx_match[__ARG_NELTS (static nmatch)],
+            Idx cur_node, Idx cur_idx)
 {
   int type = dfa->nodes[cur_node].type;
   if (type == OP_OPEN_SUBEXP)
-- 
2.31.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]