This list is closed, nobody may subscribe to it.
| 2000 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(12) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2001 |
Jan
(13) |
Feb
(2) |
Mar
(1) |
Apr
(1) |
May
|
Jun
(38) |
Jul
(10) |
Aug
(70) |
Sep
(63) |
Oct
(61) |
Nov
(41) |
Dec
(28) |
| 2002 |
Jan
(43) |
Feb
(11) |
Mar
(9) |
Apr
(2) |
May
(97) |
Jun
(94) |
Jul
(13) |
Aug
(49) |
Sep
(41) |
Oct
(24) |
Nov
(55) |
Dec
(126) |
| 2003 |
Jan
(90) |
Feb
(75) |
Mar
(32) |
Apr
(24) |
May
(54) |
Jun
(54) |
Jul
(22) |
Aug
(4) |
Sep
(16) |
Oct
(8) |
Nov
(6) |
Dec
(13) |
| 2004 |
Jan
|
Feb
(17) |
Mar
(60) |
Apr
(21) |
May
(12) |
Jun
|
Jul
(13) |
Aug
|
Sep
(29) |
Oct
|
Nov
|
Dec
(2) |
| 2005 |
Jan
(22) |
Feb
(3) |
Mar
(2) |
Apr
(13) |
May
(82) |
Jun
(18) |
Jul
(30) |
Aug
(17) |
Sep
(3) |
Oct
(19) |
Nov
(4) |
Dec
(8) |
| 2006 |
Jan
(1) |
Feb
(6) |
Mar
(2) |
Apr
(40) |
May
|
Jun
(21) |
Jul
(1) |
Aug
(410) |
Sep
(3) |
Oct
|
Nov
(56) |
Dec
(7) |
| 2007 |
Jan
(19) |
Feb
|
Mar
(4) |
Apr
(8) |
May
(19) |
Jun
(6) |
Jul
(4) |
Aug
(6) |
Sep
|
Oct
(4) |
Nov
(3) |
Dec
(2) |
| 2008 |
Jan
(13) |
Feb
(18) |
Mar
(12) |
Apr
|
May
(2) |
Jun
|
Jul
|
Aug
(1) |
Sep
|
Oct
|
Nov
|
Dec
|
| 2009 |
Jan
|
Feb
(6) |
Mar
(8) |
Apr
(2) |
May
(2) |
Jun
|
Jul
|
Aug
(2) |
Sep
(11) |
Oct
(13) |
Nov
(17) |
Dec
(6) |
| 2010 |
Jan
(24) |
Feb
(10) |
Mar
(27) |
Apr
(20) |
May
(108) |
Jun
(8) |
Jul
(23) |
Aug
(38) |
Sep
(49) |
Oct
(17) |
Nov
(12) |
Dec
(14) |
| 2011 |
Jan
(17) |
Feb
(7) |
Mar
(28) |
Apr
(8) |
May
(20) |
Jun
(11) |
Jul
(7) |
Aug
(12) |
Sep
(4) |
Oct
(20) |
Nov
(19) |
Dec
(2) |
| 2012 |
Jan
(2) |
Feb
(6) |
Mar
(5) |
Apr
(24) |
May
(5) |
Jun
(4) |
Jul
(6) |
Aug
(18) |
Sep
(38) |
Oct
(26) |
Nov
(12) |
Dec
(6) |
| 2013 |
Jan
(19) |
Feb
(18) |
Mar
(44) |
Apr
(35) |
May
(18) |
Jun
(21) |
Jul
(10) |
Aug
(19) |
Sep
(44) |
Oct
(25) |
Nov
(1) |
Dec
(2) |
| 2014 |
Jan
(8) |
Feb
|
Mar
|
Apr
(5) |
May
(1) |
Jun
(3) |
Jul
|
Aug
(3) |
Sep
|
Oct
(4) |
Nov
(4) |
Dec
(7) |
| 2015 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
(2) |
Jun
(4) |
Jul
(6) |
Aug
(2) |
Sep
(8) |
Oct
(2) |
Nov
(1) |
Dec
(3) |
| 2016 |
Jan
(7) |
Feb
(9) |
Mar
(5) |
Apr
(5) |
May
(9) |
Jun
(4) |
Jul
(20) |
Aug
(4) |
Sep
(7) |
Oct
(6) |
Nov
(9) |
Dec
(2) |
| 2017 |
Jan
(7) |
Feb
(7) |
Mar
(5) |
Apr
|
May
(1) |
Jun
(4) |
Jul
(12) |
Aug
(4) |
Sep
(1) |
Oct
(4) |
Nov
(11) |
Dec
(14) |
| 2018 |
Jan
(3) |
Feb
(3) |
Mar
|
Apr
|
May
|
Jun
|
Jul
(2) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
|
|
|
|
|
|
|
1
|
|
2
|
3
|
4
|
5
|
6
|
7
|
8
(1) |
|
9
(1) |
10
|
11
|
12
|
13
|
14
|
15
|
|
16
|
17
(1) |
18
|
19
|
20
|
21
|
22
|
|
23
|
24
|
25
|
26
|
27
|
28
|
29
(1) |
|
30
|
|
|
|
|
|
|
|
From: Keith M. <no...@so...> - 2014-11-29 21:01:50
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Repository: mingw-org-wsl".
The branch, legacy has been updated
via fbd0c4aa878040daf047fd34aca04e13f707542c (commit)
via 9314bd9c6f7dc68d2a8607804b07dc5f1515551e (commit)
via edd3b5b12c50ff8db36e31bfb61795e29253d545 (commit)
from 417de1ac84aedc9749f32211c83d6c3c21d69cc9 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
https://sf.net/p/mingw/mingw-org-wsl/ci/fbd0c4aa878040daf047fd34aca04e13f707542c/
commit fbd0c4aa878040daf047fd34aca04e13f707542c
Author: Keith Marshall <kei...@us...>
Date: Sat Nov 29 20:58:46 2014 +0000
Correct omission of complex conjugate functions from libmingwex.a
diff --git a/mingwrt/ChangeLog b/mingwrt/ChangeLog
index 090b96d..42912fe 100644
--- a/mingwrt/ChangeLog
+++ b/mingwrt/ChangeLog
@@ -1,3 +1,26 @@
+2014-11-29 Keith Marshall <kei...@us...>
+
+ Correct omission of complex conjugate functions from libmingwex.a
+
+ * include/complex.h (conj, conjf, conjl): Add LIBIMPL declarations.
+ (creal, crealf, creall): Likewise, for consistency of implementation.
+ (cimag, cimagf, cimagl, carg, cargf, cargl): Likewise.
+
+ * Makefile.in (libimpl_sed_script): Add processing for __CRT_INLINE
+ declarations; they should be interpreted analogously to __CRT_ALIAS.
+ (libmingwex.a): Remove object file references for functions which are
+ now declared as LIBIMPL, and sort the remainder in ASCII collating
+ order; deleted function references comprise the set consisting of...
+ (carg.$OBJEXT, cargf.$OBJEXT, cargl.$OBJEXT): ...these...
+ (creal.$OBJEXT, crealf.$OBJEXT, creall.$OBJEXT): ...these, and...
+ (cimag.$OBJEXT, cimagf.$OBJEXT, cimagl.$OBJEXT): ...these.
+
+ * mingwex/complex/carg.c: Replaced by LIBIMPL; delete it.
+ * mingwex/complex/cargf.c mingwex/complex/cargl.c: Likewise.
+ * mingwex/complex/creal.c mingwex/complex/cimag.c: Likewise.
+ * mingwex/complex/crealf.c mingwex/complex/cimagf.c: Likewise.
+ * mingwex/complex/creall.c mingwex/complex/cimagl.c: Likewise.
+
2014-11-24 Keith Marshall <kei...@us...>
Back-port improved asinh() implementation from 4.0-dev branch.
diff --git a/mingwrt/Makefile.in b/mingwrt/Makefile.in
index b6738c5..4eef297 100644
--- a/mingwrt/Makefile.in
+++ b/mingwrt/Makefile.in
@@ -364,12 +364,12 @@ libmingw32.a libmingwex.a libm.a libmingwthrd.a libgmon.a:
#
vpath %.c ${mingwrt_srcdir}/mingwex
vpath %.c ${mingwrt_srcdir}/mingwex/complex
-libmingwex.a: $(addsuffix .$(OBJEXT), cabs carg catan ccoshf clog creal csqrt \
- cabsf cargf catanf ccoshl clogf crealf csqrtf cabsl cargl catanh ccosl clogl \
- creall csqrtl cacos casin catanhf cexp cpow csin ctan cacosf casinf catanhl \
- cexpf cpowf csinf ctanf cacosh casinh catanl cexpl cpowl csinh ctanh cacoshf \
- casinhf ccos cimag cproj csinhf ctanhf cacoshl casinhl ccosf cimagf cprojf \
- csinhl ctanhl cacosl casinl ccosh cimagl cprojl csinl ctanl)
+libmingwex.a: $(addsuffix .$(OBJEXT), cabs cabsf cabsl cacos cacosf \
+ cacosh cacoshf cacoshl cacosl casin casinf casinh casinhf casinhl casinl \
+ catan catanf catanh catanhf catanhl catanl ccos ccosf ccosh ccoshf ccoshl \
+ ccosl cexp cexpf cexpl clog clogf clogl cpow cpowf cpowl cproj cprojf \
+ cprojl csin csinf csinh csinhf csinhl csinl csqrt csqrtf csqrtl \
+ ctan ctanf ctanh ctanhf ctanhl ctanl)
libmingwex.a: $(addsuffix .$(OBJEXT), isblank iswblank)
@@ -551,6 +551,7 @@ libimpl_awk_script = test -z "$1" || awk '\
#
libimpl_sed_script = sed \
-e '/__CRT_ALIAS *__LIBIMPL.*FUNCTION *= *$1[ ,)].*)/d' \
+ -e '/__CRT_INLINE *__LIBIMPL.*FUNCTION *= *$1[ ,)].*)/d' \
-e '/pragma .* system_header/d'
LIBIMPL_CFLAGS = $(CFLAGS) $(INCLUDES) -fno-align-functions
diff --git a/mingwrt/include/complex.h b/mingwrt/include/complex.h
index f21dd2f..586a7f2 100644
--- a/mingwrt/include/complex.h
+++ b/mingwrt/include/complex.h
@@ -37,9 +37,7 @@
#define I _Complex_I
-#ifdef __cplusplus
-extern "C" {
-#endif
+_BEGIN_C_DECLS
#ifndef RC_INVOKED
@@ -115,22 +113,26 @@ long double _Complex __MINGW_ATTRIB_CONST cprojl (long double _Complex);
#ifdef __GNUC__
/* double */
-__CRT_INLINE double __MINGW_ATTRIB_CONST creal (double _Complex _Z)
+__CRT_INLINE __LIBIMPL__(( FUNCTION = creal ))
+double __MINGW_ATTRIB_CONST creal (double _Complex _Z)
{
return __real__ _Z;
}
-__CRT_INLINE double __MINGW_ATTRIB_CONST cimag (double _Complex _Z)
+__CRT_INLINE __LIBIMPL__(( FUNCTION = cimag ))
+double __MINGW_ATTRIB_CONST cimag (double _Complex _Z)
{
return __imag__ _Z;
}
-__CRT_INLINE double _Complex __MINGW_ATTRIB_CONST conj (double _Complex _Z)
+__CRT_INLINE __LIBIMPL__(( FUNCTION = conj ))
+double _Complex __MINGW_ATTRIB_CONST conj (double _Complex _Z)
{
return __extension__ ~_Z;
}
-__CRT_INLINE double __MINGW_ATTRIB_CONST carg (double _Complex _Z)
+__CRT_INLINE __LIBIMPL__(( FUNCTION = carg ))
+double __MINGW_ATTRIB_CONST carg (double _Complex _Z)
{
double res;
__asm__ ("fpatan;"
@@ -140,22 +142,26 @@ __CRT_INLINE double __MINGW_ATTRIB_CONST carg (double _Complex _Z)
/* float */
-__CRT_INLINE float __MINGW_ATTRIB_CONST crealf (float _Complex _Z)
+__CRT_INLINE __LIBIMPL__(( FUNCTION = crealf ))
+float __MINGW_ATTRIB_CONST crealf (float _Complex _Z)
{
return __real__ _Z;
}
-__CRT_INLINE float __MINGW_ATTRIB_CONST cimagf (float _Complex _Z)
+__CRT_INLINE __LIBIMPL__(( FUNCTION = cimagf ))
+float __MINGW_ATTRIB_CONST cimagf (float _Complex _Z)
{
return __imag__ _Z;
}
-__CRT_INLINE float _Complex __MINGW_ATTRIB_CONST conjf (float _Complex _Z)
+__CRT_INLINE __LIBIMPL__(( FUNCTION = conjf ))
+float _Complex __MINGW_ATTRIB_CONST conjf (float _Complex _Z)
{
return __extension__ ~_Z;
}
-__CRT_INLINE float __MINGW_ATTRIB_CONST cargf (float _Complex _Z)
+__CRT_INLINE __LIBIMPL__(( FUNCTION = cargf ))
+float __MINGW_ATTRIB_CONST cargf (float _Complex _Z)
{
float res;
__asm__ ("fpatan;"
@@ -164,22 +170,26 @@ __CRT_INLINE float __MINGW_ATTRIB_CONST cargf (float _Complex _Z)
}
/* long double */
-__CRT_INLINE long double __MINGW_ATTRIB_CONST creall (long double _Complex _Z)
+__CRT_INLINE __LIBIMPL__(( FUNCTION = creall ))
+long double __MINGW_ATTRIB_CONST creall (long double _Complex _Z)
{
return __real__ _Z;
}
-__CRT_INLINE long double __MINGW_ATTRIB_CONST cimagl (long double _Complex _Z)
+__CRT_INLINE __LIBIMPL__(( FUNCTION = cimagl ))
+long double __MINGW_ATTRIB_CONST cimagl (long double _Complex _Z)
{
return __imag__ _Z;
}
-__CRT_INLINE long double _Complex __MINGW_ATTRIB_CONST conjl (long double _Complex _Z)
+__CRT_INLINE __LIBIMPL__(( FUNCTION = conjl ))
+long double _Complex __MINGW_ATTRIB_CONST conjl (long double _Complex _Z)
{
return __extension__ ~_Z;
}
-__CRT_INLINE long double __MINGW_ATTRIB_CONST cargl (long double _Complex _Z)
+__CRT_INLINE __LIBIMPL__(( FUNCTION = cargl ))
+long double __MINGW_ATTRIB_CONST cargl (long double _Complex _Z)
{
long double res;
__asm__ ("fpatan;"
@@ -188,13 +198,8 @@ __CRT_INLINE long double __MINGW_ATTRIB_CONST cargl (long double _Complex _Z)
}
#endif /* __GNUC__ */
-
-
#endif /* RC_INVOKED */
-#ifdef __cplusplus
-}
-#endif
-
+_END_C_DECLS
#endif /* _COMPLEX_H */
diff --git a/mingwrt/mingwex/complex/carg.c b/mingwrt/mingwex/complex/carg.c
deleted file mode 100644
index cb47acc..0000000
--- a/mingwrt/mingwex/complex/carg.c
+++ /dev/null
@@ -1,9 +0,0 @@
-#include <complex.h>
-double __attribute__ ((const)) carg (double _Complex _Z)
-{
- double res;
- __asm__ ("fpatan;"
- : "=t" (res) : "0" (__real__ _Z), "u" (__imag__ _Z) : "st(1)");
- return res;
-}
-
diff --git a/mingwrt/mingwex/complex/cargf.c b/mingwrt/mingwex/complex/cargf.c
deleted file mode 100644
index 360beef..0000000
--- a/mingwrt/mingwex/complex/cargf.c
+++ /dev/null
@@ -1,9 +0,0 @@
-#include <complex.h>
-float __attribute__ ((const)) cargf (float _Complex _Z)
-{
- float res;
- __asm__ ("fpatan;"
- : "=t" (res) : "0" (__real__ _Z), "u" (__imag__ _Z) : "st(1)");
- return res;
-}
-
diff --git a/mingwrt/mingwex/complex/cargl.c b/mingwrt/mingwex/complex/cargl.c
deleted file mode 100644
index 179dae7..0000000
--- a/mingwrt/mingwex/complex/cargl.c
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <complex.h>
-long double __attribute__ ((const)) cargl (long double _Complex _Z)
-{
- long double res;
- __asm__ ("fpatan;"
- : "=t" (res) : "0" (__real__ _Z), "u" (__imag__ _Z) : "st(1)");
- return res;
-}
diff --git a/mingwrt/mingwex/complex/cimag.c b/mingwrt/mingwex/complex/cimag.c
deleted file mode 100644
index b6b3256..0000000
--- a/mingwrt/mingwex/complex/cimag.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <complex.h>
-double __attribute__ ((const)) cimag (double complex _Z)
-{
- return __imag__ _Z;
-}
-
diff --git a/mingwrt/mingwex/complex/cimagf.c b/mingwrt/mingwex/complex/cimagf.c
deleted file mode 100644
index f77b9ec..0000000
--- a/mingwrt/mingwex/complex/cimagf.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <complex.h>
-float __attribute__ ((const)) cimagf (float complex _Z)
-{
- return __imag__ _Z;
-}
-
diff --git a/mingwrt/mingwex/complex/cimagl.c b/mingwrt/mingwex/complex/cimagl.c
deleted file mode 100644
index 9b023b4..0000000
--- a/mingwrt/mingwex/complex/cimagl.c
+++ /dev/null
@@ -1,5 +0,0 @@
-#include <complex.h>
-long double __attribute__ ((const)) cimagl (long double complex _Z)
-{
- return __imag__ _Z;
-}
diff --git a/mingwrt/mingwex/complex/creal.c b/mingwrt/mingwex/complex/creal.c
deleted file mode 100644
index 6905b7e..0000000
--- a/mingwrt/mingwex/complex/creal.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <complex.h>
-double __attribute__ ((const)) creal (double complex _Z)
-{
- return __real__ _Z;
-}
-
diff --git a/mingwrt/mingwex/complex/crealf.c b/mingwrt/mingwex/complex/crealf.c
deleted file mode 100644
index 16dc7ec..0000000
--- a/mingwrt/mingwex/complex/crealf.c
+++ /dev/null
@@ -1,6 +0,0 @@
-#include <complex.h>
-float __attribute__ ((const)) crealf (float complex _Z)
-{
- return __real__ _Z;
-}
-
diff --git a/mingwrt/mingwex/complex/creall.c b/mingwrt/mingwex/complex/creall.c
deleted file mode 100644
index 62470d9..0000000
--- a/mingwrt/mingwex/complex/creall.c
+++ /dev/null
@@ -1,5 +0,0 @@
-#include <complex.h>
-long double __attribute__ ((const)) creall (long double complex _Z)
-{
- return __real__ _Z;
-}
https://sf.net/p/mingw/mingw-org-wsl/ci/9314bd9c6f7dc68d2a8607804b07dc5f1515551e/
commit 9314bd9c6f7dc68d2a8607804b07dc5f1515551e
Author: Keith Marshall <kei...@us...>
Date: Mon Nov 24 22:36:19 2014 +0000
Back-port improved asinh() implementation from 4.0-dev branch.
diff --git a/mingwrt/ChangeLog b/mingwrt/ChangeLog
index 85a2e9f..090b96d 100644
--- a/mingwrt/ChangeLog
+++ b/mingwrt/ChangeLog
@@ -1,3 +1,11 @@
+2014-11-24 Keith Marshall <kei...@us...>
+
+ Back-port improved asinh() implementation from 4.0-dev branch.
+
+ * mingwex/math/asinh_generic.c: New file; it replaces...
+ * mingwex/math/asinh.c mingwex/math/asinhf.c mingwex/math/asinhl.c:
+ ...all of these; delete them.
+
2014-11-18 Keith Marshall <kei...@us...>
Enable remake of lost LIBIMPL object files.
diff --git a/mingwrt/mingwex/math/asinh.c b/mingwrt/mingwex/math/asinh.c
deleted file mode 100644
index 8759da4..0000000
--- a/mingwrt/mingwex/math/asinh.c
+++ /dev/null
@@ -1,28 +0,0 @@
-#include <math.h>
-#include <errno.h>
-#include "fastmath.h"
-
- /* asinh(x) = copysign(log(fabs(x) + sqrt(x * x + 1.0)), x) */
-double asinh(double x)
-{
- double z;
- if (!isfinite (x))
- return x;
- z = fabs (x);
-
- /* Avoid setting FPU underflow exception flag in x * x. */
-#if 0
- if ( z < 0x1p-32)
- return x;
-#endif
-
- /* Use log1p to avoid cancellation with small x. Put
- x * x in denom, so overflow is harmless.
- asinh(x) = log1p (x + sqrt (x * x + 1.0) - 1.0)
- = log1p (x + x * x / (sqrt (x * x + 1.0) + 1.0)) */
-
- z = __fast_log1p (z + z * z / (__fast_sqrt (z * z + 1.0) + 1.0));
-
- return ( x > 0.0 ? z : -z);
-}
-
diff --git a/mingwrt/mingwex/math/asinh_generic.c b/mingwrt/mingwex/math/asinh_generic.c
new file mode 100644
index 0000000..f892997
--- /dev/null
+++ b/mingwrt/mingwex/math/asinh_generic.c
@@ -0,0 +1,146 @@
+/**
+ * @file asinh_generic.c
+ * Copyright 2012, 2013 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 (including the next
+ * paragraph) 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.
+ *
+ *
+ * Implemented 2013 by Keith Marshall <kei...@us...>
+ * Copyright assigned by the author to the MinGW.org project.
+ *
+ * This is a generic implementation for all of the asinh(), asinhl(),
+ * and asinhf() functions; each is to be compiled separately, i.e.
+ *
+ * gcc -D FUNCTION=asinh -o asinh.o asinh.c
+ * gcc -D FUNCTION=asinhl -o asinhl.o asinh.c
+ * gcc -D FUNCTION=asinhf -o asinhf.o asinh.c
+ *
+ */
+#include <math.h>
+
+#ifndef FUNCTION
+/* If user neglected to specify it, the default compilation is for
+ * the asinh() function.
+ */
+# define FUNCTION asinh
+#endif
+
+#define argtype_asinh double
+#define argtype_asinhl long double
+#define argtype_asinhf float
+
+#define PASTE(PREFIX,SUFFIX) PREFIX##SUFFIX
+#define mapname(PREFIX,SUFFIX) PASTE(PREFIX,SUFFIX)
+
+#define ARGTYPE(FUNCTION) PASTE(argtype_,FUNCTION)
+#define ARGCAST(VALUE) mapname(argcast_,FUNCTION)(VALUE)
+
+#define argcast_asinh(VALUE) VALUE
+#define argcast_asinhl(VALUE) PASTE(VALUE,L)
+#define argcast_asinhf(VALUE) PASTE(VALUE,F)
+
+#define mapfunc(NAME) mapname(mapfunc_,FUNCTION)(NAME)
+
+#define mapfunc_asinh(NAME) NAME
+#define mapfunc_asinhl(NAME) PASTE(NAME,l)
+#define mapfunc_asinhf(NAME) PASTE(NAME,f)
+
+/* Prefer fast versions of mathematical functions.
+ */
+#include "fastmath.h"
+
+#define log __fast_log
+#define log1p __fast_log1p
+#define sqrt __fast_sqrt
+
+/* Define the generic function implementation.
+ */
+ARGTYPE(FUNCTION) FUNCTION( ARGTYPE(FUNCTION) x )
+{
+ if( isfinite(x) )
+ {
+ /* For all finite values of x, we may compute asinh(x) in terms of
+ * the magnitude of x...
+ */
+ ARGTYPE(FUNCTION) h, z;
+ if( (z = mapfunc(fabs)( x )) > ARGCAST(1.0) )
+ {
+ /* When z is greater than 1.0, there is a possibility of overflow
+ * in the computation of z * z; this would propagate to the result
+ * of computing sqrt( 1.0 + z * z ), even when the ultimate result
+ * should be representable. Thus, we adopt a transformation based
+ * on hypot(), which cannot overflow, viz.:
+ *
+ * sqrt( 1.0 + z * z )
+ *
+ * is equivalent to
+ *
+ * z * sqrt( 1.0 + (1.0 / z) * (1.0 / z) )
+ */
+ h = ARGCAST(1.0) / z;
+ h = z * mapfunc(sqrt)( ARGCAST(1.0) + h * h );
+ }
+ else
+ { /* z is less that 1.0: we may safely compute z * z without fear of
+ * overflow; it may underflow to zero, in which case we may simply
+ * ignore the effect, as it is insignificant.
+ */
+ h = mapfunc(sqrt)( ARGCAST(1.0) + z * z );
+ }
+
+ /* Now, we may compute the absolute value of the inverse hyperbolic
+ * sine function, according to its analytical definition:
+ *
+ * arsinh( z ) = log( z + sqrt( 1.0 + z * z ) )
+ *
+ * or, since we've already computed h = sqrt( 1.0 + z * z ):
+ *
+ * arsinh( z ) = log( z + h )
+ *
+ * We may note that, in spite of our efforts to avoid overflow in the
+ * computation of h, this expression for arsinh(z) remains vulnerable to
+ * overflow as z approaches the representable limit of finite floating
+ * point values, even when the ultimate result is both representable and
+ * computable. We may further note that h >= z is always true, with h
+ * approaching an asymptotic minimum of 1.0, as z becomes vanishingly
+ * small, while h becomes approximately equal to z as z becomes very
+ * large; thus we may transform the expression to:
+ *
+ * arsinh( z ) = log( z / h + 1.0 ) + log( h )
+ *
+ * or its equivalent representation:
+ *
+ * arsinh( z ) = log1p( z / h ) + log( h )
+ *
+ * which is computable, without overflow, for all finite values of z
+ * with corresponding finite values of h for which the logarithm is
+ * computable.
+ *
+ * Finally, we note that the ultimate result has the same sign as the
+ * original value of x, with magnitude as computed by the preceding
+ * expression; thus...
+ */
+ return mapfunc(copysign)( mapfunc(log1p)( z / h ) + mapfunc(log)( h ), x );
+ }
+ /* If we get to here, x was infinite; we can do no more than return an
+ * equivalent infinite result.
+ */
+ return x;
+}
diff --git a/mingwrt/mingwex/math/asinhf.c b/mingwrt/mingwex/math/asinhf.c
deleted file mode 100644
index d9fc12d..0000000
--- a/mingwrt/mingwex/math/asinhf.c
+++ /dev/null
@@ -1,28 +0,0 @@
-#include <math.h>
-#include <errno.h>
-#include "fastmath.h"
-
- /* asinh(x) = copysign(log(fabs(x) + sqrt(x * x + 1.0)), x) */
-float asinhf(float x)
-{
- float z;
- if (!isfinite (x))
- return x;
- z = fabsf (x);
-
- /* Avoid setting FPU underflow exception flag in x * x. */
-#if 0
- if ( z < 0x1p-32)
- return x;
-#endif
-
-
- /* Use log1p to avoid cancellation with small x. Put
- x * x in denom, so overflow is harmless.
- asinh(x) = log1p (x + sqrt (x * x + 1.0) - 1.0)
- = log1p (x + x * x / (sqrt (x * x + 1.0) + 1.0)) */
-
- z = __fast_log1p (z + z * z / (__fast_sqrt (z * z + 1.0) + 1.0));
-
- return ( x > 0.0 ? z : -z);
-}
diff --git a/mingwrt/mingwex/math/asinhl.c b/mingwrt/mingwex/math/asinhl.c
deleted file mode 100644
index ec65b1e..0000000
--- a/mingwrt/mingwex/math/asinhl.c
+++ /dev/null
@@ -1,28 +0,0 @@
-#include <math.h>
-#include <errno.h>
-#include "fastmath.h"
-
- /* asinh(x) = copysign(log(fabs(x) + sqrt(x * x + 1.0)), x) */
-long double asinhl(long double x)
-{
- long double z;
- if (!isfinite (x))
- return x;
-
- z = fabsl (x);
-
- /* Avoid setting FPU underflow exception flag in x * x. */
-#if 0
- if ( z < 0x1p-32)
- return x;
-#endif
-
- /* Use log1p to avoid cancellation with small x. Put
- x * x in denom, so overflow is harmless.
- asinh(x) = log1p (x + sqrt (x * x + 1.0) - 1.0)
- = log1p (x + x * x / (sqrt (x * x + 1.0) + 1.0)) */
-
- z = __fast_log1pl (z + z * z / (__fast_sqrtl (z * z + 1.0L) + 1.0L));
-
- return ( x > 0.0 ? z : -z);
-}
https://sf.net/p/mingw/mingw-org-wsl/ci/edd3b5b12c50ff8db36e31bfb61795e29253d545/
commit edd3b5b12c50ff8db36e31bfb61795e29253d545
Author: Keith Marshall <kei...@us...>
Date: Tue Nov 18 19:47:32 2014 +0000
Enable remake of lost LIBIMPL object files.
diff --git a/mingwrt/ChangeLog b/mingwrt/ChangeLog
index 372c0ea..85a2e9f 100644
--- a/mingwrt/ChangeLog
+++ b/mingwrt/ChangeLog
@@ -1,3 +1,10 @@
+2014-11-18 Keith Marshall <kei...@us...>
+
+ Enable remake of lost LIBIMPL object files.
+
+ * Makefile.in (libimpl_remake): New macro; define it, and...
+ (%.libimpl.$OBJEXT) [%.libimpl exists]: ...use it in build rule.
+
2014-11-17 Keith Marshall <kei...@us...>
Implement more robust _get_output_format fallback handling.
diff --git a/mingwrt/Makefile.in b/mingwrt/Makefile.in
index 9555cbc..b6738c5 100644
--- a/mingwrt/Makefile.in
+++ b/mingwrt/Makefile.in
@@ -564,9 +564,15 @@ LIBIMPL_CFLAGS = $(CFLAGS) $(INCLUDES) -fno-align-functions
> $@
# ...and ultimately discarded, after the requisite object file
-# has been compiled.
+# has been compiled; (note that this creates a vulnerability due
+# to possible loss of the object file, while the tracking file is
+# still in place; to circumvent this, we must be able to force a
+# remake of the tracking file, so also regenerating the .c file,
+# before it is compiled).
#
+libimpl_remake = { $(RM) $1; $(MAKE) --no-print-directory $1; }
%.libimpl.$(OBJEXT): %.libimpl
+ test -f $<.c || $(call libimpl_remake,$<)
$(CC) -c $(CPPFLAGS) $(LIBIMPL_CFLAGS) -o $@ $<.c
$(RM) $<.c
-----------------------------------------------------------------------
Summary of changes:
mingwrt/ChangeLog | 38 +++++++++
mingwrt/Makefile.in | 21 +++--
mingwrt/include/complex.h | 47 ++++++-----
mingwrt/mingwex/complex/carg.c | 9 --
mingwrt/mingwex/complex/cargf.c | 9 --
mingwrt/mingwex/complex/cargl.c | 8 --
mingwrt/mingwex/complex/cimag.c | 6 --
mingwrt/mingwex/complex/cimagf.c | 6 --
mingwrt/mingwex/complex/cimagl.c | 5 -
mingwrt/mingwex/complex/creal.c | 6 --
mingwrt/mingwex/complex/crealf.c | 6 --
mingwrt/mingwex/complex/creall.c | 5 -
mingwrt/mingwex/math/asinh.c | 28 -------
mingwrt/mingwex/math/asinh_generic.c | 146 ++++++++++++++++++++++++++++++++++
mingwrt/mingwex/math/asinhf.c | 28 -------
mingwrt/mingwex/math/asinhl.c | 28 -------
16 files changed, 224 insertions(+), 172 deletions(-)
delete mode 100644 mingwrt/mingwex/complex/carg.c
delete mode 100644 mingwrt/mingwex/complex/cargf.c
delete mode 100644 mingwrt/mingwex/complex/cargl.c
delete mode 100644 mingwrt/mingwex/complex/cimag.c
delete mode 100644 mingwrt/mingwex/complex/cimagf.c
delete mode 100644 mingwrt/mingwex/complex/cimagl.c
delete mode 100644 mingwrt/mingwex/complex/creal.c
delete mode 100644 mingwrt/mingwex/complex/crealf.c
delete mode 100644 mingwrt/mingwex/complex/creall.c
delete mode 100644 mingwrt/mingwex/math/asinh.c
create mode 100644 mingwrt/mingwex/math/asinh_generic.c
delete mode 100644 mingwrt/mingwex/math/asinhf.c
delete mode 100644 mingwrt/mingwex/math/asinhl.c
hooks/post-receive
--
Repository: mingw-org-wsl
|
|
From: Keith M. <no...@so...> - 2014-11-17 19:12:44
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Repository: mingw-org-wsl".
The branch, legacy has been updated
via 417de1ac84aedc9749f32211c83d6c3c21d69cc9 (commit)
via 739d533acd49940efaf062a6ddbfb4a83526aed7 (commit)
via e974c5e23a4213c6c9e22c6c812501cf35e30cd9 (commit)
from 9a09e9224a0229440fd7b4fb5210941e80ad7a1d (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
https://sf.net/p/mingw/mingw-org-wsl/ci/417de1ac84aedc9749f32211c83d6c3c21d69cc9/
commit 417de1ac84aedc9749f32211c83d6c3c21d69cc9
Author: Keith Marshall <kei...@us...>
Date: Mon Nov 17 19:10:03 2014 +0000
Implement more robust _get_output_format fallback handling.
diff --git a/mingwrt/ChangeLog b/mingwrt/ChangeLog
index 03d165c..372c0ea 100644
--- a/mingwrt/ChangeLog
+++ b/mingwrt/ChangeLog
@@ -1,3 +1,50 @@
+2014-11-17 Keith Marshall <kei...@us...>
+
+ Implement more robust _get_output_format fallback handling.
+
+ * mingwex/ofmt.c: New file; it implements...
+ (__mingw_output_format_flag): ...backing store, used by...
+ (__mingw_get_output_format, __mingw_set_output_format): ...these
+ MSVCRT.DLL version agnostic wrappers/emulators for each of these...
+ (_get_output_format, _set_output_format): ...MSVCR80.DLL and later
+ version specific Microsoft APIs, which are also supported by some
+ later versions of MSVCRT.DLL, (excluding WinXP and earlier).
+ (__mingw_get_output_format_fallback): Implement; it is aliased to...
+ (__mingw_set_output_format_fallback): ...this; together they provide
+ the emulation support for the preceding pair of functions, when they
+ are not available within the run-time platform MSVCRT.DLL
+ (__mingw_get_printf_count_output, __mingw_set_printf_count_output):
+ Implement them; they wrap, and if necessary emulate...
+ (_get_printf_count_output, _set_printf_count_output): ...these.
+ (__mingw_get_printf_count_output_fallback): Implement; aliased to...
+ (__mingw_set_printf_count_output_fallback): ...this; together they are
+ required to support emulation of the preceding pair of functions, when
+ they are not available within the run-time platform MSVCRT.DLL
+
+ * include/stdio.h (_TWO_DIGIT_EXPONENT): Define it unconditionally.
+ (_THREE_DIGIT_EXPONENT): New manifest constant; define it orthogonally.
+ (__mingw_get_output_format, __mingw_set_output_format)
+ (__mingw_get_printf_count_output, __mingw_set_printf_count_output):
+ Unconditionally declare their prototypes, for subsequent inline use.
+ [_MSVCRT_VERSION__ < 0x800] (_get_output_format): Emulate it inline.
+ [_MSVCRT_VERSION__ < 0x800] (_set_output_format): Likewise.
+ [_MSVCRT_VERSION__ < 0x800] (_get_printf_count_output): Likewise.
+ [_MSVCRT_VERSION__ < 0x800] (_set_printf_count_output): Likewise.
+ (__USE_MINGW_PRINTF): New manifest constant; define it. It is a
+ counterpart to __USE_MINGW_ANSI_STDIO, which is guaranteed to always
+ represent a compilable token.
+
+ * mingwex/stdio/pformat.c (__pformat_exponent_digits): Do not require
+ _get_output_format; consult __mingw_output_format_flag directly.
+
+ * ofmt_stub.s: No longer required; delete it.
+
+ * Makefile.in (ofmt_stub.$OBJEXT): Delete reference.
+ (PFORMAT_CFLAGS) [__MSVCRT_VERSION__ = 0x800]: Remove requirement.
+ (varofmt.$OBJEXT, crtofmt.$OBJEXT, getofmt.$OBJEXT, setofmt.$OBJEXT)
+ (crtnfmt.$OBJEXT, getnfmt.$OBJEXT, setnfmt.$OBJEXT): Add build rule;
+ all are compiled from ofmt.c
+
2014-11-16 Keith Marshall <kei...@us...>
Do some more essential build tree clean up.
diff --git a/mingwrt/Makefile.in b/mingwrt/Makefile.in
index 1e10ec5..9555cbc 100644
--- a/mingwrt/Makefile.in
+++ b/mingwrt/Makefile.in
@@ -258,19 +258,6 @@ all-libmsvcrt install-mingwrt-libs: $(foreach name,$(all_msvcrt),lib$(name).a)
all-libcrtdll install-deprecated-mingwrt-libs: libcrtdll.a libcoldname.a
all-deprecated-mingwrt all-deprecated-libmsvcrt: all-libcrtdll
-# FIXME: We should aim to remove this interim work-around...
-#
-# MSVCRT.DLL, MSVCR70.DLL, and MSVCR71.DLL, (both regular and debug
-# variants), lack the _get_output_format() function, which is required
-# by the printf() module in libmingwex.a; add our own implementation.
-# (Note that we also apply this for CRTDLL.DLL, via libcrtdll.a)
-#
-vpath ofmt_stub.s ${mingwrt_srcdir}
-$(foreach ver,t 70 71,libmsvcr$(ver).a) libcrtdll.a \
-$(foreach ver,t 70 71,libmsvcr$(ver)d.a): ofmt_stub.$(OBJEXT)
-#
-# End of work-around
-
# For each import library to be built, we derive a tailored exports
# definition file, from a common source.
#
@@ -437,21 +424,21 @@ libmingwex.a: $(addsuffix .$(OBJEXT), btowc fopen64 fprintf fseeko64 ftello64 \
lseek64 pformat printf snprintf snwprintf sprintf vfprintf vfscanf vfwscanf \
vprintf vscanf vsnprintf vsnwprintf vsprintf vsscanf vswscanf vwscanf)
-# FIXME: We should adopt a semantic implementation similar to the
-# dlsym( RTLD_DEFAULT, "_get_output_format" ) call in POSIX, to let
-# us handle the following fall-back more effectively.
+# pformat.$(OBJEXT) needs an explicit build rule, since we need to
+# specify an additional header file path.
#
-# pformat.$(OBJEXT) needs an explicit build rule; we always build it
-# assuming that __MSVCRT_VERSION__ >= 0x0800, (and thus assuming that
-# the Microsoft runtime provides the _get_output_format() function);
-# we then rely on ofmt_stub.s, (in the top mingwrt source directory),
-# to provide a fall-back implementation, so maintaining forward
-# compatibility for earlier versions of MSVCRT.DLL
-#
-PFORMAT_CFLAGS = -I ${mingwrt_srcdir}/mingwex/gdtoa -D__MSVCRT_VERSION__=0x0800
+PFORMAT_CFLAGS = -I ${mingwrt_srcdir}/mingwex/gdtoa
pformat.$(OBJEXT): %.$(OBJEXT): %.c
$(CC) -c $(ALL_CFLAGS) $(PFORMAT_CFLAGS) $< -o $@
+# To support Microsoft's DLL version specific exponent digits control,
+# and "%n" format availability control APIs, in a DLL version agnostic
+# manner, we also provide the following set of wrapper functions:
+#
+libmingwex.a: $(addsuffix fmt.$(OBJEXT),varo crto geto seto crtn getn setn)
+$(addsuffix fmt.$(OBJEXT),varo crto geto seto crtn getn setn): %.$(OBJEXT): ofmt.c
+ $(CC) -c $(ALL_CFLAGS) -D__$*__ -fno-align-functions -o $@ $<
+
# Some additional miscellaneous functions, in libmingwex.a
#
#libmingwex.a: $(addsuffix .$(OBJEXT), glob membarrier)
diff --git a/mingwrt/include/stdio.h b/mingwrt/include/stdio.h
index 6ec40e2..84ab7b7 100644
--- a/mingwrt/include/stdio.h
+++ b/mingwrt/include/stdio.h
@@ -508,14 +508,80 @@ _CRTIMP int __cdecl __MINGW_NOTHROW _getmaxstdio (void);
_CRTIMP int __cdecl __MINGW_NOTHROW _setmaxstdio (int);
#endif
+/* Microsoft introduced a capability in MSVCR80.DLL and later, to
+ * set the minimum number of digits to be displayed in a printf()
+ * floating point exponent; they retro-fitted this in MSVCRT.DLL,
+ * from Windows-Vista onwards, but we provide our own wrappers in
+ * libmingwex.a, which make it possible for us to emulate the API
+ * for any version of MSVCRT.DLL (including WinXP and earlier).
+ */
+#define _TWO_DIGIT_EXPONENT 1
+
+/* While Microsoft define the preceding manifest constant, they
+ * appear to neglect to define its complement, (for restoration
+ * of their default exponent display format); for orthogonality,
+ * we will provide this regardless of Microsoft's negligence.
+ */
+#define _THREE_DIGIT_EXPONENT 0
+
+unsigned int __cdecl __mingw_get_output_format (void);
+unsigned int __cdecl __mingw_set_output_format (unsigned int);
+
+/* Also appearing for the first time in MSVCR80.DLL, and then also
+ * retro-fitted to MSVCRT.DLL from Windows-Vista onwards, was this
+ * pair of functions to control availability of "%n" formatting in
+ * the MSVCRT.DLL printf() family of functions, for which we also
+ * provide our own DLL version agnostic wrappers:
+ */
+int __cdecl __mingw_get_printf_count_output (void);
+int __cdecl __mingw_set_printf_count_output (int);
+
#if __MSVCRT_VERSION__ >= 0x800
+/*
+ * When the user declares that MSVCR80.DLL features are supported,
+ * we simply expose the corresponding APIs...
+ */
_CRTIMP unsigned int __cdecl __MINGW_NOTHROW _get_output_format (void);
_CRTIMP unsigned int __cdecl __MINGW_NOTHROW _set_output_format (unsigned int);
-#define _TWO_DIGIT_EXPONENT 1
-
_CRTIMP int __cdecl __MINGW_NOTHROW _get_printf_count_output (void);
_CRTIMP int __cdecl __MINGW_NOTHROW _set_printf_count_output (int);
+
+#else
+/* ...otherwise, we emulate the APIs, in a DLL version agnostic
+ * manner, using our own implementation wrappers.
+ */
+__CRT_ALIAS unsigned int __cdecl _get_output_format (void)
+{ return __mingw_get_output_format (); }
+
+__CRT_ALIAS unsigned int __cdecl _set_output_format (unsigned int __style)
+{ return __mingw_set_output_format (__style); }
+
+/* When using our own printf() implementation, "%n" format is ALWAYS
+ * supported, so we make this API a no-op, reporting it to be so; for
+ * the alternative case, when using MSVCRT.DLL's printf(), we delegate
+ * to our wrapper API implementation, which will invoke the API function
+ * calls within the DLL, if they are available, or persistently report
+ * the state of "%n" formatting as DISABLED if they are not.
+ */
+#if __USE_MINGW_ANSI_STDIO
+/*
+ * Note that __USE_MINGW_ANSI_STDIO is not guaranteed to resolve to any
+ * symbol which will represent a compilable logic state; map it to this
+ * alternative which will, for the true state...
+ */
+# define __USE_MINGW_PRINTF 1
+#else
+/* ...and for the false.
+ */
+# define __USE_MINGW_PRINTF 0
+#endif
+
+__CRT_ALIAS int __cdecl _get_printf_count_output (void)
+{ return __USE_MINGW_PRINTF ? 1 : __mingw_get_printf_count_output (); }
+
+__CRT_ALIAS int __cdecl _set_printf_count_output (int __mode)
+{ return __USE_MINGW_PRINTF ? 1 : __mingw_set_printf_count_output (__mode); }
#endif
#ifndef _NO_OLDNAMES
diff --git a/mingwrt/mingwex/ofmt.c b/mingwrt/mingwex/ofmt.c
new file mode 100644
index 0000000..5a8ccf3
--- /dev/null
+++ b/mingwrt/mingwex/ofmt.c
@@ -0,0 +1,241 @@
+/*
+ * ofmt.c
+ *
+ * Implement universally available replacement wrappers for each of
+ * Microsoft's _get_output_format()/_set_output_format(), and their
+ * _get_printf_count_output()/_set_printf_count_output() APIs.
+ *
+ * $Id$
+ *
+ * Written by Keith Marshall <kei...@us...>
+ * Copyright (C) 2014, 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.
+ *
+ *
+ * This source file provides a generic implementation for each of the two
+ * functions, __mingw_get_output_format() and __mingw_set_output_format(),
+ * which serve as universally available fallbacks for each of Microsoft's
+ * _get_output_format() and _set_output_format() API functions, which were
+ * introduced in MSVCR80.DLL, and are unavailable in MSVCRT.DLL prior to
+ * the release accompanying Windows-Vista; compile it with:
+ *
+ * gcc -c -O2 -D__varofmt__ -o varofmt.o ofmt.c
+ * gcc -c -O2 -D__crtofmt__ -o crtofmt.o ofmt.c
+ * gcc -c -O2 -D__getofmt__ -o getofmt.o ofmt.c
+ * gcc -c -O2 -D__setofmt__ -o setofmt.o ofmt.c
+ *
+ * for each of these two implementation cases respectively, to provide the
+ * capability for any application which #includes stdio.h to invoke either
+ * _get_output_format() or _set_output_format() in total safety, regardless
+ * of whether the underlying platform MSVCRT.DLL supports this API or not;
+ * if the API is available, it will be invoked by the wrappers, otherwise
+ * it will be emulated within the wrappers themselves.
+ *
+ * Additionally provided are wrappers for the _get_printf_count_output() and
+ * _set_printf_count_output() functions, the respective invocations of which
+ * may be compiled with:
+ *
+ * gcc -c -O2 -D__crtnfmt__ -o crtnfmt.o ofmt.c
+ * gcc -c -O2 -D__getnfmt__ -o getnfmt.o ofmt.c
+ * gcc -c -O2 -D__setnfmt__ -o setnfmt.o ofmt.c
+ *
+ * to provide similar fallback handlers for the respective API functions; in
+ * the case of this pair of functions, the respective API will be invoked if
+ * available, otherwise the call will become a no-op, always returning zero.
+ *
+ * All of these functions are provided in libmingwex.a, where each of them
+ * serves as a wrapper for their corresponding Microsoft runtime functions;
+ * each may be called safely, even when running on a version of MS-Windows
+ * where the native MSVCRT.DLL implementation lacks the corresponding API
+ * function, in which case a suitable fallback implementation is provided;
+ * in cases where the native implementation IS available, each wrapper
+ * simply delegates to the MSVCRT.DLL implementation.
+ *
+ * Note that each of these wrapper functions depends upon the MinGW.org
+ * implementation of the POSIX dlsym() function, which is also provided
+ * in libmingwex.a, and prototyped in dlfcn.h
+ *
+ */
+#include <dlfcn.h>
+#include <stdio.h>
+
+/* Storage for recorded output format state, when the MSVCRT functions
+ * aren't available; we need it to be public so that it may be shared by
+ * our two separately compiled API functions, but we keep it privately
+ * declared; users should NEVER access this, other than via our two
+ * accessor functions.
+ */
+extern unsigned int __mingw_output_format_flag;
+
+#if defined __varofmt__
+/*
+ * Here, we actually allocate the storage for recording the preferred
+ * formatting style; although POSIX might lead us to prefer an initial
+ * default of _TWO_DIGIT_EXPONENT, we choose to assign a default which
+ * is consistent with Microsoft's preference.
+ */
+unsigned int __mingw_output_format_flag = _THREE_DIGIT_EXPONENT;
+
+#elif defined __crtofmt__
+/*
+ * Here we implement the common part of the fallback API, retrieving
+ * the value stored in __mingw_output_format_flag. Note that this is
+ * sufficient for both _get_output_format() and _set_output_format(),
+ * with the set action being completed in the calling wrapper.
+ */
+extern unsigned int __mingw_get_output_format_fallback( void );
+unsigned int __mingw_get_output_format_fallback( void )
+{
+ /* Our replacement function simply returns the current setting of
+ * the assigned formatting style...
+ */
+ return __mingw_output_format_flag;
+}
+/* ...and, in the case of _set_output_format(), we simply map the
+ * requisite name to the common function implementation.
+ */
+extern unsigned int __mingw_set_output_format_fallback( unsigned int )
+__attribute__((__alias__("__mingw_get_output_format_fallback")));
+
+#elif defined __crtnfmt__
+/*
+ * Here, we implement a generic fallback hook, suitable for use as the
+ * fallback for _get_printf_count_output()/_set_printf_count_output().
+ */
+int __mingw_get_printf_count_output_fallback( void )
+__attribute__((__alias__("__mingw_set_printf_count_output_fallback")));
+
+int __mingw_set_printf_count_output_fallback( int );
+int __mingw_set_printf_count_output_fallback( int mode )
+{ return 0; }
+
+#else
+/* We want _get_output_format() to serve as our default compilation
+ * option, so deal with the "%n" availability controls, as provided by
+ * _get_printf_count_output() and _set_printf_count_output(), and also
+ * _set_output_format() compilation options first.
+ */
+#if defined __setnfmt__
+/*
+ * Here, we are wrapping the _set_printf_count_output() function...
+ */
+# define RTNTYPE int
+# define ARGTYPE int
+# define FUNCTION _set_printf_count_output
+# define ARGLIST mode
+
+#define api_helper_result api_helper( mode )
+extern int __mingw_set_printf_count_output_fallback( int );
+
+#elif defined __getnfmt__
+/*
+ * ...while here, it is _get_printf_count_output().
+ */
+# define RTNTYPE int
+# define ARGTYPE void
+# define FUNCTION _get_printf_count_output
+# define ARGLIST
+
+#define api_helper_result api_helper()
+extern int __mingw_get_printf_count_output_fallback( void );
+
+#elif defined __setofmt__
+/*
+ * This is our implementation for the _set_output_format() function,
+ * which will be called when there is no MSVCRT implementation.
+ */
+# define RTNTYPE unsigned int
+# define FUNCTION _set_output_format
+# define ARGTYPE unsigned int
+# define ARGLIST style
+
+/* Our replacement function emulates the documented behaviour of
+ * its MSVCRT counterpart, assigning a new value for the recorded
+ * formatting style, then returning the previous setting.
+ */
+#define api_helper_result api_invoke( api_helper, style )
+static __inline__ __attribute__((__always_inline__)) unsigned int
+api_invoke( unsigned int (*api_helper)(unsigned int), unsigned int style )
+{
+ /* Note that we implement this, predominantly, inline within
+ * the wrapper code, using the fallback function pointer only
+ * to retrieve the previous value for return; thus it is able
+ * to use a handler in common with _get_output_format()...
+ */
+ unsigned int retval = api_helper( style );
+ __mingw_output_format_flag = style;
+ return retval;
+}
+/* ...while declaring its formal prototype as external.
+ */
+extern unsigned int __mingw_set_output_format_fallback( unsigned int );
+
+#else /* __getofmt__, either explicitly defined, or by default */
+/*
+ * When not explicitly requested to implement _set_output_format(),
+ * assume __getofmt__ is implied, and implement _get_output_format(),
+ * for use when there is no MSVCRT implementation.
+ */
+# define RTNTYPE unsigned int
+# define FUNCTION _get_output_format
+# define ARGTYPE void
+# define ARGLIST
+
+#define api_helper_result __mingw_output_format_flag = api_helper()
+extern unsigned int __mingw_get_output_format_fallback( void );
+#endif
+
+/* Macros to facilitate a generic implementation for our replacement
+ * interface functions.
+ */
+#define __mingw_(FUNCTION) __construct_name__(__mingw,FUNCTION)
+#define __fallback_(FUNCTION) __construct_name__(FUNCTION,_fallback)
+#define __construct_name__(prefix,suffix) prefix##suffix
+
+/* Macros to map replacement function names to their equivalent
+ * symbol names, for lookup in the MSVCRT export table.
+ */
+#define __api_name__(FUNCTION) __stringify__(FUNCTION)
+#define __stringify__(TEXT) #TEXT
+
+RTNTYPE __mingw_(FUNCTION)( ARGTYPE ARGLIST )
+{
+ /* Our generic interface maps an indirect call to the API...
+ */
+ static RTNTYPE (*api_helper)( ARGTYPE ARGLIST ) = NULL;
+
+ /* ...such that it will prefer an MSVCRT implementation...
+ */
+ if( (api_helper == NULL)
+ && ((api_helper = dlsym( RTLD_DEFAULT, __api_name__(FUNCTION) )) == NULL) )
+ /*
+ * ...but substituting our replacement, when necessary...
+ */
+ api_helper = __mingw_(__fallback_(FUNCTION));
+
+ /* ...and ultimately, invoking the selected API function.
+ */
+ return api_helper_result;
+}
+#endif
+
+/* $RCSfile$: end of file */
diff --git a/mingwrt/mingwex/stdio/pformat.c b/mingwrt/mingwex/stdio/pformat.c
index 5f8bbbb..c9dbf3e 100644
--- a/mingwrt/mingwex/stdio/pformat.c
+++ b/mingwrt/mingwex/stdio/pformat.c
@@ -149,38 +149,32 @@
* The following macro allows us to replicate this behaviour.
*/
# define PFORMAT_MINEXP __pformat_exponent_digits()
- /*
- * However, this feature is unsupported for versions of the
- * MSVC runtime library prior to msvcr80.dll, and by default,
- * MinGW uses an earlier version, (equivalent to msvcr60.dll),
- * for which `_TWO_DIGIT_EXPONENT' will be undefined.
- */
-# ifndef _TWO_DIGIT_EXPONENT
- /*
- * This hack works around the lack of the `_set_output_format()'
- * feature, when supporting versions of the MSVC runtime library
- * prior to msvcr80.dll; it simply enforces Microsoft's original
- * convention, for all cases where the feature is unsupported.
- */
-# define _get_output_format() 0
-# define _TWO_DIGIT_EXPONENT 1
-# endif
/*
- * Irrespective of the MSVCRT version supported, *we* will add
- * an additional capability, through the following inline function,
- * which will allow the user to choose his own preferred default
- * for `PRINTF_EXPONENT_DIGITS', through the simple expedient
- * of defining it as an environment variable.
+ * We note that Microsoft did not implement the _set_output_format()
+ * API capability until the release of MSVCR80.DLL, although they did
+ * subsequently retro-fit it to MSVCRT.DLL from Windows-Vista onward.
+ * To circumvent this API availability limitation, *we* offer two
+ * alternative options for controlling the facility:
+ *
+ * 1) We support the explicit assignment of the user's preference
+ * for `PRINTF_EXPONENT_DIGITS', through the simple expedient of
+ * defining it as an environment variable; this mechanism will
+ * take precedence over...
+ *
+ * 2) Emulation of _set_output_format(), through the use of inline
+ * functions defined in stdio.h, and supported regardless of the
+ * availability of the API within MSVCRT.DLL; this emulated API
+ * maintains state in the global `__mingw_output_format_flag'
+ * variable, (which users should consider to be private).
*/
+extern unsigned int __mingw_output_format_flag;
static __inline__ __attribute__((__always_inline__))
int __pformat_exponent_digits( void )
{
char *exponent_digits = getenv( "PRINTF_EXPONENT_DIGITS" );
return ((exponent_digits != NULL) && ((unsigned)(*exponent_digits - '0') < 3))
- || (_get_output_format() & _TWO_DIGIT_EXPONENT)
- ? 2
- : 3
- ;
+ || (__mingw_output_format_flag & _TWO_DIGIT_EXPONENT)
+ ? 2 : 3 ;
}
#else
/*
diff --git a/mingwrt/ofmt_stub.s b/mingwrt/ofmt_stub.s
deleted file mode 100644
index 81255b0..0000000
--- a/mingwrt/ofmt_stub.s
+++ /dev/null
@@ -1,40 +0,0 @@
-/* ofmt_stub.s
- *
- * $Id$
- *
- * A trivial stub, to replace the _get_output_format() function.
- *
- * _pformat() requires this function, which is provided by MSVCRT runtimes
- * from msvcr80.dll onwards; add this stub to the import libraries for earlier
- * versions of MSVCRT, (those which do not already advertise availability of
- * any exported _get_output_format() function); this will permit _pformat()
- * to transparently interoperate with all supported versions of MSVCRT.
- * (Likewise for CRTDLL).
- *
- * Written by Keith Marshall <kei...@us...>
- * Contributed to the MinGW Project, and hereby assigned to the public domain.
- *
- * This is free software. It is provided AS IS, in the hope that it may be
- * useful. There is NO WARRANTY OF ANY KIND, not even an implied warranty of
- * merchantability, nor of fitness for any particular purpose.
- *
- */
- .text
- .p2align 1,,4
-
-.globl __get_output_format
- .def __get_output_format; .scl 2; .type 32; .endef
-
-__get_output_format:
-/*
- * int _get_output_format( void );
- *
- * Implementation is trivial: we immediately return zero, thus matching the
- * default behaviour of Microsoft's own implementation, in the absence of any
- * preceding call to _set_output_format(); (if we are using this stub, then
- * that entire API is unsupported, so no such prior call is possible).
- */
- xorl %eax, %eax
- ret
-
-/* $RCSfile$$Revision$: end of file */
https://sf.net/p/mingw/mingw-org-wsl/ci/739d533acd49940efaf062a6ddbfb4a83526aed7/
commit 739d533acd49940efaf062a6ddbfb4a83526aed7
Author: Keith Marshall <kei...@us...>
Date: Sun Nov 16 18:35:19 2014 +0000
Do some more essential build tree clean up.
diff --git a/mingwrt/ChangeLog b/mingwrt/ChangeLog
index b909330..03d165c 100644
--- a/mingwrt/ChangeLog
+++ b/mingwrt/ChangeLog
@@ -1,3 +1,10 @@
+2014-11-16 Keith Marshall <kei...@us...>
+
+ Do some more essential build tree clean up.
+
+ * Makefile.in (mostly-clean-local): Add *.libimpl; matching files get
+ in the way of a successful rebuild from clean.
+
2014-11-11 Keith Marshall <kei...@us...>
Implement wrappers for emulation of POSIX dlfcn API.
diff --git a/mingwrt/Makefile.in b/mingwrt/Makefile.in
index ed7c9f9..1e10ec5 100644
--- a/mingwrt/Makefile.in
+++ b/mingwrt/Makefile.in
@@ -818,7 +818,7 @@ clean-local: mostlyclean-local
$(RM) msvcr*.def moldname*.def mingw*.def lib*.a *.dll
mostlyclean-local:
- $(RM) *.d *.$(OBJEXT) Makefile.stub
+ $(RM) *.d *.$(OBJEXT) Makefile.stub *.libimpl
distclean-local: clean-local
$(RM) config.log config.status libm_dummy.c
https://sf.net/p/mingw/mingw-org-wsl/ci/e974c5e23a4213c6c9e22c6c812501cf35e30cd9/
commit e974c5e23a4213c6c9e22c6c812501cf35e30cd9
Author: Keith Marshall <kei...@us...>
Date: Tue Nov 11 18:13:14 2014 +0000
Implement wrappers for emulation of POSIX dlfcn API.
diff --git a/mingwrt/ChangeLog b/mingwrt/ChangeLog
index 8406336..b909330 100644
--- a/mingwrt/ChangeLog
+++ b/mingwrt/ChangeLog
@@ -1,3 +1,25 @@
+2014-11-11 Keith Marshall <kei...@us...>
+
+ Implement wrappers for emulation of POSIX dlfcn API.
+
+ * include/dlfcn.h: New file; it declares the API.
+ * mingwex/dlfcn.c: New file; implement it, with access via...
+ (__mingw_dlfcn): ...this publicly addressable vector table.
+
+ * Makefile.in (dlfcn.$OBJEXT): Add build requisite.
+ (dlopen, dlsym, dlclose, dlerror): Build call stubs, using...
+ (__LIBIMPL__): ...this automatic interface generator; implement it.
+ (libstub_refnames): New macro; it is adapted from and replaces...
+ (jmpstub_refs): ...this; when it is then invoked twice to build...
+ (Makefile.stub): ...this, it handles both JMPSTUB and LIBIMPL.
+ (jmpstub_awk_script): Adapt it to work with 'libstub_refnames'.
+ (libimpl_awk_script): New inline script; it handles automated builds
+ of LIBIMPL interfaces, as 'jmpstub_awk_script' does for JMPSTUB.
+ (libimpl_sed_script): New inline script; it prepares intermediate C
+ source code for LIBIMPL interfaces, as required to satisfy these...
+ (%.libimpl, %.libimpl.$OBJEXT): ...new implicit build objectives.
+ (LIBIMPL_CFLAGS): New macro; define it.
+
2014-11-08 Keith Marshall <kei...@us...>
Move libgen functions to __mingw_ pseudo-namespace.
diff --git a/mingwrt/Makefile.in b/mingwrt/Makefile.in
index 3cdb394..ed7c9f9 100644
--- a/mingwrt/Makefile.in
+++ b/mingwrt/Makefile.in
@@ -464,7 +464,7 @@ libmingwex.a: $(addsuffix .$(OBJEXT), _Exit atoll lltoa lltow \
ulltoa ulltow wtoll)
libmingwex.a: gettimeofday.$(OBJEXT)
-libmingwex.a: $(addsuffix .$(OBJEXT), dirent wdirent)
+libmingwex.a: $(addsuffix .$(OBJEXT), dirent wdirent dlfcn)
libmingwex.a: $(addsuffix .$(OBJEXT), fwide mbrtowc mbsinit wcrtomb wcstof \
wcstold wctob wmemchr wmemcmp wmemcpy wmemmove wmemset)
@@ -490,21 +490,37 @@ $(addsuffix .$(OBJEXT), % %f %l): %_generic.c
$(addsuffix .$(OBJEXT), llround llroundf llroundl): %.$(OBJEXT): lround_generic.c
$(CC) -c -D FUNCTION=$* $(CPPFLAGS) $(ALL_CFLAGS) -o $@ $<
+# Historically, MinGW.org's libm.a has been a dummy, delivering
+# nothing of value; FIXME: IMO, this sucks; it should deliver the
+# non-MSVCRT.DLL math functions, as noted above.
+#
+all-mingwrt-libs install-mingwrt-libs: libm.a
+libm.a: libm_dummy.$(OBJEXT)
+libm_dummy.c: Makefile
+ echo "static int __mingw_libm_dummy;" > $@
+
# The mingwrt headers define a number of functions which are normally
# expected to be compiled as inline code. Each such function must also
# be provided with an externally visible entry point; we provide such
# entry points as stubs in libmingwex.a, via the following rules:
#
sinclude Makefile.stub
-jmpstub_refs = grep -lr '__JMPSTUB.*FUNCTION'
-jmpstub_prerequisites := $(shell $(jmpstub_refs) ${mingwrt_srcdir}/include)
-Makefile.stub: Makefile $(jmpstub_prerequisites)
+vpath jmpstub.sx ${mingwrt_srcdir}/mingwex
+libstub_refnames = grep -lr '__$1.*FUNCTION *=' ${mingwrt_srcdir}
+jmpstub_prerequisites := $(shell $(call libstub_refnames,JMPSTUB)/include)
+libimpl_prerequisites := $(shell $(call libstub_refnames,LIBIMPL)/include)
+Makefile.stub: Makefile $(jmpstub_prerequisites) $(libimpl_prerequisites)
echo "# $@: automatically generated file -- do not edit!" > $@
- $(jmpstub_awk_script) $(jmpstub_prerequisites) >> $@
+ $(call jmpstub_awk_script,$(jmpstub_prerequisites)) >> $@
+ $(call libimpl_awk_script,$(libimpl_prerequisites)) >> $@
echo "# $@: end of file" >> $@
-vpath jmpstub.sx ${mingwrt_srcdir}/mingwex
-jmpstub_awk_script = test "$^" = Makefile || awk '\
+# Stubs are categorized into either of JMPSTUB or LIBIMPL classes;
+# the rules for building the JMPSTUP inplementations are written to
+# Makefile.stub, by processing each of their defining header files
+# through the following awk script...
+#
+jmpstub_awk_script = test -z "$1" || awk '\
BEGIN { \
symbol = "([A-Z_a-z][A-Z_a-z0-9]*)"; \
fmt = "\nlib%s.a: %s\n%s: jmpstub.sx\n\t$$(COMPILE.sx) %s -o $$@ $$^\n"; \
@@ -512,22 +528,60 @@ jmpstub_awk_script = test "$^" = Makefile || awk '\
/__JMPSTUB(__)? *[(].*FUNCTION/ { \
LIB = "mingwex"; \
FUNCTION = gensub( ".*[ ,(:]FUNCTION *= *"symbol".*", "\\1", 1 ); \
- OBJNAME = gensub( "_*(.*)_*", "\\1", 1, FUNCTION )".stub.$$(OBJEXT)"; \
+ OBJNAME = gensub( "_*(.*)_*", "\\1", 1, FUNCTION )".jmpstub.$$(OBJEXT)"; \
OBJNAME_CFLAGS = "-D FUNCTION="FUNCTION; \
printf fmt, LIB, OBJNAME, OBJNAME, OBJNAME_CFLAGS; \
} \
END { \
printf "\n"; \
- }'
+ }' $1
-all-mingwrt-libs install-mingwrt-libs: libm.a
-# Historically, MinGW.org's libm.a has been a dummy, delivering
-# nothing of value; FIXME: IMO, this sucks; it should deliver the
-# non-MSVCRT.DLL math functions, as noted above.
+# ...while this establishes the dependencies which apply for each
+# of those in the LIBIMPL class.
#
-libm.a: libm_dummy.$(OBJEXT)
-libm_dummy.c: Makefile
- echo "static int __mingw_libm_dummy;" > $@
+libimpl_awk_script = test -z "$1" || awk '\
+ BEGIN { \
+ symbol = "([A-Z_a-z][A-Z_a-z0-9]*)"; \
+ fmt = "\nlib%s.a: %s\n%s.libimpl: %s\n"; \
+ } \
+ /__LIBIMPL(__)? *[(].*FUNCTION/ { \
+ LIB = "mingwex"; \
+ FUNCTION = gensub( ".*[ ,(:]FUNCTION *= *"symbol".*", "\\1", 1 ); \
+ OBJNAME = gensub( "_*(.*)_*", "\\1", 1, FUNCTION )".libimpl.$$(OBJEXT)"; \
+ printf fmt, LIB, OBJNAME, FUNCTION, FILENAME; \
+ } \
+ END { \
+ printf "\n"; \
+ }' $1
+
+# In contrast to JMPSTUB implementations, which are best handled
+# by individual compilation rules in Makefile.stub, generic rules
+# are sufficient for all LIBIMPL implementations; in each case, we
+# filter the static attribute from each defined implementation, in
+# its defining header file, to create an intermediate C source for
+# each individual function; (note that we also remove any pragma
+# which identifies the originating file as a system header).
+#
+libimpl_sed_script = sed \
+ -e '/__CRT_ALIAS *__LIBIMPL.*FUNCTION *= *$1[ ,)].*)/d' \
+ -e '/pragma .* system_header/d'
+
+LIBIMPL_CFLAGS = $(CFLAGS) $(INCLUDES) -fno-align-functions
+
+# LIBIMPL dependencies are tracked using zero sized name.libimpl
+# files; the intermediate C files are generated as a side effect
+# of resolving these dependencies...
+#
+%.libimpl:
+ $(call libimpl_sed_script,$*) $< > $@.c
+ > $@
+
+# ...and ultimately discarded, after the requisite object file
+# has been compiled.
+#
+%.libimpl.$(OBJEXT): %.libimpl
+ $(CC) -c $(CPPFLAGS) $(LIBIMPL_CFLAGS) -o $@ $<.c
+ $(RM) $<.c
# Thread support libraries.
#
diff --git a/mingwrt/include/dlfcn.h b/mingwrt/include/dlfcn.h
new file mode 100644
index 0000000..3653579
--- /dev/null
+++ b/mingwrt/include/dlfcn.h
@@ -0,0 +1,94 @@
+/*
+ * dlfcn.h
+ *
+ * Public interface declarations for (approximately) POSIX conforming
+ * dlopen(), dlsym(), dlclose(), and dlerror() API functions.
+ *
+ * $Id$
+ *
+ * Written by Keith Marshall <kei...@us...>
+ * Copyright (C) 2014, 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 _DLFCN_H
+#define _DLFCN_H 1
+#pragma GCC system_header
+
+#include <_mingw.h>
+
+/* POSIX requires the following four definitions. Our implementation
+ * (currently) does not support the behaviour associated with RTLD_LAZY;
+ * if specified, it is simply ignored; RTLD_NOW behaviour will prevail.
+ */
+#define RTLD_NOW 0
+#define RTLD_LAZY 1
+#define RTLD_GLOBAL 2
+#define RTLD_LOCAL 4
+
+/* POSIX does not yet require the following pair, but reserves them for
+ * future capabilities; they will be used in contexts where a DLL module
+ * handle is expected, so we reserve values of suitable type, which are
+ * unlikely to ever occur as real module handles in practice.
+ */
+#define RTLD_DEFAULT (void *)(-1)
+#define RTLD_NEXT (void *)(-3)
+
+/* The four dlfcn API functions, dlopen(), dlsym(), dlerror(), and dlclose(),
+ * are each defined privately, and made publicly accessible via corresponding
+ * function pointers, within the following publicly visible structure.
+ */
+_EXTERN_C struct __dlfcn__
+{ void *(*dlopen)( const char *, int );
+ void *(*dlsym)( void *__restrict__, const char *__restrict__ );
+ char *(*dlerror)( void );
+ int (*dlclose)( void * );
+} __mingw_dlfcn;
+
+/* Declare the public API for each of these functions...
+ */
+_BEGIN_C_DECLS
+
+/* In any event, we always declare prototypes for all four functions.
+ */
+void * dlopen( const char *, int );
+void * dlsym( void *__restrict__, const char *__restrict__ );
+int dlclose( void * );
+char * dlerror( void );
+
+__CRT_ALIAS __LIBIMPL__(( FUNCTION = dlopen ))
+void *dlopen( const char *__name, int __mode )
+{ return __mingw_dlfcn.dlopen( __name, __mode ); }
+
+__CRT_ALIAS __LIBIMPL__(( FUNCTION = dlsym ))
+void *dlsym( void *__restrict__ __module, const char *__restrict__ __name )
+{ return __mingw_dlfcn.dlsym( __module, __name ); }
+
+__CRT_ALIAS __LIBIMPL__(( FUNCTION = dlclose ))
+int dlclose( void *__module ){ return __mingw_dlfcn.dlclose( __module ); }
+
+__CRT_ALIAS __LIBIMPL__(( FUNCTION = dlerror ))
+char *dlerror( void ){ return __mingw_dlfcn.dlerror(); }
+
+_END_C_DECLS
+
+#endif /* _DLFCN_H: $RCSfile$: end of file */
diff --git a/mingwrt/mingwex/dlfcn.c b/mingwrt/mingwex/dlfcn.c
new file mode 100644
index 0000000..59dbda2
--- /dev/null
+++ b/mingwrt/mingwex/dlfcn.c
@@ -0,0 +1,722 @@
+/*
+ * dlfcn.c
+ *
+ * Core implementation for (approximately) POSIX conforming dlopen(),
+ * dlsym(), dlclose(), and dlerror() API functions.
+ *
+ * $Id$
+ *
+ * Written by Keith Marshall <kei...@us...>
+ * Copyright (C) 2014, 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.
+ *
+ *
+ * This source file implements the core functionality for each of the POSIX
+ * dynamic loader API functions, dlopen(), dlsym(), dlclose(), and dlerror();
+ * each is implemented such that it is conveniently accessed via a macro, or
+ * an inline function representation, by way of a publicly visible table of
+ * entry point vectors (i.e. function pointers).
+ *
+ */
+#include <dlfcn.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <limits.h>
+
+/* In addition to normal C runtime services, this implementation requires
+ * the use of the MS-Windows API; the light-weight subset will suffice...
+ */
+#define WIN32_LEAN_AND_MEAN
+/*
+ * ...while accessing it throught its standard interface.
+ */
+#include <windows.h>
+
+/* In addition to the POSIX constants which are defined in dlfcn.h,
+ * we also define some private manifest constants, which POSIX does
+ * not specify, but which facilitate our implementation:
+ *
+ * RTLD_EXPLICIT, used to qualify RTLD_GLOBAL modules which have
+ * been explicitly loaded by dlopen(), so an RTLD_DEFAULT search
+ * need not consider them.
+ */
+# define RTLD_EXPLICIT 16
+/*
+ * RTLD_ALL_GLOBAL, returned by dlopen() when the module name is
+ * given as a NULL pointer; this is a fake module handle, similar
+ * to RTLD_DEFAULT and RTLD_NEXT, representing the corpus of all
+ * RTLD_GLOBAL modules, both implicitly and explicitly loaded.
+ */
+# define RTLD_ALL_GLOBAL (void *)(-5)
+
+/* Before anything else, ensure that the dlerror() implementation
+ * is in place, so that other components may access it freely.
+ *
+ * We provide TWO reference pointers for error message buffering, so
+ * that we may continue to hold a reference to allocated memory, even
+ * after dlerror() has discarded the pointer to a pending message;
+ * initially, we mark both as unassigned.
+ */
+static char *dlfcn_error_pending = NULL;
+static char *dlfcn_error_message = NULL;
+
+static void dlfcn_store_error_message( const char *fmt, ... )
+{
+ /* This private function provides printf() style formatting for
+ * dlfcn error messages, storing them into dynamically allocated
+ * memory, and updating both reference pointers for subsequent
+ * retrieval by the dlerror() accessor function.
+ */
+ int msglen;
+ va_list argv;
+ va_start( argv, fmt );
+ msglen = 1 + vsnprintf( NULL, 0, fmt, argv );
+ if( (dlfcn_error_pending = realloc( dlfcn_error_message, msglen )) != NULL )
+ /*
+ * Store message, only if a buffer was successfully allocated.
+ */
+ vsnprintf( dlfcn_error_pending, msglen, fmt, argv );
+ dlfcn_error_message = dlfcn_error_pending;
+ va_end( argv );
+}
+
+static char *dlfcn_strerror( int errcode )
+{
+ /* This private function emulates strerror(), but substitutes an
+ * errcode obtained from GetLastError() for errno.
+ */
+ char *text;
+ uint32_t description = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER
+ | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
+ errcode, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), (char *)(&text),
+ 0, NULL
+ );
+ if( description )
+ {
+ /* We successfully obtained an error description; POSIX insists
+ * that it must not be encoded with any terminating newline.
+ */
+ char *tmp = text + strlen( text );
+ while( (*--tmp == '\n') || (*tmp == '\r') ) *tmp = '\0';
+
+ /* Ensure that we consistently return the error description in
+ * a buffer which may be released by the free() function, (since
+ * we cannot be sure that LocalFree() is compatible).
+ */
+ text = strdup( tmp = text );
+ LocalFree( tmp );
+ }
+ else
+ { /* We were unable to find an error description; substitute a
+ * formatted reference to the unknown error code.
+ */
+ char *fmt = "Unknown error %d";
+ char tmp[1 + snprintf( NULL, 0, fmt, errcode )];
+ snprintf( tmp, sizeof( tmp ), fmt, errcode );
+ text = strdup( tmp );
+ }
+ /* However we derived it, the error description is now available
+ * in a dynamically allocated text buffer which may be released
+ * by calling free().
+ */
+ return text;
+}
+
+static char *dlerror_internal( void )
+{
+ /* This is the internal implementation of the public dlerror() API.
+ * POSIX does not require this to be thread safe, so we take no care
+ * to make it such.
+ */
+ if( (dlfcn_error_pending == NULL) && (dlfcn_error_message != NULL) )
+ {
+ /* There is no pending message, but a buffer remains allocated
+ * to one which has already been retrieved; we may release it.
+ */
+ free( dlfcn_error_message );
+ dlfcn_error_message = NULL;
+ }
+ /* Mark any pending error message as "retrieved"...
+ */
+ dlfcn_error_pending = NULL;
+ /*
+ * ...and return it.
+ */
+ return dlfcn_error_message;
+}
+
+typedef
+/* A pointer type, representing a reference to a function for
+ * retrieving exported symbol references from any loaded module.
+ */
+int WINAPI (*lookup_fn)( HANDLE, HMODULE *, uint32_t, uint32_t * );
+
+/* POSIX requires that dlsym() be able to look up symbol references
+ * for any dynamically loaded module within the address space of the
+ * calling process, including those which have been implicitly loaded
+ * at process start-up. To facilitate this, we will use Microsoft's
+ * PSAPI.DLL services, to enumerate such implicitly loaded modules,
+ * before we explicitly load any using dlopen(), or we perform any
+ * look-up using dlsym() itself.
+ */
+static struct
+{ /* Structure providing a convenient encapsulation of the PSAPI.DLL
+ * interface, which may itself need to be explicitly loaded.
+ */
+ HMODULE dll;
+ const char *dll_name;
+ const char *lookup_fn_name;
+ lookup_fn lookup;
+}
+psapi = { NULL, "psapi.dll", "EnumProcessModules", NULL };
+
+/* The two NULL fields, within the preceding structure, must be
+ * initialized before use; the following pair of inline functions
+ * facilitate this, with the first looking up the API entry...
+ */
+static __inline__ lookup_fn psapi_lookup_fn( HMODULE provider )
+{ return (lookup_fn)(GetProcAddress( provider, psapi.lookup_fn_name )); }
+
+/* ...when called from within the second, which both ensures that
+ * PSAPI.DLL is loaded, and assigns the requisite field values.
+ */
+static __inline__ lookup_fn psapi_lookup_fn_init( void )
+{ return psapi.lookup = ((psapi.dll = LoadLibrary( psapi.dll_name )) != NULL)
+ ? psapi_lookup_fn( psapi.dll ) : NULL;
+}
+
+/* After the PSAPI.DLL interface has been initialized, by calling
+ * the preceding function, we may call the following inline helper
+ * to retrieve a list of module handles...
+ */
+static __inline__ unsigned int psapi_enum_modules( HMODULE **modules )
+{
+ /* ...focussing on modules which are currently loaded within
+ * the address space of the current process.
+ */
+ HANDLE me = GetCurrentProcess();
+
+ /* We will dynamically allocate memory to store the handles;
+ * initially we request zero bytes of storage to receive them,
+ * then we use a while loop, which should execute exactly twice,
+ * to retrieve them; on the first pass, we determine the actual
+ * memory requirement and allocate it; on the second, we store
+ * the list of module handles into it...
+ */
+ uint32_t wanted, request = 0;
+ while( psapi.lookup( me, *modules, request, &wanted ) && (wanted > request) )
+ if( (*modules = realloc( *modules, request = wanted )) == NULL )
+ {
+ /* ...trying to record an appropriate diagnostic message on
+ * failure, (but noting that failure is likely to result from
+ * insufficient memory, so there may not be enough to record
+ * the message either)...
+ */
+ char *reason = dlfcn_strerror( ERROR_OUTOFMEMORY );
+ dlfcn_store_error_message( "dlfcn_init:enum_modules: %s", reason );
+ free( reason );
+ }
+ /* ...before ultimately returning the number retrieved.
+ */
+ return wanted / sizeof( HMODULE );
+}
+
+typedef struct dltab
+{
+ /* Structure used to map module handle references, and associated
+ * status, into the global modules list.
+ */
+ unsigned int slots;
+ unsigned char *flags;
+ HMODULE *modules;
+} dltab;
+
+/* The global modules list itself, initially empty, but suitable
+ * for reallocation on the heap.
+ */
+static dltab rtld = { 0, NULL, NULL };
+
+/* Microsoft's LoadLibrary() API is explicitly documented as being
+ * unable to handle regular slashes as directory separators in module
+ * path names, (in spite of their validity elsewhere), thus...
+ */
+static __inline__ wchar_t *normalized_form( wchar_t *pathname )
+{
+ /* ...we provide this helper, to replace them with backslashes.
+ */
+ wchar_t *scan = pathname;
+ do { if( *scan == L'/' ) *scan = L'\\'; } while( *scan++ != L'\0' );
+ return pathname;
+}
+
+static void dlopen_store_error_message( const char *name, unsigned status )
+{
+ /* A convenience helper, to record diagnostic messages to explain
+ * causes of failure encountered when calling dlopen().
+ */
+ char *reason = dlfcn_strerror( status );
+ dlfcn_store_error_message( "dlopen:'%s': %s", name, reason );
+ free( reason );
+}
+
+static void *dlopen_internal( const char *name, int mode )
+{
+ /* This is the formal implementation of the public dlopen() function;
+ * note that this (currently) ignores the RTLD_LAZY loading option, and
+ * processes each request as if specified as RTLD_NOW.
+ */
+ if( name == NULL )
+ /* POSIX specifies this as a special case, requiring us to return
+ * a handle, through which all symbols exported by all modules which
+ * are currently loaded with the RTLD_GLOBAL attribute, (explicitly
+ * or implicitly), would be accessible.
+ */
+ return RTLD_ALL_GLOBAL;
+
+ /* We will use LoadLibrary() to obtain a handle for the dlopen()ed
+ * module; Microsoft advise us that we should ensure that we always
+ * use backslashes, and to avoid use of POSIX compatible slashes, in
+ * any path name passed to this function. To ensure this, the name
+ * argument should be normalized, (working in the UTF-16LE domain,
+ * to avoid inadvertent transformation of trail bytes within MBC
+ * sequences), to transform slashes accordingly.
+ */
+ size_t buflen; wchar_t internal_name[buflen = 1 + strlen( name )];
+ MultiByteToWideChar( CP_ACP, 0, name, -1, internal_name, buflen );
+
+ /* Now, we may safely call LoadLibrary(), to obtain a module handle.
+ */
+ void *module = LoadLibraryW( normalized_form( internal_name ) );
+ if( module == NULL )
+ {
+ /* The named module could not be opened; record an appropriate
+ * error message for retrieval by dlerror().
+ */
+ dlopen_store_error_message( name, GetLastError() );
+ }
+ else
+ { /* We got a handle for the requested module; we need to ensure
+ * that it is allocated a slot in our global symbol table, but we
+ * must first check that it isn't already present.
+ */
+ int index, insertion_point = rtld.slots;
+ for( index = 0; index < rtld.slots; index++ )
+ {
+ /* As we scan the list of already loaded modules, check for any
+ * existing slot which may be vacant...
+ */
+ if( rtld.flags[index] == 0 )
+ {
+ /* ...marking the first available, if any, as a candidate for
+ * possible insertion of a new entry.
+ */
+ if( index < insertion_point )
+ insertion_point = index;
+ }
+ else if( module == rtld.modules[index] )
+ {
+ /* The requested module appears to be loaded already; calling
+ * LoadLibrary() will have increased its reference count, but
+ * our management strategy doesn't require this; reduce it...
+ */
+ FreeLibrary( module );
+ /*
+ * ...but promote its existing status to RTLD_GLOBAL, if that
+ * is indicated as required by the requested mode...
+ */
+ rtld.flags[index] |= mode & RTLD_GLOBAL;
+ /*
+ * ...and immediately return the module handle.
+ */
+ return module;
+ }
+ }
+ /* If we get to here, there is no entry for the requested module,
+ * within the global modules list; we must add it now, either using
+ * an existing vacant slot, if there is one...
+ */
+ if( insertion_point < rtld.slots )
+ {
+ /* ...but noting that we cannot simply insert a new reference
+ * within it, since that would disrupt the order in which modules
+ * are subsequently searched, and POSIX requires that this is to
+ * preserve loading order, (strictly, symbol resolution order),
+ * when searching RTLD_GLOBAL modules, (and since any module may
+ * be promoted to RTLD_GLOBAL status, even after it was originally
+ * loaded as RTLD_LOCAL, this means that we must preserve loading
+ * order for ALL active modules). Thus, we must pack the list of
+ * active modules after the nominated insertion point...
+ */
+ index = insertion_point;
+
+ /* ...after which, the first vacant slot will have been relocated
+ * to follow all active slots, and we may adjust the nominated
+ * insertion point accordingly.
+ */
+ do { /* First, we identify the first slot following the nominated
+ * insertion point, which is NOT vacant.
+ */
+ while( (index < rtld.slots) && (rtld.flags[index] == 0) )
+ ++index;
+
+ /* Now, we move that non-vacant slot, and any which follow
+ * it, upwards in the list, to fill vacant slots...
+ */
+ while( (index < rtld.slots) && (rtld.flags[index] != 0) )
+ {
+ /* ...by simply copying content from the non-vacant slots
+ * to overwrite content in the preceding slots...
+ */
+ rtld.modules[insertion_point] = rtld.modules[index];
+ rtld.flags[insertion_point++] = rtld.flags[index++];
+ }
+ /* ...repeating the entire procedure, until all vacant slots
+ * have been filled, and the nominated insertion point has
+ * been moved to follow the last relocated non-vacant entry.
+ */
+ } while( index < rtld.slots );
+
+ /* After packing, any already allocated slots after and including
+ * the relocated insertion point MUST be vacant; ensure that they
+ * are marked accordingly.
+ */
+ for( index = insertion_point; index < rtld.slots; index++ )
+ rtld.flags[index] = 0;
+ }
+ else
+ { /* There is no vacant slot: we must expand the allocated memory
+ * pool to create one; first increment the modules list size...
+ */
+ size_t slots = 1 + rtld.slots;
+ HMODULE *modules = rtld.modules;
+ if( (modules = realloc( modules, sizeof( HMODULE ) * slots )) != NULL )
+ {
+ /* ...and, having sucessfully increased the modules list memory
+ * allocation, do likewise for the associated flags...
+ */
+ unsigned char *flags = rtld.flags;
+ if( (flags = realloc( flags, slots )) != NULL )
+ /*
+ * ...initializing the new flags register, and incrementing
+ * the slots count, when that is also successful.
+ */
+ (rtld.flags = flags)[rtld.slots++] = 0;
+
+ /* Regardless of the success, or otherwise, of the flags memory
+ * adjustment, the modules list was reallocated, so we need to
+ * adjust its reference pointer accordingly.
+ */
+ rtld.modules = modules;
+ }
+ /* Before proceeding further, verify that the new slot has been
+ * fully created, and is ready to store the module data...
+ */
+ if( insertion_point == rtld.slots )
+ {
+ /* ...but if allocation failed, the nominated insertion point
+ * will lie beyond the available space, so we MUST fail, after
+ * discarding the now unreferenced module handle, and trying to
+ * record an appropriate diagnostic message, (but we note that
+ * this may also fail, due to insufficient memory).
+ */
+ FreeLibrary( module );
+ dlopen_store_error_message( name, ERROR_OUTOFMEMORY );
+ return NULL;
+ }
+ }
+ /* When we get to here, we now have a suitable slot in which to add
+ * the reference data for the newly dlopen()ed module, (either by
+ * allocation of a new slot, or by relocation of an existing vacant
+ * slot); we may safely store the appropriate reference data.
+ */
+ rtld.flags[insertion_point] = RTLD_EXPLICIT | mode;
+ rtld.modules[insertion_point] = module;
+ }
+ /* Finally, we return whatever module handle we got from LoadLibrary(),
+ * (which may be NULL, if this failed).
+ */
+ return module;
+}
+
+static void *dlsym_internal( void *module, const char *name )
+{
+ /* This is the formal implementation of the public dlsym() function.
+ */
+ static unsigned int index = 0;
+ static const char *last_named_symbol = NULL;
+ static unsigned char rtld_exclude = 0;
+ void *rtn;
+
+ if( module == RTLD_NEXT )
+ {
+ /* NOTE: We MUST identify this special case BEFORE any other!
+ *
+ * POSIX doesn't require this to be supported yet, but reserves it
+ * for future use; it should cause dlsym() to repeat its search for
+ * the named symbol, (provided it remains the same as last named in
+ * a global search), continuing from the next module in the current
+ * search order, following that in which the symbol was previously
+ * found; (this permits us to locate symbols which may defined in
+ * more than one loaded module).
+ */
+ index = (name == last_named_symbol) ? index + 1 : 0;
+ module = RTLD_ALL_GLOBAL;
+ }
+ else if( module == RTLD_DEFAULT )
+ {
+ /* NOTE: We MUST keep this AFTER the check for RTLD_NEXT!
+ *
+ * Once again, POSIX doesn't require this to be supported yet, but
+ * reserves it for future use to search for symbols which could have
+ * been found within the process address space prior to any explicit
+ * dlopen() call; this capability may be supported by searching all
+ * modules in the address space, (i.e. equivalent to a search with
+ * module == RTLD_ALL_GLOBAL), excluding those which have been
+ * explicitly loaded since process start-up.
+ */
+ module = RTLD_ALL_GLOBAL;
+ rtld_exclude = RTLD_EXPLICIT;
+ index = 0;
+ }
+ else
+ /* Neither RTLD_DEFAULT, nor RTLD_NEXT was specified; we must reset
+ * the RTLD_GLOBAL search index, and cancel all search exclusions.
+ */
+ index = rtld_exclude = 0;
+
+ if( module == RTLD_ALL_GLOBAL )
+ {
+ /* The RTLD_ALL_GLOBAL module reference represents a request to
+ * perform an in-order traversal of all modules within the process
+ * address space, either implicitly loaded, or explicitly loaded
+ * with the RTLD_GLOBAL mode attribute, either until the named
+ * symbol is found, or all such modules have been searched
+ * without finding it.
+ */
+ for( rtn = NULL; (rtn == NULL) && (index < rtld.slots); index++ )
+ if( ((rtld_exclude & rtld.flags[index]) == 0)
+ && ((rtld.flags[index] & RTLD_GLOBAL) == RTLD_GLOBAL) )
+ rtn = GetProcAddress( rtld.modules[index], name );
+
+ /* Note the symbol named in the current search, so that we may
+ * check for consistency in the event that the next search is
+ * invoked as an RTLD_NEXT request.
+ */
+ last_named_symbol = name;
+ }
+ else
+ { /* When a specific module reference is specified, confine the
+ * search to the specified module alone...
+ */
+ rtn = GetProcAddress( (HMODULE)(module), name );
+
+ /* ...and inhibit any attempt to follow this search with one
+ * specifying RTLD_NEXT; (this would not be valid, since there
+ * is no concept of a "next" module to be searched, when not
+ * searching through an ordered list of modules).
+ */
+ last_named_symbol = NULL;
+ }
+
+ if( rtn == NULL )
+ {
+ /* The named symbol was not found in any module which was searched;
+ * record the appropriate error message for retrieval by dlerror().
+ */
+ char *reason = dlfcn_strerror( GetLastError() );
+ dlfcn_store_error_message( "dlsym:'%s': %s", name, reason );
+ free( reason );
+ }
+
+ /* Return the symbol address, as assigned to the return value;
+ * (this will be NULL, if the named symbol was not found).
+ */
+ return rtn;
+}
+
+static int dlclose_store_error_message( int status )
+{
+ /* A private helper function to record an appropriate dlerror()
+ * message, on failure of dlclose().
+ */
+ char *reason = dlfcn_strerror( status = GetLastError() );
+ dlfcn_store_error_message( "dlclose: %s", reason );
+ free( reason );
+ return status;
+}
+
+static __inline__ int dlclose_internal_check_for_error( int status )
+{
+ /* A private helper function to set the return status for dlclose(),
+ * while also recording a dlerror() message, when status is "failed".
+ */
+ return (status == 0) ? dlclose_store_error_message( status ) : 0;
+}
+
+static int dlclose_internal( void *module )
+{
+ /* This is the formal implementation of the public dlclose() function;
+ * it will call Microsoft's FreeLibrary() function passing the specified
+ * module handle, provided this is listed in the global module table as
+ * having been explicitly opened by our dlopen() function.
+ */
+ int index;
+ for( index = 0; index < rtld.slots; index++ )
+ if( module == rtld.modules[index] )
+ {
+ /* The specified module handle is present in the global modules list;
+ * while we could simply call FreeLibrary() immediately, it may not be
+ * prudent to do so in respect of implicitly loaded modules, but for
+ * those which we have explicitly loaded...
+ */
+ if( ((rtld.flags[index] & RTLD_EXPLICIT) == RTLD_EXPLICIT)
+ /*
+ * ...and which can be successfully released by FreeLibrary()...
+ */
+ && (dlclose_internal_check_for_error( FreeLibrary( module )) == 0) )
+ /*
+ * ...we mark them as no longer available for dlsym() processing,
+ * and return immediately, indicating success...
+ */
+ return rtld.flags[index] = 0;
+
+ /* ...but when we didn't successfully release the module, we have
+ * no need to continue the search for its handle in the global list
+ * of modules, (because we've already found it); we may immediately
+ * abandon the search.
+ */
+ break;
+ }
+
+ /* If we get to here, we either didn't find the specified module handle in
+ * the global list of modules, or we found it but were unable to release
+ * it; in either case, we force a module error condition.
+ */
+ return dlclose_store_error_message( FreeLibrary( NULL ) );
+}
+
+static void dlfcn_init( void )
+{
+ /* This private initialization function must be called, as a
+ * prerequisite to the first use of either dlopen() or dlsym()
+ * in any process; it uses Microsoft's PSAPI.DLL interface to
+ * enumerate the implicitly loaded process modules, so that
+ * they may be searched implicitly...
[truncated message content] |
|
From: Keith M. <no...@so...> - 2014-11-09 00:16:53
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Repository: mingw-org-wsl".
The branch, legacy has been updated
via 9a09e9224a0229440fd7b4fb5210941e80ad7a1d (commit)
from 2b1bc3a0746e63a16f545bc1495720c5681a29c6 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
https://sf.net/p/mingw/mingw-org-wsl/ci/9a09e9224a0229440fd7b4fb5210941e80ad7a1d/
commit 9a09e9224a0229440fd7b4fb5210941e80ad7a1d
Author: Keith Marshall <kei...@us...>
Date: Sat Nov 8 23:54:51 2014 +0000
Move libgen functions to __mingw_ pseudo-namespace.
diff --git a/mingwrt/ChangeLog b/mingwrt/ChangeLog
index 26cc709..8406336 100644
--- a/mingwrt/ChangeLog
+++ b/mingwrt/ChangeLog
@@ -1,5 +1,20 @@
2014-11-08 Keith Marshall <kei...@us...>
+ Move libgen functions to __mingw_ pseudo-namespace.
+
+ * mingwex/dirname.c (dirname): Rename function, as implemented...
+ (__mingwex_dirname): ...to this.
+
+ * mingwex/basename.c (basename): Rename function, as implemented...
+ (__mingwex_basename): ...to this.
+
+ * include/libgen.h (__mingw_dirname, __mingw_basename): Declare
+ prototypes, matching and augmenting original declarations for...
+ (dirname, basename): ...these; reimplement as inline aliases, with
+ __JMPSTUB__ references to the renamed implementation entry points.
+
+2014-11-08 Keith Marshall <kei...@us...>
+
Implement new command line argument globbing strategy.
* include/_mingw.h: Backport feature defines from master...
diff --git a/mingwrt/include/libgen.h b/mingwrt/include/libgen.h
index a731559..bd287ce 100644
--- a/mingwrt/include/libgen.h
+++ b/mingwrt/include/libgen.h
@@ -2,13 +2,32 @@
/*
* libgen.h
*
+ * Functions for splitting pathnames into dirname and basename components.
+ *
* $Id$
*
- * This file has no copyright assigned and is placed in the Public Domain.
- * This file is a part of the mingw-runtime package.
- * No warranty is given; refer to the file DISCLAIMER within the package.
+ * Written by Keith Marshall <kei...@us...>
+ * Copyright (C) 2006, 2007, 2014, MinGW.org Project
*
- * Functions for splitting pathnames into dirname and basename components.
+ *
+ * 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.
*
*/
#define _LIBGEN_H_
@@ -16,16 +35,20 @@
/* All the headers include this file. */
#include <_mingw.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
+_BEGIN_C_DECLS
extern __cdecl __MINGW_NOTHROW char *basename (char *);
extern __cdecl __MINGW_NOTHROW char *dirname (char *);
-#ifdef __cplusplus
-}
-#endif
+extern __cdecl __MINGW_NOTHROW char *__mingw_basename (char *);
+extern __cdecl __MINGW_NOTHROW char *__mingw_dirname (char *);
-#endif /* _LIBGEN_H_: end of file */
+__CRT_ALIAS __JMPSTUB__(( FUNCTION = basename ))
+__cdecl char *basename (char *__path){ return __mingw_basename (__path); }
+
+__CRT_ALIAS __JMPSTUB__(( FUNCTION = dirname ))
+__cdecl char *dirname (char *__path){ return __mingw_dirname (__path); }
+_END_C_DECLS
+
+#endif /* _LIBGEN_H_: end of file */
diff --git a/mingwrt/mingwex/basename.c b/mingwrt/mingwex/basename.c
index 7f1adc9..859a615 100644
--- a/mingwrt/mingwex/basename.c
+++ b/mingwrt/mingwex/basename.c
@@ -1,24 +1,35 @@
/* basename.c
*
- * $Id$
- *
* Provides an implementation of the "basename" function, conforming
* to SUSv3, with extensions to accommodate Win32 drive designators,
* and suitable for use on native Microsoft(R) Win32 platforms.
*
+ * $Id$
+ *
* Written by Keith Marshall <kei...@us...>
+ * Copyright (C) 2006, 2007, 2014, MinGW.org Project
*
- * This is free software. You may redistribute and/or modify it as you
- * see fit, without restriction of copyright.
*
- * This software is provided "as is", in the hope that it may be useful,
- * but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of
- * MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no
- * time will the author accept any form of liability for any damages,
- * however caused, resulting from the use of this software.
+ * 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.
*
*/
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -29,7 +40,7 @@
#define __cdecl /* this may not be defined. */
#endif
-__cdecl char *basename( char *path )
+__cdecl char *__mingw_basename( char *path )
{
size_t len;
static char *retfail = NULL;
diff --git a/mingwrt/mingwex/dirname.c b/mingwrt/mingwex/dirname.c
index 52c11d3..f94cee4 100644
--- a/mingwrt/mingwex/dirname.c
+++ b/mingwrt/mingwex/dirname.c
@@ -1,24 +1,35 @@
/* dirname.c
*
- * $Id$
- *
* Provides an implementation of the "dirname" function, conforming
* to SUSv3, with extensions to accommodate Win32 drive designators,
* and suitable for use on native Microsoft(R) Win32 platforms.
*
+ * $Id$
+ *
* Written by Keith Marshall <kei...@us...>
+ * Copyright (C) 2006, 2007, 2014, MinGW.org Project
*
- * This is free software. You may redistribute and/or modify it as you
- * see fit, without restriction of copyright.
*
- * This software is provided "as is", in the hope that it may be useful,
- * but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of
- * MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no
- * time will the author accept any form of liability for any damages,
- * however caused, resulting from the use of this software.
+ * 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.
*
*/
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -29,7 +40,7 @@
#define __cdecl /* this may not be defined. */
#endif
-__cdecl char *dirname( char *path )
+__cdecl char *__mingw_dirname( char *path )
{
size_t len;
static char *retfail = NULL;
-----------------------------------------------------------------------
Summary of changes:
mingwrt/ChangeLog | 15 ++++++++++++++
mingwrt/include/libgen.h | 45 +++++++++++++++++++++++++++++++++----------
mingwrt/mingwex/basename.c | 33 +++++++++++++++++++++----------
mingwrt/mingwex/dirname.c | 33 +++++++++++++++++++++----------
4 files changed, 93 insertions(+), 33 deletions(-)
hooks/post-receive
--
Repository: mingw-org-wsl
|
|
From: Keith M. <no...@so...> - 2014-11-08 12:04:18
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Repository: mingw-org-wsl".
The branch, legacy has been updated
via 2b1bc3a0746e63a16f545bc1495720c5681a29c6 (commit)
via 1ce61dc61c65f2b671863cf5db63bad46dca03ec (commit)
via b5306df520b13c146594d28d4d8cf415e9ba9ac1 (commit)
via 11dde2656497d4bd446689867710e1bc62e4016e (commit)
from d3446db65f6d4b8e43fcae39597420a48ea51256 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
https://sf.net/p/mingw/mingw-org-wsl/ci/2b1bc3a0746e63a16f545bc1495720c5681a29c6/
commit 2b1bc3a0746e63a16f545bc1495720c5681a29c6
Author: Keith Marshall <kei...@us...>
Date: Sat Nov 8 11:10:32 2014 +0000
Implement new command line argument globbing strategy.
diff --git a/mingwrt/CRTglob.c b/mingwrt/CRTglob.c
index a4f5fe0..b9c54d4 100644
--- a/mingwrt/CRTglob.c
+++ b/mingwrt/CRTglob.c
@@ -1,16 +1,30 @@
/*
* CRTglob.c
- * This file has no copyright assigned and is placed in the Public Domain.
- * This file is a part of the mingw-runtime package.
- * No warranty is given; refer to the file DISCLAIMER within the package.
*
- * Include this object file to set _CRT_glob to a state that will
- * turn on command line globbing by default. NOTE: _CRT_glob has a default
- * state of on. Specify CRT_noglob.o to turn off globbing by default.
+ * This file is a part of the mingw-runtime package; it has no copyright
+ * assigned and is placed in the Public Domain. No warranty is given; refer
+ * to the file DISCLAIMER within the package.
*
- * To use this object include the object file in your link command:
- * gcc -o foo.exe foo.o CRTglob.o
+ * Link with this object file to set _CRT_glob to a state that will turn
+ * on command line globbing by default, preferring the MinGW algorithm to
+ * Microsoft's, but without enabling any of its additional features, as
+ * described in include/_mingw.h.
+ *
+ * NOTE: this file is linked by default, via libmingw32.a, if _CRT_glob
+ * is not defined elsewhere in explicitly linked object files. To turn
+ * globbing off, you may link explicitly with CRT_noglob.o, or you may
+ * define _CRT_glob with a value of zero, as a global variable in one of
+ * your own source files, (typically, the one which defines your main()
+ * function). To enable any of the additional globbing features described
+ * in include/_mingw.h, you should define _CRT_glob yourself, initializing
+ * it to the value formed by logical OR of __CRT_GLOB_USE_MINGW__ with the
+ * additional feature descriptors you wish to enable, while to select
+ * Microsoft's globbing algorithm in preference to MinGW's, you should
+ * initialize _CRT_glob = __CRT_glob = __CRT_GLOB_USE_MSVCRT__
*
*/
+#include <_mingw.h>
+
+int _CRT_glob = __CRT_GLOB_USE_MINGW__;
-int _CRT_glob = -1;
+/* $RCSfile$: end of file */
diff --git a/mingwrt/ChangeLog b/mingwrt/ChangeLog
index 9f1c22e..26cc709 100644
--- a/mingwrt/ChangeLog
+++ b/mingwrt/ChangeLog
@@ -1,3 +1,36 @@
+2014-11-08 Keith Marshall <kei...@us...>
+
+ Implement new command line argument globbing strategy.
+
+ * include/_mingw.h: Backport feature defines from master...
+ (__CRT_GLOB_USE_MINGW__, __CRT_GLOB_USE_MSVCRT__): New manifest
+ constants; define them. They select the preferred globbing algorithm.
+ [_CRT_glob & __CRT_GLOB_USE_MINGW__] (__CRT_GLOB_USE_SINGLE_QUOTE__)
+ (__CRT_GLOB_BRACKET_GROUPS__, __CRT_GLOB_CASE_SENSITIVE__): New option
+ bit-map constants; define them. When added to __CRT_GLOB_USE_MINGW__,
+ they enable optional additional features supported by this algorithm.
+ (__CRT_GLOB_ESCAPE_CHAR__): New manifest constant; define it.
+
+ * CRTglob.c (_CRT_glob): Change default to __CRT_GLOB_USE_MINGW__.
+
+ * Makefile.in (libmingw32.a): Add setargv.$OBJEXT, furnished by...
+ * setargv.c: ...new file; it implements the initialization mechanism
+ for the __CRT_GLOB_USE_MINGW__ globbing algorithm, when invoked by...
+ (_setargv) [_CRT_glob & __CRT_GLOB_USE_MINGW__]: ...this new function;
+ it invokes the algorithm via an API similar to that described by MSDN,
+ while continuing to support our original _CRT_glob interpretation.
+ (_setargv) [! _CRT_glob & __CRT_GLOB_USE_MINGW__]: Invoke Microsoft
+ algorithm, via the MSDN-alike API, by calling back to...
+
+ * crt1.c (_mingw32_init_mainargs): ...this original function, now
+ relocated to here, as a publicly addressable function; formerly...
+ (__mingw_CRTStartup): ...called directly from here, we now redirect
+ the call through _setargv(), whence it may be called indirectly.
+
+ * init.c: Redundant file; delete it. It originally provided...
+ (_mingw32_init_mainargs): ...this, now relocated as noted above, with
+ original static attribute removed, to allow global addressing.
+
2014-11-07 Keith Marshall <kei...@us...>
Backport glob implementation from master to legacy.
diff --git a/mingwrt/Makefile.in b/mingwrt/Makefile.in
index 01f48d5..3cdb394 100644
--- a/mingwrt/Makefile.in
+++ b/mingwrt/Makefile.in
@@ -363,9 +363,9 @@ $(addsuffix .def,$(all_moldname)): %.def: ${mingwrt_srcdir}/moldname.def.in
$(CC) -C -E -P -D__FILENAME__=$@ -xc-header $< > $@
all-mingwrt-libs install-mingwrt-libs: libmingw32.a libmingwex.a
-libmingw32.a: $(addsuffix .$(OBJEXT), CRTinit CRTfmode CRTglob \
- cpu_features CRT_fp10 txtmode main dllmain gccmain crtst tlsmcrt \
- tlsmthread tlssup tlsthrd pseudo-reloc pseudo-reloc-list)
+libmingw32.a: $(addsuffix .$(OBJEXT), CRTinit CRTglob setargv \
+ CRTfmode cpu_features CRT_fp10 txtmode main dllmain gccmain crtst \
+ tlsmcrt tlsmthread tlssup tlsthrd pseudo-reloc pseudo-reloc-list)
libmingw32.a libmingwex.a libm.a libmingwthrd.a libgmon.a:
$(AR) $(ARFLAGS) $@ $?
diff --git a/mingwrt/crt1.c b/mingwrt/crt1.c
index 8e24d00..8730606 100644
--- a/mingwrt/crt1.c
+++ b/mingwrt/crt1.c
@@ -10,7 +10,8 @@
*/
/* Hide the declaration of _fmode with dllimport attribute in stdlib.h to
- avoid problems with older GCC. */
+ * avoid problems with older GCC.
+ */
#define __IN_MINGW_RUNTIME
#include <stdlib.h>
#include <stdio.h>
@@ -21,36 +22,115 @@
#include <windows.h>
#include <signal.h>
-/* NOTE: The code for initializing the _argv, _argc, and environ variables
- * has been moved to a separate .c file which is included in both
- * crt1.c and dllcrt1.c. This means changes in the code don't have to
- * be manually synchronized, but it does lead to this not-generally-
- * a-good-idea use of include. */
-#include "init.c"
#include "cpu_features.h"
extern void __main ();
extern void _pei386_runtime_relocator (void);
+/* Main program entry point, and argument initialization hook.
+ */
extern int main (int, char **, char **);
-/* TLS initialization hook. */
-extern const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback;
+int _argc = 0;
+char **_argv = NULL;
-/*
- * Must have the correct app type for MSVCRT.
+/* NOTE: Thanks to Pedro A. Aranda Gutiirrez <pa...@ti...> for pointing
+ * this out: the GetMainArgs() function, (provided by CRTDLL.DDL, as an
+ * argument initialization hook), takes a fourth argument (an int), which
+ * controls the globbing of the command line; if it is non-zero the command
+ * line will be globbed (e.g. *.* will be expanded to a list, separated by
+ * spaces, of all files in the startup directory).
+ *
+ * We determine how globbing should be performed, by inspection of the two
+ * least significant bits of the global int variable _CRT_glob, (defined in
+ * the mingw32 library, with a default value of 2). If this pair of bits
+ * represent a value of 2 or more, the new MinGW globbing algorithm, (as
+ * implemented by function _setargv() in setargv.c), will be applied; for
+ * values of one or zero, _setargv() will delegate the globbing function to
+ * the _mingw32_init_mainargs() callback function implemented below, and so
+ * invoking the Microsoft GetMainArgs() algorithm, with its fourth argument
+ * set to one or zero, to match the least significant bit of _CRT_glob.
+ *
+ * The mingw32 library default value of 2 for _CRT_glob enables command line
+ * globbing using the MinGW algorithm. If you prefer to adopt the Microsoft
+ * algorithm, you should define _CRT_glob as a global variable, by including
+ * a line in one of your own source code files, like this:
+ *
+ * int _CRT_glob = 1;
+ *
+ * Alternatively, if you prefer to disable globbing, and do all command line
+ * processing yourself, (and so evade possible bogons in the Microsoft or in
+ * the MinGW globbing code), include a similar line in one of your own source
+ * code files, defining _CRT_glob with a value of zero, like this:
+ *
+ * int _CRT_glob = 0;
+ */
+extern int _CRT_glob;
+
+#ifdef __MSVCRT__
+/* In MSVCRT.DLL, Microsoft's initialization hook is called __getmainargs(),
+ * and it expects a further structure argument, (which we don't use, but pass
+ * it as a dummy, with a declared size of zero in its first and only field).
*/
+typedef struct { int newmode; } _startupinfo;
+extern void __getmainargs( int *, char ***, char ***, int, _startupinfo * );
+#else
+/* In CRTDLL.DLL, the initialization hook is called __GetMainArgs().
+ */
+extern void __GetMainArgs( int *, char ***, char ***, int );
+#endif
+
+void _mingw32_init_mainargs()
+{
+ /* This is the old start-up mechanism, in which we use a start-up
+ * hook provided by Microsoft's runtime library to initialize the
+ * argument and environment vectors.
+ *
+ * Note that the preferred method for accessing the environment
+ * vector is via a direct pointer retrieved from the runtime DLL,
+ * using a system call declared in stdlib.h; thus, we don't need
+ * to preserve the pointer returned by the start-up hook, so we
+ * may simply capture it locally, and subsequently discard it.
+ */
+ char **dummy_envp;
+
+# define _CRT_GLOB_OPT _CRT_glob & __CRT_GLOB_USE_MSVCRT__
+# ifdef __MSVCRT__
+ /* The MSVCRT.DLL start-up hook requires this invocation
+ * protocol...
+ */
+ _startupinfo start_info = { 0 };
+ __getmainargs( &_argc, &_argv, &dummy_envp, _CRT_GLOB_OPT, &start_info );
+
+# else
+ /* ...while a somewhat simpler protocol is applicable, in
+ * the case of the CRTDLL.DLL version.
+ */
+ __GetMainArgs( &_argc, &_argv, &dummy_envp, _CRT_GLOB_OPT );
+# endif
+}
+
+/* TLS initialization hook.
+ */
+extern const PIMAGE_TLS_CALLBACK __dyn_tls_init_callback;
+
+/* Must have the correct app type for MSVCRT.
+ */
#ifdef __MSVCRT__
-#define __UNKNOWN_APP 0
-#define __CONSOLE_APP 1
-#define __GUI_APP 2
+# define __UNKNOWN_APP 0
+# define __CONSOLE_APP 1
+# define __GUI_APP 2
+
__MINGW_IMPORT void __set_app_type(int);
+
#endif /* __MSVCRT__ */
-/* Global _fmode for this .exe, not the one in msvcrt.dll,
- The default is set in txtmode.o in libmingw32.a */
-/* Override the dllimport'd declarations in stdlib.h */
+/* Global _fmode for this .exe, (not the one in msvcrt.dll).
+ *
+ * The default is set in txtmode.o in libmingw32.a
+ * Override the dllimport'd declarations in stdlib.h
+ */
#undef _fmode
extern int _fmode;
#ifdef __MSVCRT__
@@ -66,42 +146,35 @@ extern int _CRT_fmode;
static void
_mingw32_init_fmode (void)
{
- /* Don't set the std file mode if the user hasn't set any value for it. */
+ /* Don't set the std file mode if the user hasn't set any value for it.
+ */
if (_CRT_fmode)
- {
- _fmode = _CRT_fmode;
-
- /*
- * This overrides the default file mode settings for stdin,
- * stdout and stderr. At first I thought you would have to
- * test with isatty, but it seems that the DOS console at
- * least is smart enough to handle _O_BINARY stdout and
- * still display correctly.
- */
- if (stdin)
- {
- _setmode (_fileno (stdin), _CRT_fmode);
- }
- if (stdout)
- {
- _setmode (_fileno (stdout), _CRT_fmode);
- }
- if (stderr)
- {
- _setmode (_fileno (stderr), _CRT_fmode);
- }
- }
-
- /* Now sync the dll _fmode to the one for this .exe. */
-#ifdef __MSVCRT__
+ {
+ _fmode = _CRT_fmode;
+
+ /* This overrides the default file mode settings for stdin,
+ * stdout and stderr. At first I thought you would have to
+ * test with isatty, but it seems that the DOS console at
+ * least is smart enough to handle _O_BINARY stdout and
+ * still display correctly.
+ */
+ if (stdin) _setmode (_fileno (stdin), _CRT_fmode);
+ if (stdout) _setmode (_fileno (stdout), _CRT_fmode);
+ if (stderr) _setmode (_fileno (stderr), _CRT_fmode);
+ }
+
+ /* Now sync the dll _fmode to the one for this .exe.
+ */
+# ifdef __MSVCRT__
*__p__fmode() = _fmode;
-#else
+# else
*_imp___fmode_dll = _fmode;
-#endif
+# endif
}
-/* This function will be called when a trap occurs. Thanks to Jacob
- Navia for his contribution. */
+/* This function will be called when a trap occurs. Thanks to
+ * Jacob Navia for this contribution.
+ */
static CALLBACK long
_gnu_exception_handler (EXCEPTION_POINTERS * exception_data)
{
@@ -181,50 +254,48 @@ _gnu_exception_handler (EXCEPTION_POINTERS * exception_data)
return action;
}
-/*
- * The function mainCRTStartup is the entry point for all console programs.
+/* The function mainCRTStartup is the entry point for all console programs.
*/
static void __MINGW_ATTRIB_NORETURN
__mingw_CRTStartup (void)
{
int nRet;
- /* Initialize TLS callback. */
+ /* Initialize TLS callback.
+ */
if (__dyn_tls_init_callback != NULL)
__dyn_tls_init_callback (NULL, DLL_THREAD_ATTACH, NULL);
- /*
- * Set up the top-level exception handler so that signal handling
+ /* Set up the top-level exception handler so that signal handling
* works as expected. The mapping between ANSI/POSIX signals and
- * Win32 SE is not 1-to-1, so caveat emptore.
+ * Win32 SE is not 1-to-1, so caveat emptor.
*
*/
SetUnhandledExceptionFilter (_gnu_exception_handler);
- /*
- * Initialize floating point unit.
+ /* Initialize floating point unit.
*/
__cpu_features_init (); /* Do we have SSE, etc.*/
_fpreset (); /* Supplied by the runtime library. */
- /*
- * Set up __argc, __argv and _environ.
+ /* Set up __argc, __argv and _environ.
*/
- _mingw32_init_mainargs ();
+ _setargv ();
- /*
- * Sets the default file mode.
+ /* Sets the default file mode.
* If _CRT_fmode is set, also set mode for stdin, stdout
* and stderr, as well
* NOTE: DLLs don't do this because that would be rude!
*/
_mingw32_init_fmode ();
- /* Adust references to dllimported data that have non-zero offsets. */
+ /* Adust references to dllimported data that have non-zero offsets.
+ */
_pei386_runtime_relocator ();
/* Align the stack to 16 bytes for the sake of SSE ops in main
- or in functions inlined into main. */
+ * or in functions inlined into main.
+ */
asm __volatile__ ("andl $-16, %%esp" : : : "%esp");
/* From libgcc.a, __main calls global class constructors via
@@ -235,16 +306,14 @@ __mingw_CRTStartup (void)
which has its own __do_global_ctors. */
__main ();
- /*
- * Call the main function. If the user does not supply one
+ /* Call the main function. If the user does not supply one
* the one in the 'libmingw32.a' library will be linked in, and
* that one calls WinMain. See main.c in the 'lib' dir
* for more details.
*/
nRet = main (_argc, _argv, environ);
- /*
- * Perform exit processing for the C library. This means
+ /* Perform exit processing for the C library. This means
* flushing output and calling 'atexit' registered functions.
*/
_cexit ();
diff --git a/mingwrt/include/_mingw.h b/mingwrt/include/_mingw.h
index eb51458..cbaf9d0 100644
--- a/mingwrt/include/_mingw.h
+++ b/mingwrt/include/_mingw.h
@@ -33,34 +33,90 @@
#endif
#endif
-/* These are defined by the user (or the compiler)
- to specify how identifiers are imported from a DLL.
-
- __DECLSPEC_SUPPORTED Defined if dllimport attribute is supported.
- __MINGW_IMPORT The attribute definition to specify imported
- variables/functions.
- _CRTIMP As above. For MS compatibility.
- __MINGW32_VERSION Runtime version.
- __MINGW32_MAJOR_VERSION Runtime major version.
- __MINGW32_MINOR_VERSION Runtime minor version.
- __MINGW32_BUILD_DATE Runtime build date.
-
- Macros to enable MinGW features which deviate from standard MSVC
- compatible behaviour; these may be specified directly in user code,
- activated implicitly, (e.g. by specifying _POSIX_C_SOURCE or such),
- or by inclusion in __MINGW_FEATURES__:
-
- __USE_MINGW_ANSI_STDIO Select a more ANSI C99 compatible
- implementation of printf() and friends.
+/* The following are defined by the user (or by the compiler), to specify how
+ * identifiers are imported from a DLL. All headers should include this first,
+ * and then use __DECLSPEC_SUPPORTED to choose between the old ``__imp__name''
+ * style or the __MINGW_IMPORT style for declarations.
+ *
+ * __DECLSPEC_SUPPORTED Defined if dllimport attribute is supported.
+ * __MINGW_IMPORT The attribute definition to specify imported
+ * variables/functions.
+ * _CRTIMP As above. For MS compatibility.
+ * __MINGW32_VERSION Runtime version.
+ * __MINGW32_MAJOR_VERSION Runtime major version.
+ * __MINGW32_MINOR_VERSION Runtime minor version.
+ * __MINGW32_BUILD_DATE Runtime build date.
+ *
+ * Macros to enable MinGW features which deviate from standard MSVC
+ * compatible behaviour; these may be specified directly in user code,
+ * activated implicitly, (e.g. by specifying _POSIX_C_SOURCE or such),
+ * or by inclusion in __MINGW_FEATURES__:
+ *
+ * __USE_MINGW_ANSI_STDIO Select a more ANSI C99 compatible
+ * implementation of printf() and friends.
+ *
+ * Other macros:
+ *
+ * __int64 define to be long long. Using a typedef
+ * doesn't work for "unsigned __int64"
+ *
+ *
+ * Manifest definitions for flags to control globbing of the command line
+ * during application start up, (before main() is called). The first pair,
+ * when assigned as bit flags within _CRT_glob, select the globbing algorithm
+ * to be used; (the MINGW algorithm overrides MSCVRT, if both are specified).
+ * Prior to mingwrt-3.21, only the MSVCRT option was supported; this choice
+ * may produce different results, depending on which particular version of
+ * MSVCRT.DLL is in use; (in recent versions, it seems to have become
+ * definitively broken, when globbing within double quotes).
+ */
+#define __CRT_GLOB_USE_MSVCRT__ 0x0001
- Other macros:
+/* From mingwrt-3.21 onward, this should be the preferred choice; it will
+ * produce consistent results, regardless of the MSVCRT.DLL version in use.
+ */
+#define __CRT_GLOB_USE_MINGW__ 0x0002
- __int64 define to be long long. Using a typedef
- doesn't work for "unsigned __int64"
+/* When the __CRT_GLOB_USE_MINGW__ flag is set, within _CRT_glob, the
+ * following additional options are also available; they are not enabled
+ * by default, but the user may elect to enable any combination of them,
+ * by setting _CRT_glob to the boolean sum (i.e. logical OR combination)
+ * of __CRT_GLOB_USE_MINGW__ and the desired options.
+ *
+ * __CRT_GLOB_USE_SINGLE_QUOTE__ allows use of single (apostrophe)
+ * quoting characters, analogously to
+ * POSIX usage, as an alternative to
+ * double quotes, for collection of
+ * arguments separated by white space
+ * into a single logical argument.
+ *
+ * __CRT_GLOB_BRACKET_GROUPS__ enable interpretation of bracketed
+ * character groups as POSIX compatible
+ * globbing patterns, matching any one
+ * character which is either included
+ * in, or excluded from the group.
+ *
+ * __CRT_GLOB_CASE_SENSITIVE__ enable case sensitive matching for
+ * globbing patterns; this is default
+ * behaviour for POSIX, but because of
+ * the case insensitive nature of the
+ * MS-Windows file system, it is more
+ * appropriate to use case insensitive
+ * globbing as the MinGW default.
+ *
+ */
+#define __CRT_GLOB_USE_SINGLE_QUOTE__ 0x0010
+#define __CRT_GLOB_BRACKET_GROUPS__ 0x0020
+#define __CRT_GLOB_CASE_SENSITIVE__ 0x0040
- All headers should include this first, and then use __DECLSPEC_SUPPORTED
- to choose between the old ``__imp__name'' style or __MINGW_IMPORT
- style declarations. */
+/* The MinGW globbing algorithm uses the ASCII DEL control code as a marker
+ * for globbing characters which were embedded within quoted arguments; (the
+ * quotes are stripped away BEFORE the argument is globbed; the globbing code
+ * treats the marked character as immutable, and strips out the DEL markers,
+ * before storing the resultant argument). The DEL code is mapped to this
+ * function here; DO NOT change it, without rebuilding the runtime.
+ */
+#define __CRT_GLOB_ESCAPE_CHAR__ (char)(127)
/* Manifest definitions identifying the flag bits, controlling activation
diff --git a/mingwrt/init.c b/mingwrt/init.c
deleted file mode 100644
index b7af07c..0000000
--- a/mingwrt/init.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * init.c
- * This file has no copyright assigned and is placed in the Public Domain.
- * This file is a part of the mingw-runtime package.
- * No warranty is given; refer to the file DISCLAIMER within the package.
- *
- * Code to initialize standard file handles and command line arguments.
- * This file is #included in both crt1.c and dllcrt1.c.
- *
- */
-
-/*
- * Access to a standard 'main'-like argument count and list. Also included
- * is a table of environment variables.
- */
-int _argc = 0;
-char **_argv = 0;
-
-/* NOTE: Thanks to Pedro A. Aranda Gutiirrez <pa...@ti...> for pointing
- * this out to me. GetMainArgs (used below) takes a fourth argument
- * which is an int that controls the globbing of the command line. If
- * _CRT_glob is non-zero the command line will be globbed (e.g. *.*
- * expanded to be all files in the startup directory). In the mingw32
- * library a _CRT_glob variable is defined as being -1, enabling
- * this command line globbing by default. To turn it off and do all
- * command line processing yourself (and possibly escape bogons in
- * MS's globbing code) include a line in one of your source modules
- * defining _CRT_glob and setting it to zero, like this:
- * int _CRT_glob = 0;
- */
-extern int _CRT_glob;
-
-#ifdef __MSVCRT__
-typedef struct {
- int newmode;
-} _startupinfo;
-extern void __getmainargs (int *, char ***, char ***, int, _startupinfo *);
-#else
-extern void __GetMainArgs (int *, char ***, char ***, int);
-#endif
-
-/*
- * Initialize the _argc, _argv and environ variables.
- */
-static void
-_mingw32_init_mainargs ()
-{
- /* The environ variable is provided directly in stdlib.h through
- * a dll function call. */
- char **dummy_environ;
-#ifdef __MSVCRT__
- _startupinfo start_info;
- start_info.newmode = 0;
-#endif
-
- /*
- * Microsoft's runtime provides a function for doing just that.
- */
-#ifdef __MSVCRT__
- (void) __getmainargs (&_argc, &_argv, &dummy_environ, _CRT_glob,
- &start_info);
-#else
- /* CRTDLL version */
- (void) __GetMainArgs (&_argc, &_argv, &dummy_environ, _CRT_glob);
-#endif
-}
-
diff --git a/mingwrt/setargv.c b/mingwrt/setargv.c
new file mode 100644
index 0000000..3e823e8
--- /dev/null
+++ b/mingwrt/setargv.c
@@ -0,0 +1,260 @@
+/*
+ * setargv.c
+ *
+ * Implements runtime initialization code to populate the argument
+ * vector, which will subsequently be passed to the main() function;
+ * provides a _setargv() hook, similar to that described on MSDN.
+ *
+ * $Id$
+ *
+ * Written by Keith Marshall <kei...@us...>
+ * Copyright (C) 2014, 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.
+ *
+ * ---------------------------------------------------------------------------
+ *
+ */
+#include <glob.h>
+#include <string.h>
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+/* Access to a standard 'main'-like argument count and list.
+ */
+extern int _argc;
+extern char ** _argv;
+extern int _CRT_glob;
+
+#define ARGV_INLINE static __inline__ __attribute__((__always_inline__))
+
+#define ARGV_ESCAPE __CRT_GLOB_ESCAPE_CHAR__
+#define ARGV_SQUOTE __CRT_GLOB_USE_SINGLE_QUOTE__
+#define ARGV_NOGROUP __CRT_GLOB_BRACKET_GROUPS__
+
+ARGV_INLINE
+char *backslash( int count, char *buf )
+{
+ /* Helper used by the MinGW replacement command line globbing handler,
+ * to provide appropriate handling of backslashes while preparing the
+ * command line arguments for globbing.
+ */
+ while( count-- )
+ *buf++ = '\\';
+ return buf;
+}
+
+ARGV_INLINE
+char *unquote( int quote, int altquote, int escape, int *state, char *buf )
+{
+ /* Helper used by the MinGW replacement command line globbing handler,
+ * to provide a single level of reduction for balanced quotation marks,
+ * while preparing the command line arguments for globbing.
+ */
+ buf = backslash( escape >> 1, buf );
+ if( (escape & 1) || (*state == altquote) )
+ /*
+ * In this case, the quotation mark is to be interpreted as a literal,
+ * and is NOT a candidate for reduction...
+ */
+ *buf++ = quote;
+ else
+ /* ...while this is the more usual case, of a quotation mark used to
+ * delimit a single argument; it must be reduced.
+ */
+ *state ^= quote;
+ return buf;
+}
+
+ARGV_INLINE
+void __mingw32_setargv( const char *cmdline )
+{
+ /* Implementation of the MinGW replacement command line interpreter.
+ */
+ char cmdbuf[1 + strlen( cmdline ) << 1];
+ int c, gotarg = 0, quoted = 0, bracket = 0, bslash = 0;
+ char *argptr = cmdbuf; const char *cmdptr = cmdline;
+ glob_t gl_argv;
+
+ /* Capture any non-default globbing options, which the user may have
+ * specified via a custom setting for _CRT_glob.
+ */
+ int gl_opts = GLOB_NOCHECK;
+ if( _CRT_glob & __CRT_GLOB_CASE_SENSITIVE__ )
+ gl_opts |= GLOB_CASEMATCH;
+
+ /* We explicitly DO NOT use the GLOB_DOOFFS capability; ensure that
+ * the associated field, in the glob_t structure, is initialized to
+ * correctly reflect this.
+ */
+ gl_argv.gl_offs = 0;
+
+ /* Scan the command line, and prepare it for globbing.
+ */
+ while( c = *cmdptr++ )
+ {
+ /* Got a character to process...
+ */
+ switch( c )
+ {
+ /* Specific characters, which serve as globbing tokens,
+ * need special handling.
+ */
+ case '\\':
+ /* We don't (yet) know if this is a literal backslash,
+ * (directory separator), or an escape for a following
+ * quote character; just note its presence, until we
+ * have looked far enough ahead to decide.
+ */
+ ++bslash;
+ break;
+
+ case '[':
+ /* POSIX defines this as a globbing token, (introducing
+ * a character group); we don't support this by default,
+ * so defeat it, unless the extended behaviour has been
+ * requested by the user.
+ */
+ bracket = (_CRT_glob & ARGV_NOGROUP) ? 0 : ARGV_NOGROUP;
+
+ case '*':
+ case '?':
+ /* These standard globbing tokens...
+ */
+ case ARGV_ESCAPE:
+ /* ...and the escape character itself, need to be escaped
+ * when they appear in any context in which they should be
+ * interpreted literally, rather than globbed.
+ */
+ argptr = backslash( bslash, argptr );
+ if( quoted || (bracket == ARGV_NOGROUP) || (c == ARGV_ESCAPE) )
+ *argptr++ = ARGV_ESCAPE;
+ bracket = bslash = 0;
+ *argptr++ = c;
+ break;
+
+ case '"':
+ /* The double quote always acts as an argument quoting
+ * character, (unless escaped); handle it accordingly.
+ */
+ argptr = unquote( c, '\'', bslash, "ed, argptr );
+ gotarg = 1; bslash = 0;
+ break;
+
+ case '\'':
+ /* POSIX also defines the single quote as a quoting
+ * character, but MS-Windows does not; we offer this
+ * extended handling...
+ */
+ if( _CRT_glob & ARGV_SQUOTE )
+ {
+ /* ...only when the user has explicitly enabled the
+ * POSIX compatible extended quoting option.
+ */
+ argptr = unquote( c, '"', bslash, "ed, argptr );
+ gotarg = 1; bslash = 0;
+ break;
+ }
+
+ default:
+ /* With one exception, any other character is handled
+ * literally, after flushing out any pending backslashes.
+ */
+ argptr = backslash( bslash, argptr );
+ if( (quoted == 0) && isspace( c ) )
+ {
+ /* The one exception is any white space character,
+ * when it is not contained within quotes; this acts
+ * as an argument separator, (or is simply discarded
+ * if there is no argument already collected)...
+ */
+ if( gotarg || (argptr > cmdbuf) )
+ {
+ /* ...so, when there is a argument pending, we may
+ * now add it to the globbed argument vector.
+ */
+ *argptr = '\0';
+ __mingw_glob( argptr = cmdbuf, gl_opts, NULL, &gl_argv );
+ gl_opts |= GLOB_APPEND;
+ gotarg = 0;
+ }
+ }
+ else
+ /* In every other case, we simply collect the current
+ * literal character into the next pending argument.
+ */
+ *argptr++ = c;
+
+ /* Irrespective of how we handled the current character,
+ * we can be certain that there are no pending backslashes
+ * by the time we get to here.
+ */
+ bslash = 0;
+ }
+ }
+ /* Finally, when we've run out of command line characters to process,
+ * flush out any final pending backslashes, ...
+ */
+ argptr = backslash( bslash, argptr );
+ if( gotarg || (argptr > cmdbuf) )
+ {
+ /* ...and add any final pending argument to the globbed vector.
+ */
+ *argptr = '\0';
+ __mingw_glob( argptr = cmdbuf, gl_opts, NULL, &gl_argv );
+ }
+ /* ...and store the resultant globbed vector into the "argc" and "argv"
+ * variables to be passed to main(); note that this allows us to safely
+ * discard our working glob_t structure, but we MUST NOT globfree() it,
+ * as that would destroy the content of "argv".
+ */
+ _argc = gl_argv.gl_pathc;
+ _argv = gl_argv.gl_pathv;
+}
+
+extern void _mingw32_init_mainargs( void );
+
+void _setargv()
+{
+ /* Initialize the _argc, _argv and environ variables.
+ */
+ if( (_CRT_glob & __CRT_GLOB_USE_MINGW__) == 0 )
+ {
+ /* This is the old start-up mechanism, implemented via a callback
+ * into the CRT initialization module, in which we use a start-up
+ * hook provided by Microsoft's runtime library to initialize the
+ * argument and environment vectors.
+ */
+ _mingw32_init_mainargs();
+ }
+ else
+ { /* Here, we implement a new, more POSIX compatible mechanism,
+ * for initializing the argument vector; note that we delegate
+ * to the previously defined inline function, which avoids the
+ * broken globbing behaviour of some more recent versions of
+ * MSVCRT.DLL
+ */
+ __mingw32_setargv( GetCommandLine() );
+ }
+}
+
+/* $RCSfile$: end of file */
https://sf.net/p/mingw/mingw-org-wsl/ci/1ce61dc61c65f2b671863cf5db63bad46dca03ec/
commit 1ce61dc61c65f2b671863cf5db63bad46dca03ec
Author: Keith Marshall <kei...@us...>
Date: Fri Nov 7 01:23:36 2014 +0000
Backport glob implementation from master to legacy.
diff --git a/mingwrt/ChangeLog b/mingwrt/ChangeLog
index c1bb58f..9f1c22e 100644
--- a/mingwrt/ChangeLog
+++ b/mingwrt/ChangeLog
@@ -1,3 +1,21 @@
+2014-11-07 Keith Marshall <kei...@us...>
+
+ Backport glob implementation from master to legacy.
+
+ * include/glob.h: New file; copy it from master branch.
+ (__mingw_glob, __mingw_globfree): Add __JMPSTUB__ aliases for...
+ (glob, globfree): ...each of these, respectively.
+
+ * mingwex/glob.c: New file; copy it from master:src/libcrt/misc.
+ (CRT_GLOB_HARD_ESCAPE) [ifndef __CRT_GLOB_ESCAPE_CHAR__]: Provide a
+ fallback definition; default value is ASCII DEL, a.k.a. RUBOUT, code.
+ (accept_glob_nocheck_match): New static function; it adds support for
+ avoidance of globbing on patterns with no globbing token, so avoiding
+ the case transliteration effect reported as MinGW-Bug #2106.
+ (glob_match): Use it.
+
+ * Makefile.in: Build glob.$OBJEXT; add it to libmingwex.a
+
2014-11-05 Keith Marshall <kei...@us...>
Implement conventionally named dirent function trampolines.
diff --git a/mingwrt/Makefile.in b/mingwrt/Makefile.in
index ffa2847..01f48d5 100644
--- a/mingwrt/Makefile.in
+++ b/mingwrt/Makefile.in
@@ -455,7 +455,7 @@ pformat.$(OBJEXT): %.$(OBJEXT): %.c
# Some additional miscellaneous functions, in libmingwex.a
#
#libmingwex.a: $(addsuffix .$(OBJEXT), glob membarrier)
-libmingwex.a: $(addsuffix .$(OBJEXT), mingw-aligned-malloc mingw-fseek)
+libmingwex.a: $(addsuffix .$(OBJEXT), mingw-aligned-malloc mingw-fseek glob)
libmingwex.a: $(addsuffix .$(OBJEXT), getopt basename dirname ftruncate usleep)
libmingwex.a: $(addsuffix .$(OBJEXT), tdelete tfind tsearch twalk)
diff --git a/mingwrt/include/glob.h b/mingwrt/include/glob.h
new file mode 100644
index 0000000..b9a7655
--- /dev/null
+++ b/mingwrt/include/glob.h
@@ -0,0 +1,159 @@
+#ifndef _GLOB_H
+/*
+ * glob.h
+ *
+ * Header file supporting a MinGW implementation of an (approximately)
+ * POSIX conforming glob() and globfree() API.
+ *
+ * $Id$
+ *
+ * Written by Keith Marshall <kei...@us...>
+ * Copyright (C) 2011, 2012, 2014, 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.
+ *
+ */
+#define _GLOB_H 1
+#include <_mingw.h>
+#pragma GCC system_header
+
+#ifndef RC_INVOKED
+/* POSIX requires glob.h to define the size_t type; we need to
+ * get this from GCC, just as sys/types.h does.
+ */
+#define __need_size_t
+#include <stddef.h>
+
+typedef
+struct glob_t
+{ /* The structure, in which glob() returns the list of file system
+ * entities which it has matched.
+ */
+ void * gl_magic; /* reserved field; pointer to a glob signature */
+ size_t gl_pathc; /* counter for paths matched */
+ char ** gl_pathv; /* list of matching path names */
+ size_t gl_offs; /* number of initial unused slots in gl_pathv */
+} glob_t;
+
+/* A macro to facilitate definition of the flags which are used to
+ * control the operation of glob().
+ */
+#define __GLOB_FLAG__(NAME) (1 << __GLOB_##NAME##_OFFSET)
+enum {
+ /* Identify the zero-based offset values which are used to specify
+ * the individual bit positions for each __GLOB_FLAG; the initial
+ * list specifies the standard set of flags required by POSIX.
+ */
+ __GLOB_APPEND_OFFSET = 0,
+ __GLOB_DOOFFS_OFFSET,
+ __GLOB_ERR_OFFSET,
+ __GLOB_MARK_OFFSET,
+ __GLOB_NOCHECK_OFFSET,
+ __GLOB_NOESCAPE_OFFSET,
+ __GLOB_NOSORT_OFFSET,
+ /*
+ * GNU's implementation of glob() supports a supplementary set of
+ * options, none of which are required by POSIX. We include these
+ * for reference, and to reserve the flag identities for a possible
+ * future implementation; the current MinGW implementation does not
+ * support them.
+ */
+ __GLOB_TILDE_OFFSET,
+ __GLOB_TILDE_CHECK_OFFSET,
+ __GLOB_PERIOD_OFFSET,
+ __GLOB_BRACE_OFFSET,
+ __GLOB_ONLYDIR_OFFSET,
+ __GLOB_ALTDIRFUNC_OFFSET,
+ __GLOB_NOMAGIC_OFFSET,
+ /*
+ * This MinGW implementation DOES add support for the following
+ * custom options, which offer improved handling of MS-Windows
+ * specific peculiarities:--
+ *
+ * GLOB_CASEMATCH makes glob() respect case sensitivity
+ * in path name matches; this is similar
+ * to default behaviour on POSIX systems,
+ * but to better support the MS-Windows
+ * file system, the MinGW implementation
+ * of glob() performs a CASE INSENSITIVE
+ * character match by default, (except
+ * when matching within character group
+ * patterns, which are ALWAYS assumed to
+ * require CASE SENSITIVE matching).
+ */
+ __GLOB_CASEMATCH_OFFSET,
+ /*
+ * The following is a convenience, to mark the end of the enumeration;
+ * it is NEVER used to locate any user visible __GLOB_FLAG__, but it
+ * MUST remain as the final entry in the enumerated list.
+ */
+ __GLOB_FLAG_OFFSET_HIGH_WATER_MARK
+};
+
+/* Definitions of the mandatory flags, as specified by POSIX.
+ */
+#define GLOB_APPEND __GLOB_FLAG__(APPEND)
+#define GLOB_DOOFFS __GLOB_FLAG__(DOOFFS)
+#define GLOB_ERR __GLOB_FLAG__(ERR)
+#define GLOB_MARK __GLOB_FLAG__(MARK)
+#define GLOB_NOCHECK __GLOB_FLAG__(NOCHECK)
+#define GLOB_NOESCAPE __GLOB_FLAG__(NOESCAPE)
+#define GLOB_NOSORT __GLOB_FLAG__(NOSORT)
+
+/* Additional flags definitions, for MinGW specific extensions.
+ */
+#define GLOB_CASEMATCH __GLOB_FLAG__(CASEMATCH)
+
+_BEGIN_C_DECLS
+/*
+ * Function prototypes. Formally POSIX mandates:
+ *
+ * int glob( const char *, int, int (*)( const char *, int ), glob_t * );
+ * void globfree( glob_t * );
+ *
+ * However, our actual function implementations are provided via this
+ * pair of reserved function names...
+ */
+int __mingw_glob (const char *, int, int (*)( const char *, int ), glob_t *);
+void __mingw_globfree (glob_t *);
+
+/* ...to which the standard names are then mapped as aliases,
+ * via __CRT_ALIAS inline function expansion.
+ */
+__CRT_ALIAS __JMPSTUB__(( FUNCTION = glob ))
+int glob (const char *__pattern, int __flags, int (*__errfunc)(), glob_t *__data)
+{ return __mingw_glob (__pattern, __flags, __errfunc, __data); }
+
+__CRT_ALIAS __JMPSTUB__(( FUNCTION = globfree ))
+void globfree (glob_t *__data){ return __mingw_globfree (__data); }
+
+_END_C_DECLS
+
+/* Manifest definitions for the possible status values
+ * which glob() may return.
+ */
+#define GLOB_SUCCESS (0)
+#define GLOB_ABORTED (1)
+#define GLOB_NOMATCH (2)
+#define GLOB_NOSPACE (3)
+
+#endif /* ! RC_INVOKED */
+#endif /* ! defined _GLOB_H */
diff --git a/mingwrt/mingwex/glob.c b/mingwrt/mingwex/glob.c
new file mode 100644
index 0000000..6de4880
--- /dev/null
+++ b/mingwrt/mingwex/glob.c
@@ -0,0 +1,1073 @@
+/*
+ * glob.c
+ *
+ * MinGW implementation of (approximately) POSIX conforming glob() and
+ * globfree() API functions.
+ *
+ * $Id$
+ *
+ * Written by Keith Marshall <kei...@us...>
+ * Copyright (C) 2011-2014, 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.
+ *
+ */
+#include <glob.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <libgen.h>
+#include <dirent.h>
+#include <errno.h>
+
+enum {
+ /* Extend the flags offset enumeration, beyond the user visible
+ * high water mark, to accommodate some additional flags which are
+ * required for private use by the implementation.
+ */
+ __GLOB_DIRONLY_OFFSET = __GLOB_FLAG_OFFSET_HIGH_WATER_MARK,
+ __GLOB_PERIOD_PRIVATE_OFFSET,
+ /*
+ * For congruency, set a new high water mark above the private data
+ * range, (which we don't otherwise use).
+ */
+ __GLOB_PRIVATE_FLAGS_HIGH_WATER_MARK
+};
+
+#define GLOB_DIRONLY __GLOB_FLAG__(DIRONLY)
+#ifndef GLOB_PERIOD
+# define GLOB_PERIOD __GLOB_FLAG__(PERIOD_PRIVATE)
+#endif
+
+#ifndef GLOB_INLINE
+# define GLOB_INLINE static __inline__ __attribute__((__always_inline__))
+#endif
+
+#if defined _WIN32 || defined __MS_DOS__
+/*
+ * For the Microsoft platforms, we treat '\' and '/' interchangeably
+ * as directory separator characters...
+ */
+#define GLOB_DIRSEP ('\\')
+# define glob_is_dirsep( c ) (((c) == ('/')) || ((c) == GLOB_DIRSEP))
+/*
+ * ...and we substitute whatever may have been predefined as the
+ * manifest constant __CRT_GLOB_ESCAPE_CHAR__, (nominally ASCII DEL,
+ * a.k.a. RUBOUT), as an alternative escape character.
+ */
+# ifdef __CRT_GLOB_ESCAPE_CHAR__
+# define GLOB_HARD_ESC __CRT_GLOB_ESCAPE_CHAR__
+# else
+# define GLOB_HARD_ESC ((char)(127))
+# endif
+
+static int glob_escape_char = GLOB_HARD_ESC;
+
+GLOB_INLINE char *glob_strdup( const char *pattern )
+{
+ /* An inline wrapper around the standard strdup() function;
+ * this strips instances of the GLOB_HARD_ESC character, which
+ * have not themselves been escaped, from the strdup()ed copy.
+ */
+ char buf[1 + strlen( pattern )];
+ char *copy = buf; const char *origin = pattern;
+ do { if( *origin == GLOB_HARD_ESC ) ++origin;
+ *copy++ = *origin;
+ } while( *origin++ );
+ return strdup( buf );
+}
+
+#else
+/* Otherwise, we assume only the POSIX standard '/'...
+ */
+#define GLOB_DIRSEP ('/')
+# define glob_is_dirsep( c ) ((c) == GLOB_DIRSEP)
+/*
+ * ...and we interpret '\', as specified by POSIX, as
+ * the escape character.
+ */
+static int glob_escape_char = '\\';
+
+#define glob_strdup strdup
+#endif
+
+static int is_glob_pattern( const char *pattern, int flags )
+{
+ /* Check if "pattern" represents a globbing pattern
+ * with included wild card characters.
+ */
+ register const char *p;
+ register int c;
+
+ /* Proceed only if specified pattern is not NULL...
+ */
+ if( (p = pattern) != NULL )
+ {
+ /* ...initially, with no bracketted character set open;
+ * (none can be, because we haven't yet had any opportunity
+ * to see the opening bracket).
+ */
+ int bracket = 0;
+
+ /* Check each character in "pattern" in turn...
+ */
+ while( (c = *p++) != '\0' )
+ {
+ /* ...proceeding since we have not yet reached the NUL terminator.
+ */
+ if( ((flags & GLOB_NOESCAPE) == 0)
+ && (c == glob_escape_char) && (*p++ == '\0') )
+ /*
+ * We found an escape character, (and the escape mechanism has
+ * not been disabled), but there is no following character to
+ * escape; it may be malformed, but this certainly doesn't look
+ * like a candidate globbing pattern.
+ */
+ return 0;
+
+ else if( bracket == 0 )
+ {
+ /* Still outside of any bracketted character set...
+ */
+ if( (c == '*') || (c == '?') )
+ /*
+ * ...either of these makes "pattern" an explicit
+ * globbing pattern...
+ */
+ return 1;
+
+ if( c == '[' )
+ /*
+ * ...while this marks the start of a bracketted
+ * character set.
+ */
+ bracket++;
+ }
+
+ else if( (bracket > 1) && (c == ']') )
+ /*
+ * Within a bracketted character set, where it is not
+ * the first character, ']' marks the end of the set,
+ * making "pattern" a globbing pattern.
+ */
+ return 1;
+
+ else if( c != '!' )
+ /*
+ * Also within a bracketted character set, '!' is special
+ * when the first character, and shouldn't be counted; note
+ * that it should be counted when not the first character,
+ * but the short count resulting from ignoring it doesn't
+ * affect our desired outcome.
+ */
+ bracket++;
+ }
+ }
+
+ /* If we get to here, then we ran off the end of "pattern" without
+ * identifying it as a globbing pattern.
+ */
+ return 0;
+}
+
+static const char *glob_set_adjusted( const char *pattern, int flags )
+{
+ /* Adjust the globbing pattern pointer, to make it refer to the
+ * next character (if any) following a character set specification;
+ * this adjustment is required when pattern matching is to resume
+ * after matching a set specification, irrespective of whether the
+ * match was successful or not; (a failed match is the desired
+ * outcome for an excluded character set).
+ */
+ register const char *p = pattern;
+
+ /* We need to move the pointer forward, until we find the ']'
+ * which marks the end of the set specification.
+ */
+ while( *p != ']' )
+ {
+ /* We haven't found it yet; advance by one character...
+ */
+ if( (*p == glob_escape_char) && ((flags & GLOB_NOESCAPE) == 0) )
+ /*
+ * ...or maybe even two, when we identify a need to
+ * step over any character which has been escaped...
+ */
+ p++;
+
+ if( *p++ == '\0' )
+ /*
+ * ...but if we find a NUL on the way, then the pattern
+ * is malformed, so we return NULL to report a bad match.
+ */
+ return NULL;
+ }
+ /* We found the expected ']'; return a pointer to the NEXT
+ * character, (which may be ANYTHING; even NUL is okay).
+ */
+ return ++p;
+}
+
+static const char *glob_in_set( const char *set, int test, int flags )
+{
+ /* Check if the single character "test" is present in the set
+ * of characters represented by "set", (a specification of the
+ * form "[SET]", or "[!SET]" in the case of an excluded set).
+ *
+ * On entry, "set" always points to the first character in the
+ * set to be tested, i.e. the character FOLLOWING the '[' which
+ * opens an inclusive set, or FOLLOWING the initial '!' which
+ * marks the set as exclusive.
+ *
+ * Matching is ALWAYS performed as if checking an inclusive set;
+ * return value is a pointer to the globbing pattern character
+ * following the closing ']' of "set", when "test" IS in "set",
+ * or NULL when it is not. Caller performing an inclusive match
+ * should handle NULL as a failed match, and non-NULL as success.
+ * Caller performing an exclusive match should handle non-NULL as
+ * a failed match, with NULL indicating success, and should call
+ * glob_set_adjusted() before resuming pattern matching in the
+ * case of a successful match.
+ */
+ register int c, lastc;
+ if( ((lastc = *set) == ']') || (lastc == '-') )
+ {
+ /* This is the special case of matching ']' or '-' as the
+ * first character in the set, where it must match literally...
+ */
+ if( lastc == test )
+ /*
+ * ...which it does, so immediately report it so.
+ */
+ return glob_set_adjusted( ++set, flags );
+
+ /* ...otherwise we didn't match this special case of ']' or '-',
+ * so we simply ignore this special set entry, thus handling it
+ * as an implicitly escaped literal which has not been matched.
+ */
+ set++;
+ }
+ while( (c = *set++) != ']' )
+ {
+ /* We are still scanning the set, and have not yet reached the
+ * closing ']' sentinel character.
+ */
+ if( (c == '-') && (*set != ']') && ((c = *set++) != '\0') )
+ {
+ /* Since the current character is a '-', and is not immediately
+ * followed by the set's closing sentinel, nor is it at the end
+ * of the (malformed) pattern, it specifies a character range,
+ * running from the last character scanned...
+ */
+ while( lastc < c )
+ {
+ /* ...in incremental collating sequence order, to the next
+ * character following the '-'...
+ */
+ if( lastc++ == test )
+ /*
+ * ...returning immediately on a successful match...
+ */
+ return glob_set_adjusted( set, flags );
+ }
+ while( lastc > c )
+ {
+ /* ...or failing that, consider the possibility that the
+ * range may have been specified in decrementing collating
+ * sequence order...
+ */
+ if( lastc-- == test )
+ /*
+ * ...once again, return immediately on a successful match.
+ */
+ return glob_set_adjusted( set, flags );
+ }
+ }
+
+ if( (c == '\0')
+ /*
+ * This is a malformed set; (not closed before the end of
+ * the pattern)...
+ */
+ || glob_is_dirsep( c ) )
+ /*
+ * ...or it attempts to explicitly match a directory separator,
+ * which is invalid in this context. We MUST fail it, in either
+ * case, reporting a mismatch.
+ */
+ return NULL;
+
+ if( c == test )
+ /*
+ * We found the test character within the set; adjust the pattern
+ * reference, to resume after the end of the set, and return the
+ * successful match.
+ */
+ return glob_set_adjusted( set, flags );
+
+ /* If we get to here, we haven't yet found the test character within
+ * this set; remember the character within the set which we just tried
+ * to match, as it may represent the start of a character range, then
+ * continue the scan, until we exhaust the set.
+ */
+ lastc = c;
+ }
+ /* Having exhausted the set, without finding a match, we return NULL
+ * to indicate that the test character was NOT found in the set.
+ */
+ return NULL;
+}
+
+GLOB_INLINE int glob_case_match( int flags, int check, int match )
+{
+ /* Local helper function, used to facilitate the case insensitive
+ * glob character matching appropriate for MS-Windows systems.
+ */
+ return (flags & GLOB_CASEMATCH) ? check - match
+ : tolower( check ) - tolower( match );
+}
+
+static int glob_strcmp( const char *pattern, const char *text, int flags )
+{
+ /* Compare "text" to a specified globbing "pattern" using semantics
+ * comparable to "strcmp()"; returns zero for a complete match, else
+ * non-zero for a mismatch.
+ *
+ * Within "pattern":
+ * '?' matches any one character in "text" (except '\0')
+ * '*' matches any sequence of zero or more characters in "text"
+ * [SET] matches any one character in "text" which is also in "SET"
+ * [!SET] matches any one character in "text" which is NOT in "SET"
+ */
+ register const char *p = pattern, *t = text;
+ register int c;
+
+ if( (*t == '.') && (*p != '.') && ((flags & GLOB_PERIOD) == 0) )
+ /*
+ * The special GNU extension allowing wild cards to match a period
+ * as first character is NOT in effect; "text" DOES have an initial
+ * period character AND "pattern" DOES NOT match it EXPLICITLY, so
+ * this comparison must report a MISMATCH.
+ */
+ return *p - *t;
+
+ /* Attempt to match "pattern", character by character...
+ */
+ while( (c = *p++) != '\0' )
+ {
+ /* ...so long as we haven't exhausted it...
+ */
+ switch( c )
+ {
+ case '?':
+ /* Match any one character...
+ */
+ if( *t++ == '\0' )
+ /* ...but when there isn't one left to be matched,
+ * then we must report a mismatch.
+ */
+ return '?';
+ break;
+
+ case '*':
+ /* Match any sequence of zero or more characters...
+ */
+ while( *p == '*' )
+ /*
+ * ...ignoring any repeated '*' in the pattern...
+ */
+ p++;
+
+ /* ...and if we've exhausted the pattern...
+ */
+ if( *p == '\0' )
+ /*
+ * ...then we simply match all remaining characters,
+ * to the end of "text", so we may return immediately,
+ * reporting a successful match.
+ */
+ return 0;
+
+ /* When we haven't exhausted the pattern, then we may
+ * attempt to recursively match the remainder of the
+ * pattern to some terminal substring of "text"; we do
+ * this iteratively, stepping over as many characters
+ * of "text" as necessary, (and which thus match the '*'
+ * in "pattern"), until we either find the start of this
+ * matching substring, or we exhaust "text" without any
+ * possible match...
+ */
+ do { c = glob_strcmp( p, t, flags | GLOB_PERIOD );
+ } while( (c != 0) && (*t++ != '\0') );
+ /*
+ * ...and ultimately, we return the result of this
+ * recursive attempt to find a match.
+ */
+ return c;
+
+ case '[':
+ /* Here we need to match (or not match) exactly one
+ * character from the candidate text with any one of
+ * a set of characters in the pattern...
+ */
+ if( (c = *t++) == '\0' )
+ /*
+ * ...but, we must return a mismatch if there is no
+ * candidate character left to match.
+ */
+ return '[';
+
+ if( *p == '!' )
+ {
+ /* Match any one character which is NOT in the SET
+ * specified by [!SET].
+ */
+ if( glob_in_set( ++p, c, flags ) == NULL )
+ {
+ if( *p == ']' )
+ p++;
+ p = glob_set_adjusted( p, flags );
+ }
+ }
+ else
+ { /* Match any one character which IS in the SET
+ * specified by [SET].
+ */
+ p = glob_in_set( p, c, flags );
+ }
+ if( p == NULL )
+ /*
+ * The character under test didn't satisfy the SET
+ * matching criterion; return as unmatched.
+ */
+ return ']';
+ break;
+
+ default:
+ /* The escape character cannot be handled as a regular
+ * switch case, because the escape character is specified
+ * as a variable, (to better support Microsoft nuisances).
+ * The escape mechanism may have been disabled within the
+ * glob() call...
+ */
+ if( ((flags & GLOB_NOESCAPE) == 0)
+ /*
+ * ...but when it is active, and we find an escape
+ * character without exhausting the pattern...
+ */
+ && (c == glob_escape_char) && ((c = *p) != 0) )
+ /*
+ * ...then we handle the escaped character here, as
+ * a literal, and step over it, within the pattern.
+ */
+ ++p;
+
+ /* When we get to here, a successful match requires that
+ * the current pattern character "c" is an exact literal
+ * match for the next available character "t", if any,
+ * in the candidate text string...
+ */
+ if( (*t == '\0') || (glob_case_match( flags, c, *t ) != 0) )
+ /*
+ * ...otherwise we return a mismatch.
+ */
+ return c - *t;
+
+ /* No mismatch yet; proceed to test the following character
+ * within the candidate text string.
+ */
+ t++;
+ }
+ }
+ /* When we've exhausted the pattern, then this final check will return
+ * a match if we've simultaneously exhausted the candidate text string,
+ * or a mismatch otherwise.
+ */
+ return c - *t;
+}
+
+#ifdef DT_DIR
+/*
+ * When this is defined, we assume that we can safely interrogate
+ * the d_type member of a globbed dirent structure, to determine if
+ * the referenced directory entry is itself a subdirectory entry.
+ */
+# define GLOB_ISDIR( ent ) ((ent)->d_type == DT_DIR)
+
+#else
+/* We can't simply check for (ent)->d_type == DT_DIR, so we must
+ * use stat() to identify subdirectory entries.
+ */
+# include <sys/stat.h>
+
+ GLOB_INLINE
+ int GLOB_ISDIR( const struct *dirent ent )
+ {
+ struct stat entinfo;
+ if( stat( ent->d_name, &entinfo ) == 0 )
+ return S_ISDIR( entinfo.st_mode );
+ return 0;
+ }
+#endif
+
+#if _DIRENT_HAVE_D_NAMLEN
+/*
+ * Our DIRENT implementation provides a direct indication
+ * of the length of the file system entity name returned by
+ * the last readdir operation...
+ */
+# define D_NAMLEN( entry ) ((entry)->d_namlen)
+#else
+/*
+ * ...otherwise, we have to scan for it.
+ */
+# define D_NAMLEN( entry ) (strlen( (entry)->d_name ))
+#endif
+
+static int glob_initialise( glob_t *gl_data )
+{
+ /* Helper routine to initialise a glob_t structure
+ * for first time use.
+ */
+ if( gl_data != NULL )
+ {
+ /* Caller gave us a valid pointer to what we assume has been
+ * defined as a glob_t structure; allocate space on the heap,
+ * for storage of the globbed paths vector...
+ */
+ int entries = gl_data->gl_offs + 1;
+ if( (gl_data->gl_pathv = malloc( entries * sizeof( char ** ) )) == NULL )
+ /*
+ * ...bailing out, if insufficient free heap memory.
+ */
+ return GLOB_NOSPACE;
+
+ /* On successful allocation, clear the initial path count...
+ */
+ gl_data->gl_pathc = 0;
+ while( entries > 0 )
+ /*
+ * ...and place a NULL pointer in each allocated slot...
+ */
+ gl_data->gl_pathv[--entries] = NULL;
+ }
+ /* ...ultimately returning a successful initialisation status.
+ */
+ return GLOB_SUCCESS;
+}
+
+GLOB_INLINE int glob_expand( glob_t *gl_buf )
+{
+ /* Inline helper to compute the new size allocation required
+ * for buf->gl_pathv, prior to adding a new glob result.
+ */
+ return ((2 + gl_buf->gl_pathc + gl_buf->gl_offs) * sizeof( char ** ));
+}
+
+static int glob_store_entry( char *path, glob_t *gl_buf )
+{
+ /* Local helper routine to add a single path name entity
+ * to the globbed path vector, after first expanding the
+ * allocated memory space to accommodate it.
+ */
+ char **pathv;
+ if( (path != NULL) && (gl_buf != NULL)
+ && ((pathv = realloc( gl_buf->gl_pathv, glob_expand( gl_buf ))) != NULL) )
+ {
+ /* Memory expansion was successful; store the new path name
+ * in place of the former NULL pointer at the end of the old
+ * vector...
+ */
+ gl_buf->gl_pathv = pathv;
+ gl_buf->gl_pathv[gl_buf->gl_offs + gl_buf->gl_pathc++] = path;
+ /*
+ * ...then place a further NULL pointer into the newly allocated
+ * slot, to mark the new end of the vector...
+ */
+ gl_buf->gl_pathv[gl_buf->gl_offs + gl_buf->gl_pathc] = NULL;
+ /*
+ * ...before returning a successful completion status.
+ */
+ return GLOB_SUCCESS;
+ }
+ /* If we get to here, then we were unsuccessful.
+ */
+ return GLOB_ABORTED;
+}
+
+struct glob_collator
+{
+ /* A private data structure, used to keep an ordered collection
+ * of globbed path names in collated sequence within a (possibly
+ * unbalanced) binary tree.
+ */
+ struct glob_collator *prev;
+ struct glob_collator *next;
+ char *entry;
+};
+
+GLOB_INLINE struct glob_collator
+*glob_collate_entry( struct glob_collator *collator, ch...
[truncated message content] |