bug-gnulib
[Top][All Lists]
Advanced

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

[PATCH] maint.mk: add a syntax-check rule to ensure tightly-scoped symbo


From: Jim Meyering
Subject: [PATCH] maint.mk: add a syntax-check rule to ensure tightly-scoped symbols
Date: Mon, 09 May 2011 12:44:14 +0200

I've been using a precursor of this rule in coreutils for many years,
added it to idutils a year or two ago and added it to grep just recently.
I did not like having to duplicate and customize bits
in the separate copies, depending on where I used it,
so finally have made it general enough so that the same
code works in coreutils, diffutils, gzip and grep.
The only customization required was for gzip:

    # Tell the tight_scope rule that sources are in ".".
    export _gl_TS_dir = .

    # Tell the tight_scope rule that these variables are deliberately "extern".
    export _gl_TS_unmarked_extern_vars = \
      block_start d_buf inbuf outbuf prev read_buf strstart window

The first is to tell the rule that the sources are in ".",
rather than src/, and the second is to identify as deliberately-extern
that list of variables.  An alternative would have been to add
explicitly "extern" declarations in a file like gzip.h, but that
would have been more invasive.

There's still room for generalization -- like if you
have more than one directory in which to run this rule.
And I probably should not have hard-coded XTERN in the
default regexp.  I expect to remove it eventually, and to add
the kludge only for gzip, where it's currently required.

As a syntax-check rule, this one is unusual in two ways:
  - it creates a file in the current (top level) directory
  - it extracts a portion of maint.mk (sc_tight_scope-0) to
      be used in a sub-make.
  - this new rule must be customized, yet it is being run in the sub-make
      where normal assignments from cfg.mk would not take affect.
      Thus, any customizing assignment must use "export", as mentioned
      in the comments.

>From 811627be3732ccbdaaea86b0dafdda1748375671 Mon Sep 17 00:00:00 2001
From: Jim Meyering <address@hidden>
Date: Mon, 9 May 2011 12:30:55 +0200
Subject: [PATCH] maint.mk: add a syntax-check rule to ensure tightly-scoped
 symbols

* top/maint.mk (sc_tight_scope): New rule.
(sc_tight_scope-0): New rule, ifdef'd out.
(_gl_TS_dir): Default.
(_gl_TS_unmarked_extern_functions, _gl_TS_function_regex): Define.
(_gl_TS_unmarked_extern_vars, _gl_TS_var_regex): Define.
---
 ChangeLog    |    9 ++++++++
 top/maint.mk |   62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 71 insertions(+), 0 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index f7e0a33..7feeba0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2011-05-09  Jim Meyering  <address@hidden>
+
+       maint.mk: add a syntax-check rule to ensure tightly-scoped symbols
+       * top/maint.mk (sc_tight_scope): New rule.
+       (sc_tight_scope-0): New rule, ifdef'd out.
+       (_gl_TS_dir): Default.
+       (_gl_TS_unmarked_extern_functions, _gl_TS_function_regex): Define.
+       (_gl_TS_unmarked_extern_vars, _gl_TS_var_regex): Define.
+
 2011-05-09  Simon Josefsson  <address@hidden>

        * m4/gc.m4: Remove gl_PREREQ_GC (not used).  Reported by Bruno
diff --git a/top/maint.mk b/top/maint.mk
index 03a9036..793915c 100644
--- a/top/maint.mk
+++ b/top/maint.mk
@@ -1325,3 +1325,65 @@ update-copyright:
        grep -l -w Copyright                                             \
          $$(export VC_LIST_EXCEPT_DEFAULT=COPYING && $(VC_LIST_EXCEPT)) \
          | $(update-copyright-env) xargs $(build_aux)/$@
+
+# NOTE: This test is silently skipped if $(_gl_TS_dir)/Makefile.am
+# does not mention noinst_HEADERS.
+# NOTE: to override these _gl_TS_* default values, you must
+# define the variable(s) using "export" in cfg.mk.
+_gl_TS_dir ?= src
+ALL_RECURSIVE_TARGETS += sc_tight_scope
+sc_tight_scope: tight-scope.mk
+       @grep noinst_HEADERS $(_gl_TS_dir)/Makefile.am > /dev/null 2>&1 \
+         && $(MAKE) -s -C $(_gl_TS_dir)                                \
+             -f Makefile -f '$(abs_srcdir)/tight-scope.mk' address@hidden      
\
+         || :
+       @rm -f $<
+
+tight-scope.mk: $(ME)
+       @rm -f $@ address@hidden
+       @perl -ne '/^# TS-start/.../^# TS-end/ and print' $(ME) > address@hidden
+       @chmod a=r address@hidden && mv address@hidden $@
+
+ifeq (a,b)
+# TS-start
+# Most functions should have static scope.
+# Any that don't must be marked with `extern', but `main'
+# and `usage' are exceptions: they're always extern, but
+# do not need to be marked.
+_gl_TS_unmarked_extern_functions ?= main usage
+_gl_TS_function_regex ?= \
+  ^(?:extern|XTERN) +(?:void|(?:struct |const |enum )?\S+) +\**(\S+) +\(
+
+# The second nm|grep checks for file-scope variables with `extern' scope.
+# Without gnulib's progname module, you might put program_name here.
+_gl_TS_unmarked_extern_vars ?=
+_gl_TS_var_regex ?= ^(?:extern|XTERN) .*?\**(\w+)(\[.*?\])?;
+.PHONY: sc_tight_scope-0
+sc_tight_scope-0: $(bin_PROGRAMS)
+       t=exceptions-$$$$;                                              \
+       trap 's=$$?; rm -f $$t; exit $$s' 0;                            \
+       for sig in 1 2 3 13 15; do                                      \
+         eval "trap 'v=`expr $$sig + 128`; (exit $$v); exit $$v' $$sig"; \
+       done;                                                           \
+       src=`for f in $(SOURCES); do                                    \
+              test -f $$f && d= || d=$(srcdir)/; echo $$d$$f; done`;   \
+       hdr=`for f in $(noinst_HEADERS); do                             \
+              test -f $$f && d= || d=$(srcdir)/; echo $$d$$f; done`;   \
+       ( printf '^%s$$\n' $(_gl_TS_unmarked_extern_functions);         \
+         grep -h -A1 '^extern .*[^;]$$' $$src                          \
+           | grep -vE '^(extern |--)' | sed 's/ .*//';                 \
+         perl -lne '/$(_gl_TS_function_regex)/'                        \
+                 -e 'and print $$1' $$hdr;                             \
+       ) | sort -u | sed 's/^/^/;s/$$/$$/' > $$t;                      \
+       nm -e *.$(OBJEXT) | sed -n 's/.* T //p' | grep -Ev -f $$t       \
+         && { echo the above functions should have static scope >&2;   \
+              exit 1; } || : ;                                         \
+       ( printf '^%s$$\n' $(_gl_TS_unmarked_extern_vars);              \
+         perl -lne '/$(_gl_TS_var_regex)/ and print "^$$1\$$"'         \
+           $$hdr *.h ) | sort -u > $$t;                                \
+       nm -e *.$(OBJEXT) | sed -n 's/.* [BCDGRS] //p'                  \
+            | sort -u | grep -Ev -f $$t                                        
\
+         && { echo the above variables should have static scope >&2;   \
+              exit 1; } || :
+# TS-end
+endif
--
1.7.5.1.332.g711ff



reply via email to

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