summaryrefslogtreecommitdiffstats
path: root/src/bin/psql/create_help.pl
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/psql/create_help.pl')
-rw-r--r--src/bin/psql/create_help.pl218
1 files changed, 218 insertions, 0 deletions
diff --git a/src/bin/psql/create_help.pl b/src/bin/psql/create_help.pl
new file mode 100644
index 0000000..ee82e64
--- /dev/null
+++ b/src/bin/psql/create_help.pl
@@ -0,0 +1,218 @@
+#! /usr/bin/perl
+
+#################################################################
+# create_help.pl -- converts SGML docs to internal psql help
+#
+# Copyright (c) 2000-2020, PostgreSQL Global Development Group
+#
+# src/bin/psql/create_help.pl
+#################################################################
+
+#
+# This script automatically generates the help on SQL in psql from
+# the SGML docs. So far the format of the docs was consistent
+# enough that this worked, but this here is by no means an SGML
+# parser.
+#
+# 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;
+use warnings;
+
+my $docdir = $ARGV[0] or die "$0: missing required argument: docdir\n";
+my $hfile = $ARGV[1] . '.h'
+ or die "$0: missing required argument: output file\n";
+my $cfile = $ARGV[1] . '.c';
+
+my $hfilebasename;
+if ($hfile =~ m!.*/([^/]+)$!)
+{
+ $hfilebasename = $1;
+}
+else
+{
+ $hfilebasename = $hfile;
+}
+
+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(my $hfile_handle, '>', $hfile)
+ or die "$0: could not open output file '$hfile': $!\n";
+open(my $cfile_handle, '>', $cfile)
+ or die "$0: could not open output file '$cfile': $!\n";
+
+print $hfile_handle "/*
+ * *** Do not change this file by hand. It is automatically
+ * *** generated from the DocBook documentation.
+ *
+ * generated by src/bin/psql/create_help.pl
+ *
+ */
+
+#ifndef $define
+#define $define
+
+#include \"pqexpbuffer.h\"
+
+struct _helpStruct
+{
+ const char *cmd; /* the command name */
+ const char *help; /* the help associated with it */
+ const char *docbook_id; /* DocBook XML id (for generating URL) */
+ void (*syntaxfunc)(PQExpBuffer); /* function that prints the syntax associated with it */
+ int nl_count; /* number of newlines in syntax (for pager) */
+};
+
+extern const struct _helpStruct QL_HELP[];
+";
+
+print $cfile_handle "/*
+ * *** Do not change this file by hand. It is automatically
+ * *** generated from the DocBook documentation.
+ *
+ * generated by src/bin/psql/create_help.pl
+ *
+ */
+
+#define N_(x) (x) /* gettext noop */
+
+#include \"postgres_fe.h\"
+#include \"$hfile\"
+
+";
+
+my $maxlen = 0;
+
+my %entries;
+
+foreach my $file (sort readdir DIR)
+{
+ my ($cmdid, @cmdnames, $cmddesc, $cmdsynopsis);
+ $file =~ /\.sgml$/ or next;
+
+ open(my $fh, '<', "$docdir/$file") or next;
+ my $filecontent = join('', <$fh>);
+ close $fh;
+
+ # Ignore files that are not for SQL language statements
+ $filecontent =~
+ m!<refmiscinfo>\s*SQL - Language Statements\s*</refmiscinfo>!i
+ or next;
+
+ $filecontent =~ m!<refentry id="([a-z-]+)">!
+ and $cmdid = $1;
+
+ # Collect multiple refnames
+ LOOP:
+ {
+ $filecontent =~ m!\G.*?<refname>\s*([a-z ]+?)\s*</refname>!cgis
+ and push @cmdnames, $1
+ and redo LOOP;
+ }
+ $filecontent =~ m!<refpurpose>\s*(.+?)\s*</refpurpose>!is
+ and $cmddesc = $1;
+ $filecontent =~ m!<synopsis>\s*(.+?)\s*</synopsis>!is
+ and $cmdsynopsis = $1;
+
+ if (@cmdnames && $cmddesc && $cmdid && $cmdsynopsis)
+ {
+ s/\"/\\"/g foreach @cmdnames;
+
+ $cmddesc =~ s/<[^>]+>//g;
+ $cmddesc =~ s/\s+/ /g;
+ $cmddesc =~ s/\"/\\"/g;
+
+ my @params = ();
+
+ my $nl_count = () = $cmdsynopsis =~ /\n/g;
+
+ $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} = {
+ cmdid => $cmdid,
+ cmddesc => $cmddesc,
+ cmdsynopsis => $cmdsynopsis,
+ params => \@params,
+ nl_count => $nl_count
+ };
+ $maxlen =
+ ($maxlen >= length $cmdname) ? $maxlen : length $cmdname;
+ }
+ }
+ else
+ {
+ die "$0: parsing file '$file' failed (N='@cmdnames' D='$cmddesc')\n";
+ }
+}
+
+foreach (sort keys %entries)
+{
+ my $prefix = "\t" x 5 . ' ';
+ my $id = $_;
+ $id =~ s/ /_/g;
+ my $synopsis = "\"$entries{$_}{cmdsynopsis}\"";
+ $synopsis =~ s/\\n/\\n"\n$prefix"/g;
+ my @args =
+ ("buf", $synopsis, map("_(\"$_\")", @{ $entries{$_}{params} }));
+ print $cfile_handle "static void
+sql_help_$id(PQExpBuffer buf)
+{
+\tappendPQExpBuffer(" . join(",\n$prefix", @args) . ");
+}
+
+";
+}
+
+print $cfile_handle "
+const struct _helpStruct QL_HELP[] = {
+";
+foreach (sort keys %entries)
+{
+ my $id = $_;
+ $id =~ s/ /_/g;
+ print $cfile_handle " { \"$_\",
+ N_(\"$entries{$_}{cmddesc}\"),
+ \"$entries{$_}{cmdid}\",
+ sql_help_$id,
+ $entries{$_}{nl_count} },
+
+";
+}
+
+print $cfile_handle "
+ { NULL, NULL, NULL } /* End of list marker */
+};
+";
+
+print $hfile_handle "
+#define QL_HELP_COUNT "
+ . scalar(keys %entries) . " /* number of help items */
+#define QL_MAX_CMD_LEN $maxlen /* largest strlen(cmd) */
+
+
+#endif /* $define */
+";
+
+close $cfile_handle;
+close $hfile_handle;
+closedir DIR;