8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-26 10:43:03 +01:00
firebird-mirror/src/dsql/errd.cpp

364 lines
9.0 KiB
C++
Raw Normal View History

2001-05-23 15:26:42 +02:00
/*
* PROGRAM: Dynamic SQL runtime support
* MODULE: err.c
* DESCRIPTION: Error handlers
*
* 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-06-29 08:56:51 +02:00
*
* 27 Nov 2001 Ann W. Harrison - preserve string arguments in
* ERRD_post_warning
*
* 2002.10.28 Sean Leyne - Code cleanup, removed obsolete "MPEXL" port
*
2002-10-30 07:40:58 +01:00
* 2002.10.29 Sean Leyne - Removed obsolete "Netware" port
*
2001-05-23 15:26:42 +02:00
*/
#include "firebird.h"
2001-05-23 15:26:42 +02:00
#include "../jrd/ib_stdio.h"
#include <string.h>
#include "../jrd/common.h"
2001-07-12 07:46:06 +02:00
#ifdef HAVE_STDARG_H
2001-05-23 15:26:42 +02:00
#include <stdarg.h>
2001-07-12 07:46:06 +02:00
#endif
2001-05-23 15:26:42 +02:00
#include "../dsql/dsql.h"
#include "../dsql/sqlda.h"
#include "gen/codes.h"
2001-05-23 15:26:42 +02:00
#include "../jrd/iberr.h"
#include "../dsql/errd_proto.h"
#include "../dsql/utld_proto.h"
#include "../jrd/err_proto.h"
2001-05-23 15:26:42 +02:00
#include "../jrd/gds_proto.h"
#include "../jrd/thd_proto.h"
extern "C" {
ASSERT_FILENAME /* Define things assert() needs */
#ifdef DEV_BUILD
2001-12-24 03:51:06 +01:00
void ERRD_assert_msg(const char* msg, const char* file, ULONG lineno)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* E R R D _ a s s e r t _ m s g
*
**************************************
*
* Functional description
* Generate an assertion failure with a message
*
**************************************/
char buffer[100];
sprintf(buffer, "Assertion failure: %s File: %s Line: %ld\n", /* NTX: dev build */
2001-12-24 03:51:06 +01:00
(msg ? msg : ""), (file ? file : ""), lineno);
2001-05-23 15:26:42 +02:00
ERRD_bugcheck(buffer);
}
#endif /* DEV_BUILD */
2001-12-24 03:51:06 +01:00
void ERRD_bugcheck(const char* text)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* E R R D _ b u g c h e c k
*
**************************************
*
* Functional description
* Somebody has screwed up. Bugcheck.
*
**************************************/
TEXT s[128];
sprintf(s, "INTERNAL: %s", text); /* TXNN */
ERRD_error(-1, s);
}
2001-12-24 03:51:06 +01:00
void ERRD_error( int code, const char* text)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* E R R D _ e r r o r
*
**************************************
*
* Functional description
* This routine should only be used by fatal
* error messages, those that cannot use the
* normal error routines because something
* is very badly wrong. ERRD_post() should
* be used by most error messages, especially
* so that strings will be handled.
*
**************************************/
2002-12-10 12:53:53 +01:00
TEXT s[256];
2001-05-23 15:26:42 +02:00
TSQL tdsql;
2002-06-29 08:56:51 +02:00
STATUS *status_vector;
2001-05-23 15:26:42 +02:00
tdsql = GET_THREAD_DATA;
sprintf(s, "** DSQL error: %s **\n", text);
TRACE(s);
2002-06-29 08:56:51 +02:00
if (status_vector = tdsql->tsql_status) {
*status_vector++ = gds_arg_gds;
*status_vector++ = gds_random;
2002-06-29 08:56:51 +02:00
*status_vector++ = gds_arg_cstring;
*status_vector++ = strlen(s);
*status_vector++ = reinterpret_cast<long>(s);
2002-06-29 08:56:51 +02:00
*status_vector++ = gds_arg_end;
}
ERRD_punt();
2001-05-23 15:26:42 +02:00
}
BOOLEAN ERRD_post_warning(STATUS status, ...)
{
/**************************************
*
* E R R D _ p o s t _ w a r n i n g
*
**************************************
*
* Functional description
* Post a warning to the current status vector.
*
**************************************/
va_list args;
int type, len;
#pragma FB_COMPILER_MESSAGE("Warning, using STATUS array to hold pointers to STATUSes!")
STATUS *status_vector;
int indx = 0, warning_indx = 0;
VA_START(args, status);
status_vector = ((TSQL) GET_THREAD_DATA)->tsql_status;
if (status_vector[0] != gds_arg_gds ||
(status_vector[0] == gds_arg_gds && status_vector[1] == 0 &&
status_vector[2] != gds_arg_warning)) {
/* this is a blank status vector */
status_vector[0] = gds_arg_gds;
status_vector[1] = 0;
status_vector[2] = gds_arg_end;
indx = 2;
}
else
{
/* find end of a status vector */
PARSE_STATUS(status_vector, indx, warning_indx);
if (indx)
--indx;
}
/* stuff the warning */
if (indx + 3 < ISC_STATUS_LENGTH) {
status_vector[indx++] = gds_arg_warning;
status_vector[indx++] = status;
2002-06-29 08:56:51 +02:00
while ((type = va_arg(args, int)) && (indx + 3 < ISC_STATUS_LENGTH)) {
char* pszTmp = NULL;
2001-05-23 15:26:42 +02:00
switch (status_vector[indx++] = type) {
case gds_arg_warning:
status_vector[indx++] = (STATUS) va_arg(args, STATUS);
break;
2002-06-29 08:56:51 +02:00
case gds_arg_string:
pszTmp = va_arg(args, char*);
if (strlen(pszTmp) >= MAX_ERRSTR_LEN) {
status_vector[(indx - 1)] = gds_arg_cstring;
status_vector[indx++] = MAX_ERRSTR_LEN;
}
status_vector[indx++] = reinterpret_cast<long>(ERR_cstring(pszTmp));
2001-05-23 15:26:42 +02:00
break;
2002-06-29 08:56:51 +02:00
case gds_arg_interpreted:
pszTmp = va_arg(args, char*);
status_vector[indx++] = reinterpret_cast<long>(ERR_cstring(pszTmp));
2001-05-23 15:26:42 +02:00
break;
case gds_arg_cstring:
2002-06-29 08:56:51 +02:00
len = va_arg(args, int);
status_vector[indx++] =
(STATUS) (len >= MAX_ERRSTR_LEN) ? MAX_ERRSTR_LEN : len;
pszTmp = va_arg(args, char*);
status_vector[indx++] = reinterpret_cast<long>(ERR_cstring(pszTmp));
2001-05-23 15:26:42 +02:00
break;
case gds_arg_number:
status_vector[indx++] = (STATUS) va_arg(args, SLONG);
break;
case gds_arg_vms:
case gds_arg_unix:
case gds_arg_win32:
default:
status_vector[indx++] = (STATUS) va_arg(args, int);
break;
}
2002-06-29 08:56:51 +02:00
}
2001-05-23 15:26:42 +02:00
status_vector[indx] = gds_arg_end;
return TRUE;
}
else {
/* not enough free space */
return FALSE;
}
}
2001-12-29 12:41:29 +01:00
void ERRD_post(STATUS status, ...)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* E R R D _ p o s t
*
**************************************
*
* Functional description
* Post an error, copying any potentially
2001-12-29 12:41:29 +01:00
* transient data before we punt.
2001-05-23 15:26:42 +02:00
*
**************************************/
2001-12-29 12:41:29 +01:00
STATUS tmp_status[ISC_STATUS_LENGTH];
STATUS warning_status[ISC_STATUS_LENGTH];
int tmp_status_len = 0;
int status_len = 0;
int warning_indx = 0;
STATUS*status_vector = ((TSQL) GET_THREAD_DATA)->tsql_status;
2001-05-23 15:26:42 +02:00
/* stuff the status into temp buffer */
MOVE_CLEAR(tmp_status, sizeof(tmp_status));
STUFF_STATUS(tmp_status, status);
/* calculate length of the status */
PARSE_STATUS(tmp_status, tmp_status_len, warning_indx);
assert(warning_indx == 0);
if (status_vector[0] != gds_arg_gds ||
(status_vector[0] == gds_arg_gds && status_vector[1] == 0 &&
2001-12-29 12:41:29 +01:00
status_vector[2] != gds_arg_warning))
{
2001-05-23 15:26:42 +02:00
/* this is a blank status vector */
status_vector[0] = gds_arg_gds;
status_vector[1] = gds_dsql_error;
2001-05-23 15:26:42 +02:00
status_vector[2] = gds_arg_end;
}
PARSE_STATUS(status_vector, status_len, warning_indx);
if (status_len)
--status_len;
2001-12-29 12:41:29 +01:00
// check for duplicated error code
int i;
for (i = 0; i < ISC_STATUS_LENGTH; i++)
{
if (status_vector[i] == gds_arg_end && i == status_len) {
2001-05-23 15:26:42 +02:00
break; /* end of argument list */
2001-12-29 12:41:29 +01:00
}
2001-05-23 15:26:42 +02:00
2001-12-29 12:41:29 +01:00
if (i && i == warning_indx) {
2001-05-23 15:26:42 +02:00
break; /* vector has no more errors */
2001-12-29 12:41:29 +01:00
}
2001-05-23 15:26:42 +02:00
if (status_vector[i] == tmp_status[1] && i &&
status_vector[i - 1] != gds_arg_warning &&
i + tmp_status_len - 2 < ISC_STATUS_LENGTH &&
(memcmp(&status_vector[i], &tmp_status[1],
2001-12-29 12:41:29 +01:00
sizeof(STATUS) * (tmp_status_len - 2)) == 0))
{
2001-05-23 15:26:42 +02:00
/* duplicate found */
ERRD_punt();
}
}
2001-12-29 12:41:29 +01:00
// if the status_vector has only warnings then adjust err_status_len
int err_status_len = i;
if (err_status_len == 2 && warning_indx) {
2001-05-23 15:26:42 +02:00
err_status_len = 0;
2001-12-29 12:41:29 +01:00
}
int warning_count = 0;
2001-05-23 15:26:42 +02:00
if (warning_indx) {
/* copy current warning(s) to a temp buffer */
MOVE_CLEAR(warning_status, sizeof(warning_status));
MOVE_FASTER(&status_vector[warning_indx], warning_status,
sizeof(STATUS) * (ISC_STATUS_LENGTH - warning_indx));
PARSE_STATUS(warning_status, warning_count, warning_indx);
}
2001-12-29 12:41:29 +01:00
// add the status into a real buffer right in between last
// error and first warning
2001-05-23 15:26:42 +02:00
2001-12-29 12:41:29 +01:00
i = err_status_len + tmp_status_len;
if (i < ISC_STATUS_LENGTH)
{
2001-05-23 15:26:42 +02:00
MOVE_FASTER(tmp_status, &status_vector[err_status_len],
sizeof(STATUS) * tmp_status_len);
/* copy current warning(s) to the status_vector */
2001-12-29 12:41:29 +01:00
if (warning_count && i + warning_count - 1 < ISC_STATUS_LENGTH)
{
2001-05-23 15:26:42 +02:00
MOVE_FASTER(warning_status, &status_vector[i - 1],
sizeof(STATUS) * warning_count);
}
}
ERRD_punt();
}
void ERRD_punt(void)
{
/**************************************
*
* E R R D _ p u n t
*
**************************************
*
* Functional description
* Error stuff has been copied to
* status vector. Now punt.
*
**************************************/
TSQL tdsql;
tdsql = GET_THREAD_DATA;
/* Save any strings in a permanent location */
UTLD_save_status_strings(tdsql->tsql_status);
/* Give up whatever we were doing and return to the user. */
2001-12-29 12:41:29 +01:00
Firebird::status_exception::raise(tdsql->tsql_status[1]);
2001-05-23 15:26:42 +02:00
}
} // extern "C"