mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-25 02:03:03 +01:00
484c6ec372
Having done my best to merge everyone else's changes, I hope the tree can be build with whatever other tools != MSVC6.
349 lines
7.8 KiB
Plaintext
349 lines
7.8 KiB
Plaintext
/*
|
|
* PROGRAM: JRD Command Oriented Query Language
|
|
* MODULE: help.epp
|
|
* DESCRIPTION: Help module.
|
|
*
|
|
* The contents of this file are subject to the Interbase Public
|
|
* License Version 1.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy
|
|
* of the License at http://www.Inprise.com/IPL.html
|
|
*
|
|
* Software distributed under the License is distributed on an
|
|
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
|
* or implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code was created by Inprise Corporation
|
|
* and its predecessors. Portions created by Inprise Corporation are
|
|
* Copyright (C) Inprise Corporation.
|
|
*
|
|
* All Rights Reserved.
|
|
* Contributor(s): ______________________________________.
|
|
*
|
|
* 2002.10.30 Sean Leyne - Removed support for obsolete "PC_PLATFORM" define
|
|
*
|
|
*/
|
|
|
|
#include "firebird.h"
|
|
#include "../jrd/ib_stdio.h"
|
|
#include <string.h>
|
|
#include "../jrd/gds.h"
|
|
#include "../qli/dtr.h"
|
|
#include "../qli/compile.h"
|
|
#include "../qli/parse.h"
|
|
#include "../qli/err_proto.h"
|
|
#include "../qli/help_proto.h"
|
|
#include "../qli/lex_proto.h"
|
|
#include "../jrd/gds_proto.h"
|
|
|
|
#define INDENT " "
|
|
#define COLUMN_WIDTH 20
|
|
#define RIGHT_MARGIN 70
|
|
|
|
#ifdef VMS
|
|
#define TARGET "[syshlp]help.fdb"
|
|
#endif
|
|
|
|
#ifdef UNIX
|
|
#define TARGET "help/help.fdb"
|
|
#endif
|
|
|
|
#if (defined WIN_NT)
|
|
#define TARGET "help/help.fdb"
|
|
#endif
|
|
|
|
DATABASE HELP_DB = STATIC "help.fdb" RUNTIME target;
|
|
|
|
static int additional_topics(TEXT *, TEXT *, TEXT *);
|
|
static void print_more(USHORT, USHORT, TEXT **, USHORT *, TEXT *, bool);
|
|
static void print_topic(USHORT, USHORT, TEXT **, USHORT *, TEXT *, bool);
|
|
static TEXT *strip(TEXT *);
|
|
|
|
|
|
void HELP_fini(void)
|
|
{
|
|
/**************************************
|
|
*
|
|
* H E L P _ f i n i
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
*
|
|
**************************************/
|
|
|
|
if (HELP_DB) {
|
|
COMMIT;
|
|
FINISH;
|
|
}
|
|
}
|
|
|
|
|
|
void HELP_help( SYN node)
|
|
{
|
|
/**************************************
|
|
*
|
|
* H E L P _ h e l p
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
* Give the poor sucker help.
|
|
*
|
|
**************************************/
|
|
NAM *ptr, *end;
|
|
USHORT max_level;
|
|
TEXT target[MAXPATHLEN], **topic, *topics[16];
|
|
|
|
if (!HELP_DB) {
|
|
gds__prefix(target, TARGET);
|
|
READY
|
|
ON_ERROR
|
|
ERRQ_database_error(NULL, gds_status);
|
|
END_ERROR;
|
|
START_TRANSACTION;
|
|
}
|
|
|
|
max_level = 0;
|
|
topic = topics;
|
|
*topic++ = "QLI";
|
|
|
|
for (ptr = (NAM *) node->syn_arg, end = ptr + node->syn_count; ptr < end;
|
|
ptr++)
|
|
*topic++ = (*ptr)->nam_string;
|
|
|
|
print_topic(0, node->syn_count, topics, &max_level, "", false);
|
|
|
|
if (max_level < node->syn_count)
|
|
print_topic(0, node->syn_count, topics, &max_level, "", true);
|
|
}
|
|
|
|
|
|
static int additional_topics( TEXT * parent, TEXT * banner, TEXT * string)
|
|
{
|
|
/**************************************
|
|
*
|
|
* a d d i t i o n a l _ t o p i c s
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
* Print a list of other known topics.
|
|
*
|
|
**************************************/
|
|
TEXT line[256];
|
|
|
|
/* Print list of know topics. When we find the first,
|
|
print the banner, if any */
|
|
|
|
TEXT* ptr = line;
|
|
USHORT topics = 0;
|
|
USHORT l = strlen(parent);
|
|
|
|
FOR X IN TOPICS WITH X.PARENT EQ parent SORTED BY X.TOPIC
|
|
if (QLI_abort)
|
|
return 0;
|
|
TEXT* p = X.TOPIC;
|
|
while (*p && *p != ' ')
|
|
p++;
|
|
if (!(l = p - X.TOPIC))
|
|
continue;
|
|
if (++topics == 1 && banner)
|
|
ib_printf("%s%s%s\n", banner, string, parent);
|
|
p =
|
|
line +
|
|
((ptr - line + COLUMN_WIDTH - 1) / COLUMN_WIDTH) * COLUMN_WIDTH;
|
|
if (p + l > line + RIGHT_MARGIN) {
|
|
*ptr = 0;
|
|
ib_printf("%s%s\n", INDENT, line);
|
|
p = ptr = line;
|
|
}
|
|
while (ptr < p)
|
|
*ptr++ = ' ';
|
|
p = X.TOPIC;
|
|
do {
|
|
*ptr++ = *p++;
|
|
} while (--l);
|
|
*ptr++ = ' ';
|
|
END_FOR;
|
|
|
|
if (ptr != line) {
|
|
*ptr = 0;
|
|
ib_printf("%s%s\n", INDENT, line);
|
|
}
|
|
|
|
return topics;
|
|
}
|
|
|
|
|
|
static void print_more(
|
|
USHORT level,
|
|
USHORT depth,
|
|
TEXT ** topics,
|
|
USHORT * max_level,
|
|
TEXT * parent,
|
|
bool error_flag) // unused
|
|
{
|
|
/**************************************
|
|
*
|
|
* p r i n t _ m o r e
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
* We have printed a topic with additional sub-topics. Ask the user if he
|
|
* wants more.
|
|
*
|
|
**************************************/
|
|
TEXT buffer[256], topic[80], prompt[80], *p, *q;
|
|
|
|
ERRQ_msg_get(502, prompt); /* Msg502 "Subtopic? " */
|
|
|
|
// Prompt the user for a line
|
|
|
|
if (!LEX_get_line(prompt, buffer, sizeof(buffer)))
|
|
return;
|
|
|
|
// Upcase the response and zap the blanks
|
|
|
|
topics[1] = p = topic;
|
|
|
|
for (q = buffer; *q && *q != '\n'; q++)
|
|
if (*q != ' ')
|
|
*p++ = UPPER(*q);
|
|
*p = 0;
|
|
|
|
// If we got anything, print the new topic
|
|
|
|
if (p != topic)
|
|
print_topic(level + 1, depth + 1, topics + 1, max_level, parent,
|
|
false); // strange, it doesn't use error_flag
|
|
}
|
|
|
|
|
|
static void print_topic(
|
|
USHORT level,
|
|
USHORT depth,
|
|
TEXT ** topics,
|
|
USHORT * max_level, TEXT * parent, bool error_flag)
|
|
{
|
|
/**************************************
|
|
*
|
|
* p r i n t _ t o p i c
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
* Lookup topic in path. If we find a topic, and are not level
|
|
* zero, recurse. Otherwise print out the topic. In any case,
|
|
* remember the lowest level on which a topic was found. If the
|
|
* error flag is set, print out a list of sub-topics.
|
|
*
|
|
**************************************/
|
|
USHORT count;
|
|
TEXT string[128], banner[128], *next, *p, *q, *path, buffer[128],
|
|
prompt[80];
|
|
|
|
// Copy the parent string inserting a blank at the end
|
|
|
|
p = string;
|
|
|
|
if (*parent) {
|
|
q = parent;
|
|
while (*q)
|
|
*p++ = *q++;
|
|
*p++ = ' ';
|
|
}
|
|
|
|
next = p;
|
|
count = 0;
|
|
|
|
FOR X IN TOPICS WITH X.FACILITY EQ "QLI" AND
|
|
(X.TOPIC STARTING WITH * topics AND X.PARENT EQ parent) OR
|
|
(X.TOPIC = X.FACILITY AND X.TOPIC = *topics AND X.TOPIC = X.PARENT)
|
|
count++;
|
|
END_FOR;
|
|
|
|
if (count > 1)
|
|
ERRQ_msg_put(80, (TEXT *) (ULONG) count, *topics, NULL, NULL, NULL); /* Msg80 [%d topics matched %s] */
|
|
|
|
count = 0;
|
|
|
|
FOR(LEVEL level) X IN TOPICS WITH X.FACILITY EQ "QLI" AND
|
|
(X.TOPIC STARTING WITH * topics AND X.PARENT EQ parent) OR
|
|
(X.TOPIC = X.FACILITY AND X.TOPIC = *topics AND X.TOPIC = X.PARENT)
|
|
SORTED BY X.TOPIC
|
|
|
|
if (QLI_abort)
|
|
return;
|
|
|
|
if (count) {
|
|
ERRQ_msg_get(503, prompt); /* Msg503 "\ntype <cr> for next topic or <EOF> to stop: " */
|
|
if (!LEX_get_line(prompt, buffer, sizeof(buffer)))
|
|
return;
|
|
}
|
|
++count;
|
|
if (level > *max_level)
|
|
*max_level = level;
|
|
p = next;
|
|
q = X.TOPIC;
|
|
while (*q && *q != ' ')
|
|
*p++ = *q++;
|
|
*p = 0;
|
|
if (level < depth)
|
|
print_topic(level + 1, depth, topics + 1, max_level, string,
|
|
error_flag);
|
|
else {
|
|
ib_printf("\n%s\n\n", strip(string));
|
|
QLI_skip_line = TRUE;
|
|
FOR B IN X.TEXT
|
|
if (QLI_abort)
|
|
return;
|
|
B.SEGMENT[B.LENGTH] = 0;
|
|
ib_printf("%s%s", INDENT, B.SEGMENT);
|
|
END_FOR;
|
|
ERRQ_msg_format(81, sizeof(banner), banner, INDENT, NULL, NULL,
|
|
NULL, NULL); // Msg81 %sSub-topics available:
|
|
if (additional_topics(string, banner, INDENT))
|
|
print_more(level, depth, topics, max_level, string,
|
|
error_flag);
|
|
}
|
|
END_FOR;
|
|
|
|
if (!count && error_flag && level > *max_level) {
|
|
path = strip(parent);
|
|
ERRQ_msg_put(82, path, *topics, NULL, NULL, NULL); // Msg82 No help is available for %s %s
|
|
ERRQ_msg_format(83, sizeof(banner), banner, path, NULL, NULL, NULL, NULL); // Msg83 Sub-topics available for %s are:
|
|
additional_topics(parent, banner, path);
|
|
}
|
|
}
|
|
|
|
|
|
static TEXT *strip( TEXT * string)
|
|
{
|
|
/**************************************
|
|
*
|
|
* s t r i p
|
|
*
|
|
**************************************
|
|
*
|
|
* Functional description
|
|
* Strip off the first topic in the path.
|
|
*
|
|
**************************************/
|
|
TEXT *p;
|
|
|
|
p = string;
|
|
|
|
while (*p != ' ')
|
|
if (!*p++)
|
|
return string;
|
|
|
|
while (*p == ' ')
|
|
if (!*p++)
|
|
return string;
|
|
|
|
return p;
|
|
}
|
|
|