mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-31 00:43:02 +01:00
235db035ce
1. Bring trace DSQL, DYN and BLR trace logging up-to-date 2. Remove redundant CSB pointer dereferences in BLR parser and request compiler 3. Convert RIGHT JOIN to LEFT JOIN early during BLR parsing 4. Check BLR syntax for unititalized contexts usage 5. Some type-safety and const-correctness fixes
4650 lines
121 KiB
C++
4650 lines
121 KiB
C++
//____________________________________________________________
|
|
//
|
|
// PROGRAM: General preprocessor
|
|
// MODULE: cob.cpp
|
|
// DESCRIPTION: COBOL text generator
|
|
//
|
|
// 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): ______________________________________.
|
|
// Solaris x86 changes - Konstantin Kuznetsov, Neil McCalden
|
|
// 8-Mar-2002 FSG (Frank Schlottmann-Gödde) tiny cobol support
|
|
// fixed Bug No. 526204*
|
|
//
|
|
//
|
|
//____________________________________________________________
|
|
//
|
|
// $Id: cob.cpp,v 1.29 2003-09-28 21:35:58 skidder Exp $
|
|
//
|
|
// 2002.10.27 Sean Leyne - Completed removal of obsolete "DG_X86" port
|
|
// 2002.10.27 Sean Leyne - Code Cleanup, removed obsolete "UNIXWARE" port
|
|
//
|
|
// 2002.10.28 Sean Leyne - Completed removal of obsolete "DGUX" port
|
|
// 2002.10.28 Sean Leyne - Completed removal of obsolete "HP700" port
|
|
//
|
|
//
|
|
|
|
#include "firebird.h"
|
|
#include "../jrd/ib_stdio.h"
|
|
#include "../jrd/common.h"
|
|
#include <stdarg.h>
|
|
#include "../jrd/gds.h"
|
|
#include "../jrd/gds_proto.h"
|
|
#include "../gpre/gpre.h"
|
|
#include "../gpre/pat.h"
|
|
#include "../gpre/cmp_proto.h"
|
|
#include "../gpre/lang_proto.h"
|
|
#include "../gpre/pat_proto.h"
|
|
#include "../gpre/prett_proto.h"
|
|
#include "../gpre/gpre_proto.h"
|
|
|
|
#ifdef HAVE_STRING_H
|
|
#include <string.h>
|
|
#endif
|
|
|
|
// vms requires all caps in function call names; hp requires lc
|
|
|
|
#ifdef VMS
|
|
#define GIVING_SUPPORTED
|
|
#define OMITTED "OMITTED"
|
|
#define RAW_BLR_TEMPLATE "03 %s%d%s%d PIC S9(9) USAGE COMP VALUE IS %"SLONGFORMAT"."
|
|
#define RAW_TPB_TEMPLATE "03 %s%d%s%d PIC S9(9) USAGE COMP VALUE IS %"SLONGFORMAT"."
|
|
#define BY_VALUE "BY VALUE "
|
|
#define END_VALUE ""
|
|
#define BY_REF "BY REFERENCE "
|
|
#define BY_DESC "BY DESCRIPTOR "
|
|
#define ISC_BLOB "ISC_%s_BLOB"
|
|
#define CLOSE "CLOSE"
|
|
#define CANCEL "CANCEL"
|
|
#define COMP_VALUE "COMP"
|
|
#define ISC_CANCEL_BLOB "ISC_CANCEL_BLOB"
|
|
#define ISC_COMPILE_REQUEST "ISC_COMPILE_REQUEST"
|
|
#define ISC_CREATE_DATABASE "ISC_CREATE_DATABASE"
|
|
#define ISC_DDL "ISC_DDL"
|
|
#define ISC_COMMIT_TRANSACTION "ISC_COMMIT_TRANSACTION"
|
|
#define ISC_ROLLBACK_TRANSACTION "ISC_ROLLBACK_TRANSACTION"
|
|
#define ISC_DROP_DATABASE "ISC_DROP_DATABASE"
|
|
#define ISC_CLOSE "ISC_EMBED_DSQL_CLOSE"
|
|
#define ISC_DECLARE "ISC_EMBED_DSQL_DECLARE"
|
|
#define ISC_DESCRIBE "ISC_EMBED_DSQL_DESCRIBE"
|
|
#define ISC_DESCRIBE_BIND "ISC_EMBED_DSQL_DESCRIBE_BIND"
|
|
#define ISC_EXECUTE "ISC_EMBED_DSQL_EXECUTE"
|
|
#define ISC_EXECUTE2 "ISC_EMBED_DSQL_EXECUTE2"
|
|
#define ISC_EXECUTE_IMMEDIATE "ISC_EMBED_DSQL_EXECUTE_IMMED_D"
|
|
#define ISC_EXECUTE_IMMEDIATE2 "ISC_EMBED_DSQL_EXECUTE_IMMED2_D"
|
|
#define ISC_FETCH "ISC_EMBED_DSQL_FETCH"
|
|
#define ISC_INSERT "ISC_EMBED_DSQL_INSERT"
|
|
#define ISC_OPEN "ISC_EMBED_DSQL_OPEN"
|
|
#define ISC_OPEN2 "ISC_EMBED_DSQL_OPEN2"
|
|
#define ISC_PREPARE "ISC_EMBED_DSQL_PREPARE_D"
|
|
#define ISC_DSQL_ALLOCATE "ISC_DSQL_ALLOC_STATEMENT2"
|
|
#define ISC_DSQL_EXECUTE "ISC_DSQL_EXECUTE_M"
|
|
#define ISC_DSQL_FREE "ISC_DSQL_FREE_STATEMENT"
|
|
#define ISC_DSQL_SET_CURSOR "ISC_DSQL_SET_CURSOR_NAME"
|
|
#define ISC_SQLCODE_CALL "ISC_SQLCODE"
|
|
#define ISC_DETACH_DATABASE "ISC_DETACH_DATABASE"
|
|
#define ISC_GET_SLICE "ISC_GET_SLICE"
|
|
#define ISC_PUT_SLICE "ISC_PUT_SLICE"
|
|
#define ISC_GET_SEGMENT "ISC_GET_SEGMENT"
|
|
#define ISC_PUT_SEGMENT "ISC_PUT_SEGMENT"
|
|
#define ISC_RECEIVE "ISC_RECEIVE"
|
|
#define ISC_RELEASE_REQUEST "ISC_RELEASE_REQUEST"
|
|
#define ISC_UNWIND_REQUEST "ISC_UNWIND_REQUEST"
|
|
#define ISC_SEND "ISC_SEND"
|
|
#define ISC_GET_SLICE "ISC_GET_SLICE"
|
|
#define ISC_PUT_SLICE "ISC_PUT_SLICE"
|
|
#define ISC_START_TRANSACTION "ISC_START_TRANSACTION"
|
|
#define ISC_START_AND_SEND "ISC_START_AND_SEND"
|
|
#define ISC_START_REQUEST "ISC_START_REQUEST"
|
|
#define ISC_TRANSACT_REQUEST "ISC_TRANSACT_REQUEST"
|
|
#define ISC_COMMIT_RETAINING "ISC_COMMIT_RETAINING"
|
|
#define ISC_ATTACH_DATABASE_D "ISC_ATTACH_DATABASE_D"
|
|
#define ISC_ATTACH_DATABASE "ISC_ATTACH_DATABASE"
|
|
#define ISC_MODIFY_DPB "ISC_MODIFY_DPB"
|
|
#define ISC_FREE "ISC_FREE"
|
|
#define ISC_PREPARE_TRANSACTION "ISC_PREPARE_TRANSACTION"
|
|
#define ISC_EVENT_BLOCK "ISC_EVENT_BLOCK_A"
|
|
#define ISC_EVENT_COUNTS "ISC_EVENT_COUNTS"
|
|
#define ISC_EVENT_WAIT "ISC_EVENT_WAIT"
|
|
#define ISC_BADDRESS "ISC_BADDRESS"
|
|
|
|
#else
|
|
|
|
#if (defined AIX || defined AIX_PPC)
|
|
#define MICROFOCUS
|
|
#endif
|
|
#if (defined sparc || defined SOLX86 )
|
|
#define MICROFOCUS
|
|
#endif
|
|
/* RITTER - added HP11 to the line below */
|
|
#if (defined HP10 || defined HP11)
|
|
#define MICROFOCUS
|
|
#endif
|
|
|
|
#ifdef SINIXZ
|
|
#define MICROFOCUS
|
|
#endif
|
|
|
|
#ifdef LINUX
|
|
#define MICROFOCUS
|
|
#endif
|
|
|
|
#ifdef DARWIN
|
|
#define MICROFOCUS
|
|
#endif
|
|
|
|
#if defined FREEBSD || defined NETBSD
|
|
#define MICROFOCUS
|
|
#endif
|
|
|
|
#ifdef WIN_NT
|
|
#define MICROFOCUS
|
|
#endif
|
|
|
|
#ifdef MICROFOCUS
|
|
#define OMITTED "BY VALUE 0"
|
|
#define BY_VALUE "BY VALUE "
|
|
#define END_VALUE ""
|
|
#define BY_REF "BY REFERENCE "
|
|
#define BY_DESC "BY REFERENCE "
|
|
#define RAW_BLR_TEMPLATE "03 %s%d%s%d PIC XXXX USAGE COMP-X VALUE IS %"ULONGFORMAT"."
|
|
#define RAW_TPB_TEMPLATE "03 %s%d%s%d PIC XXXX USAGE COMP-X VALUE IS %"ULONGFORMAT"."
|
|
#define COMP_VALUE "COMP-5"
|
|
#endif
|
|
|
|
#ifndef COMP_VALUE
|
|
#define COMP_VALUE "COMP"
|
|
#endif
|
|
|
|
#ifndef STRING_LENGTH
|
|
#define STRING_LENGTH "\"isc_embed_dsql_length\""
|
|
#endif
|
|
|
|
#define ISC_BLOB "isc_%s_blob"
|
|
#define CLOSE "close"
|
|
#define CANCEL "cancel"
|
|
#define ISC_CANCEL_BLOB "isc_cancel_blob"
|
|
#define ISC_COMPILE_REQUEST "isc_compile_request"
|
|
#define ISC_CREATE_DATABASE "isc_create_database"
|
|
#define ISC_DDL "isc_ddl"
|
|
#define ISC_COMMIT_TRANSACTION "isc_commit_transaction"
|
|
#define ISC_ROLLBACK_TRANSACTION "isc_rollback_transaction"
|
|
#define ISC_DROP_DATABASE "isc_drop_database"
|
|
#define ISC_CLOSE "isc_embed_dsql_close"
|
|
#define ISC_DECLARE "isc_embed_dsql_declare"
|
|
#define ISC_DESCRIBE "isc_embed_dsql_describe"
|
|
#define ISC_DESCRIBE_BIND "isc_embed_dsql_describe_bind"
|
|
#define ISC_EXECUTE "isc_embed_dsql_execute"
|
|
#define ISC_EXECUTE2 "isc_embed_dsql_execute2"
|
|
#define ISC_EXECUTE_IMMEDIATE "isc_embed_dsql_execute_immed"
|
|
#define ISC_EXECUTE_IMMEDIATE2 "isc_embed_dsql_execute_immed2"
|
|
#define ISC_INSERT "isc_embed_dsql_insert"
|
|
#define ISC_OPEN "isc_embed_dsql_open"
|
|
#define ISC_OPEN2 "isc_embed_dsql_open2"
|
|
#define ISC_PREPARE "isc_embed_dsql_prepare"
|
|
#define ISC_DSQL_ALLOCATE "isc_dsql_alloc_statement2"
|
|
#define ISC_DSQL_EXECUTE "isc_dsql_execute_m"
|
|
#define ISC_DSQL_FREE "isc_dsql_free_statement"
|
|
#define ISC_DSQL_SET_CURSOR "isc_dsql_set_cursor_name"
|
|
#define ISC_COMMIT_ROLLBACK_TRANSACTION "isc_%s_transaction"
|
|
#define ISC_DETACH_DATABASE "isc_detach_database"
|
|
#define ISC_GET_SLICE "isc_get_slice"
|
|
#define ISC_PUT_SLICE "isc_put_slice"
|
|
#define ISC_GET_SEGMENT "isc_get_segment"
|
|
#define ISC_PUT_SEGMENT "isc_put_segment"
|
|
#define ISC_RECEIVE "isc_receive"
|
|
#define ISC_RELEASE_REQUEST "isc_release_request"
|
|
#define ISC_UNWIND_REQUEST "isc_unwind_request"
|
|
#define ISC_SEND "isc_send"
|
|
#define ISC_GET_SLICE "isc_get_slice"
|
|
#define ISC_PUT_SLICE "isc_put_slice"
|
|
#define ISC_START_TRANSACTION "isc_start_transaction"
|
|
#define ISC_START_AND_SEND "isc_start_and_send"
|
|
#define ISC_START_REQUEST "isc_start_request"
|
|
#define ISC_TRANSACT_REQUEST "isc_transact_request"
|
|
#define ISC_COMMIT_RETAINING "isc_commit_retaining"
|
|
#define ISC_ATTACH_DATABASE_D "isc_attach_database"
|
|
#define ISC_ATTACH_DATABASE "isc_attach_database"
|
|
#define ISC_MODIFY_DPB "isc_modify_dpb"
|
|
#define ISC_FREE "isc_free"
|
|
#ifdef GIVING_SUPPORTED
|
|
#define ISC_SQLCODE_CALL "isc_sqlcode"
|
|
#define ISC_FETCH "isc_embed_dsql_fetch"
|
|
#define ISC_EVENT_BLOCK "isc_event_block_a"
|
|
#else
|
|
#define ISC_SQLCODE_CALL "isc_sqlcode_s"
|
|
#define ISC_FETCH "isc_embed_dsql_fetch_a"
|
|
#define ISC_EVENT_BLOCK "isc_event_block_s"
|
|
#endif
|
|
#define ISC_PREPARE_TRANSACTION "isc_prepare_transaction"
|
|
#define ISC_EVENT_WAIT "isc_wait_for_event"
|
|
#define ISC_EVENT_COUNTS "isc_event_counts"
|
|
#ifdef GIVING_SUPPORTED
|
|
#define ISC_BADDRESS "isc_baddress"
|
|
#else
|
|
#define ISC_BADDRESS "isc_baddress_s"
|
|
#endif
|
|
#endif
|
|
|
|
#if (defined AIX || defined AIX_PPC)
|
|
#define USAGE_COMP " USAGE IS COMP"
|
|
#endif
|
|
|
|
#if (defined sparc || defined SOLX86 )
|
|
#define USAGE_COMP " USAGE IS COMP"
|
|
#endif
|
|
|
|
/* RITTER - added HP11 to the line below */
|
|
#if (defined HP10 || defined HP11)
|
|
#define USAGE_COMP " USAGE IS COMP"
|
|
#endif
|
|
|
|
#ifndef FLOATS_COMPS_DECLARED
|
|
#define FLOATS_COMPS_DECLARED
|
|
#define DCL_FLOAT "USAGE IS COMP-1"
|
|
#define DCL_DOUBLE "USAGE IS COMP-2"
|
|
#endif
|
|
|
|
#ifndef USAGE_COMP
|
|
#define USAGE_COMP " USAGE IS COMP"
|
|
#endif
|
|
|
|
extern DBB isc_databases;
|
|
extern GPRE_REQ requests;
|
|
extern IB_FILE *out_file;
|
|
|
|
#ifdef NOT_USED_OR_REPLACED
|
|
static void align(int column);
|
|
#endif
|
|
static void asgn_from (ACT, REF);
|
|
static void asgn_to (ACT, REF);
|
|
static void asgn_to_proc (REF);
|
|
static void gen_any (ACT);
|
|
static void gen_at_end (ACT);
|
|
static void gen_based (ACT);
|
|
static void gen_blob_close (ACT);
|
|
static void gen_blob_end (ACT);
|
|
static void gen_blob_for (ACT);
|
|
static void gen_blob_open (ACT);
|
|
static void gen_blr (void *, SSHORT, const char*);
|
|
static void gen_clear_handles (ACT);
|
|
static void gen_compile (ACT);
|
|
static void gen_create_database (ACT);
|
|
static void gen_cursor_close (ACT, GPRE_REQ);
|
|
static void gen_cursor_init (ACT);
|
|
static void gen_cursor_open (ACT, GPRE_REQ);
|
|
static void gen_database (ACT);
|
|
static void gen_ddl (ACT);
|
|
static void gen_dyn_close (ACT);
|
|
static void gen_dyn_declare (ACT);
|
|
static void gen_dyn_describe(ACT, bool);
|
|
static void gen_dyn_execute (ACT);
|
|
static void gen_dyn_fetch (ACT);
|
|
static void gen_dyn_immediate (ACT);
|
|
static void gen_dyn_insert (ACT);
|
|
static void gen_dyn_open (ACT);
|
|
static void gen_dyn_prepare (ACT);
|
|
static void gen_emodify (ACT);
|
|
static void gen_estore (ACT);
|
|
static void gen_end_fetch (ACT);
|
|
static void gen_endfor (ACT);
|
|
static void gen_erase (ACT);
|
|
static SSHORT gen_event_block (ACT);
|
|
static void gen_event_init (ACT);
|
|
static void gen_event_wait (ACT);
|
|
static void gen_fetch (ACT);
|
|
static void gen_finish (ACT);
|
|
static void gen_for (ACT);
|
|
static void gen_function (ACT);
|
|
static void gen_get_or_put_slice(ACT, REF, bool);
|
|
static void gen_get_segment (ACT);
|
|
static void gen_loop (ACT);
|
|
static TEXT *gen_name(TEXT *, REF, bool);
|
|
static void gen_on_error (ACT);
|
|
static void gen_procedure (ACT);
|
|
static void gen_put_segment (ACT);
|
|
static void gen_raw (UCHAR *, enum req_t, int, int);
|
|
static void gen_ready (ACT);
|
|
static void gen_receive (ACT, POR);
|
|
static void gen_release (ACT);
|
|
static void gen_request (GPRE_REQ);
|
|
static void gen_s_end (ACT);
|
|
static void gen_s_fetch (ACT);
|
|
static void gen_s_start (ACT);
|
|
static void gen_segment (ACT);
|
|
static void gen_select (ACT);
|
|
static void gen_send (ACT, POR);
|
|
static void gen_slice (ACT);
|
|
static void gen_start (ACT, POR);
|
|
static void gen_store (ACT);
|
|
static void gen_t_start (ACT);
|
|
static void gen_tpb (TPB);
|
|
static void gen_trans (ACT);
|
|
static void gen_type (ACT);
|
|
static void gen_update (ACT);
|
|
static void gen_variable (ACT);
|
|
static void gen_whenever (SWE);
|
|
static void make_array_declaration (REF);
|
|
static TEXT *make_name (TEXT *, SYM);
|
|
static TEXT *make_name_formatted (TEXT *, TEXT *, SYM);
|
|
static void make_port (POR);
|
|
static void make_ready (DBB, TEXT *, TEXT *, GPRE_REQ, USHORT);
|
|
static void printa(TEXT *, bool, TEXT *, ...) ATTRIBUTE_FORMAT(3,4);
|
|
#ifdef NOT_USED_OR_REPLACED
|
|
static void printb (TEXT *, ... ) ATTRIBUTE_FORMAT(1,2);
|
|
#endif
|
|
static TEXT *request_trans (ACT, GPRE_REQ);
|
|
static void set_sqlcode (ACT);
|
|
static TEXT *status_vector (ACT);
|
|
static void t_start_auto (GPRE_REQ, TEXT *, ACT, bool);
|
|
|
|
static TEXT output_buffer[512];
|
|
static int first_flag;
|
|
static TEXT **names;
|
|
|
|
static TEXT *vnames[] = {
|
|
"_",
|
|
"ISC_",
|
|
"isc_",
|
|
"isc_blob_null",
|
|
"ISC_TPB_",
|
|
"ISC_TRANS",
|
|
"ISC_STATUS_VECTOR",
|
|
"ISC_STATUS",
|
|
"ISC_STATUS_VECTOR2",
|
|
"ISC_STATUS2",
|
|
"ISC_WINDOW",
|
|
"ISC_WIDTH",
|
|
"ISC_HEIGHT",
|
|
"RDB$K_DB_TYPE_GDS",
|
|
"ISC_ARRAY_LENGTH",
|
|
" ", /* column */
|
|
"* ", /* comment */
|
|
"- ", /* continue */
|
|
"- \"", /* continue quote */
|
|
"- \'", /* continue single quote */
|
|
"", /* column0 */
|
|
" ", /* column indent */
|
|
"ISC_SQLCODE",
|
|
"ISC_EVENTS_VECTOR",
|
|
"ISC_EVENTS",
|
|
"ISC_EVENT_NAMES_VECTOR",
|
|
"ISC_EVENT_NAMES",
|
|
"ISC_EVENT_NAMES_VECTOR2",
|
|
"ISC_EVENT_NAMES2",
|
|
NULL
|
|
};
|
|
|
|
static TEXT *anames[] = {
|
|
"-",
|
|
"ISC-",
|
|
"isc-",
|
|
"isc-blob-null",
|
|
"ISC-TPB-",
|
|
"ISC-TRANS",
|
|
"ISC-STATUS-VECTOR",
|
|
"ISC-STATUS",
|
|
"ISC-STATUS-VECTOR2",
|
|
"ISC-STATUS2",
|
|
"ISC-WINDOW",
|
|
"ISC-WIDTH",
|
|
"ISC-HEIGHT",
|
|
"RDB-K-DB-TYPE-GDS",
|
|
"ISC-ARRAY-LENGTH",
|
|
" ", /* column */
|
|
" * ", /* comment */
|
|
" ", /* continue */
|
|
" - \"", /* continue quote */
|
|
" - \'", /* continue single quote */
|
|
" ", /* column0 */
|
|
" ", /* column indent */
|
|
"ISC-SQL-CODE",
|
|
"ISC-EVENTS-VECTOR",
|
|
"ISC-EVENTS",
|
|
"ISC-EVENT-NAMES-VECTOR",
|
|
"ISC-EVENT-NAMES",
|
|
"ISC-EVENT-NAMES-VECTOR2",
|
|
"ISC-EVENT-NAMES2",
|
|
NULL
|
|
};
|
|
|
|
#define UNDER 0
|
|
#define ISC_ 1
|
|
#define isc_ 2
|
|
#define isc_blob_null 3
|
|
#define ISC_TPB_ 4
|
|
#define ISC_TRANS 5
|
|
#define ISC_STATUS_VECTOR 6
|
|
/* replace definition of ISC_STATUS from gds.h */
|
|
#undef ISC_STATUS
|
|
#define ISC_STATUS 7
|
|
#define ISC_STATUS_VECTOR2 8
|
|
#define ISC_STATUS2 9
|
|
#define ISC_WINDOW 10
|
|
#define ISC_WIDTH 11
|
|
#define ISC_HEIGHT 12
|
|
#define RDB$K_DB_TYPE_GDS 13
|
|
#define ISC_ARRAY_LENGTH 14
|
|
#define COLUMN 15
|
|
#define COMMENT 16
|
|
#define CONTINUE 17
|
|
#define CONTINUE_QUOTE 18
|
|
#define CONTINUE_SINGLE_QUOTE 19
|
|
#define COLUMN_0 20
|
|
#define COLUMN_INDENT 21
|
|
#define ISC_SQLCODE 22
|
|
#define ISC_EVENTS_VECTOR 23
|
|
#define ISC_EVENTS 24
|
|
#define ISC_EVENT_NAMES_VECTOR 25
|
|
#define ISC_EVENT_NAMES 26
|
|
#define ISC_EVENT_NAMES_VECTOR2 27
|
|
#define ISC_EVENT_NAMES2 28
|
|
|
|
#define INDENT " "
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
//
|
|
|
|
void COB_action( ACT action, int column)
|
|
{
|
|
|
|
if (action->act_flags & ACT_break)
|
|
first_flag = FALSE;
|
|
|
|
switch (action->act_type) {
|
|
case ACT_alter_database:
|
|
case ACT_alter_domain:
|
|
case ACT_alter_table:
|
|
case ACT_alter_index:
|
|
case ACT_create_domain:
|
|
case ACT_create_generator:
|
|
case ACT_create_index:
|
|
case ACT_create_shadow:
|
|
case ACT_create_table:
|
|
case ACT_create_view:
|
|
case ACT_declare_filter:
|
|
case ACT_declare_udf:
|
|
case ACT_statistics:
|
|
case ACT_drop_domain:
|
|
case ACT_drop_filter:
|
|
case ACT_drop_index:
|
|
case ACT_drop_shadow:
|
|
case ACT_drop_table:
|
|
case ACT_drop_udf:
|
|
case ACT_drop_view:
|
|
gen_ddl(action);
|
|
break;
|
|
case ACT_any:
|
|
gen_any(action);
|
|
return;
|
|
case ACT_at_end:
|
|
gen_at_end(action);
|
|
return;
|
|
case ACT_commit:
|
|
gen_trans(action);
|
|
break;
|
|
case ACT_commit_retain_context:
|
|
gen_trans(action);
|
|
break;
|
|
case ACT_basedon:
|
|
gen_based(action);
|
|
return;
|
|
case ACT_b_declare:
|
|
gen_database(action);
|
|
return;
|
|
case ACT_blob_cancel:
|
|
gen_blob_close(action);
|
|
return;
|
|
case ACT_blob_close:
|
|
gen_blob_close(action);
|
|
break;
|
|
case ACT_blob_create:
|
|
gen_blob_open(action);
|
|
break;
|
|
case ACT_blob_for:
|
|
gen_blob_for(action);
|
|
return;
|
|
case ACT_blob_handle:
|
|
gen_segment(action);
|
|
return;
|
|
case ACT_blob_open:
|
|
gen_blob_open(action);
|
|
break;
|
|
case ACT_clear_handles:
|
|
gen_clear_handles(action);
|
|
break;
|
|
case ACT_close:
|
|
gen_s_end(action);
|
|
break;
|
|
case ACT_create_database:
|
|
gen_create_database(action);
|
|
break;
|
|
case ACT_cursor:
|
|
gen_cursor_init(action);
|
|
return;
|
|
case ACT_database:
|
|
gen_database(action);
|
|
return;
|
|
case ACT_disconnect:
|
|
gen_finish(action);
|
|
break;
|
|
case ACT_dyn_close:
|
|
gen_dyn_close(action);
|
|
break;
|
|
case ACT_dyn_cursor:
|
|
gen_dyn_declare(action);
|
|
break;
|
|
case ACT_dyn_describe:
|
|
gen_dyn_describe(action, false);
|
|
break;
|
|
case ACT_dyn_describe_input:
|
|
gen_dyn_describe(action, true);
|
|
break;
|
|
case ACT_dyn_execute:
|
|
gen_dyn_execute(action);
|
|
break;
|
|
case ACT_dyn_fetch:
|
|
gen_dyn_fetch(action);
|
|
break;
|
|
case ACT_dyn_grant:
|
|
gen_ddl(action);
|
|
break;
|
|
case ACT_dyn_immediate:
|
|
gen_dyn_immediate(action);
|
|
break;
|
|
case ACT_dyn_insert:
|
|
gen_dyn_insert(action);
|
|
break;
|
|
case ACT_dyn_open:
|
|
gen_dyn_open(action);
|
|
break;
|
|
case ACT_dyn_prepare:
|
|
gen_dyn_prepare(action);
|
|
break;
|
|
case ACT_dyn_revoke:
|
|
gen_ddl(action);
|
|
break;
|
|
case ACT_endblob:
|
|
gen_blob_end(action);
|
|
return;
|
|
case ACT_enderror:
|
|
sprintf(output_buffer, "%sEND-IF", names[COLUMN]);
|
|
COB_print_buffer(output_buffer, FALSE);
|
|
return;
|
|
case ACT_endfor:
|
|
gen_endfor(action);
|
|
break;
|
|
case ACT_endmodify:
|
|
gen_emodify(action);
|
|
break;
|
|
case ACT_endstore:
|
|
gen_estore(action);
|
|
break;
|
|
case ACT_erase:
|
|
gen_erase(action);
|
|
return;
|
|
case ACT_event_init:
|
|
gen_event_init(action);
|
|
return;
|
|
case ACT_event_wait:
|
|
gen_event_wait(action);
|
|
return;
|
|
case ACT_fetch:
|
|
gen_fetch(action);
|
|
break;
|
|
case ACT_finish:
|
|
gen_finish(action);
|
|
break;
|
|
case ACT_for:
|
|
gen_for(action);
|
|
return;
|
|
case ACT_function:
|
|
gen_function(action);
|
|
return;
|
|
case ACT_get_segment:
|
|
gen_get_segment(action);
|
|
break;
|
|
case ACT_get_slice:
|
|
gen_slice(action);
|
|
return;
|
|
case ACT_hctef:
|
|
gen_end_fetch(action);
|
|
return;
|
|
case ACT_insert:
|
|
gen_s_start(action);
|
|
break;
|
|
case ACT_loop:
|
|
gen_loop(action);
|
|
break;
|
|
case ACT_open:
|
|
gen_s_start(action);
|
|
break;
|
|
case ACT_on_error:
|
|
gen_on_error(action);
|
|
return;
|
|
case ACT_prepare:
|
|
gen_trans(action);
|
|
break;
|
|
case ACT_procedure:
|
|
gen_procedure(action);
|
|
break;
|
|
case ACT_put_segment:
|
|
gen_put_segment(action);
|
|
break;
|
|
case ACT_put_slice:
|
|
gen_slice(action);
|
|
return;
|
|
case ACT_ready:
|
|
gen_ready(action);
|
|
return;
|
|
case ACT_release:
|
|
gen_release(action);
|
|
break;
|
|
case ACT_rfinish:
|
|
gen_finish(action);
|
|
return;
|
|
case ACT_rollback:
|
|
gen_trans(action);
|
|
break;
|
|
case ACT_routine:
|
|
return;
|
|
case ACT_s_end:
|
|
gen_s_end(action);
|
|
return;
|
|
case ACT_s_fetch:
|
|
gen_s_fetch(action);
|
|
break;
|
|
case ACT_s_start:
|
|
gen_s_start(action);
|
|
break;
|
|
case ACT_select:
|
|
gen_select(action);
|
|
break;
|
|
case ACT_segment_length:
|
|
gen_segment(action);
|
|
return;
|
|
case ACT_segment:
|
|
gen_segment(action);
|
|
return;
|
|
case ACT_sql_dialect:
|
|
sw_sql_dialect = ((SDT) action->act_object)->sdt_dialect;
|
|
return;
|
|
case ACT_start:
|
|
gen_t_start(action);
|
|
break;
|
|
case ACT_store:
|
|
gen_store(action);
|
|
break;
|
|
case ACT_type:
|
|
gen_type(action);
|
|
return;
|
|
case ACT_update:
|
|
gen_update(action);
|
|
break;
|
|
case ACT_variable:
|
|
gen_variable(action);
|
|
return;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
if ((action->act_flags & ACT_sql) && action->act_whenever)
|
|
gen_whenever(action->act_whenever);
|
|
else
|
|
ib_fprintf(out_file, names[COLUMN]);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// point 'names' at the appropriate list
|
|
// ANSI has no underscores.
|
|
//
|
|
|
|
void COB_name_init(bool ansi)
|
|
{
|
|
|
|
names = ansi ? anames : vnames;
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Print a statment, breaking it into
|
|
// reasonable 80 character hunks. This
|
|
// function now works for COBOL statements
|
|
// which are function calls and non-function
|
|
// calls.
|
|
//
|
|
|
|
void COB_print_buffer(TEXT * output_buffer,
|
|
bool function_call)
|
|
{
|
|
TEXT s[80], *p, *q, *tempq;
|
|
bool open_quote = false;
|
|
bool single_quote = false;
|
|
bool save_open_quote;
|
|
bool save_single_quote;
|
|
USHORT max_line;
|
|
|
|
if (sw_ansi)
|
|
max_line = 72;
|
|
else
|
|
max_line = 79;
|
|
|
|
p = s;
|
|
|
|
for (q = output_buffer; *q; q++) {
|
|
*p++ = *q;
|
|
|
|
/* If we have a single or double quote, toggle the
|
|
quote switch and indicate single or double quote */
|
|
if (*q == '\"') {
|
|
open_quote = !open_quote;
|
|
single_quote = false;
|
|
}
|
|
else if (*q == '\'') {
|
|
open_quote = !open_quote;
|
|
single_quote = true;
|
|
}
|
|
|
|
if ((p - s) > max_line) {
|
|
tempq = q;
|
|
save_open_quote = open_quote;
|
|
save_single_quote = single_quote;
|
|
if (function_call) {
|
|
/* Back up until we reach a comma */
|
|
for (p--; (p > s); p--, q--) {
|
|
if (*(p + 1) == '\"' || *(p + 1) == '\'') {
|
|
/* If we have a single or double quote, toggle the
|
|
quote switch and indicate single or double quote */
|
|
open_quote = !open_quote;
|
|
if (open_quote)
|
|
single_quote = (*(p + 1) == '\'');
|
|
else
|
|
single_quote = false;
|
|
}
|
|
if (!open_quote && (*p == ','))
|
|
break;
|
|
}
|
|
/* if p == s, this is a call with no commas. back up to a blank */
|
|
if (p == s) {
|
|
q = tempq;
|
|
p = s + max_line;
|
|
open_quote = save_open_quote;
|
|
single_quote = save_single_quote;
|
|
for (p--; p > s; p--, q--) {
|
|
if (*(p + 1) == '\"' || *(p + 1) == '\'') {
|
|
/* If we have a single or double quote, toggle the
|
|
quote switch and indicate single or double quote */
|
|
open_quote = !open_quote;
|
|
if (open_quote)
|
|
single_quote = (*(p + 1) == '\'');
|
|
else
|
|
single_quote = false;
|
|
}
|
|
if (!open_quote && (*p == ' '))
|
|
break;
|
|
}
|
|
q--;
|
|
if (p == s) {
|
|
q = tempq - 1;
|
|
p = s + max_line;
|
|
open_quote = save_open_quote;
|
|
single_quote = save_single_quote;
|
|
}
|
|
*p = 0;
|
|
}
|
|
else
|
|
*++p = 0;
|
|
}
|
|
else {
|
|
/* back up to a blank */
|
|
for (p--; p > s; p--, q--) {
|
|
if (*(p + 1) == '\"' || *(p + 1) == '\'') {
|
|
/* If we have a single or double quote, toggle the
|
|
quote switch and indicate single or double quote */
|
|
open_quote = !open_quote;
|
|
if (open_quote)
|
|
single_quote = (*(p + 1) == '\'');
|
|
else
|
|
single_quote = false;
|
|
}
|
|
if (!open_quote && (*p == ' '))
|
|
break;
|
|
}
|
|
q--;
|
|
if (p == s) {
|
|
q = tempq - 1;
|
|
p = s + max_line;
|
|
open_quote = save_open_quote;
|
|
single_quote = save_single_quote;
|
|
}
|
|
*p = 0;
|
|
}
|
|
|
|
ib_fprintf(out_file, "%s\n", s);
|
|
if (open_quote) {
|
|
if (single_quote)
|
|
strcpy(s, names[CONTINUE_SINGLE_QUOTE]);
|
|
else
|
|
strcpy(s, names[CONTINUE_QUOTE]);
|
|
}
|
|
else
|
|
strcpy(s, names[CONTINUE]);
|
|
for (p = s; *p; p++);
|
|
}
|
|
}
|
|
*p = 0;
|
|
ib_fprintf(out_file, "%s", s);
|
|
output_buffer[0] = 0;
|
|
}
|
|
|
|
|
|
#ifdef NOT_USED_OR_REPLACED
|
|
//____________________________________________________________
|
|
//
|
|
// Align output to a specific column for output. If the
|
|
// column is negative, don't do anything.
|
|
//
|
|
|
|
static void align( int column)
|
|
{
|
|
int i;
|
|
|
|
if (column < 0)
|
|
return;
|
|
|
|
ib_putc('\n', out_file);
|
|
|
|
for (i = column / 8; i; --i)
|
|
ib_putc('\t', out_file);
|
|
|
|
for (i = column % 8; i; --i)
|
|
ib_putc(' ', out_file);
|
|
}
|
|
#endif
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Build an assignment from a host language variable to
|
|
// a port variable.
|
|
//
|
|
|
|
static void asgn_from( ACT action, REF reference)
|
|
{
|
|
GPRE_FLD field;
|
|
TEXT *value, name[64], variable[20], temp[20];
|
|
|
|
for (; reference; reference = reference->ref_next) {
|
|
field = reference->ref_field;
|
|
if (field->fld_array_info)
|
|
if (!(reference->ref_flags & REF_array_elem)) {
|
|
printa(names[COLUMN], true, "CALL \"isc_qtoq\" USING %s, %s",
|
|
names[isc_blob_null], gen_name(name, reference, true));
|
|
gen_get_or_put_slice(action, reference, false);
|
|
continue;
|
|
}
|
|
|
|
if (!reference->ref_source && !reference->ref_value)
|
|
continue;
|
|
gen_name(variable, reference, true);
|
|
if (reference->ref_source)
|
|
value = gen_name(temp, reference->ref_source, true);
|
|
else
|
|
value = reference->ref_value;
|
|
if (!reference->ref_master || (reference->ref_flags & REF_literal))
|
|
sprintf(output_buffer, "%sMOVE %s TO %s\n",
|
|
names[COLUMN], value, variable);
|
|
else {
|
|
sprintf(output_buffer, "%sIF %s < 0 THEN\n",
|
|
names[COLUMN], value);
|
|
COB_print_buffer(output_buffer, FALSE);
|
|
sprintf(output_buffer, "%sMOVE -1 TO %s\n", names[COLUMN_INDENT],
|
|
variable);
|
|
COB_print_buffer(output_buffer, FALSE);
|
|
sprintf(output_buffer, "%sELSE\n", names[COLUMN]);
|
|
COB_print_buffer(output_buffer, FALSE);
|
|
sprintf(output_buffer, "%sMOVE 0 TO %s\n", names[COLUMN_INDENT],
|
|
variable);
|
|
COB_print_buffer(output_buffer, FALSE);
|
|
sprintf(output_buffer, "%sEND-IF\n", names[COLUMN]);
|
|
}
|
|
COB_print_buffer(output_buffer, FALSE);
|
|
}
|
|
}
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Build an assignment to a host language variable from
|
|
// a port variable.
|
|
//
|
|
|
|
static void asgn_to( ACT action, REF reference)
|
|
{
|
|
GPRE_FLD field;
|
|
REF source;
|
|
TEXT s[64];
|
|
|
|
source = reference->ref_friend;
|
|
field = source->ref_field;
|
|
gen_name(s, source, true);
|
|
|
|
if (field->fld_array_info) {
|
|
source->ref_value = reference->ref_value;
|
|
gen_get_or_put_slice(action, source, true);
|
|
return;
|
|
}
|
|
|
|
field = reference->ref_field;
|
|
sprintf(output_buffer, "%sMOVE %s TO %s\n",
|
|
names[COLUMN], s, reference->ref_value);
|
|
COB_print_buffer(output_buffer, FALSE);
|
|
|
|
// Pick up NULL value if one is there
|
|
|
|
if (reference = reference->ref_null) {
|
|
sprintf(output_buffer, "%sMOVE %s TO %s\n",
|
|
names[COLUMN], gen_name(s, reference, true),
|
|
reference->ref_value);
|
|
COB_print_buffer(output_buffer, FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Build an assignment to a host language variable from
|
|
// a port variable.
|
|
//
|
|
|
|
static void asgn_to_proc( REF reference)
|
|
{
|
|
GPRE_FLD field;
|
|
TEXT s[64];
|
|
|
|
for (; reference; reference = reference->ref_next) {
|
|
if (!reference->ref_value)
|
|
continue;
|
|
field = reference->ref_field;
|
|
gen_name(s, reference, true);
|
|
sprintf(output_buffer, "%sMOVE %s TO %s\n",
|
|
names[COLUMN], s, reference->ref_value);
|
|
COB_print_buffer(output_buffer, FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate a function call for free standing ANY. Somebody else
|
|
// will need to generate the actual function.
|
|
//
|
|
|
|
static void gen_any( ACT action)
|
|
{
|
|
GPRE_REQ request;
|
|
POR port;
|
|
REF reference;
|
|
|
|
request = action->act_request;
|
|
|
|
ib_fprintf(out_file, "%s_r (&%s, &%s",
|
|
request->req_handle, request->req_handle, request->req_trans);
|
|
|
|
if (port = request->req_vport)
|
|
for (reference = port->por_references; reference;
|
|
reference = reference->ref_next)
|
|
ib_fprintf(out_file, ", %s", reference->ref_value);
|
|
|
|
ib_fprintf(out_file, ")");
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate code for AT END clause of FETCH.
|
|
//
|
|
|
|
static void gen_at_end( ACT action)
|
|
{
|
|
GPRE_REQ request;
|
|
TEXT s[20];
|
|
|
|
request = action->act_request;
|
|
printa(names[COLUMN], false,
|
|
"IF %s = 0 THEN", gen_name(s, request->req_eof, true));
|
|
ib_fprintf(out_file, names[COLUMN]);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Substitute for a BASED ON <field name> clause.
|
|
//
|
|
|
|
static void gen_based( ACT action)
|
|
{
|
|
BAS based_on;
|
|
GPRE_FLD field;
|
|
TEXT s[64];
|
|
USHORT datatype;
|
|
SLONG length;
|
|
SSHORT digits;
|
|
|
|
based_on = (BAS) action->act_object;
|
|
field = based_on->bas_field;
|
|
|
|
if (based_on->bas_flags & BAS_segment) {
|
|
datatype = dtype_text;
|
|
if (!(length = field->fld_seg_length))
|
|
length = 256;
|
|
}
|
|
else if (field->fld_array_info) {
|
|
IBERROR("Based on currently not implemented for arrays.");
|
|
//
|
|
// TBD - messy
|
|
// datatype = field->fld_array_info->ary_dtype;
|
|
// for (dimension = field->fld_array_info->ary_dimension; dimension;
|
|
// dimension = dimension->dim_next)
|
|
// {
|
|
// ib_fprintf (out_file, "
|
|
//
|
|
}
|
|
else
|
|
datatype = field->fld_dtype;
|
|
|
|
switch (datatype) {
|
|
case dtype_short:
|
|
case dtype_long:
|
|
digits = (datatype == dtype_short) ? 4 : 9;
|
|
ib_fprintf(out_file, "%sPIC S", names[COLUMN]);
|
|
if (field->fld_scale >= -digits && field->fld_scale <= 0) {
|
|
if (field->fld_scale > -digits)
|
|
ib_fprintf(out_file, "9(%d)", digits + field->fld_scale);
|
|
if (field->fld_scale)
|
|
ib_fprintf(out_file, "V9(%d)",
|
|
digits - (digits + field->fld_scale));
|
|
ib_fprintf(out_file, USAGE_COMP);
|
|
}
|
|
else if (field->fld_scale > 0)
|
|
ib_fprintf(out_file, "9(%d)P(%d)", digits, field->fld_scale);
|
|
else
|
|
ib_fprintf(out_file, "VP(%d)9(%d)", -(field->fld_scale + digits),
|
|
digits);
|
|
break;
|
|
|
|
case dtype_date:
|
|
case dtype_blob:
|
|
ib_fprintf(out_file, "%sPIC S9(18)%s", names[COLUMN], USAGE_COMP);
|
|
break;
|
|
|
|
case dtype_quad:
|
|
ib_fprintf(out_file, "%sPIC S9(", names[COLUMN]);
|
|
ib_fprintf(out_file, "%d)", 18 + field->fld_scale);
|
|
if (field->fld_scale < 0)
|
|
ib_fprintf(out_file, "V9(%d)", -field->fld_scale);
|
|
else if (field->fld_scale > 0)
|
|
ib_fprintf(out_file, "P(%d)", field->fld_scale);
|
|
ib_fprintf(out_file, USAGE_COMP);
|
|
break;
|
|
|
|
case dtype_text:
|
|
ib_fprintf(out_file, "%sPIC X(%d)", names[COLUMN], field->fld_length);
|
|
break;
|
|
|
|
case dtype_float:
|
|
ib_fprintf(out_file, "%s%s", names[COLUMN], DCL_FLOAT);
|
|
break;
|
|
|
|
case dtype_double:
|
|
ib_fprintf(out_file, "%s%s", names[COLUMN], DCL_DOUBLE);
|
|
break;
|
|
|
|
default:
|
|
sprintf(s, "datatype %d unknown\n", field->fld_dtype);
|
|
CPR_error(s);
|
|
return;
|
|
}
|
|
|
|
if (*based_on->bas_terminator == '.')
|
|
ib_fprintf(out_file, "%s\n", based_on->bas_terminator);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Make a blob FOR loop.
|
|
//
|
|
|
|
static void gen_blob_close( ACT action)
|
|
{
|
|
TEXT *command, buffer[80];
|
|
BLB blob;
|
|
|
|
if (action->act_flags & ACT_sql) {
|
|
gen_cursor_close(action, action->act_request);
|
|
blob = (BLB) action->act_request->req_blobs;
|
|
}
|
|
else
|
|
blob = (BLB) action->act_object;
|
|
|
|
command = (action->act_type == ACT_blob_cancel) ? (TEXT*) CANCEL : (TEXT*) CLOSE;
|
|
sprintf(buffer, ISC_BLOB, command);
|
|
|
|
printa(names[COLUMN], true, "CALL \"%s\" USING %s, %s%s%d",
|
|
buffer,
|
|
status_vector(action), BY_REF, names[ISC_], blob->blb_ident);
|
|
|
|
set_sqlcode(action);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// End a blob FOR loop.
|
|
//
|
|
|
|
static void gen_blob_end( ACT action)
|
|
{
|
|
BLB blob;
|
|
|
|
blob = (BLB) action->act_object;
|
|
gen_get_segment(action);
|
|
printa(names[COLUMN], false, "END-PERFORM");
|
|
if (action->act_error)
|
|
printa(names[COLUMN], true,
|
|
"%sCALL \"%s\" USING %s%s, %s%s%d",
|
|
INDENT,
|
|
ISC_CANCEL_BLOB,
|
|
BY_REF, names[ISC_STATUS_VECTOR2],
|
|
BY_REF, names[ISC_], blob->blb_ident);
|
|
else
|
|
printa(names[COLUMN], true,
|
|
"%sCALL \"%s\" USING %s, %s%s%d",
|
|
INDENT, ISC_CANCEL_BLOB,
|
|
status_vector(0), BY_REF, names[ISC_], blob->blb_ident);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Make a blob FOR loop.
|
|
//
|
|
|
|
static void gen_blob_for( ACT action)
|
|
{
|
|
|
|
gen_blob_open(action);
|
|
gen_get_segment(action);
|
|
printa(names[COLUMN], false, "PERFORM UNTIL");
|
|
|
|
printa(names[COLUMN], false, "%s%s(2) NOT = 0 AND %s(2) NOT = 335544366",
|
|
INDENT, names[ISC_STATUS], names[ISC_STATUS]);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate the call to open (or create) a blob.
|
|
//
|
|
|
|
static void gen_blob_open( ACT action)
|
|
{
|
|
BLB blob;
|
|
USHORT column;
|
|
PAT args;
|
|
REF reference;
|
|
TEXT s[20];
|
|
#ifdef VMS
|
|
TEXT *pattern1 =
|
|
"CALL \"ISC_%IFCREATE%ELOPEN%EN_BLOB2\" USING %V1, %RF%DH%RE, %RF%RT%RE, %RF%BH%RE, %RF%FR%RE, %VF%N1%VE, %RF%I1%RE\n",
|
|
*pattern2 =
|
|
"CALL \"ISC_%IFCREATE%ELOPEN%EN_BLOB2\" USING %V1, %RF%DH%RE, %RF%RT%RE, %RF%BH%RE, %RF%FR%RE, %VF0%VE, %VF0%VE\n";
|
|
#else
|
|
TEXT *pattern1 =
|
|
"CALL \"isc_%IFcreate%ELopen%EN_blob2\" USING %V1, %RF%DH%RE, %RF%RT%RE, %RF%BH%RE, %RF%FR%RE, %VF%N1%VE, %RF%I1%RE\n",
|
|
*pattern2 =
|
|
"CALL \"isc_%IFcreate%ELopen%EN_blob2\" USING %V1, %RF%DH%RE, %RF%RT%RE, %RF%BH%RE, %RF%FR%RE, %VF0%VE, %VF0%VE\n";
|
|
#endif
|
|
|
|
if (sw_auto && (action->act_flags & ACT_sql)) {
|
|
t_start_auto(action->act_request, status_vector(action), action, true);
|
|
printa(names[COLUMN], false, "IF %s NOT = 0 THEN",
|
|
request_trans(action, action->act_request));
|
|
}
|
|
|
|
if (action->act_flags & ACT_sql) {
|
|
gen_cursor_open(action, action->act_request);
|
|
blob = (BLB) action->act_request->req_blobs;
|
|
reference = ((OPN) action->act_object)->opn_using;
|
|
gen_name(s, reference, true);
|
|
}
|
|
else {
|
|
blob = (BLB) action->act_object;
|
|
reference = blob->blb_reference;
|
|
}
|
|
|
|
column = strlen(names[COLUMN]);
|
|
args.pat_condition = (action->act_type == ACT_blob_create); // open or create blob
|
|
args.pat_vector1 = status_vector(action); // status vector
|
|
args.pat_database = blob->blb_request->req_database; // database handle
|
|
args.pat_request = blob->blb_request; // transaction handle
|
|
args.pat_blob = blob; // blob handle
|
|
args.pat_reference = reference; // blob identifier
|
|
args.pat_ident1 = blob->blb_bpb_ident; // blob parameter block
|
|
|
|
if ((action->act_flags & ACT_sql) && action->act_type == ACT_blob_open)
|
|
printa(names[COLUMN], false, "MOVE %s TO %s",
|
|
reference->ref_value, s);
|
|
|
|
if (args.pat_value1 = blob->blb_bpb_length)
|
|
PATTERN_expand(column, pattern1, &args);
|
|
else
|
|
PATTERN_expand(column, pattern2, &args);
|
|
|
|
if (action->act_flags & ACT_sql) {
|
|
printa(names[COLUMN], false, "END-IF");
|
|
printa(names[COLUMN], false, "END-IF");
|
|
printa(names[COLUMN], false, "END-IF");
|
|
printa(names[COLUMN], false, "END-IF");
|
|
if (sw_auto)
|
|
printa(names[COLUMN], false, "END-IF");
|
|
set_sqlcode(action);
|
|
if (action->act_type == ACT_blob_create) {
|
|
printa(names[COLUMN], false, "IF SQLCODE = 0 THEN");
|
|
printa(names[COLUMN], false, "MOVE %s TO %s",
|
|
s, reference->ref_value);
|
|
printa(names[COLUMN], false, "END-IF");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Callback routine for BLR pretty printer.
|
|
//
|
|
|
|
static void gen_blr(void *user_arg, SSHORT offset, const char* string)
|
|
{
|
|
int indent, length, comment, i, max_line, max_diff;
|
|
const char *p, *q;
|
|
bool open_quote;
|
|
bool first_line = true;
|
|
|
|
if (sw_ansi) {
|
|
max_line = 70;
|
|
max_diff = 7;
|
|
}
|
|
else {
|
|
max_line = 255;
|
|
max_diff = 30;
|
|
}
|
|
comment = strlen(names[COMMENT]);
|
|
indent = 2 * strlen(INDENT);
|
|
p = string;
|
|
while (*p == ' ') {
|
|
p++;
|
|
indent++;
|
|
}
|
|
length = strlen(p);
|
|
|
|
if (comment + indent > max_line)
|
|
indent = max_line - comment;
|
|
|
|
while (length > 0 && length + indent + comment > max_line) {
|
|
/* if we did not find somewhere to break between the 200th and 256th
|
|
character just print out 256 characters */
|
|
|
|
for (q = p, open_quote = false; (q - p + indent + comment) < max_line;
|
|
q++) {
|
|
if ((q - p + indent + comment) > max_line - max_diff && *q == ','
|
|
&& !open_quote)
|
|
{
|
|
break;
|
|
}
|
|
if (*q == '\'' && *(q - 1) != '\\')
|
|
open_quote = !open_quote;
|
|
}
|
|
ib_fprintf(out_file, "%s", names[COMMENT]);
|
|
for (i = 0; i < indent; i++)
|
|
ib_fputc(' ', out_file);
|
|
q++;
|
|
char buffer[256];
|
|
strncpy(buffer, p, q-p);
|
|
buffer[q-p] = 0;
|
|
ib_fprintf(out_file, "%s\n", buffer);
|
|
length = length - (q - p);
|
|
p = q;
|
|
if (first_line) {
|
|
first_line = false;
|
|
indent += strlen(INDENT);
|
|
if (comment + indent > max_line)
|
|
indent = max_line - comment;
|
|
}
|
|
}
|
|
|
|
ib_fprintf(out_file, "%s", names[COMMENT]);
|
|
for (i = 0; i < indent; i++)
|
|
ib_fputc(' ', out_file);
|
|
ib_fprintf(out_file, "%s\n", p);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Zap all know handles.
|
|
//
|
|
|
|
static void gen_clear_handles( ACT action)
|
|
{
|
|
GPRE_REQ request;
|
|
|
|
for (request = requests; request; request = request->req_next) {
|
|
if (!(request->req_flags & REQ_exp_hand))
|
|
printa(names[COLUMN], true, "%s = 0;", request->req_handle);
|
|
}
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate text to compile a request.
|
|
//
|
|
|
|
static void gen_compile( ACT action)
|
|
{
|
|
GPRE_REQ request;
|
|
DBB db;
|
|
SYM symbol;
|
|
BLB blob;
|
|
|
|
request = action->act_request;
|
|
db = request->req_database;
|
|
symbol = db->dbb_name;
|
|
|
|
// generate automatic ready if appropriate
|
|
|
|
if (sw_auto)
|
|
t_start_auto(request, status_vector(action), action, true);
|
|
|
|
//
|
|
// always generate a compile, a test for the success of the compile,
|
|
// and an end to the 'if not compiled test
|
|
//
|
|
|
|
// generate an 'if not compiled'
|
|
|
|
printa(names[COLUMN], false, "IF %s = 0 THEN", request->req_handle);
|
|
|
|
if (sw_auto && action->act_error)
|
|
printa(names[COLUMN], false, "IF %s NOT = 0 THEN",
|
|
request_trans(action, request));
|
|
|
|
sprintf(output_buffer,
|
|
"%sCALL \"%s%s\" USING %s, %s%s, %s%s, %s%d%s, %s%s%d\n",
|
|
names[COLUMN], ISC_COMPILE_REQUEST,
|
|
(request->req_flags & REQ_exp_hand) ? "" : "2",
|
|
status_vector(action), BY_REF, symbol->sym_string, BY_REF,
|
|
request->req_handle, BY_VALUE, request->req_length, END_VALUE,
|
|
BY_REF, names[ISC_], request->req_ident);
|
|
|
|
COB_print_buffer(output_buffer, TRUE);
|
|
if (sw_auto && action->act_error)
|
|
printa(names[COLUMN], false, "END-IF");
|
|
|
|
set_sqlcode(action);
|
|
printa(names[COLUMN], false, "END-IF");
|
|
|
|
// If blobs are present, zero out all of the blob handles. After this
|
|
// point, the handles are the user's responsibility
|
|
|
|
if (blob = request->req_blobs)
|
|
for (; blob; blob = blob->blb_next) {
|
|
sprintf(output_buffer, "%sMOVE 0 TO %s%d\n",
|
|
names[COLUMN], names[ISC_], blob->blb_ident);
|
|
|
|
COB_print_buffer(output_buffer, FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate a call to create a database.
|
|
//
|
|
|
|
static void gen_create_database( ACT action)
|
|
{
|
|
GPRE_REQ request;
|
|
DBB db, dbisc;
|
|
TEXT s1[32], s1Tmp[32], s2[32], s2Tmp[32], db_name[128];
|
|
bool save_sw_auto;
|
|
|
|
request = ((MDBB) action->act_object)->mdbb_dpb_request;
|
|
db = (DBB) request->req_database;
|
|
if (request) {
|
|
sprintf(s1, "%s%dL", names[isc_], request->req_ident);
|
|
if (request->req_flags & REQ_extend_dpb)
|
|
sprintf(s2, "%s%dp", names[isc_], request->req_ident);
|
|
else
|
|
sprintf(s2, "%s%d", names[isc_], request->req_ident);
|
|
|
|
/* if the dpb needs to be extended at runtime to include items
|
|
in host variables, do so here; this assumes that there is
|
|
always a request generated for runtime variables */
|
|
|
|
if (request->req_flags & REQ_extend_dpb) {
|
|
if (request->req_length) {
|
|
sprintf(output_buffer, "%sMOVE isc_%d to %s\n",
|
|
names[COLUMN], request->req_ident, s2);
|
|
}
|
|
if (db->dbb_r_user) {
|
|
sprintf(output_buffer,
|
|
"%sCALL \"%s\" USING %s%s, %s%s, BY VALUE 28, %s %s, %s%d%s\n",
|
|
names[COLUMN],
|
|
ISC_MODIFY_DPB,
|
|
BY_REF, s2,
|
|
BY_REF, s1,
|
|
BY_DESC, db->dbb_r_user,
|
|
BY_VALUE, strlen(db->dbb_r_user) - 2, END_VALUE);
|
|
COB_print_buffer(output_buffer, TRUE);
|
|
}
|
|
if (db->dbb_r_password) {
|
|
sprintf(output_buffer,
|
|
"%sCALL \"%s\" USING %s%s, %s%s, BY VALUE 29, %s %s, %s%d%s\n",
|
|
names[COLUMN],
|
|
ISC_MODIFY_DPB,
|
|
BY_REF, s2,
|
|
BY_REF, s1,
|
|
BY_DESC, db->dbb_r_password,
|
|
BY_VALUE, strlen(db->dbb_r_password) - 2, END_VALUE);
|
|
COB_print_buffer(output_buffer, TRUE);
|
|
}
|
|
|
|
/*
|
|
** ==================================================
|
|
** ==
|
|
** == Process Role Name, isc_dpb_sql_role_name/60
|
|
** ==
|
|
** ==================================================
|
|
*/
|
|
|
|
if (db->dbb_r_sql_role) {
|
|
sprintf(output_buffer,
|
|
"%sCALL \"%s\" USING %s%s, %s%s, BY VALUE 60, %s %s, %s%d%s\n",
|
|
names[COLUMN],
|
|
ISC_MODIFY_DPB,
|
|
BY_REF, s2,
|
|
BY_REF, s1,
|
|
BY_DESC, db->dbb_r_sql_role,
|
|
BY_VALUE, strlen(db->dbb_r_sql_role) - 2, END_VALUE);
|
|
COB_print_buffer(output_buffer, TRUE);
|
|
}
|
|
|
|
if (db->dbb_r_lc_messages) {
|
|
sprintf(output_buffer,
|
|
"%sCALL \"%s\" USING %s%s, %s%s, BY VALUE 47, %s %s, %s%d%s\n",
|
|
names[COLUMN],
|
|
ISC_MODIFY_DPB,
|
|
BY_REF, s2,
|
|
BY_REF, s1,
|
|
BY_REF, db->dbb_r_lc_messages,
|
|
BY_VALUE, strlen(db->dbb_r_lc_messages) - 2,
|
|
END_VALUE);
|
|
COB_print_buffer(output_buffer, TRUE);
|
|
}
|
|
if (db->dbb_r_lc_ctype) {
|
|
sprintf(output_buffer,
|
|
"%sCALL \"%s\" USING %s%s %s%s, BY VALUE 48, %s %s, %s%d%s\n",
|
|
names[COLUMN],
|
|
ISC_MODIFY_DPB,
|
|
BY_REF, s2,
|
|
BY_REF, s1,
|
|
BY_REF, db->dbb_r_lc_ctype,
|
|
BY_VALUE, strlen(db->dbb_r_lc_ctype) - 2, END_VALUE);
|
|
COB_print_buffer(output_buffer, TRUE);
|
|
}
|
|
}
|
|
|
|
if (request->req_flags & REQ_extend_dpb) {
|
|
sprintf(s1Tmp, "%s%s%s", BY_VALUE, s1, END_VALUE);
|
|
sprintf(s2Tmp, "%s%s%s", BY_VALUE, s2, END_VALUE);
|
|
}
|
|
else {
|
|
sprintf(s2Tmp, "%s%s", BY_REF, s2);
|
|
sprintf(s1Tmp, "%s%d%s", BY_VALUE, request->req_length,
|
|
END_VALUE);
|
|
}
|
|
}
|
|
|
|
#ifdef VMS
|
|
sprintf(db_name, "\"%s\"", db->dbb_filename);
|
|
#else
|
|
for (dbisc = isc_databases; dbisc; dbisc = dbisc->dbb_next)
|
|
if (strcmp(dbisc->dbb_filename, db->dbb_filename) == 0)
|
|
db->dbb_id = dbisc->dbb_id;
|
|
sprintf(db_name, "isc-%ddb", db->dbb_id);
|
|
#endif
|
|
|
|
sprintf(output_buffer,
|
|
"%sCALL \"%s\" USING %s, %s%d%s, %s%s, %s%s, %s, %s, %s0%s\n",
|
|
names[COLUMN],
|
|
ISC_CREATE_DATABASE,
|
|
status_vector(action),
|
|
BY_VALUE, strlen(db->dbb_filename), END_VALUE,
|
|
BY_REF, db_name,
|
|
BY_REF, db->dbb_name->sym_string,
|
|
(request->req_length) ? s1Tmp : OMITTED,
|
|
(request->req_length) ? s2Tmp : OMITTED, BY_VALUE, END_VALUE);
|
|
|
|
COB_print_buffer(output_buffer, TRUE);
|
|
// if the dpb was extended, free it here
|
|
|
|
if (request && request->req_flags & REQ_extend_dpb) {
|
|
if (request->req_length) {
|
|
sprintf(output_buffer,
|
|
"if (%s != isc_%d)", s2, request->req_ident);
|
|
COB_print_buffer(output_buffer, TRUE);
|
|
}
|
|
|
|
sprintf(output_buffer,
|
|
"%sCALL \"%s\" USING %s\n", names[COLUMN], ISC_FREE, s2Tmp);
|
|
COB_print_buffer(output_buffer, TRUE);
|
|
|
|
/* reset the length of the dpb */
|
|
sprintf(output_buffer, "%sMOVE %d to %s",
|
|
names[COLUMN], request->req_length, s1);
|
|
COB_print_buffer(output_buffer, TRUE);
|
|
}
|
|
save_sw_auto = sw_auto;
|
|
sw_auto = true;
|
|
printa(names[COLUMN], false, "IF %s(2) = 0 THEN", names[ISC_STATUS]);
|
|
gen_ddl(action);
|
|
sw_auto = save_sw_auto;
|
|
printa(names[COLUMN], false, "END-IF");
|
|
set_sqlcode(action);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate substitution text for END_STREAM.
|
|
//
|
|
|
|
static void gen_cursor_close( ACT action, GPRE_REQ request)
|
|
{
|
|
|
|
printa(names[COLUMN], false, "IF %s%dS NOT = 0 THEN",
|
|
names[ISC_], request->req_ident);
|
|
printa(names[COLUMN], true,
|
|
"CALL \"%s\" USING %s, %s%s%dS, %s%d%s",
|
|
ISC_DSQL_FREE,
|
|
status_vector(action),
|
|
BY_REF, names[ISC_], request->req_ident, BY_VALUE, 1, END_VALUE);
|
|
printa(names[COLUMN], false, "IF %s(2) = 0 THEN", names[ISC_STATUS]);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate text to initialize a cursor.
|
|
//
|
|
|
|
static void gen_cursor_init( ACT action)
|
|
{
|
|
|
|
// If blobs are present, zero out all of the blob handles. After this
|
|
// point, the handles are the user's responsibility
|
|
|
|
if (action->act_request->
|
|
req_flags & (REQ_sql_blob_open | REQ_sql_blob_create))
|
|
printa(names[COLUMN], false, "MOVE 0 TO %s%d", names[ISC_],
|
|
action->act_request->req_blobs->blb_ident);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate text to open an embedded SQL cursor.
|
|
//
|
|
|
|
static void gen_cursor_open( ACT action, GPRE_REQ request)
|
|
{
|
|
TEXT s[64];
|
|
|
|
if (action->act_type != ACT_open)
|
|
printa(names[COLUMN], false, "IF %s%dS = 0 THEN",
|
|
names[ISC_], request->req_ident);
|
|
else
|
|
printa(names[COLUMN], false, "IF (%s%dS = 0) AND %s NOT = 0 THEN",
|
|
names[ISC_], request->req_ident, request->req_handle);
|
|
if (sw_auto)
|
|
printa(names[COLUMN], false, "IF %s NOT = 0 THEN",
|
|
request->req_database->dbb_name->sym_string);
|
|
printa(names[COLUMN], true, "CALL \"%s\" USING %s, %s%s, %s%s%dS",
|
|
ISC_DSQL_ALLOCATE,
|
|
status_vector(action),
|
|
BY_REF, request->req_database->dbb_name->sym_string,
|
|
BY_REF, names[ISC_], request->req_ident);
|
|
if (sw_auto)
|
|
printa(names[COLUMN], false, "END-IF");
|
|
printa(names[COLUMN], false, "END-IF");
|
|
|
|
printa(names[COLUMN], false, "IF %s%dS NOT = 0 THEN",
|
|
names[ISC_], request->req_ident);
|
|
if (sw_auto)
|
|
printa(names[COLUMN], false, "IF %s NOT = 0 THEN",
|
|
request_trans(action, request));
|
|
#ifndef VMS
|
|
make_name_formatted(s, "ISC-CONST-%s",
|
|
((OPN) action->act_object)->opn_cursor);
|
|
#else
|
|
make_name(s, ((OPN) action->act_object)->opn_cursor);
|
|
#endif
|
|
printa(names[COLUMN], true,
|
|
"CALL \"%s\" USING %s, %s%s%dS, %s%s, %s0%s",
|
|
ISC_DSQL_SET_CURSOR,
|
|
status_vector(action),
|
|
BY_REF, names[ISC_], request->req_ident,
|
|
BY_REF, s, BY_VALUE, END_VALUE);
|
|
printa(names[COLUMN], false, "IF %s(2) = 0 THEN", names[ISC_STATUS]);
|
|
printa(names[COLUMN], true,
|
|
"CALL \"%s\" USING %s, %s%s, %s%s%dS, %s0%s, %s, %s-1%s, %s0%s, %s",
|
|
ISC_DSQL_EXECUTE,
|
|
status_vector(action),
|
|
BY_REF, request_trans(action, request),
|
|
BY_REF, names[ISC_], request->req_ident,
|
|
BY_VALUE, END_VALUE,
|
|
OMITTED, BY_VALUE, END_VALUE, BY_VALUE, END_VALUE, OMITTED);
|
|
printa(names[COLUMN], false, "IF %s(2) = 0 THEN", names[ISC_STATUS]);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate insertion text for the database statement.
|
|
//
|
|
|
|
static void gen_database( ACT action)
|
|
{
|
|
DBB db;
|
|
GPRE_REQ request;
|
|
TEXT *name, fname[80], *s, s1[40];
|
|
USHORT count, max_count;
|
|
tpb* tpb_iterator;
|
|
POR port;
|
|
BLB blob;
|
|
bool all_static;
|
|
bool all_extern;
|
|
bool dyn_immed;
|
|
REF reference;
|
|
RDY ready;
|
|
ACT act, chck_dups;
|
|
SYM symbol, cur_stmt, dup;
|
|
GPRE_PRC procedure;
|
|
LLS stack_ptr;
|
|
|
|
if (first_flag++ != 0)
|
|
return;
|
|
|
|
sprintf(output_buffer, "\n%s**** GDS Preprocessor Definitions ****\n\n",
|
|
names[COMMENT]);
|
|
COB_print_buffer(output_buffer, FALSE);
|
|
|
|
printa(names[COLUMN_0], false, "01 %s PIC S9(18) USAGE COMP VALUE IS 0.",
|
|
names[isc_blob_null]);
|
|
printa(names[COLUMN_0], false, "01 %s PIC S9(9) USAGE COMP EXTERNAL.",
|
|
names[ISC_SQLCODE]);
|
|
|
|
all_static = true;
|
|
all_extern = true;
|
|
for (db = isc_databases, count = 0; db; db = db->dbb_next) {
|
|
all_static = all_static && (db->dbb_scope == DBB_STATIC);
|
|
all_extern = all_extern && (db->dbb_scope == DBB_EXTERN);
|
|
name = db->dbb_name->sym_string;
|
|
printa(names[COLUMN_0], false, "01 %s%s PIC S9(9) USAGE COMP%s.",
|
|
name,
|
|
(all_static) ? "" : (all_extern) ? " IS EXTERNAL" :
|
|
" IS GLOBAL", (all_extern) ? "" : " VALUE IS 0");
|
|
|
|
/* generate variables to hold database name strings for attach call */
|
|
|
|
#ifndef VMS
|
|
db->dbb_id = ++count;
|
|
if (db->dbb_runtime) {
|
|
printa(names[COLUMN_0], false,
|
|
"01 %s%ddb PIC X(%d) VALUE IS \"%s\".", names[isc_],
|
|
db->dbb_id, strlen(db->dbb_runtime), db->dbb_runtime);
|
|
}
|
|
else if (db->dbb_filename) {
|
|
printa(names[COLUMN_0], false,
|
|
"01 %s%ddb PIC X(%d) VALUE IS \"%s\".", names[isc_],
|
|
db->dbb_id, strlen(db->dbb_filename), db->dbb_filename);
|
|
}
|
|
#endif
|
|
|
|
for (tpb_iterator = db->dbb_tpbs;
|
|
tpb_iterator;
|
|
tpb_iterator = tpb_iterator->tpb_dbb_next)
|
|
{
|
|
gen_tpb(tpb_iterator);
|
|
}
|
|
}
|
|
|
|
#ifndef VMS
|
|
// loop through actions: find readys to generate vars for quoted strings
|
|
|
|
dyn_immed = false;
|
|
for (act = action; act; act = act->act_rest)
|
|
if (act->act_type == ACT_create_database) {
|
|
}
|
|
else if (act->act_type == ACT_ready) {
|
|
for (ready = (RDY) act->act_object; ready; ready = ready->rdy_next)
|
|
{
|
|
if ((s = ready->rdy_filename) && ((*s == '\'')
|
|
|| (*s == '\'')))
|
|
{
|
|
strcpy(fname, ++s);
|
|
s = fname + strlen(fname) - 1;
|
|
*s = 0;
|
|
ready->rdy_id = ++count;
|
|
printa(names[COLUMN_0], false,
|
|
"01 %s%ddb PIC X(%d) VALUE IS \"%s\".",
|
|
names[isc_], ready->rdy_id, strlen(fname), fname);
|
|
}
|
|
}
|
|
}
|
|
else if ((act->act_flags & ACT_sql) &&
|
|
(act->act_type == ACT_dyn_cursor ||
|
|
act->act_type == ACT_dyn_prepare ||
|
|
act->act_type == ACT_open ||
|
|
act->act_type == ACT_blob_open ||
|
|
act->act_type == ACT_blob_create))
|
|
{
|
|
if (act->act_type == ACT_dyn_cursor)
|
|
cur_stmt = ((DYN) act->act_object)->dyn_cursor_name;
|
|
else if (act->act_type == ACT_dyn_prepare)
|
|
cur_stmt = ((DYN) act->act_object)->dyn_statement_name;
|
|
else
|
|
cur_stmt = ((OPN) act->act_object)->opn_cursor;
|
|
|
|
/* Only generate one declaration per cursor or statement name */
|
|
|
|
for (chck_dups = act->act_rest; chck_dups;
|
|
chck_dups = chck_dups->act_rest) {
|
|
if (chck_dups->act_type == ACT_dyn_cursor)
|
|
dup = ((DYN) chck_dups->act_object)->dyn_cursor_name;
|
|
else if (chck_dups->act_type == ACT_dyn_prepare)
|
|
dup = ((DYN) chck_dups->act_object)->dyn_statement_name;
|
|
else if ((chck_dups->act_flags & ACT_sql) &&
|
|
(chck_dups->act_type == ACT_open ||
|
|
chck_dups->act_type == ACT_blob_open ||
|
|
chck_dups->act_type == ACT_blob_create))
|
|
dup = ((OPN) chck_dups->act_object)->opn_cursor;
|
|
else
|
|
continue;
|
|
|
|
if (!strcmp(dup->sym_string, cur_stmt->sym_string))
|
|
break;
|
|
}
|
|
|
|
if (!chck_dups) {
|
|
make_name(s1, cur_stmt);
|
|
printa(names[COLUMN_0], false,
|
|
"01 ISC-CONST-%s PIC X(%d) VALUE IS \"%s \".",
|
|
s1, strlen(s1) + 1, s1);
|
|
printa(names[COLUMN_0], false,
|
|
"01 ISC-CONST-%sL PIC S9(4) USAGE %s.", s1,
|
|
COMP_VALUE);
|
|
}
|
|
}
|
|
else if (act->act_type == ACT_dyn_immediate) {
|
|
if (!dyn_immed) {
|
|
dyn_immed = true;
|
|
printa(names[COLUMN_0], false,
|
|
"01 ISC-CONST-DYN-IMMEDL PIC S9(4) USAGE %s.",
|
|
COMP_VALUE);
|
|
}
|
|
}
|
|
else if (act->act_type == ACT_procedure) {
|
|
request = act->act_request;
|
|
procedure = (GPRE_PRC) act->act_object;
|
|
symbol = procedure->prc_symbol;
|
|
name = symbol->sym_string;
|
|
printa(names[COLUMN_0], false,
|
|
"01 %s%dprc PIC X(%d) VALUE IS \"%s\".",
|
|
names[isc_], request->req_ident, strlen(name), name);
|
|
}
|
|
#endif
|
|
|
|
printa(names[COLUMN_0], false, "01 %s%s PIC S9(9) USAGE COMP%s.",
|
|
names[ISC_TRANS],
|
|
(all_static) ? "" : (all_extern) ? " IS EXTERNAL" : " IS GLOBAL",
|
|
(all_extern) ? "" : " VALUE IS 0");
|
|
printa(names[COLUMN_0], false, "01 %s%s.",
|
|
names[ISC_STATUS_VECTOR],
|
|
(all_static) ? "" : (all_extern) ? " IS EXTERNAL" : " IS GLOBAL");
|
|
printa(names[COLUMN], false,
|
|
"03 %s PIC S9(9) USAGE COMP OCCURS 20 TIMES.", names[ISC_STATUS]);
|
|
printa(names[COLUMN_0], false, "01 %s%s.", names[ISC_STATUS_VECTOR2],
|
|
(all_static) ? "" : (all_extern) ? " IS EXTERNAL" : " IS GLOBAL");
|
|
printa(names[COLUMN], false,
|
|
"03 %s PIC S9(9) USAGE COMP OCCURS 20 TIMES.",
|
|
names[ISC_STATUS2]);
|
|
printa(names[COLUMN_0], false, "01 %s PIC S9(9) USAGE COMP.",
|
|
names[ISC_ARRAY_LENGTH]);
|
|
|
|
printa(names[COLUMN_0], false, "01 SQLCODE%s PIC S9(9) USAGE %s%s.",
|
|
(all_static) ? "" : (all_extern) ? " IS EXTERNAL" : " IS GLOBAL",
|
|
COMP_VALUE, (all_extern) ? "" : " VALUE IS 0");
|
|
|
|
for (request = requests; request; request = request->req_next) {
|
|
gen_request(request);
|
|
for (port = request->req_ports; port; port = port->por_next)
|
|
make_port(port);
|
|
for (blob = request->req_blobs; blob; blob = blob->blb_next) {
|
|
printa(names[COLUMN_0], false, "01 %s%d PIC S9(9) USAGE COMP.",
|
|
names[ISC_], blob->blb_ident);
|
|
printa(names[COLUMN_0], false, "01 %s%d PIC X(%d).",
|
|
names[ISC_], blob->blb_buff_ident, blob->blb_seg_length);
|
|
printa(names[COLUMN_0], false, "01 %s%d PIC S9(4) USAGE %s.",
|
|
names[ISC_], blob->blb_len_ident, COMP_VALUE);
|
|
}
|
|
|
|
/* Array declarations */
|
|
|
|
if (port = request->req_primary)
|
|
for (reference = port->por_references; reference;
|
|
reference = reference->ref_next)
|
|
if (reference->ref_field->fld_array_info)
|
|
make_array_declaration(reference);
|
|
}
|
|
|
|
// Generate event parameter block for each event
|
|
|
|
max_count = 0;
|
|
for (stack_ptr = events; stack_ptr; stack_ptr = stack_ptr->lls_next) {
|
|
count = gen_event_block((ACT) stack_ptr->lls_object);
|
|
max_count = MAX(count, max_count);
|
|
}
|
|
|
|
if (max_count) {
|
|
printa(names[COLUMN_0], false, "01 %s.", names[ISC_EVENTS_VECTOR]);
|
|
printa(names[COLUMN], false,
|
|
"03 %s PIC S9(9) USAGE COMP OCCURS %d TIMES.",
|
|
names[ISC_EVENTS], max_count);
|
|
printa(names[COLUMN_0], false, "01 %s.",
|
|
names[ISC_EVENT_NAMES_VECTOR]);
|
|
printa(names[COLUMN], false,
|
|
"03 %s PIC S9(9) USAGE COMP OCCURS %d TIMES.",
|
|
names[ISC_EVENT_NAMES], max_count);
|
|
printa(names[COLUMN_0], false, "01 %s.",
|
|
names[ISC_EVENT_NAMES_VECTOR2]);
|
|
printa(names[COLUMN], false, "03 %s PIC X(31) OCCURS %d TIMES.",
|
|
names[ISC_EVENT_NAMES2], max_count);
|
|
}
|
|
|
|
printa(names[COMMENT], false, "**** end of GPRE definitions ****\n");
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate a call to update metadata.
|
|
//
|
|
|
|
static void gen_ddl( ACT action)
|
|
{
|
|
GPRE_REQ request;
|
|
|
|
// Set up command type for call to RDB$DDL
|
|
|
|
request = action->act_request;
|
|
|
|
if (sw_auto) {
|
|
t_start_auto(0, status_vector(action), action, true);
|
|
printa(names[COLUMN], false, "IF %s NOT = 0 THEN", names[ISC_TRANS]);
|
|
}
|
|
|
|
|
|
sprintf(output_buffer,
|
|
"%sCALL \"%s\" USING %s, %s%s, %s%s, %s%d%s, %s%s%d\n",
|
|
names[COLUMN], ISC_DDL, status_vector(action), BY_REF,
|
|
request->req_database->dbb_name->sym_string, BY_REF,
|
|
names[ISC_TRANS], BY_VALUE, request->req_length, END_VALUE,
|
|
BY_REF, names[ISC_], request->req_ident);
|
|
|
|
COB_print_buffer(output_buffer, TRUE);
|
|
|
|
if (sw_auto) {
|
|
printa(names[COLUMN], false, "END-IF");
|
|
printa(names[COLUMN], false, "IF %s(2) = 0 THEN", names[ISC_STATUS]);
|
|
printa(names[COLUMN], true,
|
|
"CALL \"%s\" USING %s, %s%s", ISC_COMMIT_TRANSACTION,
|
|
status_vector(action), BY_REF, names[ISC_TRANS]);
|
|
printa(names[COLUMN], false, "END-IF");
|
|
printa(names[COLUMN], false, "IF %s(2) NOT = 0 THEN",
|
|
names[ISC_STATUS]);
|
|
printa(names[COLUMN], true,
|
|
"CALL \"%s\" USING %s, %s%s",
|
|
ISC_ROLLBACK_TRANSACTION, OMITTED, BY_REF, names[ISC_TRANS]);
|
|
printa(names[COLUMN], false, "END-IF");
|
|
}
|
|
COB_print_buffer(output_buffer, TRUE);
|
|
set_sqlcode(action);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate a dynamic SQL statement.
|
|
//
|
|
|
|
static void gen_dyn_close( ACT action)
|
|
{
|
|
DYN statement;
|
|
TEXT s[64];
|
|
|
|
statement = (DYN) action->act_object;
|
|
#ifndef VMS
|
|
make_name_formatted(s, "ISC-CONST-%s", statement->dyn_cursor_name);
|
|
#else
|
|
make_name(s, statement->dyn_cursor_name);
|
|
#endif
|
|
printa(names[COLUMN], true,
|
|
"CALL \"%s\" USING %s, %s%s",
|
|
ISC_CLOSE, status_vector(action), BY_REF, s);
|
|
set_sqlcode(action);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate a dynamic SQL statement.
|
|
//
|
|
|
|
static void gen_dyn_declare( ACT action)
|
|
{
|
|
DYN statement;
|
|
TEXT s1[64], s2[64];
|
|
|
|
statement = (DYN) action->act_object;
|
|
|
|
#ifndef VMS
|
|
make_name_formatted(s1, "ISC-CONST-%s", statement->dyn_statement_name);
|
|
make_name_formatted(s2, "ISC-CONST-%s", statement->dyn_cursor_name);
|
|
#else
|
|
make_name(s1, statement->dyn_statement_name);
|
|
make_name(s2, statement->dyn_cursor_name);
|
|
#endif
|
|
|
|
printa(names[COLUMN], true,
|
|
"CALL \"%s\" USING %s, %s%s, %s%s",
|
|
ISC_DECLARE, status_vector(action), BY_REF, s1, BY_REF, s2);
|
|
set_sqlcode(action);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate a dynamic SQL statement.
|
|
//
|
|
|
|
static void gen_dyn_describe(ACT action,
|
|
bool bind_flag)
|
|
{
|
|
DYN statement;
|
|
TEXT s[64];
|
|
|
|
statement = (DYN) action->act_object;
|
|
|
|
#ifndef VMS
|
|
make_name_formatted(s, "ISC-CONST-%s", statement->dyn_statement_name);
|
|
#else
|
|
make_name(s, statement->dyn_statement_name);
|
|
#endif
|
|
|
|
printa(names[COLUMN], true,
|
|
"CALL \"%s\" USING %s, %s%s, %s%d%s, %s%s",
|
|
bind_flag ? ISC_DESCRIBE_BIND : ISC_DESCRIBE,
|
|
status_vector(action),
|
|
BY_REF, s,
|
|
BY_VALUE, sw_sql_dialect, END_VALUE, BY_REF, statement->dyn_sqlda);
|
|
set_sqlcode(action);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate a dynamic SQL statement.
|
|
//
|
|
|
|
static void gen_dyn_execute( ACT action)
|
|
{
|
|
DYN statement;
|
|
TEXT *transaction, s[64];
|
|
gpre_req* request;
|
|
gpre_req req_const;
|
|
|
|
statement = (DYN) action->act_object;
|
|
if (statement->dyn_trans) {
|
|
transaction = statement->dyn_trans;
|
|
request = &req_const;
|
|
request->req_trans = transaction;
|
|
}
|
|
else {
|
|
transaction = names[ISC_TRANS];
|
|
request = NULL;
|
|
}
|
|
|
|
if (sw_auto) {
|
|
t_start_auto(request, status_vector(action), action, true);
|
|
printa(names[COLUMN], false, "IF %s NOT = 0 THEN", transaction);
|
|
}
|
|
|
|
#ifndef VMS
|
|
make_name_formatted(s, "ISC-CONST-%s", statement->dyn_statement_name);
|
|
#else
|
|
make_name(s, statement->dyn_statement_name);
|
|
#endif
|
|
|
|
printa(names[COLUMN], true,
|
|
(statement->dyn_sqlda2) ?
|
|
(TEXT*) "CALL \"%s\" USING %s, %s%s, %s%s, %s%d%s, %s%s, %s%s" :
|
|
(TEXT*) "CALL \"%s\" USING %s, %s%s, %s%s, %s%d%s, %s%s",
|
|
(statement->dyn_sqlda2) ? ISC_EXECUTE2 : ISC_EXECUTE,
|
|
status_vector(action),
|
|
BY_REF, transaction,
|
|
BY_REF, s,
|
|
BY_VALUE, sw_sql_dialect, END_VALUE,
|
|
(statement->dyn_sqlda) ? BY_REF : "",
|
|
(statement->dyn_sqlda) ? statement->dyn_sqlda : OMITTED,
|
|
(statement->dyn_sqlda2) ? BY_REF : "",
|
|
(statement->dyn_sqlda2) ? statement->dyn_sqlda2 : OMITTED);
|
|
|
|
if (sw_auto)
|
|
printa(names[COLUMN], false, "END-IF");
|
|
|
|
set_sqlcode(action);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate a dynamic SQL statement.
|
|
//
|
|
|
|
static void gen_dyn_fetch( ACT action)
|
|
{
|
|
DYN statement;
|
|
TEXT s[64];
|
|
|
|
#ifdef GIVING_SUPPORTED
|
|
#define FETCH_CALL_TEMPLATE "CALL \"%s\" USING %s, %s%s, %s%d%s, %s%s GIVING SQLCODE"
|
|
#else
|
|
#define FETCH_CALL_TEMPLATE "CALL \"%s\" USING %s, BY REFERENCE SQLCODE, %s%s, %s%d%s, %s%s"
|
|
#endif
|
|
|
|
statement = (DYN) action->act_object;
|
|
|
|
#ifndef VMS
|
|
make_name_formatted(s, "ISC-CONST-%s", statement->dyn_cursor_name);
|
|
#else
|
|
make_name(s, statement->dyn_cursor_name);
|
|
#endif
|
|
|
|
printa(names[COLUMN], true,
|
|
FETCH_CALL_TEMPLATE,
|
|
ISC_FETCH,
|
|
status_vector(action),
|
|
BY_REF, s,
|
|
BY_VALUE, sw_sql_dialect, END_VALUE,
|
|
(statement->dyn_sqlda) ? BY_REF : "",
|
|
(statement->dyn_sqlda) ? statement->dyn_sqlda : OMITTED);
|
|
|
|
printa(names[COLUMN], false, "IF SQLCODE NOT = 100 THEN");
|
|
|
|
set_sqlcode(action);
|
|
|
|
printa(names[COLUMN], false, "END-IF");
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate code for an EXECUTE IMMEDIATE dynamic SQL statement.
|
|
//
|
|
|
|
static void gen_dyn_immediate( ACT action)
|
|
{
|
|
DYN statement;
|
|
DBB database;
|
|
TEXT *transaction, s[64], *s2;
|
|
gpre_req* request;
|
|
gpre_req req_const;
|
|
|
|
#ifdef GIVING_SUPPORTED
|
|
#define GET_LEN_CALL_TEMPLATE "CALL %s USING %s GIVING %s"
|
|
#else
|
|
#define GET_LEN_CALL_TEMPLATE "CALL %s USING %s, %s"
|
|
#endif
|
|
|
|
statement = (DYN) action->act_object;
|
|
if (statement->dyn_trans) {
|
|
transaction = statement->dyn_trans;
|
|
request = &req_const;
|
|
request->req_trans = transaction;
|
|
}
|
|
else {
|
|
transaction = names[ISC_TRANS];
|
|
request = NULL;
|
|
}
|
|
|
|
database = statement->dyn_database;
|
|
|
|
#ifndef VMS
|
|
s2 = "ISC-CONST-DYN-IMMEDL";
|
|
printa(names[COLUMN], true, GET_LEN_CALL_TEMPLATE,
|
|
STRING_LENGTH, statement->dyn_string, s2);
|
|
sprintf(s, " %s%s%s,", BY_VALUE, s2, END_VALUE);
|
|
#else
|
|
s[0] = 0;
|
|
#endif
|
|
|
|
if (sw_auto) {
|
|
t_start_auto(request, status_vector(action), action, true);
|
|
printa(names[COLUMN], false, "IF %s NOT = 0 THEN", transaction);
|
|
}
|
|
|
|
printa(names[COLUMN], true,
|
|
(statement->dyn_sqlda2) ?
|
|
(TEXT*) "CALL \"%s\" USING %s, %s%s, %s%s,%s %s%s, %s%d%s, %s%s, %s%s" :
|
|
(TEXT*) "CALL \"%s\" USING %s, %s%s, %s%s,%s %s%s, %s%d%s, %s%s",
|
|
(statement->
|
|
dyn_sqlda2) ? ISC_EXECUTE_IMMEDIATE2 : ISC_EXECUTE_IMMEDIATE,
|
|
status_vector(action), BY_REF, database->dbb_name->sym_string,
|
|
BY_REF, transaction, s, BY_DESC, statement->dyn_string, BY_VALUE,
|
|
sw_sql_dialect, END_VALUE, (statement->dyn_sqlda) ? BY_REF : "",
|
|
(statement->dyn_sqlda) ? statement->dyn_sqlda : OMITTED,
|
|
(statement->dyn_sqlda2) ? BY_REF : "",
|
|
(statement->dyn_sqlda2) ? statement->dyn_sqlda2 : OMITTED);
|
|
|
|
if (sw_auto)
|
|
printa(names[COLUMN], false, "END-IF");
|
|
|
|
set_sqlcode(action);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate a dynamic SQL statement.
|
|
//
|
|
|
|
static void gen_dyn_insert( ACT action)
|
|
{
|
|
DYN statement;
|
|
TEXT s[64];
|
|
|
|
statement = (DYN) action->act_object;
|
|
|
|
#ifndef VMS
|
|
make_name_formatted(s, "ISC-CONST-%s", statement->dyn_cursor_name);
|
|
#else
|
|
make_name(s, statement->dyn_cursor_name);
|
|
#endif
|
|
|
|
printa(names[COLUMN], true,
|
|
"CALL \"%s\" USING %s, %s%s, %s%d%s, %s%s",
|
|
ISC_INSERT,
|
|
status_vector(action),
|
|
BY_REF, s,
|
|
BY_VALUE, sw_sql_dialect, END_VALUE,
|
|
(statement->dyn_sqlda) ? BY_REF : "",
|
|
(statement->dyn_sqlda) ? statement->dyn_sqlda : OMITTED);
|
|
|
|
set_sqlcode(action);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate a dynamic SQL statement.
|
|
//
|
|
|
|
static void gen_dyn_open( ACT action)
|
|
{
|
|
DYN statement;
|
|
TEXT *transaction, s[64];
|
|
gpre_req* request;
|
|
gpre_req req_const;
|
|
|
|
statement = (DYN) action->act_object;
|
|
if (statement->dyn_trans) {
|
|
transaction = statement->dyn_trans;
|
|
request = &req_const;
|
|
request->req_trans = transaction;
|
|
}
|
|
else {
|
|
transaction = names[ISC_TRANS];
|
|
request = NULL;
|
|
}
|
|
|
|
#ifndef VMS
|
|
make_name_formatted(s, "ISC-CONST-%s", statement->dyn_cursor_name);
|
|
#else
|
|
make_name(s, statement->dyn_cursor_name);
|
|
#endif
|
|
|
|
if (sw_auto) {
|
|
t_start_auto(request, status_vector(action), action, true);
|
|
printa(names[COLUMN], false, "IF %s NOT = 0 THEN", transaction);
|
|
}
|
|
|
|
printa(names[COLUMN], true,
|
|
(statement->dyn_sqlda2) ?
|
|
(TEXT*) "CALL \"%s\" USING %s, %s%s, %s%s, %s%d%s, %s%s, %s%s" :
|
|
(TEXT*) "CALL \"%s\" USING %s, %s%s, %s%s, %s%d%s, %s%s",
|
|
(statement->dyn_sqlda2) ? ISC_OPEN2 : ISC_OPEN,
|
|
status_vector(action),
|
|
BY_REF, transaction,
|
|
BY_REF, s,
|
|
BY_VALUE, sw_sql_dialect, END_VALUE,
|
|
(statement->dyn_sqlda) ? BY_REF : "",
|
|
(statement->dyn_sqlda) ? statement->dyn_sqlda : OMITTED,
|
|
(statement->dyn_sqlda2) ? BY_REF : "",
|
|
(statement->dyn_sqlda2) ? statement->dyn_sqlda2 : OMITTED);
|
|
|
|
if (sw_auto)
|
|
printa(names[COLUMN], false, "END-IF");
|
|
|
|
set_sqlcode(action);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate a dynamic SQL statement.
|
|
//
|
|
|
|
static void gen_dyn_prepare( ACT action)
|
|
{
|
|
DYN statement;
|
|
DBB database;
|
|
TEXT *transaction, s[64], s2[64], s3[64];
|
|
gpre_req* request;
|
|
gpre_req req_const;
|
|
|
|
statement = (DYN) action->act_object;
|
|
database = statement->dyn_database;
|
|
|
|
if (statement->dyn_trans) {
|
|
transaction = statement->dyn_trans;
|
|
request = &req_const;
|
|
request->req_trans = transaction;
|
|
}
|
|
else {
|
|
transaction = names[ISC_TRANS];
|
|
request = NULL;
|
|
}
|
|
|
|
#ifndef VMS
|
|
make_name_formatted(s, "ISC-CONST-%s", statement->dyn_statement_name);
|
|
sprintf(s2, "%sL", s);
|
|
printa(names[COLUMN], true, GET_LEN_CALL_TEMPLATE,
|
|
STRING_LENGTH, statement->dyn_string, s2);
|
|
sprintf(s3, " %s%s%s,", BY_VALUE, s2, END_VALUE);
|
|
#else
|
|
make_name(s, statement->dyn_statement_name);
|
|
s3[0] = 0;
|
|
#endif
|
|
|
|
if (sw_auto) {
|
|
t_start_auto(request, status_vector(action), action, true);
|
|
printa(names[COLUMN], false, "IF %s NOT = 0 THEN", transaction);
|
|
}
|
|
|
|
printa(names[COLUMN], true,
|
|
"CALL \"%s\" USING %s, %s%s, %s%s, %s%s,%s %s%s, %s%d%s, %s%s",
|
|
ISC_PREPARE,
|
|
status_vector(action),
|
|
BY_REF, database->dbb_name->sym_string,
|
|
BY_REF, transaction,
|
|
BY_REF, s,
|
|
s3,
|
|
BY_DESC, statement->dyn_string,
|
|
BY_VALUE, sw_sql_dialect, END_VALUE,
|
|
(statement->dyn_sqlda) ? BY_REF : "",
|
|
(statement->dyn_sqlda) ? statement->dyn_sqlda : OMITTED);
|
|
|
|
if (sw_auto)
|
|
printa(names[COLUMN], false, "END-IF");
|
|
|
|
set_sqlcode(action);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate substitution text for END_MODIFY.
|
|
//
|
|
|
|
static void gen_emodify( ACT action)
|
|
{
|
|
UPD modify;
|
|
REF reference, source;
|
|
GPRE_FLD field;
|
|
TEXT s1[20], s2[20];
|
|
|
|
modify = (UPD) action->act_object;
|
|
|
|
for (reference = modify->upd_port->por_references; reference;
|
|
reference = reference->ref_next) {
|
|
if (!(source = reference->ref_source))
|
|
continue;
|
|
field = reference->ref_field;
|
|
gen_name(s1, source, true);
|
|
gen_name(s2, reference, true);
|
|
if (field->fld_dtype == dtype_blob ||
|
|
field->fld_dtype == dtype_quad || field->fld_dtype == dtype_date)
|
|
sprintf(output_buffer, "%sCALL \"isc_qtoq\" USING %s, %s\n",
|
|
names[COLUMN], s1, s2);
|
|
else
|
|
sprintf(output_buffer, "%sMOVE %s TO %s\n",
|
|
names[COLUMN], s1, s2);
|
|
COB_print_buffer(output_buffer, TRUE);
|
|
if (field->fld_array_info)
|
|
gen_get_or_put_slice(action, reference, false);
|
|
}
|
|
|
|
gen_send(action, modify->upd_port);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate substitution text for END_STORE.
|
|
//
|
|
|
|
static void gen_estore( ACT action)
|
|
{
|
|
GPRE_REQ request;
|
|
|
|
request = action->act_request;
|
|
gen_start(action, request->req_primary);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate end-if for AT_END if statement
|
|
//
|
|
|
|
static void gen_end_fetch( ACT action)
|
|
{
|
|
|
|
printa(names[COLUMN], false, "END-IF");
|
|
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate definitions associated with a single request.
|
|
//
|
|
|
|
static void gen_endfor( ACT action)
|
|
{
|
|
GPRE_REQ request;
|
|
|
|
request = action->act_request;
|
|
|
|
if (request->req_sync)
|
|
gen_send(action, request->req_sync);
|
|
gen_receive(action, request->req_primary);
|
|
printa(names[COLUMN], false, "END-PERFORM");
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate substitution text for ERASE.
|
|
//
|
|
|
|
static void gen_erase( ACT action)
|
|
{
|
|
UPD erase;
|
|
|
|
erase = (UPD) action->act_object;
|
|
gen_send(action, erase->upd_port);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate event parameter blocks for use
|
|
// with a particular call to isc_event_wait.
|
|
//
|
|
|
|
static SSHORT gen_event_block( ACT action)
|
|
{
|
|
GPRE_NOD init, list;
|
|
int ident;
|
|
|
|
init = (GPRE_NOD) action->act_object;
|
|
|
|
ident = CMP_next_ident();
|
|
init->nod_arg[2] = (GPRE_NOD) ident;
|
|
|
|
printa(names[COLUMN_0], false, "01 %s%dA PIC S9(9) USAGE COMP.",
|
|
names[ISC_], ident);
|
|
printa(names[COLUMN_0], false, "01 %s%dB PIC S9(9) USAGE COMP.",
|
|
names[ISC_], ident);
|
|
printa(names[COLUMN_0], false, "01 %s%dL PIC S9(4) USAGE COMP.",
|
|
names[ISC_], ident);
|
|
|
|
list = init->nod_arg[1];
|
|
|
|
return list->nod_count;
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate substitution text for EVENT_INIT.
|
|
//
|
|
|
|
static void gen_event_init( ACT action)
|
|
{
|
|
GPRE_NOD init, event_list, *ptr, *end, node;
|
|
REF reference;
|
|
PAT args;
|
|
TEXT variable[20];
|
|
SSHORT column, count;
|
|
#ifdef GIVING_SUPPORTED
|
|
TEXT *pattern1 =
|
|
"CALL \"%S1\" USING %RF%S4%N1A%RE, %RF%S4%N1B%RE, %VF%N2%VE, %RF%S6%RE GIVING %S4%N1L";
|
|
#else
|
|
TEXT *pattern1 =
|
|
"CALL \"%S1\" USING %RF%S4%N1A%RE, %RF%S4%N1B%RE, %VF%N2%VE, %RF%S6%RE, %RF%S4%N1L%RE";
|
|
#endif
|
|
TEXT *pattern2 =
|
|
"CALL \"%S2\" USING %V1, %RF%DH%RE, %VF%S4%N1L%VE, %VF%S4%N1A%VE, %VF%S4%N1B%VE";
|
|
TEXT *pattern3 =
|
|
"CALL \"%S3\" USING %S5, %VF%S4%N1L%VE, %VF%S4%N1A%VE, %VF%S4%N1B%VE";
|
|
|
|
#ifdef GIVING_SUPPORTED
|
|
#define EVENT_MOVE_TEMPLATE "CALL \"%s\" USING %s(%d) GIVING %s(%d)"
|
|
#else
|
|
#define EVENT_MOVE_TEMPLATE "CALL \"%s\" USING %s(%d), %s(%d)"
|
|
#endif
|
|
|
|
init = (GPRE_NOD) action->act_object;
|
|
event_list = init->nod_arg[1];
|
|
|
|
column = strlen(names[COLUMN]);
|
|
|
|
args.pat_database = (DBB) init->nod_arg[3];
|
|
args.pat_vector1 = status_vector(action);
|
|
args.pat_value1 = (int) init->nod_arg[2];
|
|
args.pat_value2 = (int) event_list->nod_count;
|
|
args.pat_string1 = ISC_EVENT_BLOCK;
|
|
args.pat_string2 = ISC_EVENT_WAIT;
|
|
args.pat_string3 = ISC_EVENT_COUNTS;
|
|
args.pat_string4 = names[ISC_];
|
|
args.pat_string5 = names[ISC_EVENTS_VECTOR];
|
|
args.pat_string6 = names[ISC_EVENT_NAMES_VECTOR];
|
|
|
|
// generate call to dynamically generate event blocks
|
|
|
|
for (ptr = event_list->nod_arg, count = 0, end =
|
|
ptr + event_list->nod_count; ptr < end; ptr++) {
|
|
count++;
|
|
node = *ptr;
|
|
if (node->nod_type == nod_field) {
|
|
reference = (REF) node->nod_arg[0];
|
|
gen_name(variable, reference, true);
|
|
printa(names[COLUMN], false, "MOVE %s TO %s(%d)", variable,
|
|
names[ISC_EVENT_NAMES2], count);
|
|
}
|
|
else
|
|
printa(names[COLUMN], false, "MOVE %s TO %s(%d)",
|
|
(TEXT *) node->nod_arg[0], names[ISC_EVENT_NAMES2], count);
|
|
|
|
printa(names[COLUMN], true, EVENT_MOVE_TEMPLATE, ISC_BADDRESS,
|
|
names[ISC_EVENT_NAMES2], count, names[ISC_EVENT_NAMES], count);
|
|
}
|
|
|
|
PATTERN_expand(column, pattern1, &args);
|
|
|
|
// generate actual call to event_wait
|
|
|
|
PATTERN_expand(column, pattern2, &args);
|
|
|
|
// get change in event counts, copying event parameter block for reuse
|
|
|
|
PATTERN_expand(column, pattern3, &args);
|
|
set_sqlcode(action);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate substitution text for EVENT_WAIT.
|
|
//
|
|
|
|
static void gen_event_wait( ACT action)
|
|
{
|
|
PAT args;
|
|
GPRE_NOD event_init;
|
|
SYM event_name, stack_name;
|
|
DBB database;
|
|
LLS stack_ptr;
|
|
ACT event_action;
|
|
SSHORT column;
|
|
int ident;
|
|
TEXT s[64];
|
|
TEXT *pattern1 =
|
|
"CALL \"%S2\" USING %V1, %RF%DH%RE, %VF%S4%N1L%VE, %VF%S4%N1A%VE, %VF%S4%N1B%VE";
|
|
TEXT *pattern2 =
|
|
"CALL \"%S3\" USING %S5, %VF%S4%N1L%VE, %VF%S4%N1A%VE, %VF%S4%N1B%VE";
|
|
|
|
event_name = (SYM) action->act_object;
|
|
|
|
// go through the stack of events, checking to see if the
|
|
// event has been initialized and getting the event identifier
|
|
|
|
ident = -1;
|
|
for (stack_ptr = events; stack_ptr; stack_ptr = stack_ptr->lls_next) {
|
|
event_action = (ACT) stack_ptr->lls_object;
|
|
event_init = (GPRE_NOD) event_action->act_object;
|
|
stack_name = (SYM) event_init->nod_arg[0];
|
|
if (!strcmp(event_name->sym_string, stack_name->sym_string)) {
|
|
ident = (int) event_init->nod_arg[2];
|
|
database = (DBB) event_init->nod_arg[3];
|
|
}
|
|
}
|
|
|
|
if (ident < 0) {
|
|
sprintf(s, "event handle \"%s\" not found", event_name->sym_string);
|
|
IBERROR(s);
|
|
return;
|
|
}
|
|
|
|
column = strlen(names[COLUMN]);
|
|
|
|
args.pat_database = database;
|
|
args.pat_vector1 = status_vector(action);
|
|
args.pat_value1 = (int) ident;
|
|
args.pat_string2 = ISC_EVENT_WAIT;
|
|
args.pat_string3 = ISC_EVENT_COUNTS;
|
|
args.pat_string4 = names[ISC_];
|
|
args.pat_string5 = names[ISC_EVENTS_VECTOR];
|
|
|
|
// generate calls to wait on the event and to fill out the events array
|
|
|
|
PATTERN_expand(column, pattern1, &args);
|
|
PATTERN_expand(column, pattern2, &args);
|
|
set_sqlcode(action);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate replacement text for the SQL FETCH statement. The
|
|
// epilog FETCH statement is handled by GEN_S_FETCH (generate
|
|
// stream fetch).
|
|
//
|
|
|
|
static void gen_fetch( ACT action)
|
|
{
|
|
GPRE_REQ request;
|
|
GPRE_NOD var_list;
|
|
int i;
|
|
SCHAR s[20];
|
|
#ifdef SCROLLABLE_CURSORS
|
|
POR port;
|
|
REF reference;
|
|
SCHAR *direction, *offset;
|
|
VAL value;
|
|
#endif
|
|
|
|
request = action->act_request;
|
|
|
|
#ifdef SCROLLABLE_CURSORS
|
|
if (port = request->req_aport) {
|
|
/* set up the reference to point to the correct value
|
|
in the linked list of values, and prepare for the
|
|
next FETCH statement if applicable */
|
|
|
|
for (reference = port->por_references; reference;
|
|
reference = reference->ref_next) {
|
|
value = reference->ref_values;
|
|
reference->ref_value = value->val_value;
|
|
reference->ref_values = value->val_next;
|
|
}
|
|
|
|
/* find the direction and offset parameters */
|
|
|
|
reference = port->por_references;
|
|
offset = reference->ref_value;
|
|
reference = reference->ref_next;
|
|
direction = reference->ref_value;
|
|
|
|
/* the direction in which the engine will scroll is sticky, so check to see
|
|
the last direction passed to the engine; if the direction is the same and
|
|
the offset is 1, then there is no need to pass the message; this prevents
|
|
extra packets and allows for batch fetches in either direction */
|
|
|
|
printa(names[COLUMN], false,
|
|
"IF %s%dDI MOD 2 NOT = %s || %s NOT = 1 THEN", names[ISC_],
|
|
request->req_ident, direction, offset);
|
|
|
|
/* assign the direction and offset parameters to the appropriate message,
|
|
then send the message to the engine */
|
|
|
|
asgn_from(action, port->por_references);
|
|
gen_send(action, port);
|
|
printa(names[COLUMN], false, "MOVE %s TO %s%dDI",
|
|
names[ISC_], direction, request->req_ident);
|
|
printa(names[COLUMN], false, "END-IF");
|
|
|
|
printa(names[COLUMN], false, "IF SQLCODE NOT = 0 THEN");
|
|
}
|
|
#endif
|
|
|
|
if (request->req_sync)
|
|
gen_send(action, request->req_sync);
|
|
|
|
gen_receive(action, request->req_primary);
|
|
printa(names[COLUMN], false,
|
|
"IF %s NOT = 0 THEN", gen_name(s, request->req_eof, true));
|
|
printa(names[COLUMN], false, "MOVE 0 TO SQLCODE");
|
|
if (var_list = (GPRE_NOD) action->act_object)
|
|
for (i = 0; i < var_list->nod_count; i++) {
|
|
asgn_to(action, (REF) var_list->nod_arg[i]);
|
|
}
|
|
printa(names[COLUMN], false, "ELSE");
|
|
printa(names[COLUMN], false, "MOVE 100 TO SQLCODE");
|
|
printa(names[COLUMN], false, "END-IF");
|
|
|
|
#ifdef SCROLLABLE_CURSORS
|
|
if (port)
|
|
printa(names[COLUMN], false, "END-IF");
|
|
#endif
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate substitution text for FINISH
|
|
//
|
|
|
|
static void gen_finish( ACT action)
|
|
{
|
|
DBB db;
|
|
RDY ready;
|
|
#ifdef VMS
|
|
#define COMMIT "COMMIT"
|
|
#define ROLLBACK "ROLLBACK"
|
|
#else
|
|
#define COMMIT "commit"
|
|
#define ROLLBACK "rollback"
|
|
#endif
|
|
|
|
if (sw_auto || ((action->act_flags & ACT_sql) &&
|
|
(action->act_type != ACT_disconnect))) {
|
|
printa(names[COLUMN], false, "IF %s NOT = 0 THEN", names[ISC_TRANS]);
|
|
printa(names[COLUMN], true,
|
|
" CALL \"%s\" USING %s, %s%s",
|
|
(action->act_type !=
|
|
ACT_rfinish) ? ISC_COMMIT_TRANSACTION :
|
|
ISC_ROLLBACK_TRANSACTION, status_vector(action), BY_REF,
|
|
names[ISC_TRANS]);
|
|
printa(names[COLUMN], false, "END-IF");
|
|
}
|
|
|
|
// the user may have supplied one or more handles
|
|
|
|
db = NULL;
|
|
for (ready = (RDY) action->act_object; ready; ready = ready->rdy_next) {
|
|
db = ready->rdy_database;
|
|
printa(names[COLUMN], false,
|
|
"IF %s NOT = 0 THEN", db->dbb_name->sym_string);
|
|
printa(names[COLUMN], true,
|
|
"CALL \"%s\" USING %s, %s%s",
|
|
ISC_DETACH_DATABASE,
|
|
status_vector(action), BY_REF, db->dbb_name->sym_string);
|
|
printa(names[COLUMN], false, "END-IF");
|
|
}
|
|
|
|
// no handles, so finish all known databases
|
|
|
|
if (!db)
|
|
for (db = isc_databases; db; db = db->dbb_next) {
|
|
printa(names[COLUMN], false,
|
|
"IF %s NOT = 0 THEN", db->dbb_name->sym_string);
|
|
printa(names[COLUMN], true,
|
|
"CALL \"%s\" USING %s, %s%s",
|
|
ISC_DETACH_DATABASE,
|
|
status_vector(action), BY_REF, db->dbb_name->sym_string);
|
|
printa(names[COLUMN], false, "END-IF");
|
|
}
|
|
set_sqlcode(action);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate substitution text for FOR statement.
|
|
//
|
|
|
|
static void gen_for( ACT action)
|
|
{
|
|
GPRE_REQ request;
|
|
TEXT s[20];
|
|
REF reference;
|
|
POR port;
|
|
|
|
gen_s_start(action);
|
|
request = action->act_request;
|
|
gen_receive(action, request->req_primary);
|
|
printa(names[COLUMN], false, "PERFORM UNTIL %s = 0",
|
|
gen_name(s, request->req_eof, true));
|
|
|
|
if (port = action->act_request->req_primary)
|
|
for (reference = port->por_references; reference;
|
|
reference = reference->ref_next)
|
|
{
|
|
if (reference->ref_field->fld_array_info)
|
|
gen_get_or_put_slice(action, reference, true);
|
|
}
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate a function for free standing ANY or statistical.
|
|
//
|
|
|
|
static void gen_function( ACT function)
|
|
{
|
|
GPRE_REQ request;
|
|
POR port;
|
|
REF reference;
|
|
GPRE_FLD field;
|
|
ACT action;
|
|
TEXT *dtype, s[64];
|
|
|
|
action = (ACT) function->act_object;
|
|
|
|
if (action->act_type != ACT_any) {
|
|
IBERROR("can't generate function");
|
|
return;
|
|
}
|
|
|
|
request = action->act_request;
|
|
|
|
ib_fprintf(out_file, "static %s_r (request, transaction", request->req_handle);
|
|
|
|
if (port = request->req_vport)
|
|
for (reference = port->por_references; reference;
|
|
reference = reference->ref_next)
|
|
ib_fprintf(out_file, ", %s",
|
|
gen_name(s, reference->ref_source, true));
|
|
|
|
ib_fprintf(out_file,
|
|
")\n isc_req_handle\trequest;\n isc_tr_handle\ttransaction;\n");
|
|
|
|
if (port)
|
|
for (reference = port->por_references; reference;
|
|
reference = reference->ref_next) {
|
|
field = reference->ref_field;
|
|
switch (field->fld_dtype) {
|
|
case dtype_short:
|
|
dtype = "short";
|
|
break;
|
|
|
|
case dtype_long:
|
|
dtype = "long";
|
|
break;
|
|
|
|
case dtype_cstring:
|
|
case dtype_text:
|
|
dtype = "char*";
|
|
break;
|
|
|
|
case dtype_quad:
|
|
dtype = "ISC_QUAD";
|
|
break;
|
|
|
|
case dtype_date:
|
|
case dtype_blob:
|
|
dtype = "ISC_QUAD";
|
|
break;
|
|
|
|
case dtype_real:
|
|
dtype = "float";
|
|
break;
|
|
|
|
case dtype_double:
|
|
dtype = "double";
|
|
break;
|
|
|
|
default:
|
|
IBERROR("gen_function: unsupported datatype");
|
|
return;
|
|
}
|
|
ib_fprintf(out_file, " %s\t%s;\n", dtype,
|
|
gen_name(s, reference->ref_source, true));
|
|
}
|
|
|
|
ib_fprintf(out_file, "{\n");
|
|
for (port = request->req_ports; port; port = port->por_next)
|
|
make_port(port);
|
|
|
|
ib_fprintf(out_file, "\n\n");
|
|
gen_s_start(action);
|
|
gen_receive(action, request->req_primary);
|
|
|
|
for (port = request->req_ports; port; port = port->por_next)
|
|
for (reference = port->por_references; reference;
|
|
reference = reference->ref_next)
|
|
{
|
|
if (reference->ref_field->fld_array_info)
|
|
gen_get_or_put_slice(action, reference, true);
|
|
}
|
|
|
|
port = request->req_primary;
|
|
ib_fprintf(out_file, "\nreturn %s;\n}\n",
|
|
gen_name(s, port->por_references, true));
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate a call to isc_get_slice
|
|
// or isc_put_slice for an array.
|
|
//
|
|
|
|
static void gen_get_or_put_slice(ACT action,
|
|
REF reference,
|
|
bool get)
|
|
{
|
|
int column;
|
|
PAT args;
|
|
TEXT s1[25], s2[10], s4[10];
|
|
TEXT *pattern1 =
|
|
"CALL \"%S7\" USING %V1, %RF%DH%RE, %RF%S1%RE, %RF%S2%RE, %VF%N1%VE, %RF%S3%RE, %VF%N2%VE, %VF%S4%VE, %VF%L1%VE, %RF%S5%RE, %RF%S6%RE";
|
|
TEXT *pattern2 =
|
|
"CALL \"%S7\" USING %V1, %RF%DH%RE, %RF%S1%RE, %RF%S2%RE, %VF%N1%VE, %RF%S3%RE, %VF%N2%VE, %VF%S4%VE, %VF%L1%VE, %RF%S5%RE";
|
|
|
|
if (!(reference->ref_flags & REF_fetch_array))
|
|
return;
|
|
|
|
column = strlen(names[COLUMN]);
|
|
|
|
args.pat_condition = get; // get or put slice
|
|
args.pat_vector1 = status_vector(action); // status vector
|
|
args.pat_database = action->act_request->req_database; // database handle
|
|
args.pat_string1 = action->act_request->req_trans; // transaction handle
|
|
|
|
gen_name(s1, reference, true); // blob handle
|
|
args.pat_string2 = s1;
|
|
|
|
args.pat_value1 = reference->ref_sdl_length; /* slice descr length */
|
|
|
|
sprintf(s2, "%s%d", names[ISC_], reference->ref_sdl_ident); /* slice description */
|
|
args.pat_string3 = s2;
|
|
|
|
args.pat_value2 = 0; /* parameter length */
|
|
|
|
args.pat_string4 = "0"; /* parameter */
|
|
|
|
args.pat_long1 = reference->ref_field->fld_array_info->ary_size;
|
|
/* slice size */
|
|
if (action->act_flags & ACT_sql) {
|
|
args.pat_string5 = reference->ref_value;
|
|
}
|
|
else {
|
|
sprintf(s4, "%s%dL", names[ISC_],
|
|
reference->ref_field->fld_array_info->ary_ident);
|
|
args.pat_string5 = s4; /* array name */
|
|
}
|
|
|
|
args.pat_string6 = names[ISC_ARRAY_LENGTH]; /* return length */
|
|
args.pat_string7 = (get) ? (TEXT*) ISC_GET_SLICE : (TEXT*) ISC_PUT_SLICE;
|
|
|
|
PATTERN_expand(column, (get) ? pattern1 : pattern2, &args);
|
|
ib_fprintf(out_file, "\n");
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate the code to do a get segment.
|
|
//
|
|
|
|
static void gen_get_segment( ACT action)
|
|
{
|
|
BLB blob;
|
|
REF into;
|
|
TEXT buffer[128];
|
|
|
|
#ifdef GIVING_SUPPORTED
|
|
#define GET_SEG_CALL_TEMPLATE "%sCALL \"%s\" USING %s, %s%d, %s%d, %s%d%s, %s%s%d GIVING %s (2)\n"
|
|
#else
|
|
#define GET_SEG_CALL_TEMPLATE "%sCALL \"%s\" USING %s, %s%d, %s%d, %s%d%s, %s%s%d\n"
|
|
#endif
|
|
|
|
if (action->act_flags & ACT_sql)
|
|
blob = (BLB) action->act_request->req_blobs;
|
|
else
|
|
blob = (BLB) action->act_object;
|
|
|
|
strcpy(buffer, GET_SEG_CALL_TEMPLATE);
|
|
sprintf(output_buffer,
|
|
buffer,
|
|
names[COLUMN],
|
|
ISC_GET_SEGMENT,
|
|
names[ISC_STATUS_VECTOR],
|
|
names[ISC_], blob->blb_ident,
|
|
names[ISC_], blob->blb_len_ident,
|
|
BY_VALUE, blob->blb_seg_length, END_VALUE,
|
|
BY_REF, names[ISC_], blob->blb_buff_ident, names[ISC_STATUS]);
|
|
|
|
COB_print_buffer(output_buffer, TRUE);
|
|
|
|
if (action->act_flags & ACT_sql) {
|
|
into = action->act_object;
|
|
set_sqlcode(action);
|
|
printa(names[COLUMN], false, "IF SQLCODE = 0 OR SQLCODE = 101 THEN ");
|
|
printa(names[COLUMN], false, "MOVE ISC-%d TO %s",
|
|
blob->blb_buff_ident, into->ref_value);
|
|
if (into->ref_null_value)
|
|
printa(names[COLUMN], false, "MOVE ISC-%d TO %s",
|
|
blob->blb_len_ident, into->ref_null_value);
|
|
printa(names[COLUMN], false, "END-IF");
|
|
}
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate text to compile and start a SQL mass update.
|
|
//
|
|
//
|
|
|
|
static void gen_loop( ACT action)
|
|
{
|
|
GPRE_REQ request;
|
|
POR port;
|
|
TEXT name[20];
|
|
|
|
gen_s_start(action);
|
|
request = action->act_request;
|
|
printa(names[COLUMN], false, "IF SQLCODE = 0 THEN");
|
|
port = request->req_primary;
|
|
gen_receive(action, port);
|
|
gen_name(name, port->por_references, true);
|
|
printa(names[COLUMN], false, "IF SQLCODE = 0 AND %s = 0 THEN ", name);
|
|
printa(names[COLUMN], false, "MOVE 100 TO SQLCODE");
|
|
printa(names[COLUMN], false, "END-IF");
|
|
printa(names[COLUMN], false, "END-IF");
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate a name for a reference. Name is constructed from
|
|
// port and parameter idents.
|
|
//
|
|
|
|
static TEXT *gen_name(TEXT * string,
|
|
REF reference,
|
|
bool as_blob)
|
|
{
|
|
|
|
if (reference->ref_field->fld_array_info && !as_blob)
|
|
sprintf(string, "%s%d", names[ISC_],
|
|
reference->ref_field->fld_array_info->ary_ident);
|
|
else
|
|
sprintf(string, "%s%d", names[isc_], reference->ref_ident);
|
|
|
|
return string;
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate a block to handle errors.
|
|
//
|
|
|
|
static void gen_on_error( ACT action)
|
|
{
|
|
|
|
printa(names[COLUMN], false, "IF %s (2) NOT = 0 THEN", names[ISC_STATUS]);
|
|
ib_fprintf(out_file, names[COLUMN]);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate code for an EXECUTE PROCEDURE.
|
|
//
|
|
|
|
static void gen_procedure( ACT action)
|
|
{
|
|
PAT args;
|
|
TEXT *pattern;
|
|
GPRE_REQ request;
|
|
POR in_port, out_port;
|
|
USHORT column;
|
|
|
|
request = action->act_request;
|
|
in_port = request->req_vport;
|
|
out_port = request->req_primary;
|
|
|
|
args.pat_database = request->req_database;
|
|
args.pat_request = action->act_request;
|
|
args.pat_vector1 = status_vector(action);
|
|
args.pat_request = request;
|
|
args.pat_port = in_port;
|
|
args.pat_port2 = out_port;
|
|
#ifndef VMS
|
|
if (in_port && in_port->por_length)
|
|
pattern =
|
|
"CALL \"isc_transact_request\" USING %V1, %RF%DH%RE, %RF%RT%RE, %VF%RS%VE, %RF%RI%RE, %VF%PL%VE, %RF%PI%RE, %VF%QL%VE, %RF%QI%RE\n";
|
|
else
|
|
pattern =
|
|
"CALL \"isc_transact_request\" USING %V1, %RF%DH%RE, %RF%RT%RE, %VF%RS%VE, %RI, %VF0%VE, 0, %VF%QL%VE, %RF%QI%RE\n";
|
|
#else
|
|
if (in_port && in_port->por_length)
|
|
pattern =
|
|
"CALL \"isc_transact_request\" USING %V1, %RF%DH%RE, %RF%RT%RE, %VF%RS%VE, %RF%RI%RE, %VF%PL%VE, %RF%PI%RE, %VF%QL%VE, %RF%QI%RE\n";
|
|
else
|
|
pattern =
|
|
"CALL \"isc_transact_request\" USING %V1, %RF%DH%RE, %RF%RT%RE, %VF%RS%VE, %RI, %VF0%VE, 0, %VF%QL%VE, %RF%QI%RE\n";
|
|
#endif
|
|
|
|
// Get database attach and transaction started
|
|
|
|
if (sw_auto)
|
|
t_start_auto(0, status_vector(action), action, true);
|
|
|
|
// Move in input values
|
|
|
|
asgn_from(action, request->req_values);
|
|
|
|
// Execute the procedure
|
|
|
|
column = strlen(names[COLUMN]);
|
|
PATTERN_expand(column, pattern, &args);
|
|
|
|
set_sqlcode(action);
|
|
|
|
printa(names[COLUMN], false, "IF SQLCODE = 0 THEN");
|
|
|
|
// Move out output values
|
|
|
|
asgn_to_proc(request->req_references);
|
|
printa(names[COLUMN], false, "END-IF");
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate the code to do a put segment.
|
|
//
|
|
|
|
static void gen_put_segment( ACT action)
|
|
{
|
|
BLB blob;
|
|
REF from;
|
|
TEXT buffer[128];
|
|
|
|
#ifdef GIVING_SUPPORTED
|
|
#define PUT_SEG_CALL_TEMPLATE "%sCALL \"%s\" USING %s, %s%s%d, %s%s%d%s, %s%s%d GIVING %s (2)\n"
|
|
#else
|
|
#define PUT_SEG_CALL_TEMPLATE "%sCALL \"%s\" USING %s, %s%s%d, %s%s%d%s, %s%s%d\n"
|
|
#endif
|
|
|
|
if (action->act_flags & ACT_sql) {
|
|
blob = (BLB) action->act_request->req_blobs;
|
|
from = action->act_object;
|
|
printa(names[COLUMN], false, "MOVE %s TO ISC-%d",
|
|
from->ref_value, blob->blb_buff_ident);
|
|
printa(names[COLUMN], false, "MOVE %s TO ISC-%d",
|
|
from->ref_null_value, blob->blb_len_ident);
|
|
}
|
|
else
|
|
blob = (BLB) action->act_object;
|
|
|
|
strcpy(buffer, PUT_SEG_CALL_TEMPLATE);
|
|
sprintf(output_buffer,
|
|
buffer,
|
|
names[COLUMN],
|
|
ISC_PUT_SEGMENT,
|
|
status_vector(action),
|
|
BY_REF, names[ISC_], blob->blb_ident,
|
|
BY_VALUE, names[ISC_], blob->blb_len_ident, END_VALUE,
|
|
BY_REF, names[ISC_], blob->blb_buff_ident, names[ISC_STATUS]);
|
|
COB_print_buffer(output_buffer, TRUE);
|
|
|
|
set_sqlcode(action);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate BLR in raw, numeric form. Ughly but dense.
|
|
//
|
|
|
|
static void gen_raw(
|
|
UCHAR * blr,
|
|
enum req_t request_type, int request_length, int ident)
|
|
{
|
|
UCHAR *c;
|
|
TEXT s[256];
|
|
int blr_length, length;
|
|
union {
|
|
#ifdef VMS
|
|
SCHAR bytewise_blr[4];
|
|
SLONG longword_blr;
|
|
#else
|
|
UCHAR bytewise_blr[4];
|
|
ULONG longword_blr;
|
|
#endif
|
|
} blr_hunk;
|
|
|
|
length = 1;
|
|
blr_length = request_length;
|
|
|
|
while (blr_length) {
|
|
s[0] = 0;
|
|
blr_hunk.longword_blr = 0;
|
|
for (c = blr_hunk.bytewise_blr;
|
|
c < blr_hunk.bytewise_blr + sizeof(SLONG); c++)
|
|
{
|
|
if (--blr_length)
|
|
*c = *blr++;
|
|
else {
|
|
if (request_type == REQ_slice)
|
|
*c = isc_sdl_eoc;
|
|
else if ((request_type == REQ_ddl) ||
|
|
(request_type == REQ_create_database))
|
|
{
|
|
*c = *blr++;
|
|
}
|
|
else
|
|
*c = blr_eoc;
|
|
break;
|
|
}
|
|
}
|
|
|
|
strcat(s, names[COLUMN]);
|
|
strcat(s, RAW_BLR_TEMPLATE);
|
|
strcat(s, "\n");
|
|
sprintf(output_buffer, s, names[ISC_], ident, names[UNDER], length++,
|
|
blr_hunk.longword_blr);
|
|
COB_print_buffer(output_buffer, FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate substitution text for READY
|
|
// This becomes baroque for mpexl where we
|
|
// must generate a variable if the user gives us
|
|
// a string literal. mpexl cobol doesn't take
|
|
// string literals as CALL parameters.
|
|
//
|
|
|
|
static void gen_ready( ACT action)
|
|
{
|
|
RDY ready;
|
|
DBB db, dbisc;
|
|
TEXT *filename, *vector, dbname[96];
|
|
USHORT namelength;
|
|
|
|
vector = status_vector(action);
|
|
|
|
for (ready = (RDY) action->act_object; ready; ready = ready->rdy_next) {
|
|
db = ready->rdy_database;
|
|
dbisc = (DBB) db->dbb_name->sym_object;
|
|
if (!(filename = ready->rdy_filename)) {
|
|
filename = db->dbb_runtime;
|
|
if (filename) {
|
|
namelength = strlen(filename);
|
|
#ifndef VMS
|
|
sprintf(dbname, "isc-%ddb", dbisc->dbb_id);
|
|
filename = dbname;
|
|
#endif
|
|
}
|
|
else
|
|
namelength = 0;
|
|
}
|
|
else
|
|
namelength = strlen(filename);
|
|
#ifndef VMS
|
|
/* string literal or user defined variable? */
|
|
|
|
if (ready->rdy_id) {
|
|
sprintf(dbname, "isc-%ddb", ready->rdy_id);
|
|
filename = dbname;
|
|
namelength -= 2;
|
|
}
|
|
else
|
|
namelength = 0;
|
|
#endif
|
|
make_ready(db, filename, vector, ready->rdy_request, namelength);
|
|
set_sqlcode(action);
|
|
}
|
|
|
|
ib_fprintf(out_file, names[COLUMN]);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate substitution text for RELEASE_REQUESTS
|
|
// For active databases, call isc_release_request.
|
|
// for all others, just zero the handle. For the
|
|
// release request calls, ignore error returns, which
|
|
// are likely if the request was compiled on a database
|
|
// which has been released and re-readied. If there is
|
|
// a serious error, it will be caught on the next statement.
|
|
//
|
|
|
|
static void gen_release( ACT action)
|
|
{
|
|
DBB db, exp_db;
|
|
GPRE_REQ request;
|
|
|
|
exp_db = (DBB) action->act_object;
|
|
|
|
for (request = requests; request; request = request->req_next) {
|
|
db = request->req_database;
|
|
if (exp_db && db != exp_db)
|
|
continue;
|
|
if (!(request->req_flags & REQ_exp_hand)) {
|
|
printa(names[COLUMN], false, "IF %s = 0 THEN",
|
|
db->dbb_name->sym_string);
|
|
printa(names[COLUMN], true, "CALL \"%s\" USING %s, %s%s",
|
|
ISC_RELEASE_REQUEST, status_vector(action), BY_REF,
|
|
request->req_handle);
|
|
printa(names[COLUMN], false, "END-IF");
|
|
printa(names[COLUMN], false, "MOVE 0 to %s", request->req_handle);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate a send or receive call for a port.
|
|
//
|
|
|
|
static void gen_receive( ACT action, POR port)
|
|
{
|
|
GPRE_REQ request;
|
|
|
|
request = action->act_request;
|
|
sprintf(output_buffer,
|
|
"%sCALL \"%s\" USING %s, %s%s, %s%d%s, %s%d%s, %s%s%d, %s%s%s\n",
|
|
names[COLUMN],
|
|
ISC_RECEIVE,
|
|
status_vector(action),
|
|
BY_REF, request->req_handle,
|
|
BY_VALUE, port->por_msg_number, END_VALUE,
|
|
BY_VALUE, port->por_length, END_VALUE,
|
|
BY_REF, names[ISC_], port->por_ident,
|
|
BY_VALUE, request->req_request_level, END_VALUE);
|
|
COB_print_buffer(output_buffer, TRUE);
|
|
|
|
set_sqlcode(action);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate definitions associated with a single request.
|
|
// Requests are generated as raw BLR in longword chunks
|
|
// because COBOL is a miserable excuse for a language
|
|
// and doesn't allow byte value assignments to character
|
|
// fields.
|
|
//
|
|
|
|
static void gen_request( GPRE_REQ request)
|
|
{
|
|
REF reference;
|
|
BLB blob;
|
|
POR port;
|
|
TEXT *string_type;
|
|
|
|
if (!(request->req_flags & (REQ_exp_hand | REQ_sql_blob_open
|
|
| REQ_sql_blob_create)) && request->req_type != REQ_slice
|
|
&& request->req_type != REQ_procedure)
|
|
{
|
|
printa(names[COLUMN_0], false,
|
|
"01 %s PIC S9(9) USAGE COMP VALUE IS 0.",
|
|
request->req_handle);
|
|
}
|
|
|
|
if (request->req_type == REQ_ready)
|
|
printa(names[COLUMN_0], false,
|
|
"01 %s%dL PIC S9(4) USAGE %s VALUE IS %d.", names[ISC_],
|
|
request->req_ident, COMP_VALUE, request->req_length);
|
|
|
|
// check the case where we need to extend the dpb dynamically at runtime,
|
|
// in which case we need dpb length and a pointer to be defined even if
|
|
// there is no static dpb defined
|
|
|
|
if (request->req_flags & REQ_extend_dpb) {
|
|
printa(names[COLUMN_0], false,
|
|
"01 ISC-%dP PIC S9(9) USAGE COMP-5 VALUE IS 0.",
|
|
request->req_ident);
|
|
}
|
|
|
|
if (request->req_flags & (REQ_sql_blob_open | REQ_sql_blob_create))
|
|
printa(names[COLUMN_0], false,
|
|
"01 %s%dS PIC S9(9) USAGE COMP VALUE IS 0.", names[ISC_],
|
|
request->req_ident);
|
|
|
|
// generate the request as BLR long words
|
|
|
|
if (request->req_length) {
|
|
if (request->req_flags & REQ_sql_cursor)
|
|
printa(names[COLUMN_0], false,
|
|
"01 %s%dS PIC S9(9) USAGE COMP VALUE IS 0.", names[ISC_],
|
|
request->req_ident);
|
|
#ifdef SCROLLABLE_CURSORS
|
|
if (request->req_flags & REQ_scroll)
|
|
printa(names[COLUMN_0], false,
|
|
"01 %s%dDI PIC S9(4) USAGE COMP VALUE IS 0.", names[ISC_],
|
|
request->req_ident);
|
|
#endif
|
|
printa(names[COLUMN_0], false, "01 %s%d.",
|
|
names[ISC_], request->req_ident);
|
|
gen_raw(request->req_blr, request->req_type, request->req_length,
|
|
request->req_ident);
|
|
if (!(sw_raw)) {
|
|
printa(names[COMMENT], false, " ");
|
|
printa(names[COMMENT], false, "FORMATTED REQUEST BLR FOR %s%d = ",
|
|
names[ISC_], request->req_ident);
|
|
switch (request->req_type) {
|
|
case REQ_create_database:
|
|
case REQ_ready:
|
|
string_type = "DPB";
|
|
if (PRETTY_print_cdb(request->req_blr, gen_blr, 0, 0))
|
|
IBERROR("internal error during parameter generation");
|
|
break;
|
|
|
|
|
|
case REQ_ddl:
|
|
string_type = "DYN";
|
|
if (PRETTY_print_dyn(request->req_blr, gen_blr, 0, 0))
|
|
IBERROR("internal error during dynamic DDL generation");
|
|
break;
|
|
case REQ_slice:
|
|
string_type = "SDL";
|
|
if (PRETTY_print_sdl(request->req_blr, gen_blr, 0, 0))
|
|
IBERROR("internal error during SDL generation");
|
|
break;
|
|
|
|
default:
|
|
string_type = "BLR";
|
|
if (gds__print_blr(request->req_blr, gen_blr, 0, 0))
|
|
IBERROR("internal error during BLR generation");
|
|
}
|
|
}
|
|
else {
|
|
switch (request->req_type) {
|
|
case REQ_create_database:
|
|
case REQ_ready:
|
|
string_type = "DPB";
|
|
break;
|
|
|
|
case REQ_ddl:
|
|
string_type = "DYN";
|
|
break;
|
|
case REQ_slice:
|
|
string_type = "SDL";
|
|
break;
|
|
|
|
default:
|
|
string_type = "BLR";
|
|
}
|
|
}
|
|
printa(names[COMMENT], false, " ");
|
|
printa(names[COMMENT], false, "END OF %s STRING FOR REQUEST %s%d\n",
|
|
string_type, names[ISC_], request->req_ident);
|
|
}
|
|
|
|
// Print out slice description language if there are arrays associated with request
|
|
|
|
for (port = request->req_ports; port; port = port->por_next)
|
|
for (reference = port->por_references; reference;
|
|
reference = reference->ref_next)
|
|
{
|
|
if (reference->ref_sdl) {
|
|
printa(names[COLUMN_0], false, "01 %s%d.", names[ISC_],
|
|
reference->ref_sdl_ident);
|
|
gen_raw((UCHAR*) reference->ref_sdl, REQ_slice,
|
|
reference->ref_sdl_length, reference->ref_sdl_ident);
|
|
if (!sw_raw)
|
|
if (PRETTY_print_sdl(reference->ref_sdl, gen_blr, 0, 0))
|
|
IBERROR("internal error during SDL generation");
|
|
|
|
printa(names[COMMENT], false, " ");
|
|
printa(names[COMMENT], false,
|
|
"END OF SDL STRING FOR %s%d */\n", names[ISC_],
|
|
reference->ref_sdl_ident);
|
|
}
|
|
}
|
|
|
|
// Print out any blob parameter blocks required
|
|
for (blob = request->req_blobs; blob; blob = blob->blb_next)
|
|
if (blob->blb_const_from_type || blob->blb_const_to_type) {
|
|
printa(names[COLUMN_0], false, "01 %s%d.",
|
|
names[ISC_], blob->blb_bpb_ident);
|
|
gen_raw(blob->blb_bpb, request->req_type, blob->blb_bpb_length,
|
|
(int) request);
|
|
printa(names[COMMENT], false, " ");
|
|
}
|
|
// If this is a GET_SLICE/PUT_slice, allocate some variables
|
|
|
|
if (request->req_type == REQ_slice) {
|
|
printa(names[COLUMN_0], false, "01 %s%dv.", names[isc_],
|
|
request->req_ident);
|
|
printa(names[COLUMN], false,
|
|
" 03 %s%dv_3 PIC S9(9) USAGE COMP OCCURS %d TIMES.",
|
|
names[isc_], request->req_ident, MAX(1,
|
|
request->req_slice->
|
|
slc_parameters));
|
|
printa(names[COLUMN_0], false, "01 %s%ds PIC S9(9) USAGE COMP.",
|
|
names[isc_], request->req_ident);
|
|
}
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate substitution text for END_STREAM.
|
|
//
|
|
|
|
static void gen_s_end( ACT action)
|
|
{
|
|
GPRE_REQ request;
|
|
|
|
request = action->act_request;
|
|
|
|
if (action->act_type == ACT_close)
|
|
gen_cursor_close(action, request);
|
|
|
|
printa(names[COLUMN], true,
|
|
"CALL \"%s\" USING %s, %s%s, %s%s%s",
|
|
ISC_UNWIND_REQUEST,
|
|
status_vector(action),
|
|
BY_REF, request->req_handle,
|
|
BY_VALUE, request->req_request_level, END_VALUE);
|
|
|
|
if (action->act_type == ACT_close) {
|
|
printa(names[COLUMN], false, "END-IF");
|
|
printa(names[COLUMN], false, "END-IF");
|
|
}
|
|
|
|
set_sqlcode(action);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate substitution text for FETCH.
|
|
//
|
|
|
|
static void gen_s_fetch( ACT action)
|
|
{
|
|
GPRE_REQ request;
|
|
|
|
request = action->act_request;
|
|
if (request->req_sync)
|
|
gen_send(action, request->req_sync);
|
|
|
|
gen_receive(action, request->req_primary);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate text to compile and start a stream. This is
|
|
// used both by START_STREAM and FOR
|
|
//
|
|
|
|
static void gen_s_start( ACT action)
|
|
{
|
|
GPRE_REQ request;
|
|
POR port;
|
|
|
|
request = action->act_request;
|
|
|
|
gen_compile(action);
|
|
|
|
if (port = request->req_vport)
|
|
asgn_from(action, port->por_references);
|
|
|
|
if (action->act_type == ACT_open)
|
|
gen_cursor_open(action, request);
|
|
|
|
// Do not call "gen_start" in case if "gen_compile" failed
|
|
|
|
if (action->act_error || (action->act_flags & ACT_sql)) {
|
|
if (sw_auto)
|
|
printa(names[COLUMN], false, "IF %s NOT = 0 AND %s NOT = 0 THEN",
|
|
request_trans(action, request), request->req_handle);
|
|
else
|
|
printa(names[COLUMN], false, "IF %s NOT = 0 THEN",
|
|
request->req_handle);
|
|
}
|
|
|
|
gen_start(action, port);
|
|
|
|
if (action->act_error || (action->act_flags & ACT_sql))
|
|
printa(names[COLUMN], false, "END-IF");
|
|
|
|
if (action->act_type == ACT_open) {
|
|
printa(names[COLUMN], false, "END-IF");
|
|
printa(names[COLUMN], false, "END-IF");
|
|
if (sw_auto)
|
|
printa(names[COLUMN], false, "END-IF");
|
|
printa(names[COLUMN], false, "END-IF");
|
|
set_sqlcode(action);
|
|
}
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate a send call for a port.
|
|
//
|
|
|
|
static void gen_send( ACT action, POR port)
|
|
{
|
|
GPRE_REQ request;
|
|
|
|
request = action->act_request;
|
|
|
|
sprintf(output_buffer,
|
|
"%sCALL \"%s\" USING %s, %s%s, %s%d%s, %s%d%s, %s%s%d, %s%s%s\n",
|
|
names[COLUMN],
|
|
ISC_SEND,
|
|
status_vector(action),
|
|
BY_REF, request->req_handle,
|
|
BY_VALUE, port->por_msg_number, END_VALUE,
|
|
BY_VALUE, port->por_length, END_VALUE,
|
|
BY_REF, names[ISC_], port->por_ident,
|
|
BY_VALUE, request->req_request_level, END_VALUE);
|
|
|
|
COB_print_buffer(output_buffer, TRUE);
|
|
set_sqlcode(action);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate support for get/put slice statement.
|
|
//
|
|
|
|
static void gen_slice( ACT action)
|
|
{
|
|
GPRE_REQ request, parent_request;
|
|
REF reference, upper, lower;
|
|
SLC slice;
|
|
USHORT column;
|
|
PAT args;
|
|
slc::slc_repeat *tail, *end;
|
|
TEXT *pattern1 =
|
|
"CALL \"%S7\" USING %V1, %RF%DH%RE, %RF%RT%RE, %RF%FR%RE, %VF%N1%VE, %RF%I1%RE, %VF%N2%VE, %RF%I1v%RE, %VF%I1s%VE, %RF%S5%RE, %RF%S6%RE";
|
|
TEXT *pattern2 =
|
|
"CALL \"%S7\" USING %V1, %RF%DH%RE, %RF%RT%RE, %RF%FR%RE, %VF%N1%VE, %RF%I1%RE, %VF%N2%VE, %RF%I1v%RE, %VF%I1s%VE, %RF%S5%RE";
|
|
|
|
column = strlen(names[COLUMN]);
|
|
request = action->act_request;
|
|
slice = (SLC) action->act_object;
|
|
parent_request = slice->slc_parent_request;
|
|
|
|
// Compute array size
|
|
|
|
ib_fprintf(out_file, " COMPUTE %s%ds = %d",
|
|
names[isc_],
|
|
request->req_ident, slice->slc_field->fld_array->fld_length);
|
|
|
|
for (tail = slice->slc_rpt, end = tail + slice->slc_dimensions;
|
|
tail < end; ++tail)
|
|
if (tail->slc_upper != tail->slc_lower) {
|
|
lower = (REF) tail->slc_lower->nod_arg[0];
|
|
upper = (REF) tail->slc_upper->nod_arg[0];
|
|
if (lower->ref_value)
|
|
ib_fprintf(out_file, " * ( %s - %s + 1)", upper->ref_value,
|
|
lower->ref_value);
|
|
else
|
|
ib_fprintf(out_file, " * ( %s + 1)", upper->ref_value);
|
|
}
|
|
ib_fprintf(out_file, "\n");
|
|
|
|
// Make assignments to variable vector
|
|
|
|
for (reference = request->req_values; reference;
|
|
reference = reference->ref_next)
|
|
{
|
|
printa(names[COLUMN], false, "MOVE %s TO %s%dv (%d)",
|
|
reference->ref_value, names[ISC_],
|
|
request->req_ident, reference->ref_id);
|
|
}
|
|
|
|
args.pat_reference = slice->slc_field_ref;
|
|
args.pat_request = parent_request; /* blob id request */
|
|
args.pat_vector1 = status_vector(action); /* status vector */
|
|
args.pat_database = parent_request->req_database; /* database handle */
|
|
args.pat_string1 = action->act_request->req_trans; /* transaction handle */
|
|
args.pat_value1 = request->req_length; /* slice descr. length */
|
|
args.pat_ident1 = request->req_ident; /* request name */
|
|
args.pat_value2 = slice->slc_parameters * sizeof(SLONG); /* parameter length */
|
|
|
|
reference = (REF) slice->slc_array->nod_arg[0];
|
|
args.pat_string5 = reference->ref_value; /* array name */
|
|
args.pat_string6 = names[ISC_ARRAY_LENGTH];
|
|
args.pat_string7 =
|
|
(action->act_type == ACT_get_slice) ? (TEXT*) ISC_GET_SLICE : (TEXT*) ISC_PUT_SLICE;
|
|
|
|
PATTERN_expand(column,
|
|
(action->act_type == ACT_get_slice) ? pattern1 : pattern2,
|
|
&args);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Substitute for a segment, segment length, or blob handle.
|
|
//
|
|
|
|
static void gen_segment( ACT action)
|
|
{
|
|
BLB blob;
|
|
|
|
blob = (BLB) action->act_object;
|
|
|
|
ib_fprintf(out_file, "%s%d",
|
|
names[ISC_],
|
|
(action->act_type == ACT_segment) ? blob->blb_buff_ident :
|
|
(action->act_type ==
|
|
ACT_segment_length) ? blob->blb_len_ident : blob->blb_ident);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
//
|
|
|
|
static void gen_select( ACT action)
|
|
{
|
|
GPRE_REQ request;
|
|
POR port;
|
|
GPRE_NOD var_list;
|
|
int i;
|
|
TEXT name[20];
|
|
|
|
request = action->act_request;
|
|
port = request->req_primary;
|
|
gen_name(name, request->req_eof, true);
|
|
|
|
gen_s_start(action);
|
|
|
|
// BUG8321: Do not call "receive" in case if SQLCODE is not equal 0
|
|
printa(names[COLUMN], false, "IF SQLCODE = 0 THEN");
|
|
|
|
gen_receive(action, port);
|
|
|
|
printa(names[COLUMN], false, "IF %s NOT = 0 THEN", name);
|
|
if (var_list = (GPRE_NOD) action->act_object)
|
|
for (i = 0; i < var_list->nod_count; i++) {
|
|
asgn_to(action, (REF) var_list->nod_arg[i]);
|
|
}
|
|
|
|
if (request->req_database->dbb_flags & DBB_v3) {
|
|
gen_receive(action, port);
|
|
printa(names[COLUMN], false, "IF %s NOT = 0 THEN", name);
|
|
printa(names[COLUMN], false, "MOVE -1 TO SQLCODE");
|
|
printa(names[COLUMN], false, "ELSE");
|
|
printa(names[COLUMN], false, "MOVE 0 TO SQLCODE");
|
|
printa(names[COLUMN], false, "END-IF");
|
|
}
|
|
|
|
printa(names[COLUMN], false, "ELSE");
|
|
printa(names[COLUMN], false, "MOVE 100 TO SQLCODE");
|
|
printa(names[COLUMN], false, "END-IF");
|
|
printa(names[COLUMN], false, "END-IF");
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate either a START or START_AND_SEND depending
|
|
// on whether or a not a port is present.
|
|
//
|
|
|
|
static void gen_start( ACT action, POR port)
|
|
{
|
|
GPRE_REQ request;
|
|
TEXT *vector;
|
|
REF reference;
|
|
|
|
request = action->act_request;
|
|
vector = status_vector(action);
|
|
|
|
if (port) {
|
|
for (reference = port->por_references; reference;
|
|
reference = reference->ref_next)
|
|
{
|
|
if (reference->ref_field->fld_array_info)
|
|
gen_get_or_put_slice(action, reference, false);
|
|
}
|
|
|
|
sprintf(output_buffer,
|
|
"%sCALL \"%s\" USING %s, %s%s, %s%s, %s%d%s, %s%d%s, %s%s%d, %s%s%s\n",
|
|
names[COLUMN],
|
|
ISC_START_AND_SEND,
|
|
vector,
|
|
BY_REF, request->req_handle,
|
|
BY_REF, request_trans(action, request),
|
|
BY_VALUE, port->por_msg_number, END_VALUE,
|
|
BY_VALUE, port->por_length, END_VALUE,
|
|
BY_REF, names[ISC_], port->por_ident,
|
|
BY_VALUE, request->req_request_level, END_VALUE);
|
|
}
|
|
else
|
|
sprintf(output_buffer,
|
|
"%sCALL \"%s\" USING %s, %s%s, %s%s, %s%s%s\n",
|
|
names[COLUMN],
|
|
ISC_START_REQUEST,
|
|
vector,
|
|
BY_REF, request->req_handle,
|
|
BY_REF, request_trans(action, request),
|
|
BY_VALUE, request->req_request_level, END_VALUE);
|
|
|
|
COB_print_buffer(output_buffer, TRUE);
|
|
|
|
set_sqlcode(action);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate text for STORE statement. This includes the compile
|
|
// call and any variable initialization required.
|
|
//
|
|
|
|
static void gen_store( ACT action)
|
|
{
|
|
GPRE_REQ request;
|
|
REF reference;
|
|
GPRE_FLD field;
|
|
POR port;
|
|
TEXT name[64];
|
|
|
|
request = action->act_request;
|
|
gen_compile(action);
|
|
|
|
// Initialize any blob fields
|
|
|
|
port = request->req_primary;
|
|
for (reference = port->por_references; reference;
|
|
reference = reference->ref_next) {
|
|
field = reference->ref_field;
|
|
if (field->fld_flags & FLD_blob)
|
|
printa(names[COLUMN], true, "CALL \"isc_qtoq\" USING %s, %s",
|
|
names[isc_blob_null], gen_name(name, reference, true));
|
|
}
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate substitution text for START_TRANSACTION.
|
|
//
|
|
|
|
static void gen_t_start( ACT action)
|
|
{
|
|
DBB db;
|
|
GPRE_TRA trans;
|
|
tpb* tpb_iterator;
|
|
TEXT *filename, dbname[80];
|
|
USHORT namelength;
|
|
|
|
// if this is a purely default transaction, just let it through
|
|
|
|
if (!action || !(trans = (GPRE_TRA) action->act_object)) {
|
|
t_start_auto(0, status_vector(action), action, false);
|
|
return;
|
|
}
|
|
|
|
// build a complete statement, including tpb's. Ready db's as gpre_req.
|
|
|
|
if (sw_auto)
|
|
for (tpb_iterator = trans->tra_tpb;
|
|
tpb_iterator;
|
|
tpb_iterator = tpb_iterator->tpb_tra_next)
|
|
{
|
|
db = tpb_iterator->tpb_database;
|
|
if ((filename = db->dbb_runtime) || !(db->dbb_flags & DBB_sqlca)) {
|
|
printa(names[COLUMN], false, "IF %s = 0 THEN",
|
|
db->dbb_name->sym_string);
|
|
namelength = filename ? strlen(filename) : 0;
|
|
#ifndef VMS
|
|
if (filename) {
|
|
sprintf(dbname, "isc-%ddb", db->dbb_id);
|
|
filename = dbname;
|
|
}
|
|
#endif
|
|
make_ready(db, filename, status_vector(action), 0,
|
|
namelength);
|
|
set_sqlcode(action);
|
|
printa(names[COLUMN], false, "END-IF");
|
|
}
|
|
}
|
|
|
|
printa(names[COLUMN], true,
|
|
"CALL \"%s\" USING %s, %s%s, %s%d%s",
|
|
ISC_START_TRANSACTION,
|
|
status_vector(action),
|
|
BY_REF, (trans->tra_handle) ? trans->tra_handle : names[ISC_TRANS],
|
|
BY_VALUE, trans->tra_db_count, END_VALUE);
|
|
|
|
for (tpb_iterator = trans->tra_tpb;
|
|
tpb_iterator;
|
|
tpb_iterator = tpb_iterator->tpb_tra_next)
|
|
{
|
|
printa(names[CONTINUE], true, ", %s%s, %s%d%s, %s%s%d",
|
|
BY_REF, tpb_iterator->tpb_database->dbb_name->sym_string,
|
|
BY_VALUE, tpb_iterator->tpb_length, END_VALUE,
|
|
BY_REF, names[ISC_TPB_], tpb_iterator->tpb_ident);
|
|
}
|
|
|
|
set_sqlcode(action);
|
|
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Initialize a TPB in the output file
|
|
//
|
|
|
|
static void gen_tpb(tpb* tpb_buffer)
|
|
{
|
|
UCHAR *text, *c;
|
|
int length, char_len;
|
|
union {
|
|
#ifdef VMS
|
|
SCHAR bytewise_tpb[4];
|
|
#else
|
|
UCHAR bytewise_tpb[4];
|
|
#endif
|
|
SLONG longword_tpb;
|
|
} tpb_hunk;
|
|
|
|
//
|
|
// TPBs are generated as raw BLR in longword chunks
|
|
// because COBOL is a miserable excuse for a language
|
|
// and doesn't allow byte value assignments to character
|
|
// fields.
|
|
//
|
|
|
|
printa(names[COLUMN_0], false, "01 %s%d.",
|
|
names[ISC_TPB_], tpb_buffer->tpb_ident);
|
|
|
|
text = tpb_buffer->tpb_string;
|
|
char_len = tpb_buffer->tpb_length;
|
|
length = 1;
|
|
|
|
while (char_len) {
|
|
for (c = tpb_hunk.bytewise_tpb;
|
|
c < tpb_hunk.bytewise_tpb + sizeof(SLONG); c++) {
|
|
*c = *text++;
|
|
if (!(--char_len))
|
|
break;
|
|
}
|
|
|
|
printa(names[COLUMN], false, RAW_TPB_TEMPLATE,
|
|
names[ISC_TPB_], tpb_buffer->tpb_ident,
|
|
names[UNDER], length++, tpb_hunk.longword_tpb);
|
|
}
|
|
|
|
sprintf(output_buffer, "%sEnd of data for %s%d\n",
|
|
names[COMMENT], names[ISC_TPB_], tpb_buffer->tpb_ident);
|
|
COB_print_buffer(output_buffer, FALSE);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate substitution text for COMMIT, ROLLBACK, PREPARE, and SAVE
|
|
//
|
|
|
|
static void gen_trans( ACT action)
|
|
{
|
|
|
|
if (action->act_type == ACT_commit_retain_context)
|
|
printa(names[COLUMN], true, "CALL \"%s\" USING %s, %s%s",
|
|
ISC_COMMIT_RETAINING,
|
|
status_vector(action),
|
|
BY_REF,
|
|
(action->act_object) ? (TEXT *) (action->
|
|
act_object) :
|
|
names[ISC_TRANS]);
|
|
else
|
|
printa(names[COLUMN], true, "CALL \"%s\" USING %s, %s%s",
|
|
(action->act_type ==
|
|
ACT_commit) ? ISC_COMMIT_TRANSACTION : (action->act_type ==
|
|
ACT_rollback) ?
|
|
ISC_ROLLBACK_TRANSACTION : ISC_PREPARE_TRANSACTION,
|
|
status_vector(action), BY_REF,
|
|
(action->act_object) ? (TEXT *) (action->
|
|
act_object) :
|
|
names[ISC_TRANS]);
|
|
set_sqlcode(action);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Substitute for a variable reference.
|
|
//
|
|
|
|
static void gen_type( ACT action)
|
|
{
|
|
|
|
printa(names[COLUMN], true, "%ld", (SLONG) action->act_object);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate substitution text for UPDATE ... WHERE CURRENT OF ...
|
|
//
|
|
|
|
static void gen_update( ACT action)
|
|
{
|
|
POR port;
|
|
UPD modify;
|
|
|
|
modify = (UPD) action->act_object;
|
|
port = modify->upd_port;
|
|
asgn_from(action, port->por_references);
|
|
gen_send(action, port);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Substitute for a variable reference.
|
|
//
|
|
|
|
static void gen_variable( ACT action)
|
|
{
|
|
TEXT s[20];
|
|
REF reference;
|
|
|
|
reference = action->act_object;
|
|
ib_fprintf(out_file, "\n%s%s",
|
|
names[COLUMN], gen_name(s, reference, false));
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate tests for any WHENEVER clauses that may have been declared.
|
|
//
|
|
|
|
static void gen_whenever( SWE label)
|
|
{
|
|
TEXT *condition;
|
|
|
|
while (label) {
|
|
switch (label->swe_condition) {
|
|
case SWE_error:
|
|
condition = "SQLCODE < 0";
|
|
break;
|
|
|
|
case SWE_warning:
|
|
condition = "SQLCODE > 0 AND SQLCODE NOT = 100";
|
|
break;
|
|
|
|
case SWE_not_found:
|
|
condition = "SQLCODE = 100";
|
|
break;
|
|
}
|
|
ib_fprintf(out_file, "%sIF (%s) THEN GO TO %s",
|
|
names[COLUMN], condition, label->swe_label);
|
|
if (label->swe_condition == SWE_warning)
|
|
ib_fprintf(out_file, "\n%s", names[COLUMN_INDENT]);
|
|
label = label->swe_next;
|
|
ib_fprintf(out_file, " END-IF%s", (label) ? ".\n" : "");
|
|
}
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate a declaration of an array in the
|
|
// output file.
|
|
//
|
|
|
|
static void make_array_declaration( REF reference)
|
|
{
|
|
GPRE_FLD field;
|
|
TEXT *name, space[128], string1[256], *p;
|
|
DIM dimension;
|
|
int i, dimension_size;
|
|
SSHORT digits, scale;
|
|
|
|
field = reference->ref_field;
|
|
name = field->fld_symbol->sym_string;
|
|
|
|
// Don't generate multiple declarations for the array. V3 Bug 569.
|
|
|
|
if (field->fld_array_info->ary_declared)
|
|
return;
|
|
|
|
field->fld_array_info->ary_declared = true;
|
|
|
|
ib_fprintf(out_file, "%s01 %s%dL.\n",
|
|
names[COLUMN_0], names[ISC_],
|
|
field->fld_array_info->ary_ident);
|
|
strcpy(space, " ");
|
|
|
|
// Print out the dimension part of the declaration
|
|
for (dimension = field->fld_array_info->ary_dimension, i = 3;
|
|
dimension->dim_next; dimension = dimension->dim_next, i += 2) {
|
|
dimension_size = dimension->dim_upper - dimension->dim_lower + 1;
|
|
printa(space, false, "%02d %s%d%s%d OCCURS %d TIMES.",
|
|
i, names[ISC_], field->fld_array_info->ary_ident,
|
|
names[UNDER], i, dimension_size);
|
|
strcat(space, " ");
|
|
}
|
|
|
|
p = string1;
|
|
dimension_size = dimension->dim_upper - dimension->dim_lower + 1;
|
|
sprintf(p, "%02d %s%d OCCURS %d TIMES ",
|
|
i, names[ISC_], field->fld_array_info->ary_ident, dimension_size);
|
|
while (*p)
|
|
p++;
|
|
|
|
switch (field->fld_array_info->ary_dtype) {
|
|
case dtype_short:
|
|
case dtype_long:
|
|
digits = (field->fld_array_info->ary_dtype == dtype_short) ? 4 : 9;
|
|
scale = field->fld_array->fld_scale;
|
|
strcpy(p, "PIC S");
|
|
while (*p)
|
|
p++;
|
|
if (scale >= -digits && scale <= 0) {
|
|
if (scale > -digits)
|
|
sprintf(p, "9(%d)", digits + scale);
|
|
while (*p)
|
|
p++;
|
|
if (scale)
|
|
sprintf(p, "V9(%d)", digits - (digits + scale));
|
|
}
|
|
else if (scale > 0)
|
|
sprintf(p, "9(%d)P(%d)", digits, scale);
|
|
else
|
|
sprintf(p, "VP(%d)9(%d)", -(scale + digits), digits);
|
|
while (*p)
|
|
p++;
|
|
strcpy(p, USAGE_COMP);
|
|
strcat(p, ".");
|
|
break;
|
|
|
|
case dtype_cstring:
|
|
case dtype_text:
|
|
case dtype_varying:
|
|
sprintf(p, "PIC X(%d).", field->fld_array->fld_length);
|
|
break;
|
|
|
|
case dtype_date:
|
|
strcpy(p, "PIC S9(18)");
|
|
strcat(p, USAGE_COMP);
|
|
strcat(p, ".");
|
|
break;
|
|
|
|
case dtype_quad:
|
|
sprintf(p, "PIC S9(%d)", 18 + field->fld_array->fld_scale);
|
|
while (*p)
|
|
p++;
|
|
if (field->fld_array->fld_scale < 0)
|
|
sprintf(p, "V9(%d)", -field->fld_array->fld_scale);
|
|
else if (field->fld_array->fld_scale > 0)
|
|
sprintf(p, "P(%d)", field->fld_array->fld_scale);
|
|
while (*p)
|
|
p++;
|
|
strcpy(p, USAGE_COMP);
|
|
strcat(p, ".");
|
|
break;
|
|
|
|
case dtype_float:
|
|
strcpy(p, DCL_FLOAT);
|
|
strcat(p, ".");
|
|
break;
|
|
|
|
case dtype_double:
|
|
strcpy(p, DCL_DOUBLE);
|
|
strcat(p, ".");
|
|
break;
|
|
|
|
default:
|
|
sprintf(space, "datatype %d unknown for field %s",
|
|
field->fld_array_info->ary_dtype, name);
|
|
IBERROR(space);
|
|
return;
|
|
}
|
|
|
|
printa(space, false, string1);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Turn a symbol into a varying string.
|
|
//
|
|
|
|
static TEXT *make_name( TEXT * string, SYM symbol)
|
|
{
|
|
|
|
#ifndef VMS
|
|
sprintf(string, "%s", symbol->sym_string);
|
|
while (*string) {
|
|
if (*string == '_')
|
|
*string = '-';
|
|
string++;
|
|
}
|
|
#else
|
|
sprintf(string, "'%s '", symbol->sym_string);
|
|
#endif
|
|
|
|
return string;
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Turn a symbol into a varying string.
|
|
//
|
|
|
|
static TEXT *make_name_formatted( TEXT * string, TEXT * format, SYM symbol)
|
|
{
|
|
TEXT *s;
|
|
|
|
sprintf(string, format, symbol->sym_string);
|
|
for (s = string; *s; s++)
|
|
if (*s == '_')
|
|
*s = '-';
|
|
|
|
return string;
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Insert a port record description in output.
|
|
//
|
|
|
|
static void make_port( POR port)
|
|
{
|
|
GPRE_FLD field;
|
|
REF reference;
|
|
SYM symbol;
|
|
TEXT *name, s[80];
|
|
SSHORT digits;
|
|
|
|
printa(names[COLUMN_0], false, "01 %s%d.", names[ISC_], port->por_ident);
|
|
|
|
for (reference = port->por_references; reference;
|
|
reference = reference->ref_next) {
|
|
field = reference->ref_field;
|
|
if (symbol = field->fld_symbol)
|
|
name = symbol->sym_string;
|
|
else
|
|
name = "<expression>";
|
|
if (reference->ref_value && (reference->ref_flags & REF_array_elem))
|
|
field = field->fld_array;
|
|
switch (field->fld_dtype) {
|
|
case dtype_short:
|
|
case dtype_long:
|
|
digits = (field->fld_dtype == dtype_short) ? 4 : 9;
|
|
ib_fprintf(out_file, "%s03 %s%d PIC S",
|
|
names[COLUMN], names[ISC_], reference->ref_ident);
|
|
if (field->fld_scale >= -digits && field->fld_scale <= 0) {
|
|
if (field->fld_scale > -digits)
|
|
ib_fprintf(out_file, "9(%d)", digits + field->fld_scale);
|
|
if (field->fld_scale)
|
|
ib_fprintf(out_file, "V9(%d)",
|
|
digits - (digits + field->fld_scale));
|
|
}
|
|
else if (field->fld_scale > 0)
|
|
ib_fprintf(out_file, "9(%d)P(%d)", digits, field->fld_scale);
|
|
else
|
|
ib_fprintf(out_file, "VP(%d)9(%d)",
|
|
-(field->fld_scale + digits), digits);
|
|
ib_fprintf(out_file, "%s.\n", USAGE_COMP);
|
|
break;
|
|
|
|
case dtype_cstring:
|
|
case dtype_text:
|
|
printa(names[COLUMN], false, "03 %s%d PIC X(%d).",
|
|
names[ISC_], reference->ref_ident, field->fld_length);
|
|
break;
|
|
|
|
case dtype_date:
|
|
case dtype_quad:
|
|
case dtype_blob:
|
|
ib_fprintf(out_file, "%s03 %s%d PIC S9(",
|
|
names[COLUMN], names[ISC_], reference->ref_ident);
|
|
ib_fprintf(out_file, "%d)", 18 + field->fld_scale);
|
|
if (field->fld_scale < 0)
|
|
ib_fprintf(out_file, "V9(%d)", -field->fld_scale);
|
|
else if (field->fld_scale > 0)
|
|
ib_fprintf(out_file, "P(%d)", field->fld_scale);
|
|
ib_fprintf(out_file, "%s.\n", USAGE_COMP);
|
|
break;
|
|
|
|
case dtype_float:
|
|
printa(names[COLUMN], false, "03 %s%d %s.",
|
|
names[ISC_], reference->ref_ident, DCL_FLOAT);
|
|
break;
|
|
|
|
case dtype_double:
|
|
printa(names[COLUMN], false, "03 %s%d %s.",
|
|
names[ISC_], reference->ref_ident, DCL_DOUBLE);
|
|
break;
|
|
|
|
default:
|
|
sprintf(s, "datatype %d unknown for field %s, msg %d",
|
|
field->fld_dtype, name, port->por_msg_number);
|
|
CPR_error(s);
|
|
return;
|
|
}
|
|
}
|
|
|
|
printa(names[COLUMN], false, " ");
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate the actual ready call.
|
|
//
|
|
|
|
static void make_ready(
|
|
DBB db,
|
|
TEXT * filename,
|
|
TEXT * vector, GPRE_REQ request, USHORT namelength)
|
|
{
|
|
TEXT s1[32], s1Tmp[32], s2[32], s2Tmp[32], dbname[128];
|
|
DBB dbisc = (DBB) db->dbb_name->sym_object;
|
|
|
|
if (request) {
|
|
sprintf(s1, "%s%dL", names[isc_], request->req_ident);
|
|
if (request->req_flags & REQ_extend_dpb)
|
|
sprintf(s2, "%s%dp", names[isc_], request->req_ident);
|
|
else
|
|
sprintf(s2, "%s%d", names[isc_], request->req_ident);
|
|
|
|
/* if the dpb needs to be extended at runtime to include items
|
|
in host variables, do so here; this assumes that there is
|
|
always a request generated for runtime variables */
|
|
|
|
if (request->req_flags & REQ_extend_dpb) {
|
|
if (request->req_length) {
|
|
sprintf(output_buffer, "%sMOVE isc_%d to %s\n",
|
|
names[COLUMN], request->req_ident, s2);
|
|
|
|
}
|
|
if (db->dbb_r_user) {
|
|
sprintf(output_buffer,
|
|
"%sCALL \"%s\" USING %s%s, %s%s, BY VALUE 28, %s %s, %s%d%s\n",
|
|
names[COLUMN],
|
|
ISC_MODIFY_DPB,
|
|
BY_REF, s2,
|
|
BY_REF, s1,
|
|
BY_DESC, db->dbb_r_user,
|
|
BY_VALUE, strlen(db->dbb_r_user) - 2, END_VALUE);
|
|
COB_print_buffer(output_buffer, TRUE);
|
|
}
|
|
if (db->dbb_r_password) {
|
|
sprintf(output_buffer,
|
|
"%sCALL \"%s\" USING %s%s, %s%s, BY VALUE 29, %s %s, %s%d%s\n",
|
|
names[COLUMN],
|
|
ISC_MODIFY_DPB,
|
|
BY_REF, s2,
|
|
BY_REF, s1,
|
|
BY_DESC, db->dbb_r_password,
|
|
BY_VALUE, strlen(db->dbb_r_password) - 2, END_VALUE);
|
|
COB_print_buffer(output_buffer, TRUE);
|
|
}
|
|
|
|
/*
|
|
** ==================================================
|
|
** ==
|
|
** == Process Role Name, isc_dpb_sql_role_name/60
|
|
** ==
|
|
** ==================================================
|
|
*/
|
|
|
|
if (db->dbb_r_sql_role) {
|
|
sprintf(output_buffer,
|
|
"%sCALL \"%s\" USING %s%s, %s%s, BY VALUE 60, %s %s, %s%d%s\n",
|
|
names[COLUMN],
|
|
ISC_MODIFY_DPB,
|
|
BY_REF, s2,
|
|
BY_REF, s1,
|
|
BY_DESC, db->dbb_r_sql_role,
|
|
BY_VALUE, strlen(db->dbb_r_sql_role) - 2, END_VALUE);
|
|
COB_print_buffer(output_buffer, TRUE);
|
|
}
|
|
|
|
if (db->dbb_r_lc_messages) {
|
|
sprintf(output_buffer,
|
|
"%sCALL \"%s\" USING %s%s, %s%s, BY VALUE 47, %s %s, %s%d%s\n",
|
|
names[COLUMN],
|
|
ISC_MODIFY_DPB,
|
|
BY_REF, s2,
|
|
BY_REF, s1,
|
|
BY_REF, db->dbb_r_lc_messages,
|
|
BY_VALUE, strlen(db->dbb_r_lc_messages) - 2,
|
|
END_VALUE);
|
|
COB_print_buffer(output_buffer, TRUE);
|
|
}
|
|
if (db->dbb_r_lc_ctype) {
|
|
sprintf(output_buffer,
|
|
"%sCALL \"%s\" USING %s%s %s%s, BY VALUE 48, %s %s, %s%d%s\n",
|
|
names[COLUMN],
|
|
ISC_MODIFY_DPB,
|
|
BY_REF, s2,
|
|
BY_REF, s1,
|
|
BY_REF, db->dbb_r_lc_ctype,
|
|
BY_VALUE, strlen(db->dbb_r_lc_ctype) - 2, END_VALUE);
|
|
COB_print_buffer(output_buffer, TRUE);
|
|
}
|
|
}
|
|
|
|
if (request->req_flags & REQ_extend_dpb) {
|
|
sprintf(s1Tmp, "%s%s%s", BY_VALUE, s1, END_VALUE);
|
|
sprintf(s2Tmp, "%s%s%s", BY_VALUE, s2, END_VALUE);
|
|
}
|
|
else {
|
|
sprintf(s2Tmp, "%s%s", BY_REF, s2);
|
|
sprintf(s1Tmp, "%s%d%s", BY_VALUE, request->req_length,
|
|
END_VALUE);
|
|
}
|
|
}
|
|
|
|
#ifdef VMS
|
|
|
|
if (filename) {
|
|
sprintf(output_buffer,
|
|
"%sCALL \"%s\" USING %s, %s%s, %s%s, %s, %s\n",
|
|
names[COLUMN],
|
|
ISC_ATTACH_DATABASE_D,
|
|
vector,
|
|
BY_DESC, filename,
|
|
BY_REF, db->dbb_name->sym_string,
|
|
request ? s1Tmp : OMITTED, request ? s2Tmp : OMITTED);
|
|
}
|
|
else {
|
|
sprintf(output_buffer,
|
|
"%sCALL \"%s\" USING %s, %s%d%s, %s \"%s\", %s%s, %s, %s\n",
|
|
names[COLUMN],
|
|
ISC_ATTACH_DATABASE,
|
|
vector,
|
|
BY_VALUE, strlen(db->dbb_filename), END_VALUE,
|
|
BY_REF, db->dbb_filename,
|
|
BY_REF, db->dbb_name->sym_string,
|
|
request ? s1Tmp : OMITTED, request ? s2Tmp : OMITTED);
|
|
}
|
|
|
|
#else
|
|
|
|
if (!filename) {
|
|
sprintf(dbname, "%s%ddb", names[isc_], dbisc->dbb_id);
|
|
filename = dbname;
|
|
namelength = strlen(db->dbb_filename);
|
|
|
|
}
|
|
sprintf(output_buffer,
|
|
"%sCALL \"%s\" USING %s, %s%d%s, %s %s, %s%s, %s, %s\n",
|
|
names[COLUMN],
|
|
ISC_ATTACH_DATABASE,
|
|
vector,
|
|
BY_VALUE, namelength, END_VALUE,
|
|
BY_REF, filename,
|
|
BY_REF, db->dbb_name->sym_string,
|
|
request ? s1Tmp : OMITTED, request ? s2Tmp : OMITTED);
|
|
|
|
#endif
|
|
|
|
COB_print_buffer(output_buffer, TRUE);
|
|
|
|
// if the dpb was extended, free it here
|
|
|
|
if (request && request->req_flags & REQ_extend_dpb) {
|
|
if (request->req_length) {
|
|
sprintf(output_buffer,
|
|
"if (%s != isc_%d)", s2, request->req_ident);
|
|
COB_print_buffer(output_buffer, TRUE);
|
|
}
|
|
|
|
sprintf(output_buffer,
|
|
"%sCALL \"%s\" USING %s\n", names[COLUMN], ISC_FREE, s2Tmp);
|
|
COB_print_buffer(output_buffer, TRUE);
|
|
|
|
/* reset the length of the dpb */
|
|
sprintf(output_buffer, "%sMOVE %d to %s\n",
|
|
names[COLUMN], request->req_length, s1);
|
|
COB_print_buffer(output_buffer, TRUE);
|
|
}
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Print a fixed string at a particular COLUMN.
|
|
//
|
|
|
|
static void printa(TEXT * column,
|
|
bool call,
|
|
TEXT * string,
|
|
...)
|
|
{
|
|
va_list ptr;
|
|
TEXT s[256];
|
|
|
|
VA_START(ptr, string);
|
|
strcpy(s, column);
|
|
strcat(s, string);
|
|
strcat(s, "\n");
|
|
vsprintf(output_buffer, s, ptr);
|
|
COB_print_buffer(output_buffer, call);
|
|
}
|
|
|
|
|
|
#ifdef NOT_USED_OR_REPLACED
|
|
//____________________________________________________________
|
|
//
|
|
// Print a fixed string at a particular column.
|
|
//
|
|
|
|
static void printb( TEXT * string, ...)
|
|
{
|
|
va_list ptr;
|
|
|
|
VA_START(ptr, string);
|
|
ib_vfprintf(out_file, string, ptr);
|
|
}
|
|
#endif
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate the appropriate transaction handle.
|
|
//
|
|
|
|
static TEXT *request_trans( ACT action, GPRE_REQ request)
|
|
{
|
|
TEXT *trname;
|
|
|
|
if (action->act_type == ACT_open) {
|
|
if (!(trname = ((OPN) action->act_object)->opn_trans))
|
|
trname = names[ISC_TRANS];
|
|
return trname;
|
|
}
|
|
else
|
|
return (request) ? request->req_trans : names[ISC_TRANS];
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// generate a CALL to the appropriate SQLCODE routine.
|
|
// Note that not all COBOLs have the concept of a function.
|
|
|
|
static void set_sqlcode( ACT action)
|
|
{
|
|
TEXT buffer[128];
|
|
|
|
#ifdef GIVING_SUPPORTED
|
|
#define SQLCODE_CALL_TEMPLATE "CALL \"%s\" USING %s GIVING SQLCODE"
|
|
#else
|
|
#define SQLCODE_CALL_TEMPLATE "CALL \"%s\" USING %s, BY REFERENCE SQLCODE"
|
|
#endif
|
|
|
|
if (action && action->act_flags & ACT_sql) {
|
|
strcpy(buffer, SQLCODE_CALL_TEMPLATE);
|
|
printa(names[COLUMN], true,
|
|
buffer, ISC_SQLCODE_CALL, names[ISC_STATUS_VECTOR]);
|
|
}
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate the appropriate status vector parameter for a gds
|
|
// call depending on where or not the action has an error clause.
|
|
//
|
|
|
|
static TEXT *status_vector( ACT action)
|
|
{
|
|
|
|
if (action && (action->act_error || (action->act_flags & ACT_sql)))
|
|
return names[ISC_STATUS_VECTOR];
|
|
|
|
return (OMITTED);
|
|
}
|
|
|
|
|
|
//____________________________________________________________
|
|
//
|
|
// Generate substitution text for START_TRANSACTION,
|
|
// when it's being generated automatically by a compile
|
|
// call.
|
|
//
|
|
|
|
static void t_start_auto(GPRE_REQ request,
|
|
TEXT * vector,
|
|
ACT action,
|
|
bool test)
|
|
{
|
|
DBB db;
|
|
int count, stat;
|
|
USHORT namelength;
|
|
TEXT *filename, dbname[80], *col, buffer[256], temp[40], *trname;
|
|
|
|
trname = request_trans(action, request);
|
|
|
|
// find out whether we're using a status vector or not
|
|
|
|
stat = !strcmp(vector, names[ISC_STATUS_VECTOR]);
|
|
|
|
// this is a default transaction, make sure all databases are ready
|
|
|
|
if (sw_auto) {
|
|
buffer[0] = 0;
|
|
for (count = 0, db = isc_databases; db; db = db->dbb_next, count++)
|
|
if ((filename = db->dbb_runtime) || !(db->dbb_flags & DBB_sqlca)) {
|
|
ib_fprintf(out_file, "%sIF %s = 0", names[COLUMN],
|
|
db->dbb_name->sym_string);
|
|
if (stat && buffer[0])
|
|
ib_fprintf(out_file, " AND %s(2) = 0", names[ISC_STATUS]);
|
|
ib_fprintf(out_file, " THEN\n");
|
|
namelength = filename ? strlen(filename) : 0;
|
|
#ifndef VMS
|
|
if (filename) {
|
|
sprintf(dbname, "isc-%ddb", db->dbb_id);
|
|
filename = dbname;
|
|
}
|
|
#endif
|
|
make_ready(db, filename, vector, 0, namelength);
|
|
printa(names[COLUMN], false, "END-IF");
|
|
if (buffer[0])
|
|
strcat(buffer, ") AND (");
|
|
sprintf(temp, "%s NOT = 0", db->dbb_name->sym_string);
|
|
strcat(buffer, temp);
|
|
}
|
|
if (test)
|
|
if (buffer[0])
|
|
printa(names[COLUMN], false, "IF (%s) AND %s = 0 THEN",
|
|
buffer, trname);
|
|
|
|
else
|
|
printa(names[COLUMN], false, "IF %s = 0 THEN", trname);
|
|
else if (buffer[0])
|
|
printa(names[COLUMN], false, "IF (%s) THEN", buffer);
|
|
}
|
|
else
|
|
for (count = 0, db = isc_databases; db; db = db->dbb_next, count++);
|
|
|
|
col = (stat) ? names[COLUMN_INDENT] : names[COLUMN];
|
|
|
|
printa(col, true, "CALL \"%s\" USING %s, %s%s, %s%d%s",
|
|
ISC_START_TRANSACTION, vector, BY_REF, trname,
|
|
BY_VALUE, count, END_VALUE);
|
|
|
|
for (db = isc_databases; db; db = db->dbb_next)
|
|
printa(names[CONTINUE], true, ", %s%s, %s, %s",
|
|
BY_REF, db->dbb_name->sym_string, OMITTED, OMITTED);
|
|
|
|
if (sw_auto && (test || buffer[0]))
|
|
printa(names[COLUMN], false, "END-IF");
|
|
|
|
|
|
set_sqlcode(action);
|
|
}
|