Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Fix our getopt_long's behavior for a command line argument of just "-".
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 23 Mar 2020 15:58:01 +0000 (11:58 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 23 Mar 2020 15:58:01 +0000 (11:58 -0400)
src/port/getopt_long.c failed on such an argument, always seeing it
as an unrecognized switch.  This is unhelpful; better is to treat such
an item as a non-switch argument.  That behavior is what we find in
GNU's getopt_long(); it's what src/port/getopt.c does; and it is
required by POSIX for getopt(), which getopt_long() ought to be
generally a superset of.  Moreover, it's expected by ecpg, which
intends an argument of "-" to mean "read from stdin".  So fix it.

Also add some documentation about ecpg's behavior in this area, since
that was miserably underdocumented.  I had to reverse-engineer it
from the code.

Per bug #16304 from James Gray.  Back-patch to all supported branches,
since this has been broken forever.

Discussion: https://postgr.es/m/16304-c662b00a1322db7f@postgresql.org

doc/src/sgml/ref/ecpg-ref.sgml
src/port/getopt_long.c

index 8bfb47c4d79ff813b77d99967d5d481d85260690..3953972ee1d63e1b2861656b08546170a5e1eee8 100644 (file)
@@ -41,14 +41,21 @@ PostgreSQL documentation
 
   <para>
    <command>ecpg</command> will convert each input file given on the
-   command line to the corresponding C output file.  Input files
-   preferably have the extension <filename>.pgc</filename>.
-   The extension will be replaced by <filename>.c</filename> to
-   determine the output file name.
-   The output file name can also be overridden using the
+   command line to the corresponding C output file.  If an input file
+   name does not have any extension, <filename>.pgc</filename> is
+   assumed.  The file's extension will be replaced
+   by <filename>.c</filename> to construct the output file name.
+   But the output file name can be overridden using the
    <option>-o</option> option.
   </para>
 
+  <para>
+   If an input file name is just <literal>-</literal>,
+   <command>ecpg</command> reads the program from standard input
+   (and writes to standard output, unless that is overridden
+   with <option>-o</option>).
+  </para>
+
   <para>
    This reference page does not describe the embedded SQL language.
    See <xref linkend="ecpg"> for more information on that topic.
@@ -94,6 +101,19 @@ PostgreSQL documentation
      </listitem>
     </varlistentry>
 
+    <varlistentry>
+     <term><option>-h</option></term>
+     <listitem>
+      <para>
+       Process header files.  When this option is specified, the output file
+       extension becomes <literal>.h</literal> not <literal>.c</literal>,
+       and the default input file extension is <literal>.pgh</literal>
+       not <literal>.pgc</literal>.  Also, the <option>-c</option> option is
+       forced on.
+      </para>
+     </listitem>
+    </varlistentry>
+
     <varlistentry>
      <term><option>-i</option></term>
      <listitem>
@@ -125,6 +145,7 @@ PostgreSQL documentation
       <para>
        Specifies that <command>ecpg</command> should write all
        its output to the given <replaceable>filename</replaceable>.
+       Write <literal>-o -</literal> to send all output to standard output.
       </para>
      </listitem>
     </varlistentry>
index ff379db29b0cea0b3e4812691515a01c9e3ac06c..c9892769883a3237b128ead2318b47e06d09129c 100644 (file)
@@ -79,14 +79,22 @@ getopt_long(int argc, char *const argv[],
 
        place++;
 
-       if (place[0] && place[0] == '-' && place[1] == '\0')
-       {                       /* found "--" */
+       if (!*place)
+       {
+           /* treat "-" as not being an option */
+           place = EMSG;
+           return -1;
+       }
+
+       if (place[0] == '-' && place[1] == '\0')
+       {
+           /* found "--", treat it as end of options */
            ++optind;
            place = EMSG;
            return -1;
        }
 
-       if (place[0] && place[0] == '-' && place[1])
+       if (place[0] == '-' && place[1])
        {
            /* long option */
            size_t      namelen;