[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#954806: gcc-9: Optimizes away something it shouldn't



Package: gcc-9
Version: 9.3.0-3
Severity: normal

Dear Maintainer,

I am writing a general purpose convenience library called Mu (for
Miscellaneous Utilities). It includes an option parsing module intended
to be a replacement for getopt_long().

Options are defined in structures which include various information,
including an optional callback which will be called when the option is
found. The parse_opts() function has a flag `OPT_HELP' (or
`OPT_HELP_SHORT' or `OPT_HELP_LONG') which makes it automatically add a
'-h' and/or a '--help' option which calls a callback to print a usage
message.

The problem is, when the test program (test.c) is compiled with
optimization, the data fields (set at options.c:127-131) passed to the
callback are optimized out. This causes a segmentation fault and/or
error message when './test' is passed '-h' or '--help'. Note that when
the program is compiled without optimization, no memory errors are
reported when run under Valgrind (although memory errors *are* reported
when the program is compiled with optimization).

I thought that the problem may have been that I was casting the data
pointer to (void *), but I tried creating a test program to test that,
and that didn't seem to be the problem.

To compile the program with optimization, I ran:

    $ make CC=gcc-9 CFLAGS='-Wall -O1' clean all

And without optimization:

    $ make CC=gcc-9 CFLAGS='-Wall -O0' clean all

Note that the problem can be reproduced with GCC 10 also
(CC=gcc-10). Also note that no warnings are reported with -Wall, not
even with -O3. Three warnings are reported with -Werror, but I don't
think they are serious or relevant. Here they are, just in case
(compiled with -O3 to catch warnings it might not otherwise):

    $ make CC=gcc-9 CFLAGS='-Wall -Wextra -O3' clean all
    rm -f *.o test
    gcc-9 -Wall -Wextra -O3   -c -o test.o test.c
    gcc-9 -Wall -Wextra -O3   -c -o compat.o compat.c
    gcc-9 -Wall -Wextra -O3   -c -o format.o format.c
    format.c: In function ‘format_list’:
    format.c:277:36: warning: comparison of integer expressions of different signedness: ‘size_t’ {aka ‘long unsigned int’} and ‘int’ [-Wsign-compare]
      277 |     if (width && size + char_width > width - *col) {
          |                                    ^
    In file included from format.c:34:
    format.c:303:27: warning: comparison of integer expressions of different signedness: ‘size_t’ {aka ‘long unsigned int’} and ‘int’ [-Wsign-compare]
      303 |  assert(index + tab_width > width - *col);
          |                           ^
    format.c:314:19: warning: comparison of integer expressions of different signedness: ‘size_t’ {aka ‘long unsigned int’} and ‘int’ [-Wsign-compare]
      314 |  assert(index + 1 > width - *col);
          |                   ^
    gcc-9 -Wall -Wextra -O3   -c -o io.o io.c
    gcc-9 -Wall -Wextra -O3   -c -o options.o options.c
    gcc-9 -Wall -Wextra -O3   -c -o safe.o safe.c
    gcc-9   test.o compat.o format.o io.o options.o safe.o   -o test

Also note that when compiled with Clang (CC=clang), even with -O3, the
program works as expected and no memory errors are reported by Valgrind.

Note that only the -O* and all the -O* options trigger the bug. I tried
manually passing all the -f* options which (according to the
documentation) are enabled by the various -O* options. However,
strangely, I could not reproduce the bug that way.

The following patch adds a nop() function to options.c that is used to
prevent the data fields from being optimized out. When this patch is
applied, the issue is no longer present, even when compiled with -O3
(with gcc-9 or gcc-10).
--- options.c~	2020-03-23 14:23:08.625333110 -0400
+++ options.c	2020-03-23 14:23:17.841369826 -0400
@@ -81,6 +81,13 @@
 static int free_opts(const char *, const OPTION *);
 static int format_help_callback(void *, char *);
 
+static void nop(const void *data, ...) {
+  /* We have to do this so GCC doesn't optimize calls to us away. */
+  va_list ap;
+  va_start(ap, data);
+  va_end(ap);
+}
+
 /*
  * Parse options. Returns zero on success or nonzero on error, in
  * which case an error message will be printed to `stderr'. The last
@@ -137,6 +144,7 @@
     opt->callback_none	= format_help_callback;
     opt->data		= &data;
     opt->help		= "print this help and exit";
+    nop(data.prog_name, data.usage, data.desc, data.notes, data.options);
   }
   else {
     /* This is slightly evil (casting it to a non-const), but we know
Since I was not able write a simpler program that triggers the bug, I
have attached the source tarball (mu.tar.gz). README.Bugs says that I
should provide the *.i files, so I have included them in the
tarball. Different .i files are produced under optimization, so I have
included the ones produced with '-O0 --save-temps'. I have also attached
a patch (nop_preprocessed.patch) that adds the nop() function to the
preprocessed options.i.

Here is the output of 'gcc-9 -v' and 'gcc-10 -v':

    $ gcc-9 -v
    Using built-in specs.
    COLLECT_GCC=gcc-9
    COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper
    OFFLOAD_TARGET_NAMES=nvptx-none:hsa
    OFFLOAD_TARGET_DEFAULT=1
    Target: x86_64-linux-gnu
    Configured with: ../src/configure -v --with-pkgversion='Debian 9.3.0-3' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --with-build-config=bootstrap-lto-lean --enable-link-mutex
    Thread model: posix
    gcc version 9.3.0 (Debian 9.3.0-3) 

    $ gcc-10 -v
    Using built-in specs.
    COLLECT_GCC=gcc-10
    COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/10/lto-wrapper
    OFFLOAD_TARGET_NAMES=nvptx-none:amdgcn-amdhsa:hsa
    OFFLOAD_TARGET_DEFAULT=1
    Target: x86_64-linux-gnu
    Configured with: ../src/configure -v --with-pkgversion='Debian 10-20200312-2' --with-bugurl=file:///usr/share/doc/gcc-10/README.Bugs --enable-languages=c,c++,go,brig,d,fortran,objc,obj-c++,m2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-10 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib=auto --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none,amdgcn-amdhsa,hsa --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
    Thread model: posix
    Supported LTO compression algorithms: zlib zstd
    gcc version 10.0.1 20200312 (experimental) [master revision c56871dd15a:7ba6e7f0f21:daf2852b883762d921361462dad1f99320faca2a] (Debian 10-20200312-2) 

I think this may be an upstream bug, but I'm not sure and README.Bugs
says "If in doubt, report the bug to the Debian BTS."

Thanks,
Asher

-- 
He was part of my dream, of course -- but then I was part of his dream too.
		-- Lewis Carroll
                               --------
I prefer to send and receive mail encrypted. Please send me your
public key, and if you do not have my public key, please let me
know. Thanks.

GPG fingerprint: 38F3 975C D173 4037 B397  8095 D4C9 C4FC 5460 8E68


-- System Information:
Debian Release: bullseye/sid
  APT prefers testing-debug
  APT policy: (500, 'testing-debug'), (500, 'testing')
Architecture: amd64 (x86_64)

Kernel: Linux 5.4.0-4-amd64 (SMP w/2 CPU cores)
Kernel taint flags: TAINT_FIRMWARE_WORKAROUND
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), LANGUAGE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Versions of packages gcc-9 depends on:
ii  binutils      2.34-5
ii  cpp-9         9.3.0-3
ii  gcc-9-base    9.3.0-3
ii  libc6         2.30-2
ii  libcc1-0      10-20200312-2
ii  libgcc-9-dev  9.3.0-3
ii  libgcc-s1     10-20200312-2
ii  libgmp10      2:6.2.0+dfsg-4
ii  libisl22      0.22.1-1
ii  libmpc3       1.1.0-1
ii  libmpfr6      4.0.2-1
ii  libstdc++6    10-20200312-2
ii  zlib1g        1:1.2.11.dfsg-2

Versions of packages gcc-9 recommends:
ii  libc6-dev  2.30-2

Versions of packages gcc-9 suggests:
ii  gcc-9-doc       9.2.0-1
pn  gcc-9-locales   <none>
pn  gcc-9-multilib  <none>

-- no debconf information

Attachment: mu.tar.gz
Description: Mu source tarball

--- options.i~	2020-03-23 14:56:38.434556710 -0400
+++ options.i	2020-03-23 14:56:47.334654330 -0400
@@ -2487,6 +2487,33 @@
 static int free_opts(const char *, const OPTION *);
 static int format_help_callback(void *, char *);
 
+static void nop(const void *data, ...) {
+
+  va_list ap;
+  
+# 87 "options.c" 3 4
+ __builtin_va_start(
+# 87 "options.c"
+ ap
+# 87 "options.c" 3 4
+ ,
+# 87 "options.c"
+ data
+# 87 "options.c" 3 4
+ )
+# 87 "options.c"
+                   ;
+  
+# 88 "options.c" 3 4
+ __builtin_va_end(
+# 88 "options.c"
+ ap
+# 88 "options.c" 3 4
+ )
+# 88 "options.c"
+           ;
+}
+
 
 
 
@@ -2513,51 +2540,51 @@
 
 
     for (n_opts = 0; !((options + n_opts)->short_opt == '\0' && (options + n_opts)->long_opt == 
-# 109 "options.c" 3 4
+# 116 "options.c" 3 4
                      ((void *)0)
-# 109 "options.c"
+# 116 "options.c"
                      ); n_opts++) {
       const OPTION *opt = options + n_opts;
       if (flags & 0b00001000)
  
-# 112 "options.c" 3 4
+# 119 "options.c" 3 4
 ((void) sizeof ((
-# 112 "options.c"
+# 119 "options.c"
 opt->short_opt != 'h'
-# 112 "options.c" 3 4
+# 119 "options.c" 3 4
 ) ? 1 : 0), __extension__ ({ if (
-# 112 "options.c"
+# 119 "options.c"
 opt->short_opt != 'h'
-# 112 "options.c" 3 4
+# 119 "options.c" 3 4
 ) ; else __assert_fail (
-# 112 "options.c"
+# 119 "options.c"
 "opt->short_opt != 'h'"
-# 112 "options.c" 3 4
-, "options.c", 112, __extension__ __PRETTY_FUNCTION__); }))
-# 112 "options.c"
+# 119 "options.c" 3 4
+, "options.c", 119, __extension__ __PRETTY_FUNCTION__); }))
+# 119 "options.c"
                              ;
       if (flags & 0b00010000)
  
-# 114 "options.c" 3 4
+# 121 "options.c" 3 4
 ((void) sizeof ((
-# 114 "options.c"
+# 121 "options.c"
 !opt->long_opt || strcmp(opt->long_opt, "help")
-# 114 "options.c" 3 4
+# 121 "options.c" 3 4
 ) ? 1 : 0), __extension__ ({ if (
-# 114 "options.c"
+# 121 "options.c"
 !opt->long_opt || strcmp(opt->long_opt, "help")
-# 114 "options.c" 3 4
+# 121 "options.c" 3 4
 ) ; else __assert_fail (
-# 114 "options.c"
+# 121 "options.c"
 "!opt->long_opt || strcmp(opt->long_opt, \"help\")"
-# 114 "options.c" 3 4
-, "options.c", 114, __extension__ __PRETTY_FUNCTION__); }))
-# 114 "options.c"
+# 121 "options.c" 3 4
+, "options.c", 121, __extension__ __PRETTY_FUNCTION__); }))
+# 121 "options.c"
                                                        ;
     }
 
 
-    actual_opts = _xmalloc_line("options.c", 118, __func__, sizeof(*actual_opts) * (n_opts + 2));
+    actual_opts = _xmalloc_line("options.c", 125, __func__, sizeof(*actual_opts) * (n_opts + 2));
     memcpy(actual_opts, options, sizeof(*actual_opts) * n_opts);
 
     opt = actual_opts + n_opts;
@@ -2579,6 +2606,7 @@
     opt->callback_none = format_help_callback;
     opt->data = &data;
     opt->help = "print this help and exit";
+    nop(data.prog_name, data.usage, data.desc, data.notes, data.options);
   }
   else {
 
@@ -2589,9 +2617,9 @@
 
 
   for (const OPTION *opt = actual_opts; !((opt)->short_opt == '\0' && (opt)->long_opt == 
-# 149 "options.c" 3 4
+# 157 "options.c" 3 4
                                         ((void *)0)
-# 149 "options.c"
+# 157 "options.c"
                                         ); opt++) {
     if (opt->found_opt)
       *(opt->found_opt) = 0;
@@ -2614,51 +2642,51 @@
    break;
  case OPT_STRING:
    arg->arg_string = 
-# 170 "options.c" 3 4
+# 178 "options.c" 3 4
                     ((void *)0)
-# 170 "options.c"
+# 178 "options.c"
                         ;
    break;
  case OPT_FILE:
    arg->arg_file = 
-# 173 "options.c" 3 4
+# 181 "options.c" 3 4
                   ((void *)0)
-# 173 "options.c"
+# 181 "options.c"
                       ;
    break;
  case OPT_DIRECTORY:
    arg->arg_directory = 
-# 176 "options.c" 3 4
+# 184 "options.c" 3 4
                        ((void *)0)
-# 176 "options.c"
+# 184 "options.c"
                            ;
    break;
  default:
    
-# 179 "options.c" 3 4
+# 187 "options.c" 3 4
   ((void) sizeof ((
-# 179 "options.c"
+# 187 "options.c"
   !"Invalid option type"
-# 179 "options.c" 3 4
+# 187 "options.c" 3 4
   ) ? 1 : 0), __extension__ ({ if (
-# 179 "options.c"
+# 187 "options.c"
   !"Invalid option type"
-# 179 "options.c" 3 4
+# 187 "options.c" 3 4
   ) ; else __assert_fail (
-# 179 "options.c"
+# 187 "options.c"
   "!\"Invalid option type\""
-# 179 "options.c" 3 4
-  , "options.c", 179, __extension__ __PRETTY_FUNCTION__); }))
-# 179 "options.c"
+# 187 "options.c" 3 4
+  , "options.c", 187, __extension__ __PRETTY_FUNCTION__); }))
+# 187 "options.c"
                                 ;
  }
       }
 
       if (opt->argstr)
  *(opt->argstr) = 
-# 184 "options.c" 3 4
+# 192 "options.c" 3 4
                  ((void *)0)
-# 184 "options.c"
+# 192 "options.c"
                      ;
     }
   }
@@ -2666,9 +2694,9 @@
   for (int i = 1; i < argc; i++) {
     char *optstr = argv[i];
     const char *arg = (i + 1 < argc) ? argv[i+1] : 
-# 190 "options.c" 3 4
+# 198 "options.c" 3 4
                                                   ((void *)0)
-# 190 "options.c"
+# 198 "options.c"
                                                       ;
 
 
@@ -2702,21 +2730,21 @@
 
     if (flags & 0b00000001) {
       
-# 222 "options.c" 3 4
+# 230 "options.c" 3 4
      ((void) sizeof ((
-# 222 "options.c"
+# 230 "options.c"
      !(flags & 0b00000010)
-# 222 "options.c" 3 4
+# 230 "options.c" 3 4
      ) ? 1 : 0), __extension__ ({ if (
-# 222 "options.c"
+# 230 "options.c"
      !(flags & 0b00000010)
-# 222 "options.c" 3 4
+# 230 "options.c" 3 4
      ) ; else __assert_fail (
-# 222 "options.c"
+# 230 "options.c"
      "!(flags & OPT_STOP_AFTER_ARG)"
-# 222 "options.c" 3 4
-     , "options.c", 222, __extension__ __PRETTY_FUNCTION__); }))
-# 222 "options.c"
+# 230 "options.c" 3 4
+     , "options.c", 230, __extension__ __PRETTY_FUNCTION__); }))
+# 230 "options.c"
                                           ;
       argv[(*p_argc)++] = optstr;
     }
@@ -2731,9 +2759,9 @@
 
   if (*p_argc < argc)
     argv[*p_argc] = 
-# 235 "options.c" 3 4
+# 243 "options.c" 3 4
                    ((void *)0)
-# 235 "options.c"
+# 243 "options.c"
                        ;
 
   return ret == -1;
@@ -2753,9 +2781,9 @@
 
   struct winsize ws;
   if (ioctl(fileno(file), 
-# 253 "options.c" 3 4
+# 261 "options.c" 3 4
                          0x5413
-# 253 "options.c"
+# 261 "options.c"
                                    , &ws) >= 0)
     width = ws.ws_col;
   else
@@ -2768,9 +2796,9 @@
 
   if (format(file, width, &cur_col, 0, 0, "Usage: %s %s\n%s\n%s",
       prog_name, usage, desc, ((options)->short_opt == '\0' && (options)->long_opt == 
-# 264 "options.c" 3 4
+# 272 "options.c" 3 4
                              ((void *)0)
-# 264 "options.c"
+# 272 "options.c"
                              ) ? "" : "\n"))
     return 1;
 
@@ -2781,9 +2809,9 @@
 
   long_required_arg = short_opts = 0;
   for (const OPTION *opt = options; !((opt)->short_opt == '\0' && (opt)->long_opt == 
-# 273 "options.c" 3 4
+# 281 "options.c" 3 4
                                     ((void *)0)
-# 273 "options.c"
+# 281 "options.c"
                                     ); opt++) {
     if (opt->short_opt) {
       short_opts = 1;
@@ -2801,9 +2829,9 @@
 
 
   for (const OPTION *opt = options; !((opt)->short_opt == '\0' && (opt)->long_opt == 
-# 289 "options.c" 3 4
+# 297 "options.c" 3 4
                                     ((void *)0)
-# 289 "options.c"
+# 297 "options.c"
                                     ); opt++) {
     if (opt->short_opt) {
       if (format(file, width, &cur_col, 0, 0, "  -%c", opt->short_opt))
@@ -2832,7 +2860,7 @@
 
   return 0;
 }
-# 328 "options.c"
+# 336 "options.c"
 static int parse_short_opt(const char *prog_name, const char *optstr,
       const char *argument, const OPTION *options,
       int flags) {
@@ -2844,30 +2872,30 @@
   for (char c = *optstr; (c = *optstr); optstr++) {
     const OPTION *opt;
     const char *argstr = 
-# 338 "options.c" 3 4
+# 346 "options.c" 3 4
                         ((void *)0)
-# 338 "options.c"
+# 346 "options.c"
                             ;
 
 
     for (opt = options; !((opt)->short_opt == '\0' && (opt)->long_opt == 
-# 341 "options.c" 3 4
+# 349 "options.c" 3 4
                         ((void *)0)
-# 341 "options.c"
+# 349 "options.c"
                         ); opt++) {
       if (opt->short_opt == c)
  break;
     }
 
     if (((opt)->short_opt == '\0' && (opt)->long_opt == 
-# 346 "options.c" 3 4
+# 354 "options.c" 3 4
        ((void *)0)
-# 346 "options.c"
+# 354 "options.c"
        )) {
       fprintf(
-# 347 "options.c" 3 4
+# 355 "options.c" 3 4
              stderr
-# 347 "options.c"
+# 355 "options.c"
                    , "%s: '%c': invalid option\n", prog_name, c);
       return -1;
     }
@@ -2922,9 +2950,9 @@
 
   if (*optstr == '=') {
     fprintf(
-# 400 "options.c" 3 4
+# 408 "options.c" 3 4
            stderr
-# 400 "options.c"
+# 408 "options.c"
                  , "%s: %s: invalid option\n", prog_name, optstr);
     return -1;
   }
@@ -2933,9 +2961,9 @@
   index = find_unambiguously(options, optstr);
   if (index < 0) {
     fprintf(
-# 407 "options.c" 3 4
+# 415 "options.c" 3 4
            stderr
-# 407 "options.c"
+# 415 "options.c"
                  , "%s: %s: invalid option\n", prog_name, optstr);
     return -1;
   }
@@ -2977,9 +3005,9 @@
       optstr = opt->long_opt;
 
     fprintf(
-# 447 "options.c" 3 4
+# 455 "options.c" 3 4
            stderr
-# 447 "options.c"
+# 455 "options.c"
                  , "%s: '%s': option requires argument\n", prog_name, optstr);
 
     return 1;
@@ -2992,16 +3020,16 @@
     if (opt->has_arg == OPT_NONE) {
       if (is_short)
  fprintf(
-# 458 "options.c" 3 4
+# 466 "options.c" 3 4
         stderr
-# 458 "options.c"
+# 466 "options.c"
               , "%s: '%c': option does not take argument\n",
   prog_name, opt->short_opt);
       else
  fprintf(
-# 461 "options.c" 3 4
+# 469 "options.c" 3 4
         stderr
-# 461 "options.c"
+# 469 "options.c"
               , "%s: %s: option does not take argument\n",
   prog_name, opt->long_opt);
 
@@ -3034,17 +3062,17 @@
 
     case OPT_INT:
       
-# 492 "options.c" 3 4
+# 500 "options.c" 3 4
      (*__errno_location ()) 
-# 492 "options.c"
+# 500 "options.c"
            = 0;
       arg_int = strtol(argstr, &endptr, 0);
 
       if (*endptr) {
  fprintf(
-# 496 "options.c" 3 4
+# 504 "options.c" 3 4
         stderr
-# 496 "options.c"
+# 504 "options.c"
               , "%s: %s: not a%s\n", prog_name, argstr,
   (opt->type == OPT_BOOL) ? " yes or no value" : "n integer");
  return 1;
@@ -3052,34 +3080,34 @@
 
       if (opt->type == OPT_INT) {
  if (!
-# 502 "options.c" 3 4
+# 510 "options.c" 3 4
      (*__errno_location ()) 
-# 502 "options.c"
+# 510 "options.c"
            && (arg_int < opt->ibound.lower ||
          arg_int > opt->ibound.upper))
    
-# 504 "options.c" 3 4
+# 512 "options.c" 3 4
   (*__errno_location ()) 
-# 504 "options.c"
+# 512 "options.c"
         = 
-# 504 "options.c" 3 4
+# 512 "options.c" 3 4
           34
-# 504 "options.c"
+# 512 "options.c"
                 ;
 
  if (
-# 506 "options.c" 3 4
+# 514 "options.c" 3 4
     (*__errno_location ())
-# 506 "options.c"
+# 514 "options.c"
          ) {
    fprintf(
-# 507 "options.c" 3 4
+# 515 "options.c" 3 4
           stderr
-# 507 "options.c"
+# 515 "options.c"
                 , "%s: %s: %s\n", prog_name, argstr, strerror(
-# 507 "options.c" 3 4
+# 515 "options.c" 3 4
                                                               (*__errno_location ())
-# 507 "options.c"
+# 515 "options.c"
                                                                    ));
    return 1;
  }
@@ -3094,51 +3122,51 @@
 
     case OPT_FLOAT:
       
-# 520 "options.c" 3 4
+# 528 "options.c" 3 4
      (*__errno_location ()) 
-# 520 "options.c"
+# 528 "options.c"
            = 0;
       p_arg->arg_float = strtod(argstr, &endptr);
 
       if (*endptr) {
  fprintf(
-# 524 "options.c" 3 4
+# 532 "options.c" 3 4
         stderr
-# 524 "options.c"
+# 532 "options.c"
               , "%s: %s: not a floating-point number\n",
   prog_name, argstr);
  return 1;
       }
 
       if (!
-# 529 "options.c" 3 4
+# 537 "options.c" 3 4
           (*__errno_location ()) 
-# 529 "options.c"
+# 537 "options.c"
                 && (p_arg->arg_float < opt->fbound.lower ||
        p_arg->arg_float > opt->fbound.upper))
  
-# 531 "options.c" 3 4
+# 539 "options.c" 3 4
 (*__errno_location ()) 
-# 531 "options.c"
+# 539 "options.c"
       = 
-# 531 "options.c" 3 4
+# 539 "options.c" 3 4
         34
-# 531 "options.c"
+# 539 "options.c"
               ;
 
       if (
-# 533 "options.c" 3 4
+# 541 "options.c" 3 4
          (*__errno_location ())
-# 533 "options.c"
+# 541 "options.c"
               ) {
  fprintf(
-# 534 "options.c" 3 4
+# 542 "options.c" 3 4
         stderr
-# 534 "options.c"
+# 542 "options.c"
               , "%s: %s: %s\n", prog_name, argstr, strerror(
-# 534 "options.c" 3 4
+# 542 "options.c" 3 4
                                                             (*__errno_location ())
-# 534 "options.c"
+# 542 "options.c"
                                                                  ));
  return 1;
       }
@@ -3153,28 +3181,28 @@
       p_arg->arg_file = file_open(argstr, opt->file_mode);
       if (!p_arg->arg_file) {
  fprintf(
-# 547 "options.c" 3 4
+# 555 "options.c" 3 4
         stderr
-# 547 "options.c"
+# 555 "options.c"
               , "%s: cannot open %s: %s\n",
   prog_name, argstr, strerror(
-# 548 "options.c" 3 4
+# 556 "options.c" 3 4
                              (*__errno_location ())
-# 548 "options.c"
+# 556 "options.c"
                                   ));
  return 1;
       }
 
       if (p_arg->arg_file == 
-# 552 "options.c" 3 4
+# 560 "options.c" 3 4
                             stdin
-# 552 "options.c"
+# 560 "options.c"
                                  )
  argstr = "<stdin>";
       else if (p_arg->arg_file == 
-# 554 "options.c" 3 4
+# 562 "options.c" 3 4
                                  stdout
-# 554 "options.c"
+# 562 "options.c"
                                        )
  argstr = "<stdout>";
 
@@ -3184,14 +3212,14 @@
       p_arg->arg_directory = opendir(argstr);
       if (!p_arg->arg_directory) {
  fprintf(
-# 562 "options.c" 3 4
+# 570 "options.c" 3 4
         stderr
-# 562 "options.c"
+# 570 "options.c"
               , "%s: cannot open directory %s: %s\n",
   prog_name, argstr, strerror(
-# 563 "options.c" 3 4
+# 571 "options.c" 3 4
                              (*__errno_location ())
-# 563 "options.c"
+# 571 "options.c"
                                   ));
  return 1;
       }
@@ -3200,21 +3228,21 @@
 
     default:
       
-# 570 "options.c" 3 4
+# 578 "options.c" 3 4
      ((void) sizeof ((
-# 570 "options.c"
+# 578 "options.c"
      !"Invalid option type"
-# 570 "options.c" 3 4
+# 578 "options.c" 3 4
      ) ? 1 : 0), __extension__ ({ if (
-# 570 "options.c"
+# 578 "options.c"
      !"Invalid option type"
-# 570 "options.c" 3 4
+# 578 "options.c" 3 4
      ) ; else __assert_fail (
-# 570 "options.c"
+# 578 "options.c"
      "!\"Invalid option type\""
-# 570 "options.c" 3 4
-     , "options.c", 570, __extension__ __PRETTY_FUNCTION__); }))
-# 570 "options.c"
+# 578 "options.c" 3 4
+     , "options.c", 578, __extension__ __PRETTY_FUNCTION__); }))
+# 578 "options.c"
                                    ;
     }
   }
@@ -3263,30 +3291,30 @@
  break;
       default:
  
-# 617 "options.c" 3 4
+# 625 "options.c" 3 4
 ((void) sizeof ((
-# 617 "options.c"
+# 625 "options.c"
 !"Invalid option type"
-# 617 "options.c" 3 4
+# 625 "options.c" 3 4
 ) ? 1 : 0), __extension__ ({ if (
-# 617 "options.c"
+# 625 "options.c"
 !"Invalid option type"
-# 617 "options.c" 3 4
+# 625 "options.c" 3 4
 ) ; else __assert_fail (
-# 617 "options.c"
+# 625 "options.c"
 "!\"Invalid option type\""
-# 617 "options.c" 3 4
-, "options.c", 617, __extension__ __PRETTY_FUNCTION__); }))
-# 617 "options.c"
+# 625 "options.c" 3 4
+, "options.c", 625, __extension__ __PRETTY_FUNCTION__); }))
+# 625 "options.c"
                               ;
       }
     }
 
     if (ret)
       fprintf(
-# 622 "options.c" 3 4
+# 630 "options.c" 3 4
              stderr
-# 622 "options.c"
+# 630 "options.c"
                    , "%s: %s\n", prog_name, err);
   }
 
@@ -3299,14 +3327,14 @@
     case OPT_FILE:
       if (file_close(p_arg->arg_file)) {
  fprintf(
-# 633 "options.c" 3 4
+# 641 "options.c" 3 4
         stderr
-# 633 "options.c"
+# 641 "options.c"
               , "%s: cannot close %s: %s\n",
   prog_name, argstr, strerror(
-# 634 "options.c" 3 4
+# 642 "options.c" 3 4
                              (*__errno_location ())
-# 634 "options.c"
+# 642 "options.c"
                                   ));
  return 1;
       }
@@ -3315,14 +3343,14 @@
     case OPT_DIRECTORY:
       if (closedir(p_arg->arg_directory)) {
  fprintf(
-# 641 "options.c" 3 4
+# 649 "options.c" 3 4
         stderr
-# 641 "options.c"
+# 649 "options.c"
               , "%s: cannot close directory %s: %s\n",
   prog_name, argstr, strerror(
-# 642 "options.c" 3 4
+# 650 "options.c" 3 4
                              (*__errno_location ())
-# 642 "options.c"
+# 650 "options.c"
                                   ));
  return 1;
       }
@@ -3356,36 +3384,36 @@
 
   n_matches = 0;
   for (n_haystack = 0; !((haystack + n_haystack)->short_opt == '\0' && (haystack + n_haystack)->long_opt == 
-# 674 "options.c" 3 4
+# 682 "options.c" 3 4
                        ((void *)0)
-# 674 "options.c"
+# 682 "options.c"
                        ); n_haystack++) {
     if (haystack[n_haystack].long_opt)
       n_matches++;
   }
 
 
-  matches = _xmalloc_line("options.c", 680, __func__, sizeof(*matches) * n_matches);
+  matches = _xmalloc_line("options.c", 688, __func__, sizeof(*matches) * n_matches);
   index = 0;
   for (int i = 0; i < n_haystack; i++) {
     const char *str = haystack[i].long_opt;
     if (str) {
       
-# 685 "options.c" 3 4
+# 693 "options.c" 3 4
      ((void) sizeof ((
-# 685 "options.c"
+# 693 "options.c"
      index < n_matches
-# 685 "options.c" 3 4
+# 693 "options.c" 3 4
      ) ? 1 : 0), __extension__ ({ if (
-# 685 "options.c"
+# 693 "options.c"
      index < n_matches
-# 685 "options.c" 3 4
+# 693 "options.c" 3 4
      ) ; else __assert_fail (
-# 685 "options.c"
+# 693 "options.c"
      "index < n_matches"
-# 685 "options.c" 3 4
-     , "options.c", 685, __extension__ __PRETTY_FUNCTION__); }))
-# 685 "options.c"
+# 693 "options.c" 3 4
+     , "options.c", 693, __extension__ __PRETTY_FUNCTION__); }))
+# 693 "options.c"
                               ;
       matches[index].match = str;
       matches[index].index = i;
@@ -3393,21 +3421,21 @@
     }
   }
   
-# 691 "options.c" 3 4
+# 699 "options.c" 3 4
  ((void) sizeof ((
-# 691 "options.c"
+# 699 "options.c"
  index == n_matches
-# 691 "options.c" 3 4
+# 699 "options.c" 3 4
  ) ? 1 : 0), __extension__ ({ if (
-# 691 "options.c"
+# 699 "options.c"
  index == n_matches
-# 691 "options.c" 3 4
+# 699 "options.c" 3 4
  ) ; else __assert_fail (
-# 691 "options.c"
+# 699 "options.c"
  "index == n_matches"
-# 691 "options.c" 3 4
- , "options.c", 691, __extension__ __PRETTY_FUNCTION__); }))
-# 691 "options.c"
+# 699 "options.c" 3 4
+ , "options.c", 699, __extension__ __PRETTY_FUNCTION__); }))
+# 699 "options.c"
                            ;
 
 
@@ -3463,9 +3491,9 @@
     break;
   case OPT_STRING:
     arg->arg_string = 
-# 745 "options.c" 3 4
+# 753 "options.c" 3 4
                      ((void *)0)
-# 745 "options.c"
+# 753 "options.c"
                          ;
     break;
 
@@ -3473,21 +3501,21 @@
     if (arg->arg_file) {
       if (file_close(arg->arg_file)) {
  fprintf(
-# 751 "options.c" 3 4
+# 759 "options.c" 3 4
         stderr
-# 751 "options.c"
+# 759 "options.c"
               , "%s: cannot close %s: %s\n", prog_name,
   opt->argstr ? *(opt->argstr) : "file", strerror(
-# 752 "options.c" 3 4
+# 760 "options.c" 3 4
                                                  (*__errno_location ())
-# 752 "options.c"
+# 760 "options.c"
                                                       ));
  return 1;
       }
       arg->arg_file = 
-# 755 "options.c" 3 4
+# 763 "options.c" 3 4
                      ((void *)0)
-# 755 "options.c"
+# 763 "options.c"
                          ;
     }
     break;
@@ -3496,22 +3524,22 @@
     if (arg->arg_directory) {
       if (closedir(arg->arg_directory)) {
  fprintf(
-# 762 "options.c" 3 4
+# 770 "options.c" 3 4
         stderr
-# 762 "options.c"
+# 770 "options.c"
               , "%s: cannot close directory%s%s: %s\n", prog_name,
   opt->argstr ? " " : "", opt->argstr ? *(opt->argstr) : "",
   strerror(
-# 764 "options.c" 3 4
+# 772 "options.c" 3 4
           (*__errno_location ())
-# 764 "options.c"
+# 772 "options.c"
                ));
  return 1;
       }
       arg->arg_directory = 
-# 767 "options.c" 3 4
+# 775 "options.c" 3 4
                           ((void *)0)
-# 767 "options.c"
+# 775 "options.c"
                               ;
     }
 
@@ -3519,29 +3547,29 @@
 
   default:
     
-# 773 "options.c" 3 4
+# 781 "options.c" 3 4
    ((void) sizeof ((
-# 773 "options.c"
+# 781 "options.c"
    !"Invalid option type"
-# 773 "options.c" 3 4
+# 781 "options.c" 3 4
    ) ? 1 : 0), __extension__ ({ if (
-# 773 "options.c"
+# 781 "options.c"
    !"Invalid option type"
-# 773 "options.c" 3 4
+# 781 "options.c" 3 4
    ) ; else __assert_fail (
-# 773 "options.c"
+# 781 "options.c"
    "!\"Invalid option type\""
-# 773 "options.c" 3 4
-   , "options.c", 773, __extension__ __PRETTY_FUNCTION__); }))
-# 773 "options.c"
+# 781 "options.c" 3 4
+   , "options.c", 781, __extension__ __PRETTY_FUNCTION__); }))
+# 781 "options.c"
                                  ;
   }
 
   if (opt->argstr)
     *(opt->argstr) = 
-# 777 "options.c" 3 4
+# 785 "options.c" 3 4
                     ((void *)0)
-# 777 "options.c"
+# 785 "options.c"
                         ;
 
   return 0;
@@ -3555,9 +3583,9 @@
   int ret = 0;
 
   for (const OPTION *opt = options; !((opt)->short_opt == '\0' && (opt)->long_opt == 
-# 789 "options.c" 3 4
+# 797 "options.c" 3 4
                                     ((void *)0)
-# 789 "options.c"
+# 797 "options.c"
                                     ); opt++)
     ret += free_opt(prog_name, opt);
 
@@ -3571,9 +3599,9 @@
 static int format_help_callback(void *data, char *err) {
   struct help_callback_data *d = data;
   int ret = format_help(
-# 801 "options.c" 3 4
+# 809 "options.c" 3 4
                        stdout
-# 801 "options.c"
+# 809 "options.c"
                              , d->prog_name, d->usage,
    d->desc, d->notes, d->options);
 
@@ -3581,15 +3609,15 @@
 
 
     fflush(
-# 807 "options.c" 3 4
+# 815 "options.c" 3 4
           stdout
-# 807 "options.c"
+# 815 "options.c"
                 );
     snprintf(err, 256, "cannot print help message: %s",
       strerror(
-# 809 "options.c" 3 4
+# 817 "options.c" 3 4
               (*__errno_location ())
-# 809 "options.c"
+# 817 "options.c"
                    ));
     return ret;
   }

Attachment: signature.asc
Description: PGP signature


Reply to: