8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-24 07:23:03 +01:00
firebird-mirror/src/gpre/languages/fbrmclib.cpp

1760 lines
47 KiB
C++
Raw Normal View History

/*____________________________________________________________
*
* PROGRAM: General preprocessor
* MODULE: fbrmc.cpp
* DESCRIPTION: RM/Cobol / fbclient interface
*
* The contents of this file are subject to the Initial
* Developer's 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.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
*
* 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 Stephen W. Boyd
* for the Firebird Open Source RDBMS project.
*
* Copyright (c) 2006 Steve Boyd <sboydlns at gmail.com>
* and all contributors signed below.
*
* The routines in this module comprise a very thin interface between
* RM/Cobol calling sequence and the native C calling sequence. In the
* interests of speed, the Cobol program is assumed to be passing the correct
* number of parameters of the correct type. No error checking is done
* on the arguments at all.
*
* All Rights Reserved.
* Contributor(s): ______________________________________.
* New module by Stephen W. Boyd 31.Aug.2006
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include <math.h>
#include <crtdbg.h>
2016-02-20 16:34:20 +01:00
#ifdef _MSC_VER
#include "autoconfig_msvc.h"
#else
#include "autoconfig.h"
2016-02-20 16:34:20 +01:00
#endif
#include "fb_types.h"
#include "ibase.h"
// Firebird transaction existence block (as defined in why.cpp)
struct ISC_TEB
{
isc_db_handle* dbb_ptr;
int tpb_len;
ISC_UCHAR* tpb_ptr;
};
// RM/Cobol parameter packet definition
struct argument_entry
{
ISC_UCHAR *a_address;
ISC_ULONG a_length;
ISC_USHORT a_type;
ISC_UCHAR a_digits;
ISC_SCHAR a_scale;
ISC_UCHAR *a_picture;
};
struct entry_table
{
2014-12-19 09:52:40 +01:00
const char *EntryPointCobolName;
int (*EntryPointAddress)(char *, int, argument_entry *, int);
2014-12-19 09:52:40 +01:00
const char *EntryPointName;
};
struct date_fmt
{
ISC_USHORT yr_start;
ISC_USHORT yr_len;
ISC_USHORT mon_start;
ISC_USHORT day_start;
ISC_USHORT hr_start;
ISC_USHORT min_start;
ISC_USHORT sec_start;
};
#ifdef __WIN32__
#define EXPORT __declspec(dllexport)
#define CDECL __cdecl
#else
#define EXPORT
#define CDECL
#endif
#define RM_PROTO(sub) int sub(char *, int, argument_entry [], int)
#define RM_ENTRY(sub) int CDECL sub(char *, int, argument_entry arg_vector[], int)
// Define all entry points to be "C" not "C++"
#ifdef __cplusplus
extern "C" {
#endif
RM_PROTO(rmc_embed_dsql_length);
RM_PROTO(rmc_cancel_blob);
RM_PROTO(rmc_close_blob);
RM_PROTO(rmc_compile_request);
RM_PROTO(rmc_create_database);
RM_PROTO(rmc_ddl);
RM_PROTO(rmc_commit_transaction);
RM_PROTO(rmc_rollback_transaction);
RM_PROTO(rmc_drop_database);
RM_PROTO(rmc_embed_dsql_close);
RM_PROTO(rmc_embed_dsql_declare);
RM_PROTO(rmc_embed_dsql_describe);
RM_PROTO(rmc_embed_dsql_describe_bind);
RM_PROTO(rmc_embed_dsql_execute);
RM_PROTO(rmc_embed_dsql_execute2);
RM_PROTO(rmc_embed_dsql_execute_immed);
RM_PROTO(rmc_embed_dsql_insert);
RM_PROTO(rmc_embed_dsql_open);
RM_PROTO(rmc_embed_dsql_open2);
RM_PROTO(rmc_embed_dsql_prepare);
RM_PROTO(rmc_dsql_alloc_statement2);
RM_PROTO(rmc_dsql_execute_m);
RM_PROTO(rmc_dsql_free_statement);
RM_PROTO(rmc_dsql_set_cursor_name);
RM_PROTO(rmc_detach_database);
RM_PROTO(rmc_get_slice);
RM_PROTO(rmc_put_slice);
RM_PROTO(rmc_get_segment);
RM_PROTO(rmc_put_segment);
RM_PROTO(rmc_receive);
RM_PROTO(rmc_release_request);
RM_PROTO(rmc_unwind_request);
RM_PROTO(rmc_send);
RM_PROTO(rmc_start_transaction);
RM_PROTO(rmc_start_and_send);
RM_PROTO(rmc_start_request);
RM_PROTO(rmc_transact_request);
RM_PROTO(rmc_commit_retaining);
2008-01-16 08:15:01 +01:00
RM_PROTO(rmc_rollback_retaining);
RM_PROTO(rmc_attach_database);
RM_PROTO(rmc_modify_dpb);
RM_PROTO(rmc_free);
RM_PROTO(rmc_sqlcode);
RM_PROTO(rmc_embed_dsql_fetch);
RM_PROTO(rmc_event_block_a);
RM_PROTO(rmc_prepare_transaction);
RM_PROTO(rmc_wait_for_event);
RM_PROTO(rmc_event_counts);
RM_PROTO(rmc_baddress);
RM_PROTO(rmc_interprete);
RM_PROTO(rmc_status_address);
RM_PROTO(rmc_expand_dpb);
RM_PROTO(rmc_compile_request2);
RM_PROTO(rmc_create_blob2);
RM_PROTO(rmc_open_blob2);
RM_PROTO(rmc_qtoq);
RM_PROTO(rmc_btoc);
RM_PROTO(rmc_ctob);
RM_PROTO(rmc_decode_date);
RM_PROTO(rmc_encode_date);
RM_PROTO(rmc_dtoc);
RM_PROTO(rmc_ctod);
RM_PROTO(rmc_ftoc);
RM_PROTO(rmc_ctof);
RM_PROTO(rmc_ctos);
RM_PROTO(rmc_stoc);
#ifdef __cplusplus
}
#endif
// Globals
const int MAX_PARAMS = 20;
static bool stringPoolInitialized = false;
static bool intPoolInitialized = false;
static bool shortPoolInitialized = false;
static ISC_UCHAR *stringPool[MAX_PARAMS];
static ISC_ULONG *intPool[MAX_PARAMS];
static ISC_USHORT *shortPool[MAX_PARAMS];
// Clear the stringPool, freeing any previously allocated strings
static void ClearStringPool()
{
2009-06-25 12:44:37 +02:00
for (int i = 0; i < MAX_PARAMS; i++)
{
if (stringPoolInitialized && stringPool[i])
free(stringPool[i]);
stringPool[i] = NULL;
}
stringPoolInitialized = true;
}
// Clear the intPool, freeing any previously allocated ints
static void ClearIntPool()
{
2009-06-25 12:44:37 +02:00
for (int i = 0; i < MAX_PARAMS; i++)
{
if (intPoolInitialized && intPool[i])
free(intPool[i]);
intPool[i] = NULL;
}
intPoolInitialized = true;
}
// Clear the shortPool, freeing any previously allocated ints
static void ClearShortPool()
{
2009-06-25 12:44:37 +02:00
for (int i = 0; i < MAX_PARAMS; i++)
{
2009-12-17 22:55:07 +01:00
if (shortPoolInitialized && shortPool[i])
free(shortPool[i]);
shortPool[i] = NULL;
}
shortPoolInitialized = true;
}
// Clear all parameter pools
static void ClearParamPool()
{
ClearIntPool();
ClearShortPool();
ClearStringPool();
}
// Allocate a buffer of n bytes in the string pool & return its buffer pointer.
// Return a NULL pointer if the pool is exhausted
static ISC_UCHAR* AllocStringPool(int n)
{
2009-06-25 12:44:37 +02:00
for (int i = 0; i < MAX_PARAMS; i++)
{
if (! stringPool[i])
{
stringPool[i] = (ISC_UCHAR *)malloc(n);
return (stringPool[i]);
}
}
return (NULL);
}
// Allocate an integer in the intPool & return a pointer to it. Return a NULL
// pointer if the pool is exhausted
static ISC_ULONG* AllocIntPool()
{
2009-06-25 12:44:37 +02:00
for (int i = 0; i < MAX_PARAMS; i++)
{
if (! intPool[i])
{
intPool[i] = (ISC_ULONG *)malloc(sizeof(ISC_ULONG));
return (intPool[i]);
}
}
return (NULL);
}
// Allocate an integer in the shortPool & return a pointer to it. Return a NULL
// pointer if the pool is exhausted
static ISC_USHORT* AllocShortPool()
{
2009-06-25 12:44:37 +02:00
for (int i = 0; i < MAX_PARAMS; i++)
{
if (! shortPool[i])
{
shortPool[i] = (ISC_USHORT *)malloc(sizeof(ISC_USHORT));
return (shortPool[i]);
}
}
return (NULL);
}
// Allocate an ISC_STATUS array to hold the status vector of isc_* functions.
// For convenience this is allocated from the string pool since there is only
// ever one per function call and there is no need to set up a separate pool
static ISC_STATUS* AllocStatusPool()
{
2008-01-16 08:15:01 +01:00
return (ISC_STATUS*) AllocStringPool(sizeof(ISC_STATUS_ARRAY));
}
// Return a Cobol argument as a C string. Trailing spaces are truncated.
static ISC_UCHAR* CobolToString(const argument_entry *arg)
{
ISC_UCHAR *s = NULL;
2009-06-25 12:44:37 +02:00
if (arg->a_address)
{
s = AllocStringPool(arg->a_length + 1);
2009-06-25 12:44:37 +02:00
if (s)
{
memset(s, 0, arg->a_length + 1);
memmove(s, arg->a_address, arg->a_length);
// Truncate trailing spaces
for (ISC_UCHAR *p = s + arg->a_length - 1; (p >= s) && (*p == ' '); p--)
*p = '\0';
}
}
return (s);
}
// Return the int64 value of an array of ASCII characters
static ISC_UINT64 atoi64(const char *s)
{
ISC_UINT64 rslt = 0;
while (*s)
{
if ((*s >= '0') && (*s <= '9'))
2009-08-06 03:06:05 +02:00
rslt = (rslt * 10) + (*s - '0');
else
return (0);
s++;
}
return (rslt);
}
// Convert a Cobol BINARY(n) to a C integer.
static ISC_UINT64 CvtCobolToInt(const ISC_UCHAR *s, ISC_USHORT len, char type)
{
ISC_UINT64 temp;
2009-01-14 09:22:32 +01:00
switch (len)
{
case 2:
2009-01-05 09:22:58 +01:00
temp = (*(s) << 8) + *(s + 1);
// If source is negative and signed, extend sign to dest
if ((*(s + 1) & 0x80) && (type == 11))
temp |= 0xffffffffffff0000;
break;
case 4:
2009-01-05 09:22:58 +01:00
temp = (*(s) << 24) + (*(s + 1) << 16) + (*(s + 2) << 8) + *(s + 3);
// If source is negative and signed, extend sign to dest
if ((*(s + 1) & 0x80) && (type == 11))
temp |= 0xffffffff00000000;
break;
case 8:
temp = ((ISC_UINT64)*(s) << 56) + ((ISC_UINT64)*(s + 1) << 48) +
((ISC_UINT64)*(s + 2) << 40) + ((ISC_UINT64)*(s + 3) << 32) +
((ISC_UINT64)*(s+ 4) << 24) + ((ISC_UINT64)*(s + 5) << 16) +
((ISC_UINT64)*(s + 6) << 8) + (ISC_UINT64)*(s + 7);
break;
default:
temp = 0;
break;
}
return (temp);
}
// Convert a cobol argument to a C integer. Make allowances for different
// data types, since constants get passed as DISPLAY (NSU or NTS) and fields
// should be BINARY (NBS or NBU)
static ISC_UINT64 CvtArgToInt(const argument_entry *arg)
{
ISC_UINT64 temp;
char *stemp;
char sign;
2009-01-14 09:22:32 +01:00
switch (arg->a_type)
{
case 1: // NSU
temp = (ISC_UINT64)atoi64((char *)CobolToString(arg));
break;
case 2: // NTS
stemp = (char *)CobolToString(arg);
sign = *(stemp + strlen(stemp) - 1);
*(stemp + strlen(stemp) - 1) = '\0';
if (sign == '-')
temp = (ISC_UINT64)((ISC_INT64)atoi64(stemp) * -1);
else
temp = atoi64(stemp);
break;
case 11: // NBS
case 12: // NBU
temp = CvtCobolToInt(arg->a_address,
(ISC_USHORT)arg->a_length,
arg->a_type);
break;
default:
temp = 0;
break;
}
return (temp);
}
// Return a Cobol BINARY(n) (big-endian) argument as a C integer
static ISC_ULONG* CobolToInt(const argument_entry *arg)
{
ISC_ULONG *i = NULL;
2009-06-25 12:44:37 +02:00
if (arg->a_address)
{
ISC_ULONG temp = CvtArgToInt(arg);
i = AllocIntPool();
if (i)
*i = temp;
}
return (i);
}
// Return a Cobol BINARY(n) (big-endian) argument as a C short integer
static ISC_USHORT* CobolToShort(const argument_entry *arg)
{
ISC_USHORT *i = NULL;
2009-06-25 12:44:37 +02:00
if (arg->a_address)
{
ISC_USHORT temp = (ISC_USHORT)CvtArgToInt(arg);
i = AllocShortPool();
if (i)
*i = temp;
}
return (i);
}
// Store a Cobol array of BINARY(4) fields into a status vector
static void CobolToStatus(ISC_STATUS *stat, const argument_entry *arg)
{
const ISC_UCHAR *src = arg->a_address;
if (src)
2009-06-25 12:44:37 +02:00
for (int i = 0; i < ISC_STATUS_LENGTH; i++)
{
*(stat++) = (ISC_STATUS)((*src << 24) +
(*(src + 1) << 16) +
(*(src + 2) << 8) +
*(src + 3));
src += 4;
}
}
// Store a C integer into a Cobol format memory buffer
static void CvtIntToCobol(ISC_UCHAR *s, ISC_UINT64 l, ISC_USHORT len)
{
memset(s, 0, len);
2009-01-14 09:22:32 +01:00
switch (len)
{
case 2:
*(s) = (ISC_UCHAR)((l >> 8) & 0xff);
*(s + 1) = (ISC_UCHAR)(l & 0xff);
break;
case 4:
*(s) = (ISC_UCHAR)((l >> 24) & 0xff);
*(s + 1) = (ISC_UCHAR)((l >> 16) & 0xff);
*(s + 2) = (ISC_UCHAR)((l >> 8) & 0xff);
*(s + 3) = (ISC_UCHAR)(l & 0xff);
break;
case 8:
*(s) = (ISC_UCHAR)((l >> 56) & 0xff);
*(s + 1) = (ISC_UCHAR)((l >> 48) & 0xff);
*(s + 2) = (ISC_UCHAR)((l >> 40) & 0xff);
*(s + 3) = (ISC_UCHAR)((l >> 32) & 0xff);
*(s + 4) = (ISC_UCHAR)((l >> 24) & 0xff);
*(s + 5) = (ISC_UCHAR)((l >> 16) & 0xff);
*(s + 6) = (ISC_UCHAR)((l >> 8) & 0xff);
*(s + 7) = (ISC_UCHAR)(l & 0xff);
break;
}
}
// Store a C integer into a Cobol BINARY(n) (big-endian) field
static void IntToCobol(argument_entry *arg, const ISC_UINT64 i)
{
if (arg->a_address)
CvtIntToCobol(arg->a_address, i, (ISC_USHORT)arg->a_length);
}
// Store a C short integer into a Cobol BINARY(n) (big-endian) field
static void ShortToCobol(argument_entry *arg, const ISC_USHORT *i)
{
if (arg->a_address)
CvtIntToCobol(arg->a_address, (ISC_ULONG)*i, (ISC_USHORT)arg->a_length);
}
// Store a C string into a COBOL PIC X field
static void StringToCobol(argument_entry *arg, const ISC_UCHAR *s)
{
2009-06-25 12:44:37 +02:00
if (arg->a_address)
{
memset(arg->a_address, ' ', arg->a_length);
memmove(arg->a_address,
s,
strlen((char *)s) > arg->a_length ? arg->a_length : strlen((char *)s));
}
}
// Store a status vector into a Cobol array of BINARY(4) fields
static void StatusToCobol(argument_entry *arg, const ISC_STATUS *stat)
{
ISC_UCHAR *dest = arg->a_address;
2009-06-25 12:44:37 +02:00
if (arg->a_address)
{
for (int i = 0; i < ISC_STATUS_LENGTH; i++)
{
*(dest++) = (ISC_UCHAR)((*stat >> 24) & 0xff);
*(dest++) = (ISC_UCHAR)((*stat >> 16) & 0xff);
*(dest++) = (ISC_UCHAR)((*stat >> 8) & 0xff);
*(dest++) = (ISC_UCHAR)(*stat & 0xff);
stat++;
}
}
}
// Parse a date format string. The format string contains the following
// specifiers:
//
// YY - 2 digit year
// YYYY - 4 digit year
// MM - 2 digit month
// DD - 2 digit day
// HH - 2 digit hour (24 hour format)
// NN - 2 digit minute
// SS - 2 digit second
static void ParseDateFormat(const ISC_UCHAR* s, date_fmt* fmt)
{
ISC_UCHAR spec = ' ';
short len = 0;
short start = 0;
short i = 0;
memset(fmt, -1, sizeof(*fmt));
2009-06-25 12:44:37 +02:00
while (*s)
{
if (toupper(*s) != spec)
{
2009-01-14 09:22:32 +01:00
switch (spec)
{
case 'Y':
fmt->yr_start = start;
fmt->yr_len = (short)(len > 4 ? 4 : len);
break;
case 'M':
fmt->mon_start = start;
break;
case 'D':
fmt->day_start = start;
break;
case 'H':
fmt->hr_start = start;
break;
case 'N':
fmt->min_start = start;
break;
case 'S':
fmt->sec_start = start;
break;
}
spec = (ISC_UCHAR)toupper(*s);
start = i;
len = 0;
}
s++;
i++;
len++;
}
// Save the last specification
2009-01-14 09:22:32 +01:00
switch (spec)
{
case 'Y':
fmt->yr_start = start;
fmt->yr_len = (short)(len > 4 ? 4 : len);
break;
case 'M':
fmt->mon_start = start;
break;
case 'D':
fmt->day_start = start;
break;
case 'H':
fmt->hr_start = start;
break;
case 'N':
fmt->min_start = start;
break;
case 'S':
fmt->sec_start = start;
break;
}
}
// RM/Cobol entry points.
//
// All entry points start with rmc_ to avoid conflicts with ibase.h.
// These are all mapped to the corresponding isc_ entry point names
// in fbrmc.def
EXPORT RM_ENTRY(rmc_embed_dsql_length)
{
ClearParamPool();
ISC_USHORT *l = CobolToShort(&arg_vector[1]);
isc_embed_dsql_length(CobolToString(&arg_vector[0]), l);
ShortToCobol(&arg_vector[1], l);
return (0);
}
EXPORT RM_ENTRY(rmc_cancel_blob)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_cancel_blob(stat, (isc_blob_handle *)arg_vector[1].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_close_blob)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_close_blob(stat, (isc_blob_handle *)arg_vector[1].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_compile_request)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_compile_request(stat,
(isc_db_handle *)arg_vector[1].a_address,
(isc_req_handle *)arg_vector[2].a_address,
*CobolToShort(&arg_vector[3]),
(char *)arg_vector[4].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_compile_request2)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_compile_request2(stat,
(isc_db_handle *)arg_vector[1].a_address,
(isc_req_handle *)arg_vector[2].a_address,
*CobolToShort(&arg_vector[3]),
(char *)arg_vector[4].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_create_database)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_create_database(stat,
*CobolToShort(&arg_vector[1]),
(char *)CobolToString(&arg_vector[2]),
(isc_db_handle *)arg_vector[3].a_address,
*CobolToShort(&arg_vector[4]),
(char *)arg_vector[5].a_address,
*CobolToShort(&arg_vector[6]));
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_ddl)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_ddl(stat,
(isc_db_handle *)arg_vector[1].a_address,
(isc_tr_handle *)arg_vector[2].a_address,
(short)*CobolToShort(&arg_vector[3]),
(char *)CobolToString(&arg_vector[4]));
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_commit_transaction)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_commit_transaction(stat, (isc_tr_handle *)arg_vector[1].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_rollback_transaction)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_rollback_transaction(stat, (isc_tr_handle *)arg_vector[1].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_drop_database)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_drop_database(stat, (isc_db_handle *)arg_vector[1].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_embed_dsql_close)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_embed_dsql_close(stat, (char *)CobolToString(&arg_vector[1]));
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_embed_dsql_declare)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_embed_dsql_declare(stat,
(char *)CobolToString(&arg_vector[1]),
(char *)CobolToString(&arg_vector[2]));
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_embed_dsql_describe)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_embed_dsql_describe(stat,
(char *)CobolToString(&arg_vector[1]),
*CobolToShort(&arg_vector[2]),
(XSQLDA *)arg_vector[3].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_embed_dsql_describe_bind)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_embed_dsql_describe_bind(stat,
(char *)CobolToString(&arg_vector[1]),
*CobolToShort(&arg_vector[2]),
(XSQLDA *)arg_vector[3].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_embed_dsql_execute)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_embed_dsql_execute(stat,
(isc_tr_handle *)arg_vector[1].a_address,
(char *)CobolToString(&arg_vector[2]),
*CobolToShort(&arg_vector[3]),
(XSQLDA *)arg_vector[4].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_embed_dsql_execute2)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_embed_dsql_execute2(stat,
(isc_tr_handle *)arg_vector[1].a_address,
(char *)CobolToString(&arg_vector[2]),
*CobolToShort(&arg_vector[3]),
(XSQLDA *)arg_vector[4].a_address,
(XSQLDA *)arg_vector[5].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_embed_dsql_execute_immed)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_embed_dsql_execute_immed(stat,
(isc_db_handle *)arg_vector[1].a_address,
(isc_tr_handle *)arg_vector[2].a_address,
*CobolToShort(&arg_vector[3]),
(char *)CobolToString(&arg_vector[4]),
*CobolToShort(&arg_vector[5]),
(XSQLDA *)arg_vector[6].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_embed_dsql_insert)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_embed_dsql_insert(stat,
(char *)CobolToString(&arg_vector[1]),
*CobolToShort(&arg_vector[2]),
(XSQLDA *)arg_vector[3].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_embed_dsql_open)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_embed_dsql_open(stat,
(isc_tr_handle *)arg_vector[1].a_address,
(char *)CobolToString(&arg_vector[2]),
*CobolToShort(&arg_vector[3]),
(XSQLDA *)arg_vector[4].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_embed_dsql_open2)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_embed_dsql_open2(stat,
(isc_tr_handle *)arg_vector[1].a_address,
(char *)CobolToString(&arg_vector[2]),
*CobolToShort(&arg_vector[3]),
(XSQLDA *)arg_vector[4].a_address,
(XSQLDA *)arg_vector[5].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_embed_dsql_prepare)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_embed_dsql_prepare(stat,
(isc_db_handle *)arg_vector[1].a_address,
(isc_tr_handle *)arg_vector[2].a_address,
(char *)CobolToString(&arg_vector[3]),
(short)*CobolToShort(&arg_vector[4]),
(char *)CobolToString(&arg_vector[5]),
(short)*CobolToShort(&arg_vector[6]),
(XSQLDA *)arg_vector[7].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_dsql_allocate_statement)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_dsql_allocate_statement(stat,
(isc_db_handle *)arg_vector[1].a_address,
(isc_tr_handle *)arg_vector[2].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_dsql_alloc_statement2)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_dsql_alloc_statement2(stat,
(isc_db_handle *)arg_vector[1].a_address,
(isc_tr_handle *)arg_vector[2].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_dsql_execute_m)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_dsql_execute_m(stat,
(isc_tr_handle *)arg_vector[1].a_address,
(isc_stmt_handle *)arg_vector[2].a_address,
*CobolToShort(&arg_vector[3]),
(char *)CobolToString(&arg_vector[4]),
*CobolToShort(&arg_vector[5]),
*CobolToShort(&arg_vector[6]),
(char *)CobolToString(&arg_vector[7]));
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_dsql_free_statement)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_dsql_free_statement(stat,
(isc_stmt_handle *)arg_vector[1].a_address,
*CobolToShort(&arg_vector[2]));
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_dsql_set_cursor_name)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_dsql_set_cursor_name(stat,
(isc_stmt_handle *)arg_vector[1].a_address,
(char *)CobolToString(&arg_vector[2]),
*CobolToShort(&arg_vector[3]));
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_detach_database)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_detach_database(stat,
(isc_db_handle *)arg_vector[1].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_get_slice)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
ISC_LONG *p1 = (ISC_LONG *)CobolToInt(&arg_vector[10]);
isc_get_slice(stat,
(isc_db_handle *)arg_vector[1].a_address,
(isc_tr_handle *)arg_vector[2].a_address,
(ISC_QUAD *)arg_vector[3].a_address,
*CobolToShort(&arg_vector[4]),
(ISC_UCHAR *)CobolToString(&arg_vector[5]),
*CobolToShort(&arg_vector[6]),
(ISC_LONG *)CobolToInt(&arg_vector[7]),
*CobolToInt(&arg_vector[8]),
(ISC_LONG *)arg_vector[9].a_address,
p1);
IntToCobol(&arg_vector[11], (ISC_UINT64)p1);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_put_slice)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_put_slice(stat,
(isc_db_handle *)arg_vector[1].a_address,
(isc_tr_handle *)arg_vector[2].a_address,
(ISC_QUAD *)arg_vector[3].a_address,
(short)*CobolToShort(&arg_vector[4]),
(char *)CobolToString(&arg_vector[5]),
(short)*CobolToShort(&arg_vector[6]),
(ISC_LONG *)CobolToInt(&arg_vector[7]),
*CobolToInt(&arg_vector[8]),
(void *)arg_vector[9].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_get_segment)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
ISC_USHORT *bytesRead = CobolToShort(&arg_vector[2]);
isc_get_segment(stat,
(isc_blob_handle *)arg_vector[1].a_address,
bytesRead,
*CobolToShort(&arg_vector[3]),
(char *)arg_vector[4].a_address);
ShortToCobol(&arg_vector[2], bytesRead);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_put_segment)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_put_segment(stat,
(isc_blob_handle *)arg_vector[1].a_address,
*CobolToShort(&arg_vector[2]),
(char *)arg_vector[3].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_receive)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_receive(stat,
(isc_req_handle *)arg_vector[1].a_address,
(short)*CobolToShort(&arg_vector[2]),
(short)*CobolToShort(&arg_vector[3]),
(void *)arg_vector[4].a_address,
(short)*CobolToShort(&arg_vector[5]));
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_release_request)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_release_request(stat,
(isc_req_handle *)arg_vector[1].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_unwind_request)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_unwind_request(stat,
(isc_tr_handle *)arg_vector[1].a_address,
(short)*CobolToShort(&arg_vector[2]));
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_send)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_send(stat,
(isc_req_handle *)arg_vector[1].a_address,
(short)*CobolToShort(&arg_vector[2]),
(short)*CobolToShort(&arg_vector[3]),
(void *)arg_vector[4].a_address,
(short)*CobolToShort(&arg_vector[5]));
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_start_transaction)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
short* dbCount = (short *)CobolToShort(&arg_vector[2]);
// Create the transaction existence block from the Cobol parameter list. Because
// of limits imposed by the converted parameter pool we can ony support up to
// MAX_PARAMS transactions.
if (*dbCount > MAX_PARAMS)
*dbCount = MAX_PARAMS;
ISC_TEB *teb = (ISC_TEB *)malloc(sizeof(ISC_TEB) * *dbCount);
2009-06-25 12:44:37 +02:00
for (int i = 0; i < *dbCount; i++)
{
teb[i].dbb_ptr = (isc_db_handle *)arg_vector[(i * 3) + 3].a_address;
teb[i].tpb_len = (int)*CobolToInt(&arg_vector[(i * 3) + 4]);
teb[i].tpb_ptr = arg_vector[(i * 3) + 5].a_address;
}
isc_start_multiple(stat,
(isc_tr_handle *)arg_vector[1].a_address,
*dbCount,
teb);
free(teb);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_start_and_send)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_start_and_send(stat,
(isc_req_handle *)arg_vector[1].a_address,
(isc_tr_handle *)arg_vector[2].a_address,
(short)*CobolToShort(&arg_vector[3]),
(short)*CobolToShort(&arg_vector[4]),
(void *)arg_vector[5].a_address,
(short)*CobolToShort(&arg_vector[6]));
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_start_request)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_start_request(stat,
(isc_req_handle *)arg_vector[1].a_address,
(isc_tr_handle *)arg_vector[2].a_address,
(short)*CobolToShort(&arg_vector[3]));
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_transact_request)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_transact_request(stat,
(isc_db_handle *)arg_vector[1].a_address,
(isc_tr_handle *)arg_vector[2].a_address,
*CobolToShort(&arg_vector[3]),
(char *)arg_vector[4].a_address,
*CobolToShort(&arg_vector[5]),
(char *)arg_vector[6].a_address,
*CobolToShort(&arg_vector[7]),
(char *)arg_vector[8].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_commit_retaining)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_commit_retaining(stat,
(isc_tr_handle *)arg_vector[1].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
2008-01-16 08:15:01 +01:00
EXPORT RM_ENTRY(rmc_rollback_retaining)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_rollback_retaining(stat,
(isc_tr_handle *)arg_vector[1].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_attach_database)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_attach_database(stat,
(short)*CobolToShort(&arg_vector[1]),
(char *)CobolToString(&arg_vector[2]),
(isc_db_handle *)arg_vector[3].a_address,
(short)*CobolToShort(&arg_vector[4]),
*(char **)arg_vector[5].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_modify_dpb)
{
ClearParamPool();
short *dpbLen = (short *)CobolToShort(&arg_vector[1]);
isc_modify_dpb((char **)arg_vector[0].a_address,
dpbLen,
*CobolToShort(&arg_vector[2]),
(char *)arg_vector[3].a_address,
(short)*CobolToShort(&arg_vector[4]));
ShortToCobol(&arg_vector[1], (ISC_USHORT *)dpbLen);
return (0);
}
EXPORT RM_ENTRY(rmc_free)
{
isc_free(*(char **)arg_vector[0].a_address);
return (0);
}
EXPORT RM_ENTRY(rmc_sqlcode)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
CobolToStatus(stat, &arg_vector[0]);
ISC_LONG sqlcode = isc_sqlcode(stat);
IntToCobol(&arg_vector[-1], (ISC_UINT64)sqlcode);
return (0);
}
EXPORT RM_ENTRY(rmc_embed_dsql_fetch)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
ISC_STATUS retval = isc_embed_dsql_fetch(stat,
(char *)CobolToString(&arg_vector[1]),
*CobolToShort(&arg_vector[2]),
(XSQLDA *)arg_vector[3].a_address);
IntToCobol(&arg_vector[-1], (ISC_UINT64)retval);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_event_block_a)
{
ClearParamPool();
ISC_USHORT retval = isc_event_block_a((char **)arg_vector[0].a_address,
(char **)arg_vector[1].a_address,
atoi((char *)CobolToString(&arg_vector[2])),
(char **)arg_vector[3].a_address);
ShortToCobol(&arg_vector[-1], &retval);
return (0);
}
EXPORT RM_ENTRY(rmc_prepare_transaction)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_prepare_transaction(stat,
(isc_tr_handle *)arg_vector[1].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_wait_for_event)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_wait_for_event(stat,
(isc_db_handle *)arg_vector[1].a_address,
(short)*CobolToShort(&arg_vector[2]),
(ISC_UCHAR *)*(char **)arg_vector[3].a_address,
(ISC_UCHAR *)*(char **)arg_vector[4].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_event_counts)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_event_counts((ISC_ULONG *)stat,
(short)*CobolToShort(&arg_vector[1]),
(ISC_UCHAR *)*(char **)arg_vector[2].a_address,
(ISC_UCHAR *)*(char **)arg_vector[3].a_address);
2009-10-02 04:17:36 +02:00
// Convert the event counts to Cobol format.
ISC_UCHAR *counts = (ISC_UCHAR *)arg_vector[0].a_address;
ISC_UCHAR *cend = counts + arg_vector[0].a_length;
int i = 0;
2009-10-02 04:17:36 +02:00
while ((counts < cend) && (i < 15))
{
CvtIntToCobol(counts, stat[i], sizeof(ISC_ULONG));
counts += sizeof(ISC_ULONG);
i++;
}
return (0);
}
EXPORT RM_ENTRY(rmc_baddress)
{
U_IPTR retval = isc_baddress((char *)arg_vector[0].a_address);
2014-12-19 09:52:40 +01:00
*(U_IPTR *)arg_vector[-1].a_address = retval;
return (0);
}
EXPORT RM_ENTRY(rmc_interprete)
{
ClearParamPool();
char *bfr = (char *)AllocStringPool(arg_vector[0].a_length + 1);
ISC_STATUS retval = isc_interprete(bfr,
(ISC_STATUS **)arg_vector[1].a_address);
StringToCobol(&arg_vector[0], (ISC_UCHAR *)bfr);
IntToCobol(&arg_vector[-1], (ISC_UINT64)retval);
return (0);
}
EXPORT RM_ENTRY(rmc_expand_dpb)
{
ClearParamPool();
short *dpbLen = (short *)CobolToShort(&arg_vector[1]);
isc_expand_dpb((char **)arg_vector[0].a_address,
dpbLen,
*CobolToShort(&arg_vector[2]),
(char *)CobolToString(&arg_vector[3]),
NULL);
ShortToCobol(&arg_vector[1], (ISC_USHORT *)dpbLen);
return (0);
}
EXPORT RM_ENTRY(rmc_create_blob2)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_create_blob2(stat,
(isc_db_handle *)arg_vector[1].a_address,
(isc_tr_handle *)arg_vector[2].a_address,
(isc_blob_handle *)arg_vector[3].a_address,
(ISC_QUAD *)arg_vector[4].a_address,
(short)*CobolToShort(&arg_vector[5]),
(char *)arg_vector[6].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_open_blob2)
{
ClearParamPool();
ISC_STATUS *stat = AllocStatusPool();
isc_open_blob2(stat,
(isc_db_handle *)arg_vector[1].a_address,
(isc_tr_handle *)arg_vector[2].a_address,
(isc_blob_handle *)arg_vector[3].a_address,
(ISC_QUAD *)arg_vector[4].a_address,
(short)*CobolToShort(&arg_vector[5]),
(ISC_UCHAR *)arg_vector[6].a_address);
StatusToCobol(&arg_vector[0], stat);
return (0);
}
EXPORT RM_ENTRY(rmc_qtoq)
{
isc_qtoq((ISC_QUAD *)arg_vector[0].a_address,
(ISC_QUAD *)arg_vector[1].a_address);
return (0);
}
EXPORT RM_ENTRY(rmc_decode_date)
{
struct tm *tim = (struct tm *)arg_vector[1].a_address;
isc_decode_date((ISC_QUAD *)arg_vector[0].a_address, tim);
CvtIntToCobol((ISC_UCHAR *)&tim->tm_sec, tim->tm_sec, sizeof(tim->tm_sec));
CvtIntToCobol((ISC_UCHAR *)&tim->tm_min, tim->tm_min, sizeof(tim->tm_min));
CvtIntToCobol((ISC_UCHAR *)&tim->tm_hour, tim->tm_hour, sizeof(tim->tm_hour));
CvtIntToCobol((ISC_UCHAR *)&tim->tm_mday, tim->tm_mday, sizeof(tim->tm_mday));
CvtIntToCobol((ISC_UCHAR *)&tim->tm_mon, tim->tm_mon, sizeof(tim->tm_mon));
CvtIntToCobol((ISC_UCHAR *)&tim->tm_year, tim->tm_year, sizeof(tim->tm_year));
CvtIntToCobol((ISC_UCHAR *)&tim->tm_wday, tim->tm_wday, sizeof(tim->tm_wday));
CvtIntToCobol((ISC_UCHAR *)&tim->tm_yday, tim->tm_yday, sizeof(tim->tm_yday));
CvtIntToCobol((ISC_UCHAR *)&tim->tm_isdst, tim->tm_isdst, sizeof(tim->tm_isdst));
return (0);
}
EXPORT RM_ENTRY(rmc_encode_date)
{
struct tm *tim = (struct tm *)arg_vector[0].a_address;
tim->tm_sec = CvtCobolToInt((ISC_UCHAR *)&tim->tm_sec, sizeof(tim->tm_sec), 11);
tim->tm_min = CvtCobolToInt((ISC_UCHAR *)&tim->tm_min, sizeof(tim->tm_min), 11);
tim->tm_hour = CvtCobolToInt((ISC_UCHAR *)&tim->tm_hour, sizeof(tim->tm_hour), 11);
tim->tm_mday = CvtCobolToInt((ISC_UCHAR *)&tim->tm_mday, sizeof(tim->tm_mday), 11);
tim->tm_mon = CvtCobolToInt((ISC_UCHAR *)&tim->tm_mon, sizeof(tim->tm_mon), 11);
tim->tm_year = CvtCobolToInt((ISC_UCHAR *)&tim->tm_year, sizeof(tim->tm_year), 11);
tim->tm_wday = CvtCobolToInt((ISC_UCHAR *)&tim->tm_wday, sizeof(tim->tm_wday), 11);
tim->tm_yday = CvtCobolToInt((ISC_UCHAR *)&tim->tm_yday, sizeof(tim->tm_yday), 11);
tim->tm_isdst = CvtCobolToInt((ISC_UCHAR *)&tim->tm_isdst, sizeof(tim->tm_isdst), 11);
isc_encode_date(tim, (ISC_QUAD *)arg_vector[1].a_address);
return (0);
}
// The following routines are needed for the RM/Cobol interface but are not
// just wrappers around the various isc_* functions.
// Return a pointer to a C format status vector. This is needed to allow
// Cobol programs to successfully call isc_interprete. We convert the status
// vector from Cobol to C format and return a pointer to a static structure
// that can be passed to isc-interprete repeatedly.
EXPORT RM_ENTRY(rmc_status_address)
{
static ISC_STATUS_ARRAY stat;
CobolToStatus(stat, &arg_vector[0]);
ISC_STATUS *p = stat;
2014-12-19 09:52:40 +01:00
*(U_IPTR *)arg_vector[-1].a_address = (U_IPTR)p;
return (0);
}
// Convert a Cobol BINARY(n) field to C format. Used to convert numeric
// data fields before calling other isc_routines
EXPORT RM_ENTRY(rmc_btoc)
{
ISC_UINT64 temp = CvtArgToInt(&arg_vector[0]);
if (arg_vector[-1].a_length == 2)
*(ISC_USHORT *)arg_vector[-1].a_address = (ISC_USHORT)temp;
else if (arg_vector[-1].a_length == 4)
*(ISC_ULONG *)arg_vector[-1].a_address = temp;
else
*(ISC_UINT64 *)arg_vector[-1].a_address = temp;
return (0);
}
// Convert a C format integer to Cobol BINARY(n) format. Used to convert
// numeric data fields after calling other isc_ routines
EXPORT RM_ENTRY(rmc_ctob)
{
ISC_UINT64 temp;
if (arg_vector[0].a_length == 2)
temp = *(ISC_USHORT *)arg_vector[0].a_address;
else if (arg_vector[0].a_length == 4)
temp = *(ISC_ULONG *)arg_vector[0].a_address;
else if (arg_vector[0].a_length == 8)
temp = *(ISC_UINT64 *)arg_vector[0].a_address;
IntToCobol(&arg_vector[-1], temp);
return (0);
}
// Convert a Cobol date field to ISC_QUAD format. Used to convert date fields
// before calling other isc_ routines.
EXPORT RM_ENTRY(rmc_dtoc)
{
char stemp[10];
struct tm tim;
date_fmt fmt;
ClearParamPool();
const int dtlen = arg_vector[1].a_length;
const ISC_UCHAR* dt = arg_vector[1].a_address;
const ISC_UCHAR* fmtString = CobolToString(&arg_vector[2]);
ParseDateFormat(fmtString, &fmt);
memset(&tim, 0, sizeof(tim));
if ((fmt.yr_start != -1) && (fmt.yr_start < dtlen))
2009-06-25 12:44:37 +02:00
{
memset(stemp, 0, sizeof(stemp));
memmove(stemp, dt + fmt.yr_start, fmt.yr_len);
tim.tm_year = atoi(stemp);
// If the year is supplied as 4 digits, no problem just decerement by 1900
// to keep isc_encode_date happy. If 2 digits, assume date > 2000 and
// add 100 to keep isc_encode_date happy.
if (fmt.yr_len > 2)
tim.tm_year -= 1900;
else
tim.tm_year += 100;
}
if ((fmt.mon_start != -1) && (fmt.mon_start < dtlen))
2009-06-25 12:44:37 +02:00
{
memset(stemp, 0, sizeof(stemp));
memmove(stemp, dt + fmt.mon_start, 2);
tim.tm_mon = atoi(stemp) - 1;
}
if ((fmt.day_start != -1) && (fmt.day_start < dtlen))
2009-06-25 12:44:37 +02:00
{
memset(stemp, 0, sizeof(stemp));
memmove(stemp, dt + fmt.day_start, 2);
tim.tm_mday = atoi(stemp);
}
if ((fmt.hr_start != -1) && (fmt.hr_start < dtlen))
2009-06-25 12:44:37 +02:00
{
memset(stemp, 0, sizeof(stemp));
memmove(stemp, dt + fmt.hr_start, 2);
tim.tm_hour = atoi(stemp);
}
if ((fmt.min_start != -1) && (fmt.min_start < dtlen))
2009-06-25 12:44:37 +02:00
{
memset(stemp, 0, sizeof(stemp));
memmove(stemp, dt + fmt.min_start, 2);
tim.tm_min = atoi(stemp);
}
if ((fmt.sec_start != -1) && (fmt.sec_start < dtlen))
2009-06-25 12:44:37 +02:00
{
memset(stemp, 0, sizeof(stemp));
memmove(stemp, dt + fmt.sec_start, 2);
tim.tm_sec = atoi(stemp);
}
isc_encode_date(&tim, (ISC_QUAD *)arg_vector[0].a_address);
return (0);
}
// Convert an ISC_QUAD to Cobol date format. Used to convert date fields after
// calling other isc _ routines
EXPORT RM_ENTRY(rmc_ctod)
{
struct tm tim;
date_fmt fmt;
char stemp[10];
ClearParamPool();
const ISC_UCHAR* fmtString = CobolToString(&arg_vector[2]);
ISC_UCHAR* dt = AllocStringPool((int)strlen((char *)fmtString) + 1);
memset(dt, 0, strlen((char *)fmtString) + 1);
isc_decode_date((ISC_QUAD *)arg_vector[1].a_address, &tim);
ParseDateFormat(fmtString, &fmt);
2009-06-25 12:44:37 +02:00
if (fmt.yr_start != -1)
{
sprintf(stemp, "%*.*d", fmt.yr_len, fmt.yr_len, tim.tm_year + 1900);
memmove(dt + fmt.yr_start, stemp, fmt.yr_len);
}
2009-06-25 12:44:37 +02:00
if (fmt.mon_start != -1)
{
sprintf(stemp, "%2.2d", tim.tm_mon + 1);
memmove(dt + fmt.mon_start, stemp, 2);
}
2009-06-25 12:44:37 +02:00
if (fmt.day_start != -1)
{
sprintf(stemp, "%2.2d", tim.tm_mday);
memmove(dt + fmt.day_start, stemp, 2);
}
2009-06-25 12:44:37 +02:00
if (fmt.hr_start != -1)
{
sprintf(stemp, "%2.2d", tim.tm_hour);
memmove(dt + fmt.hr_start, stemp, 2);
}
2009-06-25 12:44:37 +02:00
if (fmt.min_start != -1)
{
sprintf(stemp, "%2.2d", tim.tm_min);
memmove(dt + fmt.min_start, stemp, 2);
}
2009-06-25 12:44:37 +02:00
if (fmt.sec_start != -1)
{
sprintf(stemp, "%2.2d", tim.tm_sec);
memmove(dt + fmt.sec_start, stemp, 2);
}
StringToCobol(&arg_vector[0], dt);
return (0);
}
// Convert a C floating point value to Cobol format
// float = BINARY(4)
// double = BINARY(8)
EXPORT RM_ENTRY(rmc_ctof)
{
double arg;
// Get floating point value
if (arg_vector[0].a_length == 4)
arg = *(float *)arg_vector[0].a_address;
else
arg = *(double *)arg_vector[0].a_address;
// Get all significant digits into the integer part
arg *= pow(10.0, -arg_vector[0].a_scale);
ISC_INT64 intPart = (ISC_INT64)arg;
// Round the integer part
double frac = arg - intPart;
if (frac >= 0.5)
intPart++;
if (frac <= -0.5)
intPart--;
// Save as a Cobol format BINARY value
ISC_UCHAR *s = (ISC_UCHAR *)arg_vector[-1].a_address;
2009-06-25 12:44:37 +02:00
if (arg_vector[-1].a_length == 4)
{
*(s) = (ISC_UCHAR)((intPart >> 24) & 0xff);
*(s + 1) = (ISC_UCHAR)((intPart >> 16) & 0xff);
*(s + 2) = (ISC_UCHAR)((intPart >> 8) & 0xff);
*(s + 3) = (ISC_UCHAR)(intPart & 0xff);
}
2009-06-25 12:44:37 +02:00
else
{
*(s) = (ISC_UCHAR)((intPart >> 56) & 0xff);
*(s + 1) = (ISC_UCHAR)((intPart >> 48) & 0xff);
*(s + 2) = (ISC_UCHAR)((intPart >> 40) & 0xff);
*(s + 3) = (ISC_UCHAR)((intPart >> 32) & 0xff);
*(s + 4) = (ISC_UCHAR)((intPart >> 24) & 0xff);
*(s + 5) = (ISC_UCHAR)((intPart >> 16) & 0xff);
*(s + 6) = (ISC_UCHAR)((intPart >> 8) & 0xff);
*(s + 7) = (ISC_UCHAR)(intPart & 0xff);
}
return (0);
}
// Convert a Cobol format floating point to C format
// float = BINARY(4)
// double = BINARY(8)
EXPORT RM_ENTRY(rmc_ftoc)
{
ISC_INT64 intPart;
// Get Cobol value as a C 64 bit integer
ISC_UCHAR *s = (ISC_UCHAR *)arg_vector[0].a_address;
2009-06-25 12:44:37 +02:00
if (arg_vector[0].a_length == 4)
{
intPart = ((ISC_INT64)*(s) << 24) +
((ISC_INT64)*(s + 1) << 16) +
((ISC_INT64)*(s + 2) << 8) +
(ISC_INT64)*(s + 3);
}
2009-06-25 12:44:37 +02:00
else
{
intPart = ((ISC_INT64)*(s) << 56) +
((ISC_INT64)*(s + 1) << 48) +
((ISC_INT64)*(s + 2) << 40) +
((ISC_INT64)*(s + 3) << 32) +
((ISC_INT64)*(s + 4) << 24) +
((ISC_INT64)*(s + 5) << 16) +
((ISC_INT64)*(s + 6) << 8) +
(ISC_INT64)*(s + 7);
}
// Convert to a double & shift the fraction part right
double arg = (double)intPart * pow(10.0, arg_vector[0].a_scale);
// Save it into the return argument
if (arg_vector[-1].a_length == 4)
*(float *)arg_vector[-1].a_address = arg;
else
*(double *)arg_vector[-1].a_address = arg;
2008-12-05 02:20:14 +01:00
return (0);
}
2007-08-02 04:00:37 +02:00
2008-01-16 08:15:01 +01:00
// Convert a Cobol alpha (PIC X) field to a C string. This is done by trimming trailing spaces
// and adding the trailing '\0'.
EXPORT RM_ENTRY(rmc_stoc)
{
char* dest = (char*) arg_vector[-1].a_address;
const int dlen = arg_vector[-1].a_length;
const char* src = (char*) arg_vector[0].a_address;
const int slen = arg_vector[0].a_length;
2008-12-05 02:20:14 +01:00
int i = slen - 1;
while (src[i] == ' ' && i >= 0)
--i;
int len = (i + 1 < dlen) ? i + 1 : dlen - 1;
memmove(dest, src, len);
dest[len] = '\0';
return (0);
}
2007-08-02 04:00:37 +02:00
// Convert a C string to a Cobol alpha (PIC X) field. This is done by copying the original
// string and padding on the right with spaces.
EXPORT RM_ENTRY(rmc_ctos)
{
char* dest = (char*) arg_vector[-1].a_address;
const int dlen = arg_vector[-1].a_length;
const char* src = (char*) arg_vector[0].a_address;
2014-07-17 20:48:46 +02:00
const int slen = static_cast<int>(strlen(src));
memset(dest, ' ', dlen);
int len = (slen <= dlen) ? slen : dlen;
memmove(dest, src, len);
return (0);
}
2008-01-16 08:15:01 +01:00
2014-12-19 09:52:40 +01:00
static const char* banner = "Firebird Embedded SQL Interface";
#ifdef __cplusplus
extern "C" {
#endif
2014-12-19 09:52:40 +01:00
const char* RM_AddOnBanner();
const char* RM_AddOnLoadMessage();
#ifdef __cplusplus
}
#endif
// Return additional banner message for this module
2014-12-19 09:52:40 +01:00
const char* RM_AddOnBanner()
{
return (banner);
}
2014-12-19 09:52:40 +01:00
const char* RM_AddOnLoadMessage()
{
return (banner);
}
// RM/Cobol entry point table. Required for linux/unix support
2009-06-25 12:44:37 +02:00
EXPORT entry_table RM_EntryPoints[] =
{
{ "isc_embed_dsql_length", rmc_embed_dsql_length, "rmc_embed_dsql_length" },
{ "isc_cancel_blob", rmc_cancel_blob, "rmc_cancel_blob" },
{ "isc_close_blob", rmc_close_blob, "rmc_close_blob" },
{ "isc_compile_request", rmc_compile_request, "rmc_compile_request" },
{ "isc_create_database", rmc_create_database, "rmc_create_database" },
{ "isc_ddl", rmc_ddl, "rmc_ddl" },
{ "isc_commit_transaction", rmc_commit_transaction, "rmc_commit_transaction" },
{ "isc_rollback_transaction", rmc_rollback_transaction, "rmc_rollback_transaction" },
{ "isc_drop_database", rmc_drop_database, "rmc_drop_database" },
{ "isc_embed_dsql_close", rmc_embed_dsql_close, "rmc_embed_dsql_close" },
{ "isc_embed_dsql_declare", rmc_embed_dsql_declare, "rmc_embed_dsql_declare" },
{ "isc_embed_dsql_describe", rmc_embed_dsql_describe, "rmc_embed_dsql_describe" },
{ "isc_embed_dsql_describe_bind", rmc_embed_dsql_describe_bind, "rmc_embed_dsql_describe_bind" },
{ "isc_embed_dsql_execute", rmc_embed_dsql_execute, "rmc_embed_dsql_execute" },
{ "isc_embed_dsql_execute2", rmc_embed_dsql_execute2, "rmc_embed_dsql_execute2" },
{ "isc_embed_dsql_execute_immed", rmc_embed_dsql_execute_immed, "rmc_embed_dsql_execute_immed" },
{ "isc_embed_dsql_insert", rmc_embed_dsql_insert, "rmc_embed_dsql_insert" },
{ "isc_embed_dsql_open", rmc_embed_dsql_open, "rmc_embed_dsql_open" },
{ "isc_embed_dsql_open2", rmc_embed_dsql_open2, "rmc_embed_dsql_open2" },
{ "isc_embed_dsql_prepare", rmc_embed_dsql_prepare, "rmc_embed_dsql_prepare" },
{ "isc_dsql_allocate_statement", rmc_dsql_allocate_statement, "rmc_dsql_allocate_statement" },
{ "isc_dsql_alloc_statement2", rmc_dsql_alloc_statement2, "rmc_dsql_alloc_statement2" },
{ "isc_dsql_execute_m", rmc_dsql_execute_m, "rmc_dsql_execute_m" },
{ "isc_dsql_free_statement", rmc_dsql_free_statement, "rmc_dsql_free_statement" },
{ "isc_dsql_set_cursor_name", rmc_dsql_set_cursor_name, "rmc_dsql_set_cursor_name" },
{ "isc_detach_database", rmc_detach_database, "rmc_detach_database" },
{ "isc_get_slice", rmc_get_slice, "rmc_get_slice" },
{ "isc_put_slice", rmc_put_slice, "rmc_put_slice" },
{ "isc_get_segment", rmc_get_segment, "rmc_get_segment" },
{ "isc_put_segment", rmc_put_segment, "rmc_put_segment" },
{ "isc_receive", rmc_receive, "rmc_receive" },
{ "isc_release_request", rmc_release_request, "rmc_release_request" },
{ "isc_unwind_request", rmc_unwind_request, "rmc_unwind_request" },
{ "isc_send", rmc_send, "rmc_send" },
{ "isc_start_transaction", rmc_start_transaction, "rmc_start_transaction" },
{ "isc_start_and_send", rmc_start_and_send, "rmc_start_and_send" },
{ "isc_start_request", rmc_start_request, "rmc_start_request" },
{ "isc_transact_request", rmc_transact_request, "rmc_transact_request" },
{ "isc_commit_retaining", rmc_commit_retaining, "rmc_commit_retaining" },
2008-01-16 08:15:01 +01:00
{ "isc_rollback_retaining", rmc_rollback_retaining, "rmc_rollback_retaining" },
{ "isc_attach_database", rmc_attach_database, "rmc_attach_database" },
{ "isc_modify_dpb", rmc_modify_dpb, "rmc_modify_dpb" },
{ "isc_free", rmc_free, "rmc_free" },
{ "isc_sqlcode", rmc_sqlcode, "rmc_sqlcode" },
{ "isc_embed_dsql_fetch", rmc_embed_dsql_fetch, "rmc_embed_dsql_fetch" },
{ "isc_event_block_a", rmc_event_block_a, "rmc_event_block_a" },
{ "isc_prepare_transaction", rmc_prepare_transaction, "rmc_prepare_transaction" },
{ "isc_wait_for_event", rmc_wait_for_event, "rmc_wait_for_event" },
{ "isc_event_counts", rmc_event_counts, "rmc_event_counts" },
{ "isc_baddress", rmc_baddress, "rmc_baddress" },
{ "isc_interprete", rmc_interprete, "rmc_interprete" },
{ "rmc_status_address", rmc_status_address, "rmc_status_address" },
{ "isc_expand_dpb", rmc_expand_dpb, "rmc_expand_dpb" },
{ "isc_compile_request2", rmc_compile_request2, "rmc_compile_request2" },
{ "isc_create_blob2", rmc_create_blob2, "rmc_create_blob2" },
{ "isc_open_blob2", rmc_open_blob2, "rmc_open_blob2" },
{ "isc_qtoq", rmc_qtoq, "rmc_qtoq" },
{ "rmc_btoc", rmc_btoc, "rmc_btoc" },
{ "rmc_ctob", rmc_ctob, "rmc_ctob" },
{ "isc_decode_date", rmc_decode_date, "rmc_decode_date" },
{ "isc_encode_date", rmc_encode_date, "rmc_encode_date" },
{ "rmc_dtoc", rmc_dtoc, "rmc_dtoc" },
{ "rmc_ctod", rmc_ctod, "rmc_ctod" },
{ "rmc_ftoc", rmc_ftoc, "rmc_ftoc" },
{ "rmc_ctof", rmc_ctof, "rmc_ctof" },
{ "rmc_ctos", rmc_ctos, "rmc_ctos" },
{ "rmc_stoc", rmc_stoc, "RMC_stoc" },
{ NULL, NULL, NULL }
};