Menu

#1224 Mingw getopt reset bug.

closed-fixed
2014-08-24
2008-12-18
No

Following code returns no response,
with mingwrt-3.15.1-mingw32.tar.gz.

Remove optind=0; line
then it works fine ( returns "opt=U" ).

Keishi Suenaga(skeishi@yahoo.co.jp)

-------------------------------------------------
#include <stdio.h>
#include <getopt.h>

int main(int argc, char **argv)
{
int opt;
int c = 2;
char *v[2] = { "opt", "-U" };
optind = 0; /* this is the line */
opt = getopt(c, v, "Uv");
printf("opt=%c \n", opt );
return 0;
}
-------------------------------------------------

If you need fllowing Infomation.

Host Operating System Information and Version

Microsoft Windows XP
Professional x64 Edition
Version 2003
Service Pack 2

GCC Version
Using built-in specs.
Target: mingw32
Configured with: ../gcc-4.3.0/configure --enable-languages=c,ada,c++,fortran,jav
a,objc,obj-c++ --disable-sjlj-exceptions --enable-shared --enable-libgcj --enabl
e-libgomp --with-dwarf2 --disable-win32-registry --enable-libstdcxx-debug --enab
le-concept-checks --enable-version-specific-runtime-libs --build=mingw32 --with-
bugurl=http://www.mingw.org/bugs.shtml --prefix=/mingw --with-gmp=/mingw/src/gcc
/gmp-mpfr-root --with-mpfr=/mingw/src/gcc/gmp-mpfr-root --with-libiconv-prefix=/
mingw/src/gcc/libiconv-root
Thread model: win32
gcc version 4.3.0 20080305 (alpha-testing) mingw-20080502 (GCC)

Binutils Version
GNU ld (GNU Binutils) 2.18.50.20080109

Build Environment
uname -a
MINGW32_NT-5.2 MEDAKA 1.0.11(0.46/3/2) 2008-08-25 23:40 i686 Msys

Discussion

  • Keishi Suenaga

    Keishi Suenaga - 2008-12-19

    I made a patch.
    This works fine in my case.

    Keishi Suenaga(skeishi@yahoo.co.jp)

    -------------------------------------------------------------------------
    diff -c mingwrt-3.15.1-mingw32/mingwex/getopt.c.orig mingwrt-3.15.1-mingw32/mingwex/getopt.c
    *** mingwrt-3.15.1-mingw32/mingwex/getopt.c.orig Sun Oct 5 03:12:01 2008
    --- mingwrt-3.15.1-mingw32/mingwex/getopt.c Fri Dec 19 09:47:02 2008
    ***************
    *** 326,331 ****
    --- 326,332 ----
    * adjusted `optind' value, (but never to less than zero).
    */
    optmark = optbase = argind = (optind > 0) ? optind - 1 : 0;
    + if(optind <= 0) optind = 1;
    nextchar = NULL;
    }
    ---------------------------------------------------------------------------

     
  • Keith Marshall

    Keith Marshall - 2008-12-19
    • milestone: 102880 -->
    • assigned_to: nobody --> keithmarshall
     
  • Keith Marshall

    Keith Marshall - 2008-12-19

    Thanks for the report.

    Your patch confirms that my own evaluation of the problem is correct. I introduced a potential infinite recursion, when I fixed bug 2144266; using `optbase' instead of `optind' for internal state fixed that, but overlooked the need to update `optind', to break an internal recursive call cycle, if the user sets `optind' to less than 1.

    Unfortunately, while your patch appears to break the cycle, my own analysis tells me it isn't sufficient to fix it completely -- in your test case, the `optind' reset action occurs in the second pass, rather than where it belongs, in the first; however, I do have my own alternative patch almost ready to commit.

     
  • Keith Marshall

    Keith Marshall - 2009-01-04
    • status: open --> closed-fixed
     
  • Keith Marshall

    Keith Marshall - 2009-01-04

    I committed this, which I believe fixes this issue:

    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.

    Index: include/getopt.h

    RCS file: /cvs/mingw/mingw/include/getopt.h,v
    retrieving revision 1.3
    retrieving revision 1.4
    diff -u -r1.3 -r1.4
    --- include/getopt.h 31 Aug 2008 22:27:58 -0000 1.3
    +++ include/getopt.h 4 Jan 2009 17:35:36 -0000 1.4
    @@ -45,6 +45,17 @@

    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
    Index: mingwex/getopt.c
    ===================================================================
    RCS file: /cvs/mingw/mingw/mingwex/getopt.c,v
    retrieving revision 1.7
    retrieving revision 1.8
    diff -u -r1.7 -r1.8
    --- mingwex/getopt.c 3 Oct 2008 22:56:18 -0000 1.7
    +++ mingwex/getopt.c 4 Jan 2009 17:35:36 -0000 1.8
    @@ -87,6 +87,14 @@

    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 @@
    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 @@
    * 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;
    }

     
MongoDB Logo MongoDB