• R/O
  • HTTP
  • SSH
  • HTTPS

コミット

タグ
未設定

よく使われているワード(クリックで追加)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

The MinGW.org Windows System Libraries


コミットメタ情報

リビジョン1559fe3708515b7c61a0e7d2672102ec5ea1f1fa (tree)
日時2017-02-12 19:12:06
作者Keith Marshall <keithmarshall@user...>
コミッターKeith Marshall

ログメッセージ

Support brace expansion in globbing patterns.

変更サマリ

差分

--- a/mingwrt/ChangeLog
+++ b/mingwrt/ChangeLog
@@ -1,3 +1,23 @@
1+2017-02-12 Keith Marshall <keithmarshall@users.sourceforge.net>
2+
3+ Support brace expansion in globbing patterns.
4+
5+ * include/glob.h (GLOB_BRACE): New manifest constant; define it...
6+ (__GLOB_FLAG__): ...in terms of this macro.
7+
8+ * mingwex/glob.c (glob_match): Reindent, with preamble invoking...
9+ (glob_brace_expand): ...this new static inline function; implement it.
10+ (GLOB_INIT, GLOB_FREE): Redefine them, relating them to...
11+ (__GLOB_FLAG_OFFSET_HIGH_WATER_MARK): ...this.
12+
13+ * setargv.c (__mingw32_setargv) [_CRT_glob]: Check if it includes...
14+ [GLOB_CASEMATCH | GLOB_BRACE]: either of these; remove check for...
15+ [__CRT_GLOB_CASE_SENSITIVE__]: ...this defunct option.
16+
17+ * include/_mingw.h.in (GLOB_BRACE): Note its use in _CRT_glob.
18+ (GLOB_CASEMATCH): Likewise; this replaces all former usage of...
19+ (__CRT_GLOB_CASE_SENSITIVE__): ...this; delete definition.
20+
121 2017-02-11 Keith Marshall <keithmarshall@users.sourceforge.net>
222
323 Refactor <getopt.h> and <unistd.h> shared declarations.
--- a/mingwrt/include/_mingw.h.in
+++ b/mingwrt/include/_mingw.h.in
@@ -132,7 +132,10 @@
132132 * character which is either included
133133 * in, or excluded from the group.
134134 *
135- * __CRT_GLOB_CASE_SENSITIVE__ enable case sensitive matching for
135+ * The following options, which may also be specified within _CRT_glob,
136+ * are specified in terms of their glob() flags, as defined in <glob.h>
137+ *
138+ * GLOB_CASEMATCH enable case sensitive matching for
136139 * globbing patterns; this is default
137140 * behaviour for POSIX, but because of
138141 * the case insensitive nature of the
@@ -140,10 +143,13 @@
140143 * appropriate to use case insensitive
141144 * globbing as the MinGW default.
142145 *
146+ * GLOB_BRACE enable expansion of GNU style brace
147+ * delimited expression groups within
148+ * the globbing pattern.
149+ *
143150 */
144151 #define __CRT_GLOB_USE_SINGLE_QUOTE__ 0x0010
145152 #define __CRT_GLOB_BRACKET_GROUPS__ 0x0020
146-#define __CRT_GLOB_CASE_SENSITIVE__ 0x0040
147153
148154 /* The MinGW globbing algorithm uses the ASCII DEL control code as a marker
149155 * for globbing characters which were embedded within quoted arguments; (the
--- a/mingwrt/include/glob.h
+++ b/mingwrt/include/glob.h
@@ -32,12 +32,15 @@
3232 *
3333 */
3434 #define _GLOB_H 1
35-#include <_mingw.h>
3635 #pragma GCC system_header
3736
37+/* All MinGW.org system headers are required to include <_mingw.h>.
38+ */
39+#include <_mingw.h>
40+
3841 #ifndef RC_INVOKED
3942 /* POSIX requires glob.h to define the size_t type; we need to
40- * get this from GCC, just as sys/types.h does.
43+ * get this from GCC's <stddef.h>, just as <sys/types.h> does.
4144 */
4245 #define __need_size_t
4346 #include <stddef.h>
@@ -73,8 +76,8 @@ enum {
7376 * GNU's implementation of glob() supports a supplementary set of
7477 * options, none of which are required by POSIX. We include these
7578 * for reference, and to reserve the flag identities for a possible
76- * future implementation; the current MinGW implementation does not
77- * support them.
79+ * future implementation; of these extensions, the current MinGW
80+ * implementation supports only GLOB_BRACE.
7881 */
7982 __GLOB_TILDE_OFFSET,
8083 __GLOB_TILDE_CHECK_OFFSET,
@@ -115,6 +118,11 @@ enum {
115118 #define GLOB_NOESCAPE __GLOB_FLAG__(NOESCAPE)
116119 #define GLOB_NOSORT __GLOB_FLAG__(NOSORT)
117120
121+/* Flag definitions for those GNU extensions, as listed above, for which
122+ * we provide support; (i.e. GLOB_BRACE only, at present).
123+ */
124+#define GLOB_BRACE __GLOB_FLAG__(BRACE)
125+
118126 /* Additional flags definitions, for MinGW specific extensions.
119127 */
120128 #define GLOB_CASEMATCH __GLOB_FLAG__(CASEMATCH)
@@ -155,4 +163,4 @@ _END_C_DECLS
155163 #define GLOB_NOSPACE (3)
156164
157165 #endif /* ! RC_INVOKED */
158-#endif /* ! defined _GLOB_H */
166+#endif /* !_GLOB_H: $RCSfile$: end of file */
--- a/mingwrt/mingwex/glob.c
+++ b/mingwrt/mingwex/glob.c
@@ -728,6 +728,132 @@ accept_glob_nocheck_match( const char *pattern, int flags )
728728 return (flags & GLOB_NOCHECK) && (is_glob_pattern( pattern, flags ) == 0);
729729 }
730730
731+GLOB_INLINE int
732+glob_brace_expand( char *dest, const char *src, const char **resume )
733+{
734+ /* Helper to iteratively expand the first substitution field within
735+ * a glob brace expression, while recursively collecting the set of
736+ * individual globbing patterns to be processed by glob_match(), when
737+ * GLOB_BRACE is specified, and the original pattern includes a brace
738+ * expression. (Notice that this does not guarantee to fully expand
739+ * the pattern in a single pass; recursion within glob_match() will
740+ * ensure that this is achieved, before attempting to match each
741+ * possible expansion of the original pattern).
742+ *
743+ * Returns zero on a successful (possibly partial) expansion; > zero
744+ * indicates unmatched opening braces, (an error condition).
745+ */
746+ char c; int level = 1;
747+ do { /* Copy characters one by one, from the start of the current
748+ * substitution field within the original glob pattern, to the
749+ * appropriate location in the pattern which will be presented
750+ * to glob_match(). The initial part of this copy represents
751+ * the substitution for the outermost level of brace bounded
752+ * expression, terminating at either the closing brace or at
753+ * any intervening comma at this level; however...
754+ */
755+ if( (c = *++src) == glob_escape_char )
756+ { /* ...any escaped character must be copied verbatim, without
757+ * being considered as a possible substitution terminator...
758+ */
759+ *dest++ = c; *dest++ = c = *++src;
760+ /* ...while taking care not to overrun the ultimate string
761+ * terminator of the original pattern.
762+ */
763+ if( c != '\0' ) c = *++src;
764+ }
765+ /* Provided it has not been escaped, any closing brace, or a
766+ * comma separator at the outer level only, results in closure
767+ * of a brace nesting level...
768+ */
769+ if( (c == '}') || ((c == ',') && (level == 1)) ) --level;
770+ /*
771+ * ...while an opening brace creates a new (inner) level.
772+ */
773+ else if( c == '{' ) ++level;
774+
775+ /* Provided we have not closed the outermost brace expression
776+ * level, complete the copy of the current character within
777+ * the substitution...
778+ */
779+ if( level > 0 ) *dest++ = c;
780+ /* ...continuing to the next character, until the outermost
781+ * level has been reached, or the original pattern string
782+ * has been exhausted.
783+ */
784+ } while( (level > 0) && (c != '\0') );
785+
786+ /* Save a reference to the point, within the original pattern,
787+ * where the current substitution ended, and thus where the next
788+ * iteration (if any) is to begin.
789+ */
790+ *resume = src;
791+
792+ /* Complete construction of a candidate pattern, to be passed
793+ * to glob_match(), by copying any characters which follow the
794+ * closing brace of the initial brace bounded expression within
795+ * the original pattern; thus...
796+ */
797+ if( c != '\0' )
798+ { /* ...when any characters are present, beyond the current
799+ * resume point...
800+ */
801+ if( c == ',' )
802+ { /* ...and when any of these represent a substitution which
803+ * is to be made in a subsequent iteration...
804+ */
805+ level = 1;
806+ do { /* ...we simply skip over all characters, up to and
807+ * including the closing brace at the outermost level
808+ * of expression, (while once again taking care not
809+ * to overrun the string terminator)...
810+ */
811+ if( c != '\0' ) ++src;
812+ /* ...and once again, honouring escapes which may be
813+ * intended to force literal interpretation of '{'...
814+ */
815+ while( (*src == glob_escape_char) && (*++src != '\0') ) ++src;
816+ /*
817+ * ...and simply ignoring any nested (inner) brace
818+ * bounded expression...
819+ */
820+ if( *src == '{' ) ++level; else if( *src == '}' ) --level;
821+ /*
822+ * ...we continue skipping, until we find the closing
823+ * brace at the outermost level of the expression, or
824+ * we have have exhausted the original pattern.
825+ */
826+ } while( ((c = *src) != '\0') && (level > 0) );
827+ }
828+ /* Finally...
829+ */
830+ if( level == 0 )
831+ { /* ...when we've skipped to the closing brace ... (checking
832+ * that we didn't exhaust the original pattern is belt and
833+ * braces here, because *src should be '}') ... we now skip
834+ * past it...
835+ */
836+ if( c != '\0' ) ++src;
837+ /* ...we simply copy all further characters from the original
838+ * pattern, without consideration that there may be any further
839+ * possible expansion; (this will be picked up by recursion).
840+ */
841+ do { *dest++ = *src; } while( *src++ != '\0' );
842+ }
843+ else
844+ /* Alternatively, when the closing brace has not been found,
845+ * (which implies exhaustion of the original pattern), we
846+ * must ensure that the expanded copy is terminated.
847+ */
848+ *dest = '\0';
849+ }
850+ /* Regardless, we return the residual brace expansion level; zero
851+ * indicates successful expansion; > zero is an error, indicating
852+ * one (or more) unmatched opening braces.
853+ */
854+ return level;
855+}
856+
731857 static int
732858 glob_match( const char *pattern, int flags, int (*errfn)(), glob_t *gl_buf )
733859 {
@@ -735,230 +861,339 @@ glob_match( const char *pattern, int flags, int (*errfn)(), glob_t *gl_buf )
735861 * implementation, recursively decomposing the pattern into separate
736862 * globbable path components, to collect the union of all possible
737863 * matches to the pattern, in all possible matching directories.
864+ *
865+ * At the outset, assume that this will succeed.
738866 */
739- glob_t local_gl_buf;
740867 int status = GLOB_SUCCESS;
741868
742- /* Begin by separating out any path prefix from the glob pattern.
869+ /* To handle the GNU specific GLOB_BRACE option, we need a
870+ * recursive preamble to the bare glob_match() strategy; when
871+ * GLOB_BRACE expansion is specified...
743872 */
744- char dirbuf[1 + strlen( pattern )];
745- const char *dir = dirname( memcpy( dirbuf, pattern, sizeof( dirbuf )) );
746- char **dirp, preferred_dirsep = GLOB_DIRSEP;
873+ int brace_option;
874+ if( (brace_option = flags & GLOB_BRACE) == GLOB_BRACE )
875+ {
876+ /* ...we recursively parse the original pattern, so as to
877+ * decompose it into a series of substitute patterns, each
878+ * of which represents one pattern expansion to which glob
879+ * matching is applied in turn, such that the aggregate of
880+ * matches for the series represents all possible matches
881+ * for all possible expansions of the original pattern.
882+ */
883+ const char *src = pattern;
884+ char c, sub_pattern[1 + strlen( pattern )], *dest = sub_pattern;
747885
748- /* Initialise a temporary local glob_t structure, to capture the
749- * intermediate results at the current level of recursion...
750- */
751- local_gl_buf.gl_offs = 0;
752- if( (status = glob_initialise( &local_gl_buf )) != GLOB_SUCCESS )
753- /*
754- * ...bailing out if unsuccessful.
886+ /* We begin by initialising the prefix portion which is
887+ * common to all substitute patterns...
888+ */
889+ do { /* ...by copying characters one at a time, from the
890+ * original pattern to the substitute pattern buffer...
891+ */
892+ while( *src == glob_escape_char )
893+ {
894+ /* ...ensuring that all escaped characters are
895+ * copied verbatim, without consideration as a
896+ * possible brace expression initiator...
897+ */
898+ *dest++ = *src++;
899+ /*
900+ * ...but taking care that we don't overrun the
901+ * original pattern's string terminator...
902+ */
903+ if( *src != '\0') *dest++ = *src++;
904+ }
905+ /* ...copying every character up to but excluding the
906+ * opening brace of the first brace bounded expression
907+ * (if any), or up to and including the NUL terminator
908+ * otherwise...
909+ */
910+ if( (c = *src) != '{' ) *dest++ = *src++;
911+ /*
912+ * ...repeating until we either exhaust the original
913+ * pattern, or we find an opening brace.
914+ */
915+ } while( (c != '\0') && (c != '{') );
916+
917+ /* After copying the prefix, (which may represent the entire
918+ * pattern)...
755919 */
756- return status;
920+ if( c == '{' )
921+ /* ...when there is a brace bounded expression to expand...
922+ */
923+ do { /* ...iterate to construct each of its expansions in
924+ * turn, (together with any common suffix), and...
925+ */
926+ if( glob_brace_expand( dest, src, &src ) == 0 )
927+ {
928+ /* ...on success, note that there may be further
929+ * embedded brace bounded sub-expressions; recurse
930+ * to achieve full expansion...
931+ */
932+ status = glob_match( sub_pattern, flags, errfn, gl_buf );
933+ /*
934+ * ...and ensure that matches to all expansions
935+ * after the first, will be appended.
936+ */
937+ flags |= GLOB_APPEND;
938+ }
939+ else
940+ { /* Brace expansion failed, (which implies an opening
941+ * brace with no matching closing brace); bail out.
942+ *
943+ * FIXME: if errfn is specified (not NULL), perhaps we
944+ * should invoke it (but how best? POSIX says it is to
945+ * be invoked when pattern resolves to a directory which
946+ * cannot be opened, or cannot be read; maybe pass the
947+ * original failing pattern, with errno = EINVAL?).
948+ */
949+ status = GLOB_ABORTED;
950+ }
951+ /* Repeat iteration until all specified substitutions
952+ * for the current expression have been processed, (or
953+ * aborted).
954+ */
955+ } while( (status != GLOB_ABORTED) && (*src == ',') );
956+
957+ else
958+ /* The current brace expression has been reduced to its final
959+ * form, (with no further expansion pending); release it for
960+ * fall-through glob matching.
961+ */
962+ brace_option = 0;
963+ }
757964
758- /* Check if there are any globbing tokens in the path prefix...
965+ /* On falling through brace expansion, (if any)...
759966 */
760- if( is_glob_pattern( dir, flags ) )
761- /*
762- * ...and recurse to identify all possible matching prefixes,
763- * as may be necessary...
967+ if( brace_option == 0 )
968+ {
969+ /* ...we have exactly one pattern, with no possible expansions
970+ * of brace expressions, to be globbed; (alternate expansions of
971+ * any brace expressions are processed in alternative recursive
972+ * invocations of this function).
764973 */
765- status = glob_match( dir, flags | GLOB_DIRONLY, errfn, &local_gl_buf );
974+ glob_t local_gl_buf;
766975
767- else
768- /* ...or simply store the current prefix, if not.
976+ /* Begin by separating out any path prefix from the glob pattern.
769977 */
770- status = glob_store_entry( glob_strdup( dir ), &local_gl_buf );
978+ char dirbuf[1 + strlen( pattern )];
979+ const char *dir = dirname( memcpy( dirbuf, pattern, sizeof( dirbuf )) );
980+ char **dirp, preferred_dirsep = GLOB_DIRSEP;
771981
772- /* Check nothing has gone wrong, so far...
773- */
774- if( status != GLOB_SUCCESS )
775- /*
776- * ...and bail out if necessary.
777- */
778- return status;
779-
780- /* The original "pattern" argument may have included a path name
781- * prefix, which we used "dirname()" to isolate. If there was no
782- * such prefix, then "dirname()" would have reported an effective
783- * prefix which is identically equal to "."; however, this would
784- * also be the case if the prefix was "./" (or ".\\" in the case
785- * of a WIN32 host). Thus, we may deduce that...
786- */
787- if( glob_is_dirsep( pattern[1] ) || (strcmp( dir, "." ) != 0) )
788- {
789- /* ...when the prefix is not reported as ".", or even if it is
790- * but the original pattern had "./" (or ".\\") as the prefix,
791- * then we must adjust to identify the effective pattern with
792- * its original prefix stripped away...
982+ /* Initialise a temporary local glob_t structure, to capture the
983+ * intermediate results at the current level of recursion...
793984 */
794- const char *tail = pattern + strlen( dir );
795- while( (tail > pattern) && ! glob_is_dirsep( *tail ) )
796- --tail;
797- while( glob_is_dirsep( *tail ) )
798- preferred_dirsep = *tail++;
799- pattern = tail;
800- }
985+ local_gl_buf.gl_offs = 0;
986+ if( (status = glob_initialise( &local_gl_buf )) != GLOB_SUCCESS )
987+ /*
988+ * ...bailing out if unsuccessful.
989+ */
990+ return status;
801991
802- else
803- /* ...otherwise, we simply note that there was no prefix.
992+ /* Check if there are any globbing tokens in the path prefix...
804993 */
805- dir = NULL;
994+ if( is_glob_pattern( dir, flags ) )
995+ /*
996+ * ...and recurse to identify all possible matching prefixes,
997+ * as may be necessary...
998+ */
999+ status = glob_match( dir, flags | GLOB_DIRONLY, errfn, &local_gl_buf );
8061000
807- /* We now have a globbed list of prefix directories, returned from
808- * recursive processing, in local_gl_buf.gl_pathv, and we also have
809- * a separate pattern which we may attempt to match in each of them;
810- * at the outset, we have yet to match this pattern to anything.
811- */
812- status = GLOB_NOMATCH;
1001+ else
1002+ /* ...or simply store the current prefix, if not.
1003+ */
1004+ status = glob_store_entry( glob_strdup( dir ), &local_gl_buf );
8131005
814- /* When the caller has enabled the GLOB_NOCHECK option, then in the
815- * case of any pattern with no prefix, and which contains no explicit
816- * globbing token...
817- */
818- if( (dir == NULL) && accept_glob_nocheck_match( pattern, flags ) )
819- {
820- /* ...we prefer to store it as is, without any attempt to find
821- * a glob match, (which could also induce a case transliteration
822- * on MS-Windows' case-insensitive file system)...
1006+ /* Check nothing has gone wrong, so far...
8231007 */
824- glob_store_entry( glob_strdup( pattern ), gl_buf );
825- status = GLOB_SUCCESS;
826- }
827- /* ...otherwise we initiate glob matching, to find all possible
828- * file system matches for the designated pattern, within each of
829- * the identified prefix directory paths.
830- */
831- else for( dirp = local_gl_buf.gl_pathv; *dirp != NULL; free( *dirp++ ) )
832- {
833- /* Provided an earlier cycle hasn't scheduled an abort...
1008+ if( status != GLOB_SUCCESS )
1009+ /*
1010+ * ...and bail out if necessary.
1011+ */
1012+ return status;
1013+
1014+ /* The original "pattern" argument may have included a path name
1015+ * prefix, which we used "dirname()" to isolate. If there was no
1016+ * such prefix, then "dirname()" would have reported an effective
1017+ * prefix which is identically equal to "."; however, this would
1018+ * also be the case if the prefix was "./" (or ".\\" in the case
1019+ * of a WIN32 host). Thus, we may deduce that...
8341020 */
835- if( status != GLOB_ABORTED )
1021+ if( glob_is_dirsep( pattern[1] ) || (strcmp( dir, "." ) != 0) )
8361022 {
837- /* ...take each candidate directory in turn, and prepare
838- * to collate any matched entities within it...
1023+ /* ...when the prefix is not reported as ".", or even if it is
1024+ * but the original pattern had "./" (or ".\\") as the prefix,
1025+ * then we must adjust to identify the effective pattern with
1026+ * its original prefix stripped away...
1027+ */
1028+ const char *tail = pattern + strlen( dir );
1029+ while( (tail > pattern) && ! glob_is_dirsep( *tail ) )
1030+ --tail;
1031+ while( glob_is_dirsep( *tail ) )
1032+ preferred_dirsep = *tail++;
1033+ pattern = tail;
1034+ }
1035+
1036+ else
1037+ /* ...otherwise, we simply note that there was no prefix.
8391038 */
840- struct glob_collator *collator = NULL;
1039+ dir = NULL;
8411040
842- /* ...attempt to open the current candidate directory...
1041+ /* We now have a globbed list of prefix directories, returned from
1042+ * recursive processing, in local_gl_buf.gl_pathv, and we also have
1043+ * a separate pattern which we may attempt to match in each of them;
1044+ * at the outset, we have yet to match this pattern to anything.
1045+ */
1046+ status = GLOB_NOMATCH;
1047+
1048+ /* When the caller has enabled the GLOB_NOCHECK option, then in the
1049+ * case of any pattern with no prefix, and which contains no explicit
1050+ * globbing token...
1051+ */
1052+ if( (dir == NULL) && accept_glob_nocheck_match( pattern, flags ) )
1053+ {
1054+ /* ...we prefer to store it as is, without any attempt to find
1055+ * a glob match, (which could also induce a case transliteration
1056+ * on MS-Windows' case-insensitive file system)...
1057+ */
1058+ glob_store_entry( glob_strdup( pattern ), gl_buf );
1059+ status = GLOB_SUCCESS;
1060+ }
1061+ /* ...otherwise we initiate glob matching, to find all possible
1062+ * file system matches for the designated pattern, within each of
1063+ * the identified prefix directory paths.
1064+ */
1065+ else for( dirp = local_gl_buf.gl_pathv; *dirp != NULL; free( *dirp++ ) )
1066+ {
1067+ /* Provided an earlier cycle hasn't scheduled an abort...
8431068 */
844- DIR *dp;
845- if( (dp = opendir( *dirp )) != NULL )
1069+ if( status != GLOB_ABORTED )
8461070 {
847- /* ...and when successful, instantiate a dirent structure...
1071+ /* ...take each candidate directory in turn, and prepare
1072+ * to collate any matched entities within it...
1073+ */
1074+ struct glob_collator *collator = NULL;
1075+
1076+ /* ...attempt to open the current candidate directory...
8481077 */
849- struct dirent *entry;
850- size_t dirlen = (dir == NULL) ? 0 : strlen( *dirp );
851- while( (entry = readdir( dp )) != NULL )
1078+ DIR *dp;
1079+ if( (dp = opendir( *dirp )) != NULL )
8521080 {
853- /* ...into which we read each entry from the candidate
854- * directory, in turn, then...
855- */
856- if( (((flags & GLOB_DIRONLY) == 0) || GLOB_ISDIR( entry ))
857- /*
858- * ...provided we don't require it to be a subdirectory,
859- * or it actually is one...
860- */
861- && (glob_strcmp( pattern, entry->d_name, flags ) == 0) )
1081+ /* ...and when successful, instantiate a dirent structure...
1082+ */
1083+ struct dirent *entry;
1084+ size_t dirlen = (dir == NULL) ? 0 : strlen( *dirp );
1085+ while( (entry = readdir( dp )) != NULL )
8621086 {
863- /* ...and it is a globbed match for the pattern, then
864- * we allocate a temporary local buffer of sufficient
865- * size to assemble the matching path name...
1087+ /* ...into which we read each entry from the candidate
1088+ * directory, in turn, then...
8661089 */
867- char *found;
868- size_t prefix;
869- size_t matchlen = D_NAMLEN( entry );
870- char matchpath[2 + dirlen + matchlen];
871- if( (prefix = dirlen) > 0 )
1090+ if( (((flags & GLOB_DIRONLY) == 0) || GLOB_ISDIR( entry ))
1091+ /*
1092+ * ...provided we don't require it to be a subdirectory,
1093+ * or it actually is one...
1094+ */
1095+ && (glob_strcmp( pattern, entry->d_name, flags ) == 0) )
8721096 {
873- /* ...first copying the prefix, if any,
874- * followed by a directory name separator...
1097+ /* ...and it is a globbed match for the pattern, then
1098+ * we allocate a temporary local buffer of sufficient
1099+ * size to assemble the matching path name...
8751100 */
876- memcpy( matchpath, *dirp, dirlen );
877- if( ! glob_is_dirsep( matchpath[prefix - 1] ) )
878- matchpath[prefix++] = preferred_dirsep;
879- }
880- /* ...and append the matching dirent entry.
881- */
882- memcpy( matchpath + prefix, entry->d_name, matchlen + 1 );
883-
884- /* Duplicate the content of the temporary buffer to
885- * the heap, for assignment into gl_buf->gl_pathv...
886- */
887- if( (found = glob_strdup( matchpath )) == NULL )
888- /*
889- * ...setting the appropriate error code, in the
890- * event that the heap memory has been exhausted.
1101+ char *found;
1102+ size_t prefix;
1103+ size_t matchlen = D_NAMLEN( entry );
1104+ char matchpath[2 + dirlen + matchlen];
1105+ if( (prefix = dirlen) > 0 )
1106+ {
1107+ /* ...first copying the prefix, if any,
1108+ * followed by a directory name separator...
1109+ */
1110+ memcpy( matchpath, *dirp, dirlen );
1111+ if( ! glob_is_dirsep( matchpath[prefix - 1] ) )
1112+ matchpath[prefix++] = preferred_dirsep;
1113+ }
1114+ /* ...and append the matching dirent entry.
8911115 */
892- status = GLOB_NOSPACE;
1116+ memcpy( matchpath + prefix, entry->d_name, matchlen + 1 );
8931117
894- else
895- { /* This glob match has been successfully recorded on
896- * the heap, ready for assignment to gl_buf->gl_pathv;
897- * if this is the first match assigned to this gl_buf,
898- * and we haven't trapped any prior error...
1118+ /* Duplicate the content of the temporary buffer to
1119+ * the heap, for assignment into gl_buf->gl_pathv...
8991120 */
900- if( status == GLOB_NOMATCH )
1121+ if( (found = glob_strdup( matchpath )) == NULL )
9011122 /*
902- * ...then record this successful match.
1123+ * ...setting the appropriate error code, in the
1124+ * event that the heap memory has been exhausted.
9031125 */
904- status = GLOB_SUCCESS;
1126+ status = GLOB_NOSPACE;
9051127
906- if( (flags & GLOB_NOSORT) == 0 )
907- {
908- /* The results of this glob are to be sorted in
909- * collating sequence order; divert the current
910- * match into the collator.
911- */
912- collator = glob_collate_entry( collator, found, flags );
913- }
9141128 else
915- { /* Sorting has been suppressed for this glob;
916- * just add the current match directly into the
917- * result vector at gl_buf->gl_pathv.
1129+ { /* This glob match has been successfully recorded on
1130+ * the heap, ready for assignment to gl_buf->gl_pathv;
1131+ * if this is the first match assigned to this gl_buf,
1132+ * and we haven't trapped any prior error...
9181133 */
919- glob_store_entry( found, gl_buf );
1134+ if( status == GLOB_NOMATCH )
1135+ /*
1136+ * ...then record this successful match.
1137+ */
1138+ status = GLOB_SUCCESS;
1139+
1140+ if( (flags & GLOB_NOSORT) == 0 )
1141+ {
1142+ /* The results of this glob are to be sorted in
1143+ * collating sequence order; divert the current
1144+ * match into the collator.
1145+ */
1146+ collator = glob_collate_entry( collator, found, flags );
1147+ }
1148+ else
1149+ { /* Sorting has been suppressed for this glob;
1150+ * just add the current match directly into the
1151+ * result vector at gl_buf->gl_pathv.
1152+ */
1153+ glob_store_entry( found, gl_buf );
1154+ }
9201155 }
9211156 }
9221157 }
1158+ /* When we've processed all of the entries in the current
1159+ * prefix directory, we may close it.
1160+ */
1161+ closedir( dp );
9231162 }
924- /* When we've processed all of the entries in the current
925- * prefix directory, we may close it.
926- */
927- closedir( dp );
928- }
929- /* In the event of failure to open the candidate prefix directory...
930- */
931- else if( (flags & GLOB_ERR) || ((errfn != NULL) && errfn( *dirp, errno )) )
932- /*
933- * ...and when the caller has set the GLOB_ERR flag, or has provided
934- * an error handler which returns non-zero for the failure condition,
935- * then we schedule an abort.
1163+ /* In the event of failure to open the candidate prefix directory...
9361164 */
937- status = GLOB_ABORTED;
1165+ else if( (flags & GLOB_ERR) || ((errfn != NULL) && errfn(*dirp, errno)) )
1166+ /*
1167+ * ...and when the caller has set the GLOB_ERR flag, or has provided
1168+ * an error handler which returns non-zero for the failure condition,
1169+ * then we schedule an abort.
1170+ */
1171+ status = GLOB_ABORTED;
9381172
939- /* When we diverted the glob results for collation...
940- */
941- if( collator != NULL )
942- /*
943- * ...then we redirect them to gl_buf->gl_pathv now, before we
944- * begin a new cycle, to process any further prefix directories
945- * which may have been identified; note that we do this even if
946- * we scheduled an abort, so that we may return any results we
947- * may have already collected before the error occurred.
1173+ /* When we diverted the glob results for collation...
9481174 */
949- glob_store_collated_entries( collator, gl_buf );
1175+ if( collator != NULL )
1176+ /*
1177+ * ...then we redirect them to gl_buf->gl_pathv now, before we
1178+ * begin a new cycle, to process any further prefix directories
1179+ * which may have been identified; note that we do this even if
1180+ * we scheduled an abort, so that we may return any results we
1181+ * may have already collected before the error occurred.
1182+ */
1183+ glob_store_collated_entries( collator, gl_buf );
1184+ }
9501185 }
1186+ /* Finally, free the memory block allocated for the results vector
1187+ * in the internal glob buffer, to avoid leaking memory, before we
1188+ * return the resultant status code.
1189+ */
1190+ free( local_gl_buf.gl_pathv );
9511191 }
952- /* Finally, free the memory block allocated for the results vector
953- * in the internal glob buffer, to avoid leaking memory, before we
954- * return the resultant status code.
955- */
956- free( local_gl_buf.gl_pathv );
9571192 return status;
9581193 }
9591194
960-#define GLOB_INIT (0x100 << 0)
961-#define GLOB_FREE (0x100 << 1)
1195+#define GLOB_INIT (1 << __GLOB_FLAG_OFFSET_HIGH_WATER_MARK)
1196+#define GLOB_FREE (2 << __GLOB_FLAG_OFFSET_HIGH_WATER_MARK)
9621197
9631198 GLOB_INLINE int glob_signed( const char *check, const char *magic )
9641199 {
--- a/mingwrt/setargv.c
+++ b/mingwrt/setargv.c
@@ -101,9 +101,7 @@ void __mingw32_setargv( const char *cmdline )
101101 /* Capture any non-default globbing options, which the user may have
102102 * specified via a custom setting for _CRT_glob.
103103 */
104- int gl_opts = GLOB_NOCHECK;
105- if( _CRT_glob & __CRT_GLOB_CASE_SENSITIVE__ )
106- gl_opts |= GLOB_CASEMATCH;
104+ int gl_opts = GLOB_NOCHECK | (_CRT_glob & (GLOB_CASEMATCH | GLOB_BRACE));
107105
108106 /* We explicitly DO NOT use the GLOB_DOOFFS capability; ensure that
109107 * the associated field, in the glob_t structure, is initialized to