8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-31 13:23:02 +01:00
firebird-mirror/src/dudley/ddl.cpp

741 lines
18 KiB
C++
Raw Normal View History

2001-05-23 15:26:42 +02:00
/*
* PROGRAM: Data Definition Utility
2003-10-05 08:37:26 +02:00
* MODULE: ddl.cpp
2001-05-23 15:26:42 +02:00
* DESCRIPTION: Main line routine
*
* 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): ______________________________________.
*/
#include "firebird.h"
2004-04-29 00:00:03 +02:00
#include <stdio.h>
2001-05-23 15:26:42 +02:00
#include <stdlib.h>
#include <string.h>
#include "../dudley/ddl.h"
2003-11-08 00:27:24 +01:00
#include "../jrd/ibase.h"
2001-05-23 15:26:42 +02:00
#include "../jrd/license.h"
#include "../dudley/ddl_proto.h"
#include "../dudley/exe_proto.h"
#include "../dudley/expan_proto.h"
#include "../dudley/extra_proto.h"
#include "../dudley/hsh_proto.h"
#include "../dudley/lex_proto.h"
#include "../dudley/parse_proto.h"
#include "../dudley/trn_proto.h"
#include "../jrd/gds_proto.h"
#include "../jrd/why_proto.h"
2001-07-12 07:46:06 +02:00
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
2001-05-23 15:26:42 +02:00
#if defined(WIN_NT)
#include <io.h> // isatty
2001-05-23 15:26:42 +02:00
#endif
#include "../common/classes/MsgPrint.h"
using MsgFormat::SafeArg;
DudleyGlobals dudleyGlob;
2001-05-23 15:26:42 +02:00
2004-02-02 12:02:12 +01:00
static dudley_lls* free_stack;
2001-05-23 15:26:42 +02:00
static TEXT DDL_message[256];
static const char* const FOPEN_INPUT_TYPE = "r";
2001-05-23 15:26:42 +02:00
const char* DDL_EXT = ".gdl"; // normal extension for a ddl file
const int MAX_ERRORS = 50;
enum in_sw_values
{
IN_SW_GDEF_0 = 0, // null switch value
IN_SW_GDEF_G, // generate DDL from a database file
IN_SW_GDEF_R, // replace existing database
IN_SW_GDEF_D, // generate dynamic DDL
IN_SW_GDEF_Z, // print version number
IN_SW_GDEF_T, // print tokens as they are read
IN_SW_GDEF_C = 7, // source is C
IN_SW_GDEF_F, // source is FORTRAN
IN_SW_GDEF_P, // source is PASCAL
IN_SW_GDEF_COB, // source is (shudder) cobol
IN_SW_GDEF_ANSI, // source is (worse and worse!) ansi format
IN_SW_GDEF_ADA = 14, // source is ada
IN_SW_GDEF_CXX, // source is C++
IN_SW_GDEF_USER = 17, // user name for PC security
IN_SW_GDEF_PASSWORD // password for PC security
#ifdef TRUSTED_AUTH
,
IN_SW_GDEF_TRUSTED // trusted auth
#endif
};
2001-05-23 15:26:42 +02:00
static const in_sw_tab_t gdef_in_sw_table[] =
{
2002-04-04 07:36:37 +02:00
{ IN_SW_GDEF_G, 0, "EXTRACT", 0, 0, 0, FALSE, 0, 0,
"\t\textract definition from database"}, /* extract DDL from database */
{ IN_SW_GDEF_R, 0, "REPLACE", 0, 0, 0, FALSE, 0, 0,
"\t\treplace existing database"}, /* replace database */
{ IN_SW_GDEF_D, 0, "DYNAMIC", 0, 0, 0, FALSE, 0, 0,
"\t\tgenerate dynamic DDL"},
{ IN_SW_GDEF_T, 0, "T", 0, 0, 0, FALSE, 0, 0, NULL },
{ IN_SW_GDEF_C, 0, "C", 0, 0, 0, FALSE, 0, 0, "\t\tDYN for C" },
{ IN_SW_GDEF_F, 0, "FORTRAN", 0, 0, 0, FALSE, 0, 0, "\t\tDYN for FORTRAN" },
{ IN_SW_GDEF_P, 0, "PASCAL", 0, 0, 0, FALSE, 0, 0, "\t\tDYN for PASCAL" },
{ IN_SW_GDEF_COB, 0, "COB", 0, 0, 0, FALSE, 0, 0, "\t\tDYN for COBOL" },
{ IN_SW_GDEF_ANSI, 0, "ANSI", 0, 0, 0, FALSE, 0, 0,
"\t\tDYN for ANSI COBOL" },
{ IN_SW_GDEF_ADA, 0, "ADA", 0, 0, 0, FALSE, 0, 0, "\t\tDYN for ADA" },
{ IN_SW_GDEF_CXX, 0, "CXX", 0, 0, 0, FALSE, 0, 0, "\t\tDYN for C++" },
{ IN_SW_GDEF_USER, 0, "USER", 0, 0, 0, FALSE, 0, 0,
"\t\tuser name to use in attaching database" },
{ IN_SW_GDEF_PASSWORD, 0, "PASSWORD", 0, 0, 0, FALSE, 0, 0,
"\t\tpassword to use with user name" },
#ifdef TRUSTED_AUTH
{ IN_SW_GDEF_TRUSTED, 0, "TRUSTED", 0, 0, 0, FALSE, 0, 0,
"\t\tuse trusted authentication" },
#endif
2002-04-04 07:36:37 +02:00
{ IN_SW_GDEF_Z, 0, "Z", 0, 0, 0, FALSE, 0, 0, "\t\tprint version number" },
{ IN_SW_GDEF_0, 0, NULL, 0, 0, 0, FALSE, 0, 0, NULL }
2001-05-23 15:26:42 +02:00
};
2001-12-24 03:51:06 +01:00
#ifndef SUPERSERVER
int CLIB_ROUTINE main( int argc, char* argv[])
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* m a i n
*
**************************************
*
* Functional description
* Main line routine for C preprocessor. Initializes
* system, performs pass 1 and pass 2. Interpretes
* command line.
*
**************************************/
2004-03-07 08:58:55 +01:00
//TEXT buffer[256];
2001-05-23 15:26:42 +02:00
#ifdef VMS
argc = VMS_parse(&argv, argc);
#endif
// CVC: Notice that gdef is NEVER run as a service! It doesn't make sense.
/* Perform some special handling when run as a Firebird service. The
2001-05-23 15:26:42 +02:00
first switch can be "-svc" (lower case!) or it can be "-svc_re" followed
2004-04-29 00:00:03 +02:00
by 3 file descriptors to use in re-directing stdin, stdout, and stderr. */
2001-05-23 15:26:42 +02:00
dudleyGlob.DDL_service = false;
2001-05-23 15:26:42 +02:00
if (argc > 1 && !strcmp(argv[1], "-svc")) {
dudleyGlob.DDL_service = true;
2001-05-23 15:26:42 +02:00
argv++;
argc--;
}
else if (argc > 4 && !strcmp(argv[1], "-svc_re")) {
dudleyGlob.DDL_service = true;
long redir_in = atol(argv[2]);
long redir_out = atol(argv[3]);
long redir_err = atol(argv[4]);
2001-05-23 15:26:42 +02:00
#ifdef WIN_NT
redir_in = _open_osfhandle(redir_in, 0);
redir_out = _open_osfhandle(redir_out, 0);
redir_err = _open_osfhandle(redir_err, 0);
#endif
if (redir_in != 0)
if (dup2((int) redir_in, 0))
close((int) redir_in);
if (redir_out != 1)
if (dup2((int) redir_out, 1))
close((int) redir_out);
if (redir_err != 2)
if (dup2((int) redir_err, 2))
close((int) redir_err);
argv += 4;
argc -= 4;
}
dudleyGlob.DDL_file_name = NULL;
dudleyGlob.DB_file_name = NULL;
dudleyGlob.DDL_drop_database = false;
dudleyGlob.DDL_quit = false;
dudleyGlob.DDL_extract = false;
dudleyGlob.DDL_dynamic = false;
dudleyGlob.DDL_trace = false;
dudleyGlob.DDL_version = false;
dudleyGlob.DDL_trusted = false;
dudleyGlob.DDL_default_user = NULL;
dudleyGlob.DDL_default_password = NULL;
2001-05-23 15:26:42 +02:00
2004-03-07 08:58:55 +01:00
TEXT file_name_1[256], file_name_2[256];
2001-05-23 15:26:42 +02:00
file_name_1[0] = file_name_2[0] = 0;
USHORT in_sw = 0; // silence uninitialized warning
2001-05-23 15:26:42 +02:00
for (--argc; argc; argc--) {
2004-03-07 08:58:55 +01:00
const TEXT* string = *++argv;
2001-05-23 15:26:42 +02:00
if ((*string != '-') && (*string != '?')) {
if (!*file_name_1)
strcpy(file_name_1, string);
else
strcpy(file_name_2, string);
continue;
}
else if (*string == '-') {
/* iterate through the switch table, looking for matches */
in_sw = IN_SW_GDEF_0;
2003-12-31 06:36:12 +01:00
const TEXT* q;
for (const in_sw_tab_t* in_sw_tab = gdef_in_sw_table;
q = in_sw_tab->in_sw_name; in_sw_tab++)
{
const TEXT* p = string + 1;
2001-05-23 15:26:42 +02:00
/* handle orphaned hyphen case */
if (!*p--)
break;
/* compare switch to switch name in table */
while (*p) {
if (!*++p)
in_sw = in_sw_tab->in_sw;
if (UPPER(*p) != *q++)
break;
}
/* end of input means we got a match. stop looking */
if (!*p)
break;
}
}
switch (in_sw) {
case IN_SW_GDEF_D:
dudleyGlob.DDL_dynamic = true;
dudleyGlob.DYN_file_name[0] = 0;
2001-05-23 15:26:42 +02:00
if (argc == 1)
break;
string = *++argv;
if (*string != '-') {
argc--;
strcpy(dudleyGlob.DYN_file_name, string);
2001-05-23 15:26:42 +02:00
}
else
argv--;
break;
case IN_SW_GDEF_C:
dudleyGlob.language = lan_c;
2001-05-23 15:26:42 +02:00
break;
case IN_SW_GDEF_P:
dudleyGlob.language = lan_pascal;
2001-05-23 15:26:42 +02:00
break;
case IN_SW_GDEF_COB:
dudleyGlob.language = lan_cobol;
2001-05-23 15:26:42 +02:00
break;
case IN_SW_GDEF_ANSI:
dudleyGlob.language = lan_ansi_cobol;
2001-05-23 15:26:42 +02:00
break;
case IN_SW_GDEF_F:
dudleyGlob.language = lan_fortran;
2001-05-23 15:26:42 +02:00
break;
case IN_SW_GDEF_ADA:
dudleyGlob.language = lan_ada;
2001-05-23 15:26:42 +02:00
break;
case IN_SW_GDEF_CXX:
dudleyGlob.language = lan_cxx;
2001-05-23 15:26:42 +02:00
break;
case IN_SW_GDEF_G:
dudleyGlob.DDL_extract = true;
2001-05-23 15:26:42 +02:00
break;
case IN_SW_GDEF_R:
dudleyGlob.DDL_replace = true;
2001-05-23 15:26:42 +02:00
break;
case IN_SW_GDEF_T:
dudleyGlob.DDL_trace = true;
2001-05-23 15:26:42 +02:00
break;
case IN_SW_GDEF_Z:
DDL_msg_put(0, SafeArg() << GDS_VERSION); /* msg 0: gdef version %s\n */
dudleyGlob.DDL_version = true;
2001-05-23 15:26:42 +02:00
break;
case IN_SW_GDEF_PASSWORD:
if (argc > 1) {
dudleyGlob.DDL_default_password = *++argv;
2001-05-23 15:26:42 +02:00
argc--;
}
break;
case IN_SW_GDEF_USER:
if (argc > 1) {
dudleyGlob.DDL_default_user = *++argv;
2001-05-23 15:26:42 +02:00
argc--;
}
break;
#ifdef TRUSTED_AUTH
case IN_SW_GDEF_TRUSTED:
dudleyGlob.DDL_trusted = true;
break;
#endif
2001-05-23 15:26:42 +02:00
case IN_SW_GDEF_0:
if (*string != '?')
DDL_msg_put(1, SafeArg() << string); /* msg 1: gdef: unknown switch %s */
DDL_msg_put(2); /* msg 2: \tlegal switches are: */
2003-12-31 06:36:12 +01:00
for (const in_sw_tab_t* in_sw_tab = gdef_in_sw_table;
in_sw_tab->in_sw; in_sw_tab++)
{
if (in_sw_tab->in_sw_text) {
DDL_msg_put(3, SafeArg() << in_sw_tab->in_sw_name <<
in_sw_tab->in_sw_text); /* msg 3: %s%s */
2003-12-31 06:36:12 +01:00
}
}
2001-05-23 15:26:42 +02:00
DDL_exit(FINI_ERROR);
}
}
2004-04-29 00:00:03 +02:00
FILE* input_file;
2004-03-07 08:58:55 +01:00
if (dudleyGlob.DDL_extract) {
strcpy(dudleyGlob.DB_file_string, file_name_1);
strcpy(dudleyGlob.DDL_file_string, file_name_2);
if (!*dudleyGlob.DB_file_string) {
DDL_msg_put(4); /* msg 4: gdef: Database name is required for extract */
2001-05-23 15:26:42 +02:00
DDL_exit(FINI_ERROR);
}
dudleyGlob.DB_file_name = dudleyGlob.DB_file_string;
dudleyGlob.DDL_file_name = dudleyGlob.DDL_file_string;
2001-05-23 15:26:42 +02:00
DDL_ext();
DDL_exit(FINI_OK);
}
else if (*file_name_1) {
strcpy(dudleyGlob.DDL_file_string, file_name_1);
dudleyGlob.DDL_file_name = dudleyGlob.DDL_file_string;
2001-05-23 15:26:42 +02:00
}
if (dudleyGlob.DDL_file_name == NULL) {
dudleyGlob.DDL_file_name = "standard input";
2004-04-29 00:00:03 +02:00
input_file = stdin;
dudleyGlob.DDL_interactive = dudleyGlob.DDL_service || isatty(0);
2001-05-23 15:26:42 +02:00
}
else {
/*
* try to open the input DDL file.
* If it already has a .GDL extension, just try to open it.
* Otherwise, add the extension, try, remove the extension,
* and try again.
*/
input_file = NULL;
/* first find the extension by going to the end and backing up */
const TEXT* p = dudleyGlob.DDL_file_name;
2003-12-31 06:36:12 +01:00
while (*p)
++p;
while ((p != dudleyGlob.DDL_file_name) && (*p != '.') && (*p != '/'))
2003-12-31 06:36:12 +01:00
--p;
2001-05-23 15:26:42 +02:00
/* then handle the case where the input already ends in .GDL */
if (*p == '.') {
2003-12-31 06:36:12 +01:00
for (const TEXT* q2 = DDL_EXT; UPPER(*p) == UPPER(*q2); p++, q2++) {
2001-05-23 15:26:42 +02:00
if (!*p) {
input_file = fopen(dudleyGlob.DDL_file_name, FOPEN_INPUT_TYPE);
2001-05-23 15:26:42 +02:00
if (!input_file) {
DDL_msg_put(5, SafeArg() << dudleyGlob.DDL_file_name);
/* msg 5: gdef: can't open %s */
2001-05-23 15:26:42 +02:00
DDL_exit(FINI_ERROR);
}
}
2003-12-31 06:36:12 +01:00
}
2001-05-23 15:26:42 +02:00
}
/* if we got this far without opening it, it's time to add the new extension */
if (!input_file) {
sprintf(file_name_1, "%s%s", dudleyGlob.DDL_file_name, DDL_EXT);
2004-04-29 00:00:03 +02:00
input_file = fopen(file_name_1, FOPEN_INPUT_TYPE);
2001-05-23 15:26:42 +02:00
if (input_file)
dudleyGlob.DDL_file_name = file_name_1;
2001-05-23 15:26:42 +02:00
else {
input_file = fopen(dudleyGlob.DDL_file_name, FOPEN_INPUT_TYPE);
2001-05-23 15:26:42 +02:00
if (!input_file)
DDL_msg_put(6, SafeArg() << dudleyGlob.DDL_file_name << file_name_1);
2001-05-23 15:26:42 +02:00
/* msg 6: gdef: can't open %s or %s */
}
}
if (!input_file)
DDL_exit(FINI_ERROR);
}
LEX_init(input_file);
HSH_init();
PARSE_actions();
2004-04-29 00:00:03 +02:00
if (input_file != stdin)
fclose(input_file);
2001-05-23 15:26:42 +02:00
if (dudleyGlob.DDL_actions && ((dudleyGlob.DDL_errors && dudleyGlob.DDL_interactive) || dudleyGlob.DDL_quit)) {
2004-04-29 00:00:03 +02:00
rewind(stdin);
2004-03-07 08:58:55 +01:00
//*buffer = 0;
if (dudleyGlob.DDL_errors > 1)
DDL_msg_partial(7, SafeArg() << dudleyGlob.DDL_errors); /* msg 7: \n%d errors during input. */
else if (dudleyGlob.DDL_errors)
DDL_msg_partial(9); /* msg 9: \n1 error during input. */
2001-05-23 15:26:42 +02:00
else
DDL_msg_partial(8); /* msg 8: \nNo errors. */
if (DDL_yes_no(10)) { // msg 10 : save changes before exiting?
dudleyGlob.DDL_quit = false;
dudleyGlob.DDL_errors = 0;
2003-09-10 19:52:12 +02:00
}
2001-05-23 15:26:42 +02:00
}
/* Reverse the set of actions */
2003-12-31 06:36:12 +01:00
act* stack = NULL;
while (dudleyGlob.DDL_actions) {
act* temp = dudleyGlob.DDL_actions;
dudleyGlob.DDL_actions = temp->act_next;
2001-05-23 15:26:42 +02:00
temp->act_next = stack;
stack = temp;
}
dudleyGlob.DDL_actions = stack;
2001-05-23 15:26:42 +02:00
if (!dudleyGlob.DDL_errors && !dudleyGlob.DDL_quit) {
2001-05-23 15:26:42 +02:00
EXP_actions();
if (!dudleyGlob.DDL_errors && !dudleyGlob.DDL_quit) {
2001-05-23 15:26:42 +02:00
EXE_execute();
if (dudleyGlob.DDL_dynamic)
2001-05-23 15:26:42 +02:00
TRN_translate();
}
}
if (dudleyGlob.DDL_actions && (dudleyGlob.DDL_errors || dudleyGlob.DDL_quit))
if (dudleyGlob.DDL_errors)
DDL_msg_put(307); /* msg 307: Ceasing processing because of errors. */
2001-05-23 15:26:42 +02:00
else
DDL_msg_put(308); /* msg 308: Ceasing processing. */
2001-05-23 15:26:42 +02:00
EXE_fini(dudleyGlob.database);
2001-05-23 15:26:42 +02:00
if (dudleyGlob.DDL_errors) {
if (dudleyGlob.database && (dudleyGlob.database->dbb_flags & DBB_create_database)) {
for (const fil* file = dudleyGlob.database->dbb_files; file;
2003-12-31 06:36:12 +01:00
file = file->fil_next)
{
2001-05-23 15:26:42 +02:00
unlink(file->fil_name->sym_name);
2003-12-31 06:36:12 +01:00
}
unlink(dudleyGlob.database->dbb_name->sym_string);
2001-05-23 15:26:42 +02:00
}
DDL_exit(FINI_ERROR);
}
DDL_exit(FINI_OK);
2003-08-12 12:02:27 +02:00
// This will never execute, see exit() in DDL_exit. Make the compiler happy.
return 0;
2001-05-23 15:26:42 +02:00
}
2001-12-24 03:51:06 +01:00
#endif
2001-05-23 15:26:42 +02:00
UCHAR *DDL_alloc(int size)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* D D L _ a l l o c
*
**************************************
*
* Functional description
*
**************************************/
2004-03-07 08:58:55 +01:00
UCHAR* const block = (UCHAR*) gds__alloc((SLONG) size);
UCHAR* p = block;
2001-05-23 15:26:42 +02:00
#ifdef DEBUG_GDS_ALLOC
/* For V4.0 we don't care about gdef specific memory leaks */
gds_alloc_flag_unfreed(block);
#endif
if (!p)
DDL_err(14); /* msg 14: memory exhausted */
2001-05-23 15:26:42 +02:00
else
2004-03-07 08:58:55 +01:00
do {
2001-05-23 15:26:42 +02:00
*p++ = 0;
2004-03-07 08:58:55 +01:00
} while (--size);
2001-05-23 15:26:42 +02:00
return block;
}
int DDL_db_error(ISC_STATUS* status_vector,
2001-05-23 15:26:42 +02:00
USHORT number,
const SafeArg& arg)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* D D L _ d b _ e r r o r
*
**************************************
*
* Functional description
* Issue an error message.
*
**************************************/
gds__print_status(status_vector);
return DDL_err(number, arg);
2001-05-23 15:26:42 +02:00
}
int DDL_err(USHORT number,
const SafeArg& arg)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* D D L _ e r r
*
**************************************
*
* Functional description
* Issue an error message. Quit if >MAX_ERRORS
*
**************************************/
SafeArg temp;
DDL_msg_partial(15, temp << dudleyGlob.DDL_file_name << dudleyGlob.DDL_line); /*msg 15: %s:%d: */
DDL_msg_put(number, arg);
if (dudleyGlob.DDL_errors++ > MAX_ERRORS) {
temp.clear();
DDL_msg_put(16, temp << MAX_ERRORS); /* msg 16: error count exceeds limit (%d) */
DDL_msg_put(17); /* msg 17: what we have here is a failure to communicate! */
if (dudleyGlob.database && (dudleyGlob.database->dbb_flags & DBB_create_database))
unlink(dudleyGlob.DB_file_name);
2001-05-23 15:26:42 +02:00
DDL_exit(FINI_ERROR);
}
return 0;
}
void DDL_error_abort(ISC_STATUS* status_vector,
2001-05-23 15:26:42 +02:00
USHORT number,
const SafeArg& arg)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* D D L _ e r r o r _ a b o r t
*
**************************************
*
* Functional description
* Things are going very poorly, so put out an error message
* and give up.
*
**************************************/
if (status_vector)
gds__print_status(status_vector);
DDL_err(number, arg);
2001-05-23 15:26:42 +02:00
DDL_exit(FINI_ERROR);
}
void DDL_exit( int stat)
{
/**************************************
*
* D D L _ e x i t
*
**************************************
*
* Functional description
* Exit with status.
*
**************************************/
LEX_fini();
exit(stat);
}
void DDL_msg_partial(USHORT number,
const SafeArg& arg)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* D D L _ m s g _ p a r t i a l
*
**************************************
*
* Functional description
* Retrieve a message from the error file, format it, and print it
* without a newline.
*
**************************************/
fb_msg_format(0, DDL_MSG_FAC, number, sizeof(DDL_message), DDL_message, arg);
2004-04-29 00:00:03 +02:00
printf("%s", DDL_message);
2001-05-23 15:26:42 +02:00
}
void DDL_msg_put(USHORT number,
const SafeArg& arg)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* D D L _ m s g _ p u t
*
**************************************
*
* Functional description
* Retrieve a message from the error file, format it, and print it.
*
**************************************/
fb_msg_format(0, DDL_MSG_FAC, number, sizeof(DDL_message), DDL_message, arg);
2004-04-29 00:00:03 +02:00
printf("%s\n", DDL_message);
2001-05-23 15:26:42 +02:00
}
2004-02-02 12:02:12 +01:00
DUDLEY_NOD DDL_pop(dudley_lls** pointer)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* D D L _ p o p
*
**************************************
*
* Functional description
* Pop an item off a linked list stack. Free the stack node.
*
**************************************/
2004-03-07 08:58:55 +01:00
dudley_lls* stack = *pointer;
DUDLEY_NOD node = stack->lls_object;
2001-05-23 15:26:42 +02:00
*pointer = stack->lls_next;
stack->lls_next = free_stack;
free_stack = stack;
return node;
}
2004-02-02 12:02:12 +01:00
void DDL_push( DUDLEY_NOD object, dudley_lls** pointer)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* D D L _ p u s h
*
**************************************
*
* Functional description
* Push an arbitrary object onto a linked list stack.
*
**************************************/
2004-02-02 12:02:12 +01:00
dudley_lls* stack;
2001-05-23 15:26:42 +02:00
if (free_stack) {
stack = free_stack;
free_stack = stack->lls_next;
}
else
2004-02-02 12:02:12 +01:00
stack = (dudley_lls*) DDL_alloc(sizeof(dudley_lls));
2001-05-23 15:26:42 +02:00
stack->lls_object = object;
stack->lls_next = *pointer;
*pointer = stack;
}
2003-09-10 19:52:12 +02:00
bool DDL_yes_no( USHORT number)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* D D L _ y e s _ n o
*
**************************************
*
* Functional description
* Ask a yes/no question.
*
**************************************/
TEXT prompt[128], reprompt[128], yes_ans[128], no_ans[128];
static const SafeArg dummy;
2001-05-23 15:26:42 +02:00
fb_msg_format(0, DDL_MSG_FAC, number, sizeof(prompt), prompt, dummy);
2001-05-23 15:26:42 +02:00
2004-03-07 08:58:55 +01:00
USHORT yes_num = 342; /* Msg342 YES */
USHORT no_num = 343; /* Msg343 NO */
USHORT re_num = 344; /* Msg344 Please respond with YES or NO. */
2001-05-23 15:26:42 +02:00
reprompt[0] = '\0';
if (fb_msg_format
(0, DDL_MSG_FAC, no_num, sizeof(no_ans), no_ans, dummy) <= 0)
2004-03-07 08:58:55 +01:00
{
2001-05-23 15:26:42 +02:00
strcpy(no_ans, "NO"); /* default if msg_format fails */
2004-03-07 08:58:55 +01:00
}
if (fb_msg_format
(0, DDL_MSG_FAC, yes_num, sizeof(yes_ans), yes_ans, dummy) <= 0)
2004-03-07 08:58:55 +01:00
{
2001-05-23 15:26:42 +02:00
strcpy(yes_ans, "YES");
2004-03-07 08:58:55 +01:00
}
2001-05-23 15:26:42 +02:00
for (;;) {
2004-04-29 00:00:03 +02:00
printf(prompt);
if (dudleyGlob.DDL_service)
2004-04-29 00:00:03 +02:00
putc('\001', stdout);
fflush(stdout);
2004-03-07 08:58:55 +01:00
int count = 0;
int c;
2004-04-29 00:00:03 +02:00
while ((c = getc(stdin)) == ' ')
2001-05-23 15:26:42 +02:00
count++;
if (c != '\n' && c != EOF)
2004-03-07 08:58:55 +01:00
{
int d;
2004-04-29 00:00:03 +02:00
while ((d = getc(stdin)) != '\n' && d != EOF);
2004-03-07 08:58:55 +01:00
}
2001-05-23 15:26:42 +02:00
if (!count && c == EOF)
2003-09-10 19:52:12 +02:00
return false;
2001-05-23 15:26:42 +02:00
if (UPPER(c) == UPPER(yes_ans[0]))
2003-09-10 19:52:12 +02:00
return true;
2001-05-23 15:26:42 +02:00
if (UPPER(c) == UPPER(no_ans[0]))
2003-09-10 19:52:12 +02:00
return false;
2001-05-23 15:26:42 +02:00
if (!reprompt
&& fb_msg_format(0, DDL_MSG_FAC, re_num, sizeof(reprompt),
reprompt, dummy) <= 0)
2004-03-07 08:58:55 +01:00
{
2001-05-23 15:26:42 +02:00
sprintf(reprompt, "Please respond with YES or NO."); /* default if msg_format fails */
2004-03-07 08:58:55 +01:00
}
2004-04-29 00:00:03 +02:00
printf("%s\n", reprompt);
2001-05-23 15:26:42 +02:00
}
}
2004-02-02 12:02:12 +01:00