OSDN Git Service

Incorporate user-customized <features.h> configuration.
authorKeith Marshall <keith@users.osdn.me>
Tue, 22 Jan 2019 11:36:30 +0000 (11:36 +0000)
committerKeith Marshall <keith@users.osdn.me>
Tue, 22 Jan 2019 11:36:30 +0000 (11:36 +0000)
ChangeLog
Makefile.comm
mingwrt/ChangeLog
mingwrt/include/_mingw.h.in
mingwrt/tests/Makefile.in
var/features.lua [new file with mode: 0644]
w32api/ChangeLog
w32api/tests/Makefile.in

index e71ff54..4d47e53 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2019-01-22  Keith Marshall  <keith@users.osdn.me>
+
+       Incorporate user-customized <features.h> configuration.
+
+       * Makefile.comm (_mingw.h): Add prerequisite dependency on...
+       (features.h): ...this; add rule to create a build-time stub, an empty
+       file, yielding the default fall-back configuration.
+
+       * var/features.lua: New direcctory/file; this implements the mingw-get
+       post-install action, which is required to integrate management of user
+       maintained <features.h> configuration alongside project updates.
+
 2018-12-23  Keith Marshall  <keith@users.osdn.me>
 
        Adjust repository version following WSL-5.2 release.
index af83ded..d8dcb7c 100644 (file)
@@ -5,8 +5,8 @@
 #
 # $Id$
 #
-# Written by Keith Marshall <keithmarshall@users.sourceforge.net>
-# Copyright (C) 2017, MinGW.org Project
+# Written by Keith Marshall <keith@users.osdn.me>
+# Copyright (C) 2017, 2019, MinGW.org Project
 #
 #
 # Permission is hereby granted, free of charge, to any person obtaining a
@@ -82,6 +82,14 @@ vpath %.h.in ${mingwrt_srcdir}/include ${w32api_srcdir}/include
 _mingw.h w32api.h: %.h: %.h.in VERSION.m4
        $(PACKAGE_VERSION_SCRIPT) $< > $@
 
+# _mingw.h wants to include <features.h>, which is nominally a user
+# supplied header; for our build-time requirements, an empty file is
+# sufficient, as _mingw.h provides suitable fall-back definitions.
+#
+_mingw.h: features.h
+features.h:
+       > $@
+
 PACKAGE_VERSION_SCRIPT = sed \
   -e s"`$(call PACKAGE_VERSION_FORMAT,LONG,%d,$$3+1000*($$2+1000*$$1))`" \
   -e s"`$(call PACKAGE_VERSION_FORMAT,MAJOR,%7d,$$1)`" \
index 81a3946..df4517c 100644 (file)
@@ -1,3 +1,17 @@
+2019-01-22  Keith Marshall  <keith@users.osdn.me>
+
+       Incorporate user-customized <features.h> configuration.
+
+       * include/_mingw.h: Include <features.h>, or...
+       [_MINGW_FEATURES_HEADER]: ...nominated alternative header.
+       [!defined __MINGW_FEATURES__]: Provide fall-back definition.
+       (__MINGW_FEATURES_BEGIN__, __MINGW_FEATURES_ENABLE__)
+       (__MINGW_FEATURES_IGNORE__, __MINGW_FEATURES_UNSET__)
+       (__MINGW_FEATURES_END__): New macros; define them.
+
+       * tests/Makefile.in (install-mingwrt): Create <features.h> stub; this
+       is an empty file, yielding the default fall-back configuration.
+
 2019-01-21  Keith Marshall  <keith@users.osdn.me>
 
        Handle another GCC compile-time warning.
index d7621b0..b72b853 100644 (file)
@@ -7,7 +7,7 @@
  * $Id$
  *
  * Written by Mumit Khan  <khan@xraylith.wisc.edu>
- * Copyright (C) 1999, 2001-2011, 2014-2018, MinGW.org Project
+ * Copyright (C) 1999, 2001-2011, 2014-2019, MinGW.org Project
  *
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
 #define __CRT_GLOB_ESCAPE_CHAR__       (char)(127)
 
 
+/* Load any user-customized features configuration...
+ */
+#ifdef _MINGW_FEATURES_HEADER
+/* ...from a user-specified, or project-specified alternative file...
+ */
+#include _MINGW_FEATURES_HEADER
+#else
+/* ...or fall back to the default configuration file, (which may,
+ * or may not have been customized).
+ */
+#include <features.h>
+#endif
+
+#ifndef __MINGW_FEATURES__
+/* Regardless of how the preceding features configuration header was
+ * identified, we normally expect that will have defined this, but we
+ * supply this fall-back, just in case it is needed.
+ */
+#define __MINGW_FEATURES__             0ULL
+#endif
+
+/* Define macros to facilitate the user-specified configuration.
+ */
+#define __MINGW_FEATURE_ENABLE__(__FEATURE__) | (__FEATURE__)
+#define __MINGW_FEATURE_IGNORE__(__FEATURE__)
+
+#define __MINGW_FEATURES_BEGIN__       0x0000000000000000ULL
+#define __MINGW_FEATURES_UNSET__       0x0000000000000000ULL
+#define __MINGW_FEATURES_END__
+
 /* Manifest definitions identifying the flag bits, controlling activation
  * of MinGW features, as specified by the user in __MINGW_FEATURES__.
  */
index 2bdf904..5951eac 100644 (file)
@@ -5,7 +5,7 @@
 # $Id$
 #
 # Written by Keith Marshall <keithmarshall@users.sourceforge.net>
-# Copyright (C) 2016, 2017, MinGW.org Project
+# Copyright (C) 2016, 2017, 2019, MinGW.org Project
 #
 #
 # Permission is hereby granted, free of charge, to any person obtaining a
@@ -130,14 +130,16 @@ $(info )
 endef
 
 # Install a local copy of the package components to be tested; we need
-# the full mingwrt package, and also the w32api headers, to ensure that
-# we are testing what we've built, and not those which were installed
-# with whatever compiler we are using for the build.
+# the full mingwrt package, including a <features.h> stub, and also the
+# w32api headers, to ensure that we are testing what we've built, and
+# not those which were installed with whatever compiler we are using
+# for the build.
 #
 testsuite.install: install-mingwrt install-w32api-headers
 
 install-mingwrt:
        $(MAKE) -C .. --no-print-directory prefix=${CURDIR} $@
+       >> include/features.h
 
 chkconfig = ($1/config.status --version | grep $2) 2>&1 > /dev/null
 install-w32api-headers:
diff --git a/var/features.lua b/var/features.lua
new file mode 100644 (file)
index 0000000..0ce3c64
--- /dev/null
@@ -0,0 +1,445 @@
+--
+-- features.lua
+--
+-- $Id$
+--
+-- Lua 5.2 module providing a mingw-get setup hook for configuration of
+-- the user's MinGW GCC compiler <features.h> preferences.
+--
+-- Written by Keith Marshall <keithmarshall@users.sourceforge.net>
+-- Copyright (C) 2019, MinGW.org Project
+--
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a
+-- copy of this software and associated documentation files (the "Software"),
+-- to deal in the Software without restriction, including without limitation
+-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
+-- and/or sell copies of the Software, and to permit persons to whom the
+-- Software is furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included
+-- in all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+-- THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+-- DEALINGS IN THE SOFTWARE.
+--
+--
+-- We begin by initializing a container, for construction of a Lua module
+-- to encapsulate the content of this source file.
+--
+   local M = {}
+--
+-- mingw-get passes the MinGW installation root directory path, in the
+-- $MINGW32_SYSROOT environment variable; from this, we deduce the path
+-- name for the working copy of the features.h file...
+--
+   local function syspath( varname )
+--
+--   ...using this local helper function to ensure that the path name
+--   string, returned from the environment, is free from insignificant
+--   trailing directory name separators, and that all internal sequences
+--   of directory name separators are normalized to a single '/'.
+--
+     local pathname = os.getenv( varname )
+     if pathname
+     then
+       pathname = string.gsub( pathname, "[/\\]+", "/" )
+       pathname = string.match( pathname, "(.*[^/])/*$" )
+     end
+     return pathname
+   end
+   local sysroot = syspath( "MINGW32_SYSROOT" )
+   if not sysroot
+   then
+     error( "environment variable MINGW32_SYSROOT may not be set", 0 )
+   end
+   local config_file_name = sysroot .. "/include/features.h"
+--
+-- Define a template, whence the default features configuration may be
+-- deduced when writing the initial content of the <features.h> file.
+--
+   local config_default =
+   { '/*',
+     ' * features.h',
+     ' *',
+     ' * Features configuration for MinGW.org GCC implementation; users may',
+     ' * customize this file, to establish their preferred default behaviour.',
+     ' * Projects may provide an alternative, package-specific configuration,',
+     ' * either by placing their own customized <features.h> in the package',
+     ' * -I path, ahead of the system default, or by assignment of their',
+     ' * preferred alternative to the _MINGW_FEATURES_HEADER macro.',
+     ' *',
+     ' *',
+     ' * $'..'Id$',
+     ' *',
+     ' * Template written by Keith Marshall <keith@users.osdn.me>',
+     ' * Copyright (C) 2019, MinGW.org Project.',
+     ' *',
+     ' *',
+     ' * Permission is hereby granted, free of charge, to any person obtaining a',
+     ' * copy of this software and associated documentation files (the "Software"),',
+     ' * to deal in the Software without restriction, including without limitation',
+     ' * the rights to use, copy, modify, merge, publish, distribute, sublicense,',
+     ' * and/or sell copies of the Software, and to permit persons to whom the',
+     ' * Software is furnished to do so, subject to the following conditions:',
+     ' *',
+     ' * The above copyright notice, this permission notice, and the following',
+     ' * disclaimer shall be included in all copies or substantial portions of',
+     ' * the Software.',
+     ' *',
+     ' * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS',
+     ' * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,',
+     ' * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL',
+     ' * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER',
+     ' * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING',
+     ' * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER',
+     ' * DEALINGS IN THE SOFTWARE.',
+     ' *',
+     ' */',
+     '#ifndef __MINGW_FEATURES__',
+     '#pragma GCC system_header',
+     '',
+     '/* Users are expected to customize this header, but it remains subject to',
+     ' * automatic updates by system software.  To ensure that any customisation',
+     ' * is not ovewritten, during such updates, it MUST observe the following:',
+     ' *',
+     ' * This header MUST define __MINGW_FEATURES__; the definition MUST begin',
+     ' * with "#define __MINGW_FEATURES__ (__MINGW_FEATURES_BEGIN__) \\"; it MUST',
+     ' * extend over multiple lines, and terminate with "__MINGW_FEATURES_END__";',
+     ' * intervening lines may enumerate any defined features, one per line, and',
+     ' * each specified as an argument to either the __MINGW_FEATURE_ENABLE__(),',
+     ' * or the __MINGW_FEATURE_IGNORE__() macro, (ensuring that at least one',
+     ' * space separates either of these macro names from its parenthesized',
+     ' * argument name).',
+     ' *',
+     ' * CAUTION:',
+     ' * If customizing this features configuration, ALWAYS refer to features',
+     ' * using their designated symbolic constant names; NEVER usurp the use of',
+     ' * these symbolic constants for any other purpose, and NEVER assume that',
+     ' * any such constant has a specific value ... their definitions may vary',
+     ' * between distinct MinGW Runtime Library software releases!',
+     ' */',
+     '#define __MINGW_FEATURES__    (__MINGW_FEATURES_BEGIN__)        \\',
+     ' __MINGW_FEATURE_IGNORE__     (__MINGW_ANSI_STDIO__)            \\',
+     ' __MINGW_FEATURE_IGNORE__     (__MINGW_LC_MESSAGES__)           \\',
+     ' __MINGW_FEATURE_IGNORE__     (__MINGW_LC_ENVVARS__)            \\',
+     ' __MINGW_FEATURES_END__',
+     '',
+     '#endif   /* !__MINGW_FEATURES__: $'..'RCSfile$: end of file */'
+   }
+--
+   local function defines( name )
+--
+--   A local helper function, to generate a string.match
+--   pattern for identification of any C #define statement,
+--   which defines a specified symbol "name"
+--
+     return "^%s*#%s*define%s+" .. name
+   end
+--
+   local function feature( value )
+--
+--   A local helper function, to generate a string.match
+--   pattern for identification of a specified parenthesized
+--   value field, within a C #define statement.
+--
+     return "%s+%(%s*" .. value .. "%s*%)%s*"
+   end
+--
+   local function begins_definition( line, name, value )
+--
+--   A local helper function to check whether any input "line"
+--   represents the first of a multiline C #define for the "name"
+--   symbol, with its initial field matching the parenthesized
+--   "value" token (default: "__MINGW_FEATURES_BEGIN__").
+--
+     if not value then value = "__MINGW_FEATURES_BEGIN__" end
+     return string.match( line, defines( name ) .. feature( value ) .. "\\$" )
+   end
+--
+-- In the event that a features configuration has already been
+-- specified for this installation, capture this into internal
+-- "as built" configuration tables...
+--
+   local current_config, current_features
+   local config = io.open( config_file_name )
+   if config
+   then
+--   ...always starting collection into table "current_config"...
+--
+     current_config = {}
+     local active_list = current_config
+--
+--   ...reading the existing configuration file, line by line...
+--
+     for line in config:lines()
+     do if active_list == current_features
+        and string.match( line, "^%s*__MINGW_FEATURES_END__%s*$" )
+        then
+--       ...noting that actual configuration options will have
+--       been diverted to the "current_features" table; when all
+--       such options have been captured, redirect any residual
+--       content to the "current_config" table.
+--
+         active_list = current_config
+       end
+--
+--     Capture the current configuration record, into whichever
+--     diversion is currently active.
+--
+       table.insert( active_list, line )
+--
+       if begins_definition( line, "__MINGW_FEATURES__" )
+       then
+--       When we find the first line of a (possibly) well-formed
+--       features configuration, divert capture of its subsequent
+--       lines to a new "current_features" table.
+--
+         current_features = {}
+         active_list = current_features
+       end
+     end
+--
+--   When capture is complete, ensure that the input stream file
+--   is closed; (we may want to reopen it later, to rewrite it).
+--
+     io.close( config )
+--
+--   Before we go any further, check for well-formedness of the
+--   configuration which we have just captured; effectively...
+--
+     if not current_features
+     or active_list == current_features
+     then
+--     ...when no "current_features" diversion has been created,
+--     or such a diversion remains open for capture, then an error
+--     has occurred, and the configuration is not well-formed.
+--
+       local function config_error( reason )
+        error( config_file_name .." ".. reason, 0 )
+       end
+       for ref, line in next, current_config
+       do if string.match( line, defines( "__MINGW_FEATURES__" ) )
+         then
+--         In this case, a "__MINGW_FEATURES__" definition is
+--         present, but it is not well-formed; (note that, here,
+--         we rescan the "current_config" table, using a less
+--         rigorous criterion for detection of a definition of
+--         of "__MINGW_FEATURES__" than that which is required
+--         to open the "current_features" diversion)...
+--
+           config_error( "has malformed __MINGW_FEATURES__ definition" )
+         end
+       end
+--     ...while in this case, no "__MINGW_FEATURES__" definition
+--     was found, (well-formed, or otherwise).
+--
+       config_error( "does not define __MINGW_FEATURES__" )
+     end
+   end
+--
+--
+   local function update_configuration( stream_file, template, current )
+--
+--   A function to write a features configuration to a designated output
+--   stream, based on a specified template, reproducing and encapsulating
+--   any existing configuration which may also have been specified...
+--
+     local function stream_file_writeln( line )
+--
+--     ...using this helper function to write each line.
+--
+       stream_file:write( line .. "\n" )
+     end
+--
+     if current
+     then
+--     An existing configuration header is to be updated.  An image of
+--     its original content has already been loaded into "current"; copy
+--     it back to the original file, line by line...
+--
+       for ref, line in next, current
+       do if begins_definition( line, "__MINGW_FEATURES__" )
+         then
+--         ...until we reach the first active configuration record.
+--         We now wish to merge any new configuration options from the
+--         template, into the existing configuration; work through the
+--         template, line by line, ignoring all lines...
+--
+           local merge = false
+           for ref, sub in next, template
+           do if begins_definition( sub, "__MINGW_FEATURES__" )
+              then
+--              ...until we find the first line of a (possibly)
+--              well-formed features configuration record; when we
+--              find this, we decompose and reassemble it, so that
+--              we may preserve a tabulation format matching the
+--              longer of the template and actual configuration
+--              records.
+--
+                local def = string.match( sub, "^[^(]*" )
+                local usr = string.match( line, "^[^(]*" )
+                if string.len( usr ) > string.len( def )
+                then
+                  def = usr
+                end
+                usr = string.match( line, "%(.*" )
+                sub = string.match( sub, "%(.*" )
+                if string.len( usr ) > string.len( sub )
+                then
+                  sub = usr
+                end
+--
+--              Write out the reassembled features configuration
+--              start record, and activate the features merge.
+--
+                stream_file_writeln( def .. sub )
+                merge = true
+--
+--            During the merge operation, when we find the record
+--            terminator within the template...
+--
+              elseif string.match( sub, "^%s*__MINGW_FEATURES_END__%s*$" )
+              then
+--              ...we immediately write out any additional option
+--              specifications, which remain in the user specified
+--              configuration...
+--
+                for ref, sub in next, current_features
+                do
+                  stream_file_writeln( sub )
+                end
+--
+--              ...and break out of the merge cycle.
+--
+                break
+--
+              elseif merge
+              then
+--              While we remain within the merge cycle, we extract
+--              the identification of each configuration option from
+--              the template, comparing it with all entries in the
+--              "current_features" table...
+--
+                tag = string.match( sub, "%(.*%)" )
+                for ref, usr in next, current_features
+                do if string.match( usr, tag )
+                   then
+--
+--                   ...and, when we find a match, we favour the
+--                   existing configuration record over that from
+--                   the template...
+--
+                     sub = usr
+--
+--                   ...remove the corresponding entry from the
+--                   "current_features" table, and break out of
+--                   the inner matching loop, before...
+--
+                     table.remove( current_features, ref )
+                     break
+                   end
+                end
+--
+--              ...in either event, writing out a copy of each
+--              selected configuration record.
+--
+                stream_file_writeln( sub )
+              end
+           end
+         else
+--
+--         For every line in the existing configuration file, outside
+--         the scope of the "__MINGW_FEATURES__" definition itself, we
+--         simply write out a verbatim copy of each line.
+--
+           stream_file_writeln( line )
+         end
+       end
+     else
+--
+--     There is no existing configuration header, so we simply reproduce
+--     the template, processing it line by line...
+--
+       for ref, line in next, template
+       do
+--      ...and writing out each line individually.
+--
+        stream_file_writeln( line )
+       end
+     end
+   end
+--
+--
+   function M.pathname( suffix )
+--
+--   An exported utility function, to facilitate identification of
+--   the full MS-Windows path name for the features.h configuration
+--   file, as appropriate to the current installation...
+--
+     if suffix
+     then
+--     ...appending any suffix which may have been specified, (e.g.
+--     to specify a reference to the features.h.sample file)...
+--
+       return config_file_name .. suffix
+     end
+--
+--   ...otherwise, specifying a reference to features.h itself.
+--
+     return config_file_name
+   end
+--
+--
+   function M.initialize( stream_file )
+--
+--   Primary initialization function; overwrites any existing features
+--   configuration header, opened for writing as "stream_file"...
+--
+     if not stream_file
+     then
+--     ...or falling back to "io.stderr", in the event that no output
+--     stream file has been opened...
+--
+       stream_file = io.stdout
+     end
+--
+--   ...replacing any existing configuration with an exact copy of the
+--   "config_default" content specified within this module.
+--
+     update_configuration( stream_file, config_default )
+   end
+--
+--
+   function M.update( stream_file )
+--
+--   Primary API function, exported for use by mingw-get (or any other
+--   client); overwrites any existing configuration header file, which
+--   has been opened for writing as "stream_file"...
+--
+     if not stream_file
+     then
+--     ...or falling back to "io.stderr", in the event that no output
+--     stream file has been opened...
+--
+       stream_file = io.stdout
+     end
+--
+--   ...preserving any existing configuration, with the addition of
+--   any configuration options which have been included in the default
+--   template, but which do not yet appear in the existing header.
+--
+     update_configuration( stream_file, config_default, current_config )
+   end
+--
+-- Since this source file is intended to be loaded as a Lua module, we
+-- must ultimately return a reference handle for it.
+--
+   return M
+--
+-- $RCSfile$: end of file */
index 18d590d..f926e4f 100644 (file)
@@ -1,3 +1,10 @@
+2019-01-22  Keith Marshall  <keith@users.osdn.me>
+
+       Incorporate user-customized <features.h> configuration.
+
+       * tests/Makefile.in (install-mingwrt-headers): Create <features.h>
+       stub; this is an empty file, yielding the default configuration.
+
 2018-12-23  Keith Marshall  <keith@users.osdn.me>
 
        Prepare and publish MinGW.org WSL-5.2 release.
index 347ec78..f57f129 100644 (file)
@@ -5,7 +5,7 @@
 # $Id$
 #
 # Written by Keith Marshall <keithmarshall@users.sourceforge.net>
-# Copyright (C) 2017, MinGW.org Project
+# Copyright (C) 2017, 2019, MinGW.org Project
 #
 #
 # Permission is hereby granted, free of charge, to any person obtaining a
@@ -131,9 +131,10 @@ $(info )
 endef
 
 # Install a local copy of the package components to be tested; we need
-# the full w32api package, and also the mingwrt headers, to ensure that
-# we are testing what we've built, and not those which were installed
-# with whatever compiler we are using for the build.
+# the full w32api package, and also the mingwrt headers, including a stub
+# for <features.h>, to ensure that we are testing what we've built, and
+# not those which were installed with whatever compiler we are using
+# for the build.
 #
 testsuite.install: install-w32api install-mingwrt-headers
 
@@ -142,6 +143,7 @@ install-w32api:
 
 chkconfig = ($1/config.status --version | grep $2) 2>&1 > /dev/null
 install-mingwrt-headers:
+       >> include/features.h
        @for dir in ../../mingwrt*; do \
          if $(call chkconfig,$$dir,'MinGW C Runtime'); then \
             $(MAKE) -C $$dir --no-print-directory prefix=${CURDIR} $@; break; \