Easier to translate psql help
authorPeter Eisentraut <peter_e@gmx.net>
Fri, 18 Sep 2009 05:00:42 +0000 (05:00 +0000)
committerPeter Eisentraut <peter_e@gmx.net>
Fri, 18 Sep 2009 05:00:42 +0000 (05:00 +0000)
Instead of requiring translators to translate the entire SQL command
synopses, change create_help.pl to only require them to translate the
placeholders, and paste those into the synopsis using a printf mechanism.
Make some small updates to the markup to make it easier to parse.

Note: This causes msgmerge of gettext 0.17 to segfault.  You will need
the patch from https://savannah.gnu.org/bugs/?27474 to make it work.
msgmerge usually only runs on babel.postgresql.org, however.

21 files changed:
doc/src/sgml/ref/alter_database.sgml
doc/src/sgml/ref/alter_function.sgml
doc/src/sgml/ref/alter_role.sgml
doc/src/sgml/ref/alter_table.sgml
doc/src/sgml/ref/alter_user.sgml
doc/src/sgml/ref/begin.sgml
doc/src/sgml/ref/create_domain.sgml
doc/src/sgml/ref/create_group.sgml
doc/src/sgml/ref/create_role.sgml
doc/src/sgml/ref/create_table.sgml
doc/src/sgml/ref/create_user.sgml
doc/src/sgml/ref/fetch.sgml
doc/src/sgml/ref/grant.sgml
doc/src/sgml/ref/lock.sgml
doc/src/sgml/ref/select.sgml
doc/src/sgml/ref/set_transaction.sgml
doc/src/sgml/ref/start_transaction.sgml
src/bin/psql/Makefile
src/bin/psql/create_help.pl
src/bin/psql/help.c
src/bin/psql/nls.mk

index 172ed82122742c0db5e35c2df0f1dcfe196557fe..b0fe48057f19ef120373c9104702a8bc943cb3bc 100644 (file)
@@ -23,7 +23,7 @@ PostgreSQL documentation
 <synopsis>
 ALTER DATABASE <replaceable class="PARAMETER">name</replaceable> [ [ WITH ] <replaceable class="PARAMETER">option</replaceable> [ ... ] ]
 
-where <replaceable class="PARAMETER">option</replaceable> can be:
+<phrase>where <replaceable class="PARAMETER">option</replaceable> can be:</phrase>
 
     CONNECTION LIMIT <replaceable class="PARAMETER">connlimit</replaceable>
 
index 929ef55111a8cfd91f619a7a024037ba2bdd43e0..6a5ac450177357af15079a8f80a25496b2c17528 100644 (file)
@@ -30,7 +30,7 @@ ALTER FUNCTION <replaceable>name</replaceable> ( [ [ <replaceable class="paramet
 ALTER FUNCTION <replaceable>name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] )
     SET SCHEMA <replaceable>new_schema</replaceable>
 
-where <replaceable class="PARAMETER">action</replaceable> is one of:
+<phrase>where <replaceable class="PARAMETER">action</replaceable> is one of:</phrase>
 
     CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT
     IMMUTABLE | STABLE | VOLATILE
index bb9a3984202c2e6993ca470633e662dc0bc9105c..7b299746da4f803147f3ffae56e1186998ea2ee9 100644 (file)
@@ -23,7 +23,7 @@ PostgreSQL documentation
 <synopsis>
 ALTER ROLE <replaceable class="PARAMETER">name</replaceable> [ [ WITH ] <replaceable class="PARAMETER">option</replaceable> [ ... ] ]
 
-where <replaceable class="PARAMETER">option</replaceable> can be:
+<phrase>where <replaceable class="PARAMETER">option</replaceable> can be:</phrase>
     
       SUPERUSER | NOSUPERUSER
     | CREATEDB | NOCREATEDB
index 82c4aaca4b02e3a9de52d19d8661d6b64babf891..9fe94ed8d9d00b60e2d91b64b8931272b57b3144 100644 (file)
@@ -30,7 +30,7 @@ ALTER TABLE <replaceable class="PARAMETER">name</replaceable>
 ALTER TABLE <replaceable class="PARAMETER">name</replaceable>
     SET SCHEMA <replaceable class="PARAMETER">new_schema</replaceable>
 
-where <replaceable class="PARAMETER">action</replaceable> is one of:
+<phrase>where <replaceable class="PARAMETER">action</replaceable> is one of:</phrase>
 
     ADD [ COLUMN ] <replaceable class="PARAMETER">column</replaceable> <replaceable class="PARAMETER">type</replaceable> [ <replaceable class="PARAMETER">column_constraint</replaceable> [ ... ] ]
     DROP [ COLUMN ] [ IF EXISTS ] <replaceable class="PARAMETER">column</replaceable> [ RESTRICT | CASCADE ]
index 6941fce12c68b097295d3979ed6e7d6d96c6c322..5e8830b8ca0e256b52dfb89f385e33eff26c6245 100644 (file)
@@ -23,7 +23,7 @@ PostgreSQL documentation
 <synopsis>
 ALTER USER <replaceable class="PARAMETER">name</replaceable> [ [ WITH ] <replaceable class="PARAMETER">option</replaceable> [ ... ] ]
 
-where <replaceable class="PARAMETER">option</replaceable> can be:
+<phrase>where <replaceable class="PARAMETER">option</replaceable> can be:</phrase>
     
       SUPERUSER | NOSUPERUSER
     | CREATEDB | NOCREATEDB
index 0c7d0eac54592ddef29e3851f037b78776e02b96..cd16ba52166e8b4069ddf76044485030c04ed01c 100644 (file)
@@ -23,7 +23,7 @@ PostgreSQL documentation
 <synopsis>
 BEGIN [ WORK | TRANSACTION ] [ <replaceable class="parameter">transaction_mode</replaceable> [, ...] ]
 
-where <replaceable class="parameter">transaction_mode</replaceable> is one of:
+<phrase>where <replaceable class="parameter">transaction_mode</replaceable> is one of:</phrase>
 
     ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED }
     READ WRITE | READ ONLY
index 1296426b043d0f36bfaa881979b412a2d1fa936d..3358b38d003a019f5798410edc458ef7f7bc35ee 100644 (file)
@@ -22,10 +22,10 @@ PostgreSQL documentation
  <refsynopsisdiv>
 <synopsis>
 CREATE DOMAIN <replaceable class="parameter">name</replaceable> [ AS ] <replaceable class="parameter">data_type</replaceable>
-    [ DEFAULT <replaceable>expression</> ]
+    [ DEFAULT <replaceable>expression</replaceable> ]
     [ <replaceable class="PARAMETER">constraint</replaceable> [ ... ] ]
 
-where <replaceable class="PARAMETER">constraint</replaceable> is:
+<phrase>where <replaceable class="PARAMETER">constraint</replaceable> is:</phrase>
 
 [ CONSTRAINT <replaceable class="PARAMETER">constraint_name</replaceable> ]
 { NOT NULL | NULL | CHECK (<replaceable class="PARAMETER">expression</replaceable>) }
index 2e726c863da316e2d5960c6e04d58f59461549e5..ad28eded05eec0fa2b86b4335d26f9b9344544b5 100644 (file)
@@ -23,7 +23,7 @@ PostgreSQL documentation
 <synopsis>
 CREATE GROUP <replaceable class="PARAMETER">name</replaceable> [ [ WITH ] <replaceable class="PARAMETER">option</replaceable> [ ... ] ]
 
-where <replaceable class="PARAMETER">option</replaceable> can be:
+<phrase>where <replaceable class="PARAMETER">option</replaceable> can be:</phrase>
     
       SUPERUSER | NOSUPERUSER
     | CREATEDB | NOCREATEDB
index a84413340f8c632d2d4a9412e66ff1c953ebe330..82f5464c5824ed3af2e0d05d40fb90a0d5e147d3 100644 (file)
@@ -23,7 +23,7 @@ PostgreSQL documentation
 <synopsis>
 CREATE ROLE <replaceable class="PARAMETER">name</replaceable> [ [ WITH ] <replaceable class="PARAMETER">option</replaceable> [ ... ] ]
 
-where <replaceable class="PARAMETER">option</replaceable> can be:
+<phrase>where <replaceable class="PARAMETER">option</replaceable> can be:</phrase>
     
       SUPERUSER | NOSUPERUSER
     | CREATEDB | NOCREATEDB
index 17c113a2b868e310834eca37627c813b11d4f2ef..7530530f96499a60ffe8915b77ddf000f89243cf 100644 (file)
@@ -22,7 +22,7 @@ PostgreSQL documentation
  <refsynopsisdiv>
 <synopsis>
 CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable class="PARAMETER">table_name</replaceable> ( [
-  { <replaceable class="PARAMETER">column_name</replaceable> <replaceable class="PARAMETER">data_type</replaceable> [ DEFAULT <replaceable>default_expr</> ] [ <replaceable class="PARAMETER">column_constraint</replaceable> [ ... ] ]
+  { <replaceable class="PARAMETER">column_name</replaceable> <replaceable class="PARAMETER">data_type</replaceable> [ DEFAULT <replaceable>default_expr</replaceable> ] [ <replaceable class="PARAMETER">column_constraint</replaceable> [ ... ] ]
     | <replaceable>table_constraint</replaceable>
     | LIKE <replaceable>parent_table</replaceable> [ { INCLUDING | EXCLUDING } { DEFAULTS | CONSTRAINTS | INDEXES } ] ... }
     [, ... ]
@@ -32,7 +32,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } ] TABLE <replaceable class="PAR
 [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]
 [ TABLESPACE <replaceable class="PARAMETER">tablespace</replaceable> ]
 
-where <replaceable class="PARAMETER">column_constraint</replaceable> is:
+<phrase>where <replaceable class="PARAMETER">column_constraint</replaceable> is:</phrase>
 
 [ CONSTRAINT <replaceable class="PARAMETER">constraint_name</replaceable> ]
 { NOT NULL |
@@ -44,7 +44,7 @@ where <replaceable class="PARAMETER">column_constraint</replaceable> is:
     [ ON DELETE <replaceable class="parameter">action</replaceable> ] [ ON UPDATE <replaceable class="parameter">action</replaceable> ] }
 [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
 
-and <replaceable class="PARAMETER">table_constraint</replaceable> is:
+<phrase>and <replaceable class="PARAMETER">table_constraint</replaceable> is:</phrase>
 
 [ CONSTRAINT <replaceable class="PARAMETER">constraint_name</replaceable> ]
 { UNIQUE ( <replaceable class="PARAMETER">column_name</replaceable> [, ... ] ) <replaceable class="PARAMETER">index_parameters</replaceable> |
@@ -54,7 +54,7 @@ and <replaceable class="PARAMETER">table_constraint</replaceable> is:
     [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE <replaceable class="parameter">action</replaceable> ] [ ON UPDATE <replaceable class="parameter">action</replaceable> ] }
 [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]
 
-<replaceable class="PARAMETER">index_parameters</replaceable> in <literal>UNIQUE</> and <literal>PRIMARY KEY</> constraints are:
+<phrase><replaceable class="PARAMETER">index_parameters</replaceable> in <literal>UNIQUE</literal> and <literal>PRIMARY KEY</literal> constraints are:</phrase>
 
 [ WITH ( <replaceable class="PARAMETER">storage_parameter</replaceable> [= <replaceable class="PARAMETER">value</replaceable>] [, ... ] ) ]
 [ USING INDEX TABLESPACE <replaceable class="PARAMETER">tablespace</replaceable> ]
index 80a73a2022b0d776468319592fcf5d494c542176..5587663910ed7d6a26b110ea09ed209be9b8aa87 100644 (file)
@@ -23,7 +23,7 @@ PostgreSQL documentation
 <synopsis>
 CREATE USER <replaceable class="PARAMETER">name</replaceable> [ [ WITH ] <replaceable class="PARAMETER">option</replaceable> [ ... ] ]
 
-where <replaceable class="PARAMETER">option</replaceable> can be:
+<phrase>where <replaceable class="PARAMETER">option</replaceable> can be:</phrase>
     
       SUPERUSER | NOSUPERUSER
     | CREATEDB | NOCREATEDB
index ac392cbe8864b38d2e8b90eb2279790a91d80095..9751cac3e4f635494fbb8a3cac71bcc2418c3805 100644 (file)
@@ -28,7 +28,7 @@ PostgreSQL documentation
 <synopsis>
 FETCH [ <replaceable class="PARAMETER">direction</replaceable> { FROM | IN } ] <replaceable class="PARAMETER">cursorname</replaceable>
 
-where <replaceable class="PARAMETER">direction</replaceable> can be empty or one of:
+<phrase>where <replaceable class="PARAMETER">direction</replaceable> can be empty or one of:</phrase>
 
     NEXT
     PRIOR
index ff6d6b1cc44ff00a6b7a250b492c0f4af6199bbe..30c44ace7392594d6cff310e49288bb878eff95d 100644 (file)
@@ -41,11 +41,11 @@ GRANT { { CREATE | CONNECT | TEMPORARY | TEMP } [,...] | ALL [ PRIVILEGES ] }
     TO { [ GROUP ] <replaceable class="PARAMETER">rolename</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
 
 GRANT { USAGE | ALL [ PRIVILEGES ] }
-    ON FOREIGN DATA WRAPPER <replaceable>fdwname</> [, ...]
+    ON FOREIGN DATA WRAPPER <replaceable>fdwname</replaceable> [, ...]
     TO { [ GROUP ] <replaceable class="PARAMETER">rolename</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
 
 GRANT { USAGE | ALL [ PRIVILEGES ] }
-    ON FOREIGN SERVER <replaceable>servername</> [, ...]
+    ON FOREIGN SERVER <replaceable>servername</replaceable> [, ...]
     TO { [ GROUP ] <replaceable class="PARAMETER">rolename</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
 
 GRANT { EXECUTE | ALL [ PRIVILEGES ] }
@@ -61,7 +61,7 @@ GRANT { { CREATE | USAGE } [,...] | ALL [ PRIVILEGES ] }
     TO { [ GROUP ] <replaceable class="PARAMETER">rolename</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
 
 GRANT { CREATE | ALL [ PRIVILEGES ] }
-    ON TABLESPACE <replaceable>tablespacename</> [, ...]
+    ON TABLESPACE <replaceable>tablespacename</replaceable> [, ...]
     TO { [ GROUP ] <replaceable class="PARAMETER">rolename</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
 
 GRANT <replaceable class="PARAMETER">role</replaceable> [, ...] TO <replaceable class="PARAMETER">rolename</replaceable> [, ...] [ WITH ADMIN OPTION ]
index 814a831ef2d6df320a7336707a190881f31d8f3b..f8104ec5e14451c1077e5b1f6cbe95ad005122e1 100644 (file)
@@ -23,7 +23,7 @@ PostgreSQL documentation
 <synopsis>
 LOCK [ TABLE ] [ ONLY ] <replaceable class="PARAMETER">name</replaceable> [, ...] [ IN <replaceable class="PARAMETER">lockmode</replaceable> MODE ] [ NOWAIT ]
 
-where <replaceable class="PARAMETER">lockmode</replaceable> is one of:
+<phrase>where <replaceable class="PARAMETER">lockmode</replaceable> is one of:</phrase>
 
     ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE
     | SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE
index 6452933e585392122bee359cbbc1c4bc5aef62b3..37d276016365d3f9f90390232bad1eb7d709310a 100644 (file)
@@ -47,7 +47,7 @@ SELECT [ ALL | DISTINCT [ ON ( <replaceable class="parameter">expression</replac
     [ FETCH { FIRST | NEXT } [ <replaceable class="parameter">count</replaceable> ] { ROW | ROWS } ONLY ]
     [ FOR { UPDATE | SHARE } [ OF <replaceable class="parameter">table_name</replaceable> [, ...] ] [ NOWAIT ] [...] ]
 
-where <replaceable class="parameter">from_item</replaceable> can be one of:
+<phrase>where <replaceable class="parameter">from_item</replaceable> can be one of:</phrase>
 
     [ ONLY ] <replaceable class="parameter">table_name</replaceable> [ * ] [ [ AS ] <replaceable class="parameter">alias</replaceable> [ ( <replaceable class="parameter">column_alias</replaceable> [, ...] ) ] ]
     ( <replaceable class="parameter">select</replaceable> ) [ AS ] <replaceable class="parameter">alias</replaceable> [ ( <replaceable class="parameter">column_alias</replaceable> [, ...] ) ]
@@ -56,7 +56,7 @@ where <replaceable class="parameter">from_item</replaceable> can be one of:
     <replaceable class="parameter">function_name</replaceable> ( [ <replaceable class="parameter">argument</replaceable> [, ...] ] ) AS ( <replaceable class="parameter">column_definition</replaceable> [, ...] )
     <replaceable class="parameter">from_item</replaceable> [ NATURAL ] <replaceable class="parameter">join_type</replaceable> <replaceable class="parameter">from_item</replaceable> [ ON <replaceable class="parameter">join_condition</replaceable> | USING ( <replaceable class="parameter">join_column</replaceable> [, ...] ) ]
 
-and <replaceable class="parameter">with_query</replaceable> is:
+<phrase>and <replaceable class="parameter">with_query</replaceable> is:</phrase>
 
     <replaceable class="parameter">with_query_name</replaceable> [ ( <replaceable class="parameter">column_name</replaceable> [, ...] ) ] AS ( <replaceable class="parameter">select</replaceable> )
 
index 76973d8008f73d4e02b7a56ae1d5a8bf92cdcd65..9f093616b1f3a6323c6d32b3f85ca919612936c5 100644 (file)
@@ -20,7 +20,7 @@
 SET TRANSACTION <replaceable class="parameter">transaction_mode</replaceable> [, ...]
 SET SESSION CHARACTERISTICS AS TRANSACTION <replaceable class="parameter">transaction_mode</replaceable> [, ...]
 
-where <replaceable class="parameter">transaction_mode</replaceable> is one of:
+<phrase>where <replaceable class="parameter">transaction_mode</replaceable> is one of:</phrase>
 
     ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED }
     READ WRITE | READ ONLY
index 801b56723b987cbe019a25b072521b53d04a0ae1..a984768c0e97d3e26088f2269c33ed77078fbc9f 100644 (file)
@@ -23,7 +23,7 @@ PostgreSQL documentation
 <synopsis>
 START TRANSACTION [ <replaceable class="parameter">transaction_mode</replaceable> [, ...] ]
 
-where <replaceable class="parameter">transaction_mode</replaceable> is one of:
+<phrase>where <replaceable class="parameter">transaction_mode</replaceable> is one of:</phrase>
 
     ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED }
     READ WRITE | READ ONLY
index d6c3a932a7b6ef97776a7a12e0b9a974eff57ffb..9fc151191cb23fefd9626c1d7c8f6b5a93e83f35 100644 (file)
@@ -22,6 +22,7 @@ override CPPFLAGS := -I. -I$(srcdir) -I$(libpq_srcdir) -I$(top_srcdir)/src/bin/p
 OBJS=  command.o common.o help.o input.o stringutils.o mainloop.o copy.o \
        startup.o prompt.o variables.o large_obj.o print.o describe.o \
        psqlscan.o tab-complete.o mbprint.o dumputils.o keywords.o kwlookup.o \
+       sql_help.o \
        $(WIN32RES)
 
 FLEXFLAGS = -Cfe
@@ -40,8 +41,9 @@ dumputils.c keywords.c: % : $(top_srcdir)/src/bin/pg_dump/%
 kwlookup.c: % : $(top_srcdir)/src/backend/parser/%
        rm -f $@ && $(LN_S) $< .
 
+sql_help.c: sql_help.h ;
 sql_help.h: create_help.pl $(wildcard $(REFDOCDIR)/*.sgml)
-       $(PERL) $< $(REFDOCDIR) $@
+       $(PERL) $< $(REFDOCDIR) $*
 
 psqlscan.c: psqlscan.l
 ifdef FLEX
@@ -67,4 +69,4 @@ clean distclean:
        rm -f psql$(X) $(OBJS) dumputils.c keywords.c kwlookup.c
 
 maintainer-clean: distclean
-       rm -f sql_help.h psqlscan.c
+       rm -f sql_help.h sql_help.c psqlscan.c
index ea0e89c0471a52c51d631c512c55ebcf7fa8564b..ef7f3900573399e92e0079439c4b801610fb7e37 100644 (file)
@@ -14,7 +14,7 @@
 # enough that this worked, but this here is by no means an SGML
 # parser.
 #
-# Call: perl create_help.pl docdir sql_help.h
+# Call: perl create_help.pl docdir sql_help
 # The name of the header file doesn't matter to this script, but it
 # sure does matter to the rest of the source.
 #
 use strict;
 
 my $docdir = $ARGV[0] or die "$0: missing required argument: docdir\n";
-my $outputfile = $ARGV[1] or die "$0: missing required argument: output file\n";
+my $hfile = $ARGV[1] . '.h' or die "$0: missing required argument: output file\n";
+my $cfile = $ARGV[1] . '.c';
 
-my $outputfilebasename;
-if ($outputfile =~ m!.*/([^/]+)$!) {
-    $outputfilebasename = $1;
+my $hfilebasename;
+if ($hfile =~ m!.*/([^/]+)$!) {
+    $hfilebasename = $1;
 }
 else {
-    $outputfilebasename = $outputfile;
+    $hfilebasename = $hfile;
 }
 
-my $define = $outputfilebasename;
+my $define = $hfilebasename;
 $define =~ tr/a-z/A-Z/;
 $define =~ s/\W/_/g;
 
 opendir(DIR, $docdir)
     or die "$0: could not open documentation source dir '$docdir': $!\n";
-open(OUT, ">$outputfile")
-    or die "$0: could not open output file '$outputfile': $!\n";
+open(HFILE, ">$hfile")
+    or die "$0: could not open output file '$hfile': $!\n";
+open(CFILE, ">$cfile")
+    or die "$0: could not open output file '$cfile': $!\n";
 
-print OUT
+print HFILE
 "/*
  * *** Do not change this file by hand. It is automatically
  * *** generated from the DocBook documentation.
@@ -56,15 +59,31 @@ print OUT
 
 #define N_(x) (x)                              /* gettext noop */
 
+#include \"postgres_fe.h\"
+#include \"pqexpbuffer.h\"
+
 struct _helpStruct
 {
        const char         *cmd;                /* the command name */
        const char         *help;               /* the help associated with it */
-       const char         *syntax;             /* the syntax associated with it */
+       void (*syntaxfunc)(PQExpBuffer);        /* function that prints the syntax associated with it */
+       int                             nl_count;       /* number of newlines in syntax (for pager) */
 };
 
+";
+
+print CFILE
+"/*
+ * *** Do not change this file by hand. It is automatically
+ * *** generated from the DocBook documentation.
+ *
+ * generated by
+ *     $^X $0 @ARGV
+ *
+ */
+
+#include \"$hfile\"
 
-static const struct _helpStruct QL_HELP[] = {
 ";
 
 my $maxlen = 0;
@@ -95,12 +114,25 @@ foreach my $file (sort readdir DIR) {
        $cmddesc =~ s/\s+/ /g;
         $cmddesc =~ s/\"/\\"/g;
 
-       $cmdsynopsis =~ s/<[^>]+>//g;
+        my @params = ();
+
+        my $nl_count = () = $cmdsynopsis =~ /\n/g;
+
+        $cmdsynopsis =~ m!</>! and die "$0:$file: null end tag not supported in synopsis\n";
+        $cmdsynopsis =~ s/%/%%/g;
+
+        while ($cmdsynopsis =~ m!<(\w+)[^>]*>(.+?)</\1[^>]*>!) {
+            my $match = $2;
+           $match =~ s/<[^>]+>//g;
+           $match =~ s/%%/%/g;
+            push @params, $match;
+            $cmdsynopsis =~ s!<(\w+)[^>]*>.+?</\1[^>]*>!%s!;
+        }
        $cmdsynopsis =~ s/\r?\n/\\n/g;
         $cmdsynopsis =~ s/\"/\\"/g;
 
         foreach my $cmdname (@cmdnames) {
-           $entries{$cmdname} = { cmddesc => $cmddesc, cmdsynopsis => $cmdsynopsis };
+           $entries{$cmdname} = { cmddesc => $cmddesc, cmdsynopsis => $cmdsynopsis, params => \@params, nl_count => $nl_count };
            $maxlen = ($maxlen >= length $cmdname) ? $maxlen : length $cmdname;
        }
     }
@@ -109,9 +141,41 @@ foreach my $file (sort readdir DIR) {
     }
 }
 
-print OUT "    { \"$_\",\n      N_(\"".$entries{$_}{cmddesc}."\"),\n      N_(\"".$entries{$_}{cmdsynopsis}."\") },\n\n" foreach (sort keys %entries);
+foreach (sort keys %entries) {
+    my $prefix = "\t"x5 . '  ';
+    my $id = $_;
+    $id =~ s/ /_/g;
+    my $synopsis = "\"$entries{$_}{cmdsynopsis}\"";
+    $synopsis =~ s/\\n/\\n"\n$prefix"/g;
+    my @args = ("buf",
+                $synopsis,
+                map("_(\"$_\")", @{$entries{$_}{params}}));
+    print HFILE "extern void sql_help_$id(PQExpBuffer buf);\n";
+    print CFILE "void
+sql_help_$id(PQExpBuffer buf)
+{
+\tappendPQExpBuffer(".join(",\n$prefix", @args).");
+}
+
+";
+}
+
+print HFILE "
+
+static const struct _helpStruct QL_HELP[] = {
+";
+foreach (sort keys %entries) {
+    my $id = $_;
+    $id =~ s/ /_/g;
+    print HFILE "    { \"$_\",
+      N_(\"$entries{$_}{cmddesc}\"),
+      sql_help_$id,
+      $entries{$_}{nl_count} },
+
+";
+}
 
-print OUT "
+print HFILE "
     { NULL, NULL, NULL }    /* End of list marker */
 };
 
@@ -123,5 +187,6 @@ print OUT "
 #endif /* $define */
 ";
 
-close OUT;
+close CFILE;
+close HFILE;
 closedir DIR;
index 74c379f2612d1ce351a160be5d78cb6f85dceb28..d498d580b3bfe2c7a70b1f27631c16dbfb085c82 100644 (file)
@@ -349,7 +349,6 @@ helpSQL(const char *topic, unsigned short int pager)
                size_t          len,
                                        wordlen;
                int                     nl_count = 0;
-               const char *ch;
 
                /* User gets two chances: exact match, then the first word */
 
@@ -386,10 +385,8 @@ helpSQL(const char *topic, unsigned short int pager)
                                if (pg_strncasecmp(topic, QL_HELP[i].cmd, len) == 0 ||
                                        strcmp(topic, "*") == 0)
                                {
-                                       nl_count += 5;
-                                       for (ch = QL_HELP[i].syntax; *ch != '\0'; ch++)
-                                               if (*ch == '\n')
-                                                       nl_count++;
+                                       nl_count += 5 + QL_HELP[i].nl_count;
+
                                        /* If we have an exact match, exit.  Fixes \h SELECT */
                                        if (pg_strcasecmp(topic, QL_HELP[i].cmd) == 0)
                                                break;
@@ -403,13 +400,17 @@ helpSQL(const char *topic, unsigned short int pager)
                                if (pg_strncasecmp(topic, QL_HELP[i].cmd, len) == 0 ||
                                        strcmp(topic, "*") == 0)
                                {
+                                       PQExpBufferData buffer;
+
+                                       initPQExpBuffer(&buffer);
+                                       QL_HELP[i].syntaxfunc(&buffer);
                                        help_found = true;
                                        fprintf(output, _("Command:     %s\n"
                                                                          "Description: %s\n"
                                                                          "Syntax:\n%s\n\n"),
                                                        QL_HELP[i].cmd,
                                                        _(QL_HELP[i].help),
-                                                       _(QL_HELP[i].syntax));
+                                                       buffer.data);
                                        /* If we have an exact match, exit.  Fixes \h SELECT */
                                        if (pg_strcasecmp(topic, QL_HELP[i].cmd) == 0)
                                                break;
index d466b67418ccfe8e8892501a1d0b7c136f4c78b6..cc93f544137118e961725642e16a2fb0f186746e 100644 (file)
@@ -2,6 +2,6 @@
 CATALOG_NAME   := psql
 AVAIL_LANGUAGES        := cs de es fr ja pt_BR sv tr
 GETTEXT_FILES  := command.c common.c copy.c help.c input.c large_obj.c \
-                   mainloop.c print.c startup.c describe.c sql_help.h \
+                   mainloop.c print.c startup.c describe.c sql_help.h sql_help.c \
                    ../../port/exec.c
 GETTEXT_TRIGGERS:= _ N_ psql_error simple_prompt