From 97d4fa2f9e7b71fc730ff564a51f3dee4198f403 Mon Sep 17 00:00:00 2001
From: Mats Kindahl <mats@kindahl.net>
Date: Mon, 30 Dec 2024 19:58:07 +0100
Subject: [PATCH 2/7] Create coccicheck target for autoconf

This adds a coccicheck target for the autoconf-based build system. The
coccicheck target accepts one parameter MODE, which can be either "patch",
"report", or "context". The "patch" mode will generate a patch that can be
applied to the source tree, the "report" mode will generate a list of file
locations with information about what can be changed, and the "context" mode
will just highlight the line that will be affected by the semantic patch.

The following will generate a patch and apply it to the source code tree:

    make coccicheck MODE=patch | patch -p1
---
 configure              | 100 ++++++++++++++++++++++++++++++++++++++---
 configure.ac           |  12 +++++
 src/Makefile.global.in |  24 +++++++++-
 src/makefiles/pgxs.mk  |   3 ++
 4 files changed, 132 insertions(+), 7 deletions(-)

diff --git a/configure b/configure
index 22cd866147b..1091f9bc54f 100755
--- a/configure
+++ b/configure
@@ -779,6 +779,9 @@ enable_coverage
 GENHTML
 LCOV
 GCOV
+enable_coccicheck
+SPFLAGS
+SPATCH
 enable_debug
 enable_rpath
 default_port
@@ -846,6 +849,7 @@ with_pgport
 enable_rpath
 enable_debug
 enable_profiling
+enable_coccicheck
 enable_coverage
 enable_dtrace
 enable_tap_tests
@@ -1547,6 +1551,7 @@ Optional Features:
                           executables
   --enable-debug          build with debugging symbols (-g)
   --enable-profiling      build with profiling enabled
+  --enable-coccicheck     enable Coccinelle checks (requires spatch)
   --enable-coverage       build with coverage testing instrumentation
   --enable-dtrace         build with DTrace support
   --enable-tap-tests      enable TAP tests (requires Perl and IPC::Run)
@@ -3347,6 +3352,91 @@ fi
 
 
 
+#
+# --enable-coccicheck enables Coccinelle check target "coccicheck"
+#
+
+
+# Check whether --enable-coccicheck was given.
+if test "${enable_coccicheck+set}" = set; then :
+  enableval=$enable_coccicheck;
+  case $enableval in
+    yes)
+      if test -z "$SPATCH"; then
+  for ac_prog in spatch
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_SPATCH+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $SPATCH in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_SPATCH="$SPATCH" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_SPATCH="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+SPATCH=$ac_cv_path_SPATCH
+if test -n "$SPATCH"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SPATCH" >&5
+$as_echo "$SPATCH" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$SPATCH" && break
+done
+
+else
+  # Report the value of SPATCH in configure's output in all cases.
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SPATCH" >&5
+$as_echo_n "checking for SPATCH... " >&6; }
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SPATCH" >&5
+$as_echo "$SPATCH" >&6; }
+fi
+
+if test -z "$SPATCH"; then
+  as_fn_error $? "spatch not found" "$LINENO" 5
+fi
+
+      ;;
+    no)
+      :
+      ;;
+    *)
+      as_fn_error $? "no argument expected for --enable-coccicheck option" "$LINENO" 5
+      ;;
+  esac
+
+else
+  enable_coccicheck=no
+
+fi
+
+
+
+
 #
 # --enable-coverage enables generation of code coverage metrics with gcov
 #
@@ -15183,7 +15273,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -15229,7 +15319,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -15253,7 +15343,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -15298,7 +15388,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
@@ -15322,7 +15412,7 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
 		       && LARGE_OFF_T % 2147483647 == 1)
 		      ? 1 : -1];
diff --git a/configure.ac b/configure.ac
index e44943aa6fe..b75d7f49df6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -193,6 +193,18 @@ AC_SUBST(enable_debug)
 PGAC_ARG_BOOL(enable, profiling, no,
               [build with profiling enabled ])
 
+#
+# --enable-coccicheck enables Coccinelle check target "coccicheck"
+#
+PGAC_ARG_BOOL(enable, coccicheck, no,
+              [enable Coccinelle checks (requires spatch)],
+[PGAC_PATH_PROGS(SPATCH, spatch)
+if test -z "$SPATCH"; then
+  AC_MSG_ERROR([spatch not found])
+fi
+AC_SUBST(SPFLAGS)])
+AC_SUBST(enable_coccicheck)
+
 #
 # --enable-coverage enables generation of code coverage metrics with gcov
 #
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index 0aa389bc710..56977518705 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -19,7 +19,7 @@
 #
 # Meta configuration
 
-standard_targets = all install installdirs uninstall clean distclean coverage check checkprep installcheck init-po update-po
+standard_targets = all install installdirs uninstall clean distclean coccicheck coverage check checkprep installcheck init-po update-po
 # these targets should recurse even into subdirectories not being built:
 standard_always_targets = clean distclean
 
@@ -208,6 +208,7 @@ enable_rpath	= @enable_rpath@
 enable_nls	= @enable_nls@
 enable_debug	= @enable_debug@
 enable_dtrace	= @enable_dtrace@
+enable_coccicheck 	= @enable_coccicheck@
 enable_coverage	= @enable_coverage@
 enable_injection_points = @enable_injection_points@
 enable_tap_tests	= @enable_tap_tests@
@@ -389,7 +390,7 @@ CLDR_VERSION = 47
 # If a particular subdirectory knows this isn't needed in itself or its
 # children, it can set NO_GENERATED_HEADERS.
 
-all install check installcheck: submake-generated-headers
+all install check installcheck coccicheck: submake-generated-headers
 
 .PHONY: submake-generated-headers
 
@@ -538,6 +539,11 @@ FOP				= @FOP@
 XMLLINT			= @XMLLINT@
 XSLTPROC		= @XSLTPROC@
 
+# Coccinelle
+
+SPATCH = @SPATCH@
+SPFLAGS = @SPFLAGS@
+
 # Code coverage
 
 GCOV = @GCOV@
@@ -1005,6 +1011,20 @@ endif # nls.mk
 endif # enable_nls
 
 
+##########################################################################
+#
+# Coccinelle checks
+#
+
+ifeq ($(enable_coccicheck), yes)
+coccicheck_py = $(top_srcdir)/src/tools/coccicheck.py
+coccicheck = SPATCH=$(SPATCH) SPFLAGS=$(SPFLAGS) $(PYTHON) $(coccicheck_py)
+
+.PHONY: coccicheck
+coccicheck:
+	$(coccicheck) --mode=$(MODE) 'cocci/**/*.cocci' $(top_srcdir)
+endif # enable_coccicheck
+
 ##########################################################################
 #
 # Coverage
diff --git a/src/makefiles/pgxs.mk b/src/makefiles/pgxs.mk
index 039cee3dfe5..0f4e6eab619 100644
--- a/src/makefiles/pgxs.mk
+++ b/src/makefiles/pgxs.mk
@@ -95,6 +95,9 @@ endif
 ifeq ($(FLEX),)
 FLEX = flex
 endif
+ifeq ($(SPATCH),)
+SPATCH = spatch
+endif
 
 endif # PGXS
 
-- 
2.43.0

