diff options
author | Keith Marshall <keithmarshall@@users.sf.net> | 2009-01-04 17:35:36 +0000 |
---|---|---|
committer | Keith Marshall <keithmarshall@@users.sf.net> | 2009-01-04 17:35:36 +0000 |
commit | f1170e02f2463a0a296f9d3199bb7e6e8257d2ab (patch) | |
tree | 49a26f5f696a935035d66994bb44cbc825c5fee5 /winsup/mingw | |
parent | 952783ba77512e36857a6179da8cada9367ef3cc (diff) | |
download | newlib-f1170e02f2463a0a296f9d3199bb7e6e8257d2ab.zip newlib-f1170e02f2463a0a296f9d3199bb7e6e8257d2ab.tar.gz newlib-f1170e02f2463a0a296f9d3199bb7e6e8257d2ab.tar.bz2 |
Fix MinGW-Bug [2445962]; (reported by Keishi Suenaga).
Diffstat (limited to 'winsup/mingw')
-rw-r--r-- | winsup/mingw/ChangeLog | 12 | ||||
-rw-r--r-- | winsup/mingw/include/getopt.h | 11 | ||||
-rw-r--r-- | winsup/mingw/mingwex/getopt.c | 30 |
3 files changed, 51 insertions, 2 deletions
diff --git a/winsup/mingw/ChangeLog b/winsup/mingw/ChangeLog index 58fc95a..8fa373a 100644 --- a/winsup/mingw/ChangeLog +++ b/winsup/mingw/ChangeLog @@ -1,3 +1,15 @@ +2009-01-04 Keith Marshall <keithmarshall@users.sourceforge.net> + + Fix MinGW-Bug [2445962]; (reported by Keishi Suenaga). + Also add tentative support for BSD specific `optreset' feature. + + * include/getopt.h (optreset) [_BSD_SOURCE]: Define; map it to... + (__mingw_optreset): ...this new global variable. + + * mingwex/getopt.c (__mingw_optreset): Instantiate it... + (getopt_parse) [optind < 1]: ...make it true; use it to reset argument + parsing context. + 2008-12-31 Keith Marshall <keithmarshall@users.sourceforge.net> Partial fix for MinGW-Bug [2457778]: (Reported by Sisyphus). diff --git a/winsup/mingw/include/getopt.h b/winsup/mingw/include/getopt.h index 00cd547..a57d3f0 100644 --- a/winsup/mingw/include/getopt.h +++ b/winsup/mingw/include/getopt.h @@ -45,6 +45,17 @@ extern char *optarg; /* pointer to argument of current option */ extern int getopt( int, char * const [], const char * ); +#ifdef _BSD_SOURCE +/* + * BSD adds the non-standard `optreset' feature, for reinitialisation + * of `getopt' parsing. We support this feature, for applications which + * proclaim their BSD heritage, before including this header; however, + * to maintain portability, developers are advised to avoid it. + */ +# define optreset __mingw_optreset + +extern int optreset; +#endif #ifdef __cplusplus } #endif diff --git a/winsup/mingw/mingwex/getopt.c b/winsup/mingw/mingwex/getopt.c index 081cc56..29753ca 100644 --- a/winsup/mingw/mingwex/getopt.c +++ b/winsup/mingw/mingwex/getopt.c @@ -87,6 +87,14 @@ enum int optopt = getopt_unknown; /* return value for option being evaluated */ +/* Some BSD applications expect to be able to reinitialise `getopt' parsing + * by setting a global variable called `optreset'. We provide an obfuscated + * API, which allows applications to emulate this brain damage; however, any + * use of this is non-portable, and is strongly discouraged. + */ +#define optreset __mingw_optreset +int optreset = 0; + static __inline__ int getopt_missing_arg( const CHAR *optstring ) { @@ -313,7 +321,7 @@ int getopt_parse( int mode, getopt_std_args, ... ) static const CHAR *nextchar = NULL; static int optmark = 0; - if( optind < optbase ) + if( (optreset |= (optind < 1)) || (optind < optbase) ) { /* POSIX does not prescribe any definitive mechanism for restarting * a `getopt' scan, but some applications may require such capability. @@ -325,7 +333,25 @@ int getopt_parse( int mode, getopt_std_args, ... ) * adjusting all of the internal placeholders to one less than the * adjusted `optind' value, (but never to less than zero). */ - optmark = optbase = argind = (optind > 0) ? optind - 1 : 0; + if( optreset ) + { + /* User has explicitly requested reinitialisation... + * We need to reset `optind' to it's normal initial value of 1, + * to avoid a potential infinitely recursive loop; by doing this + * up front, we also ensure that the remaining placeholders will + * be correctly reinitialised to no less than zero. + */ + optind = 1; + + /* We also need to clear the `optreset' request... + */ + optreset = 0; + } + + /* Now, we may safely reinitialise the internal placeholders, to + * one less than `optind', without fear of making them negative. + */ + optmark = optbase = argind = optind - 1; nextchar = NULL; } |