2001-05-23 15:26:42 +02:00
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// PROGRAM: C preprocess
|
|
|
|
// MODULE: c_cxx.cpp
|
|
|
|
// DESCRIPTION: C and C++ code 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): ______________________________________.
|
|
|
|
// TMN (Mike Nordell) 11.APR.2001 - Reduce compiler warnings
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
2002-09-24 14:57:10 +02:00
|
|
|
// $Id: c_cxx.cpp,v 1.6 2002-09-24 12:57:07 eku Exp $
|
2001-05-23 15:26:42 +02:00
|
|
|
//
|
|
|
|
|
2001-07-30 01:43:24 +02:00
|
|
|
#include "firebird.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/ib_stdio.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include "../jrd/common.h"
|
|
|
|
#include <stdarg.h>
|
2001-07-30 01:43:24 +02:00
|
|
|
#include "../jrd/gds.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "gpre.h"
|
|
|
|
#include "../gpre/form.h"
|
|
|
|
#include "../gpre/pat.h"
|
|
|
|
#include "../gpre/cmp_proto.h"
|
|
|
|
#include "../gpre/gpre_proto.h"
|
|
|
|
#include "../gpre/lang_proto.h"
|
|
|
|
#include "../gpre/pat_proto.h"
|
|
|
|
#include "../gpre/prett_proto.h"
|
|
|
|
#include "../jrd/gds_proto.h"
|
|
|
|
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
|
|
|
|
|
|
|
|
extern TEXT *transaction_name;
|
|
|
|
|
|
|
|
#if (defined JPN_EUC || defined JPN_SJIS)
|
|
|
|
extern SCHAR default_dpb[];
|
|
|
|
extern USHORT default_dpb_size;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static void align(int);
|
|
|
|
static void asgn_from(ACT, REF, int);
|
|
|
|
static void asgn_sqlda_from(REF, int, SCHAR *, int);
|
|
|
|
static void asgn_to(ACT, REF, int);
|
|
|
|
static void asgn_to_proc(REF, int);
|
|
|
|
static void gen_any(ACT, int);
|
|
|
|
static void gen_at_end(ACT, int);
|
|
|
|
static void gen_based(ACT, int);
|
|
|
|
static void gen_blob_close(ACT, USHORT);
|
|
|
|
static void gen_blob_end(ACT, USHORT);
|
|
|
|
static void gen_blob_for(ACT, USHORT);
|
|
|
|
static void gen_blob_open(ACT, USHORT);
|
|
|
|
static int gen_blr(int *, int, TEXT *);
|
|
|
|
static void gen_clear_handles(ACT, int);
|
|
|
|
static void gen_compatibility_symbol(TEXT *, TEXT *, TEXT *);
|
|
|
|
static void gen_compile(ACT, int);
|
|
|
|
static void gen_create_database(ACT, int);
|
|
|
|
static int gen_cursor_close(ACT, REQ, int);
|
|
|
|
static void gen_cursor_init(ACT, int);
|
|
|
|
static int gen_cursor_open(ACT, REQ, int);
|
|
|
|
static void gen_database(ACT, int);
|
|
|
|
static void gen_ddl(ACT, int);
|
|
|
|
static void gen_drop_database(ACT, int);
|
|
|
|
static void gen_dyn_close(ACT, int);
|
|
|
|
static void gen_dyn_declare(ACT, int);
|
|
|
|
static void gen_dyn_describe(ACT, int, BOOLEAN);
|
|
|
|
static void gen_dyn_execute(ACT, int);
|
|
|
|
static void gen_dyn_fetch(ACT, int);
|
|
|
|
static void gen_dyn_immediate(ACT, int);
|
|
|
|
static void gen_dyn_insert(ACT, int);
|
|
|
|
static void gen_dyn_open(ACT, int);
|
|
|
|
static void gen_dyn_prepare(ACT, int);
|
|
|
|
static void gen_emodify(ACT, int);
|
|
|
|
static void gen_estore(ACT, int);
|
|
|
|
static void gen_endfor(ACT, int);
|
|
|
|
static void gen_erase(ACT, int);
|
|
|
|
static SSHORT gen_event_block(ACT);
|
|
|
|
static void gen_event_init(ACT, int);
|
|
|
|
static void gen_event_wait(ACT, int);
|
|
|
|
static void gen_fetch(ACT, int);
|
|
|
|
static void gen_finish(ACT, int);
|
|
|
|
static void gen_for(ACT, int);
|
|
|
|
static void gen_form_display(ACT, int);
|
|
|
|
static void gen_form_end(ACT, int);
|
|
|
|
static void gen_form_for(ACT, int);
|
|
|
|
static void gen_function(ACT, int);
|
|
|
|
static void gen_get_or_put_slice(ACT, REF, BOOLEAN, int);
|
|
|
|
static void gen_get_segment(ACT, int);
|
|
|
|
static void gen_item_end(ACT, int);
|
|
|
|
static void gen_item_for(ACT, int);
|
|
|
|
static void gen_loop(ACT, int);
|
|
|
|
static void gen_menu(ACT, int);
|
|
|
|
static void gen_menu_display(ACT, int);
|
|
|
|
static void gen_menu_entree(ACT, int);
|
|
|
|
static void gen_menu_entree_att(ACT, int);
|
|
|
|
static void gen_menu_end(ACT, int);
|
|
|
|
static void gen_menu_for(ACT, int);
|
|
|
|
static void gen_menu_item_end(ACT, int);
|
|
|
|
static void gen_menu_item_for(ACT, int);
|
|
|
|
static void gen_menu_request(REQ);
|
|
|
|
static TEXT *gen_name(char *, REF, BOOLEAN);
|
|
|
|
static void gen_on_error(ACT, USHORT);
|
|
|
|
static void gen_procedure(ACT, int);
|
|
|
|
static void gen_put_segment(ACT, int);
|
|
|
|
static void gen_raw(UCHAR *, int);
|
|
|
|
static void gen_ready(ACT, int);
|
|
|
|
static void gen_receive(ACT, int, POR);
|
|
|
|
static void gen_release(ACT, int);
|
|
|
|
static void gen_request(REQ);
|
|
|
|
static void gen_return_value(ACT, int);
|
|
|
|
static void gen_routine(ACT, int);
|
|
|
|
static void gen_s_end(ACT, int);
|
|
|
|
static void gen_s_fetch(ACT, int);
|
|
|
|
static void gen_s_start(ACT, int);
|
|
|
|
static void gen_segment(ACT, int);
|
|
|
|
static void gen_select(ACT, int);
|
|
|
|
static void gen_send(ACT, POR, int);
|
|
|
|
static void gen_slice(ACT, REF, int);
|
|
|
|
static void gen_start(ACT, POR, int, BOOLEAN);
|
|
|
|
static void gen_store(ACT, int);
|
|
|
|
static void gen_t_start(ACT, int);
|
|
|
|
static void gen_tpb(TPB, int);
|
|
|
|
static void gen_trans(ACT, int);
|
|
|
|
static void gen_type(ACT, int);
|
|
|
|
static void gen_update(ACT, int);
|
|
|
|
static void gen_variable(ACT, int);
|
|
|
|
static void gen_whenever(SWE, int);
|
|
|
|
static void gen_window_create(ACT, int);
|
|
|
|
static void gen_window_delete(ACT, int);
|
|
|
|
static void gen_window_suspend(ACT, int);
|
|
|
|
static void make_array_declaration(REF);
|
|
|
|
static TEXT *make_name(TEXT *, SYM);
|
|
|
|
static void make_ok_test(ACT, REQ, int);
|
|
|
|
static void make_port(POR, int);
|
|
|
|
static void make_ready(DBB, TEXT *, TEXT *, USHORT, REQ);
|
2002-09-24 14:57:10 +02:00
|
|
|
#ifdef __GNUC__
|
|
|
|
static void printa(int, const char *, ...) __attribute__ ((format(printf,2,3)));
|
|
|
|
static void printb(TEXT *, ...) __attribute__ ((format(printf,1,2)));
|
|
|
|
#else
|
2001-07-12 07:46:06 +02:00
|
|
|
static void printa(int, const char *, ...);
|
2001-05-23 15:26:42 +02:00
|
|
|
static void printb(TEXT *, ...);
|
2002-09-24 14:57:10 +02:00
|
|
|
#endif
|
2001-05-23 15:26:42 +02:00
|
|
|
static TEXT *request_trans(ACT, REQ);
|
|
|
|
static TEXT *status_vector(ACT);
|
|
|
|
static void t_start_auto(ACT, REQ, TEXT *, int, SSHORT);
|
|
|
|
|
|
|
|
static int first_flag;
|
|
|
|
static TEXT *status_name;
|
|
|
|
|
|
|
|
#define INDENT 3
|
|
|
|
#define BEGIN printa (column, "{")
|
|
|
|
#define END printa (column, "}")
|
|
|
|
|
|
|
|
#define SET_SQLCODE if (action->act_flags & ACT_sql) printa (column, "SQLCODE = isc_sqlcode (%s);", status_name)
|
|
|
|
#define NULL_STRING "(char *)0"
|
|
|
|
#define NULL_STATUS "(long*) 0L"
|
|
|
|
#define NULL_SQLDA "(XSQLDA*) 0L"
|
|
|
|
|
|
|
|
#ifdef VMS
|
|
|
|
#define GDS_INCLUDE "\"interbase:[syslib]gds.h\""
|
|
|
|
#endif
|
|
|
|
|
2001-07-12 07:46:06 +02:00
|
|
|
#ifdef DARWIN
|
|
|
|
#define GDS_INCLUDE "<Firebird/ibase.h>"
|
|
|
|
#endif
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
#ifndef GDS_INCLUDE
|
|
|
|
#define GDS_INCLUDE "<ibase.h>"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef DECOSF
|
|
|
|
#define DCL_LONG "int "
|
|
|
|
#define DCL_QUAD "long"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef DCL_LONG
|
|
|
|
#define DCL_LONG "long"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef DCL_QUAD
|
|
|
|
#define DCL_QUAD "ISC_QUAD"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
//
|
|
|
|
|
|
|
|
void C_CXX_action( ACT action, int column)
|
|
|
|
{
|
|
|
|
|
|
|
|
status_name = "isc_status";
|
|
|
|
|
|
|
|
// Put leading braces where required
|
|
|
|
|
|
|
|
switch (action->act_type) {
|
|
|
|
case ACT_alter_database:
|
|
|
|
case ACT_alter_domain:
|
|
|
|
case ACT_alter_index:
|
|
|
|
case ACT_alter_table:
|
|
|
|
case ACT_blob_close:
|
|
|
|
case ACT_blob_create:
|
|
|
|
case ACT_blob_for:
|
|
|
|
case ACT_blob_open:
|
|
|
|
case ACT_clear_handles:
|
|
|
|
case ACT_close:
|
|
|
|
case ACT_commit:
|
|
|
|
case ACT_commit_retain_context:
|
|
|
|
case ACT_create_database:
|
|
|
|
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_disconnect:
|
|
|
|
case ACT_drop_database:
|
|
|
|
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:
|
|
|
|
case ACT_dyn_close:
|
|
|
|
case ACT_dyn_cursor:
|
|
|
|
case ACT_dyn_describe:
|
|
|
|
case ACT_dyn_describe_input:
|
|
|
|
case ACT_dyn_execute:
|
|
|
|
case ACT_dyn_fetch:
|
|
|
|
case ACT_dyn_grant:
|
|
|
|
case ACT_dyn_immediate:
|
|
|
|
case ACT_dyn_insert:
|
|
|
|
case ACT_dyn_open:
|
|
|
|
case ACT_dyn_prepare:
|
|
|
|
case ACT_dyn_revoke:
|
|
|
|
case ACT_fetch:
|
|
|
|
case ACT_finish:
|
|
|
|
case ACT_for:
|
|
|
|
case ACT_form_display:
|
|
|
|
case ACT_form_for:
|
|
|
|
case ACT_get_segment:
|
|
|
|
case ACT_get_slice:
|
|
|
|
case ACT_insert:
|
|
|
|
case ACT_item_for:
|
|
|
|
case ACT_item_put:
|
|
|
|
case ACT_loop:
|
|
|
|
case ACT_menu_for:
|
|
|
|
case ACT_modify:
|
|
|
|
case ACT_open:
|
|
|
|
case ACT_prepare:
|
|
|
|
case ACT_procedure:
|
|
|
|
case ACT_put_slice:
|
|
|
|
case ACT_ready:
|
|
|
|
case ACT_release:
|
|
|
|
case ACT_rfinish:
|
|
|
|
case ACT_rollback:
|
|
|
|
case ACT_s_fetch:
|
|
|
|
case ACT_s_start:
|
|
|
|
case ACT_select:
|
|
|
|
case ACT_store:
|
|
|
|
case ACT_start:
|
|
|
|
case ACT_update:
|
|
|
|
case ACT_statistics:
|
|
|
|
BEGIN;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (action->act_type) {
|
|
|
|
case ACT_alter_database:
|
|
|
|
case ACT_alter_domain:
|
|
|
|
case ACT_alter_index:
|
|
|
|
case ACT_alter_table:
|
|
|
|
gen_ddl(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_any:
|
|
|
|
gen_any(action, column);
|
|
|
|
return;
|
|
|
|
case ACT_at_end:
|
|
|
|
gen_at_end(action, column);
|
|
|
|
return;
|
|
|
|
case ACT_b_declare:
|
|
|
|
gen_database(action, column);
|
|
|
|
gen_routine(action, column);
|
|
|
|
return;
|
|
|
|
case ACT_basedon:
|
|
|
|
gen_based(action, column);
|
|
|
|
return;
|
|
|
|
case ACT_blob_cancel:
|
|
|
|
gen_blob_close(action, (USHORT) column);
|
|
|
|
return;
|
|
|
|
case ACT_blob_close:
|
|
|
|
gen_blob_close(action, (USHORT) column);
|
|
|
|
break;
|
|
|
|
case ACT_blob_create:
|
|
|
|
gen_blob_open(action, (USHORT) column);
|
|
|
|
break;
|
|
|
|
case ACT_blob_for:
|
|
|
|
gen_blob_for(action, (USHORT) column);
|
|
|
|
return;
|
|
|
|
case ACT_blob_handle:
|
|
|
|
gen_segment(action, column);
|
|
|
|
return;
|
|
|
|
case ACT_blob_open:
|
|
|
|
gen_blob_open(action, (USHORT) column);
|
|
|
|
break;
|
|
|
|
case ACT_clear_handles:
|
|
|
|
gen_clear_handles(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_close:
|
|
|
|
gen_s_end(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_commit:
|
|
|
|
gen_trans(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_commit_retain_context:
|
|
|
|
gen_trans(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_create_database:
|
|
|
|
gen_create_database(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_create_domain:
|
|
|
|
case ACT_create_generator:
|
|
|
|
case ACT_create_index:
|
|
|
|
case ACT_create_shadow:
|
|
|
|
case ACT_create_table:
|
|
|
|
case ACT_create_view:
|
|
|
|
gen_ddl(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_cursor:
|
|
|
|
gen_cursor_init(action, column);
|
|
|
|
return;
|
|
|
|
case ACT_database:
|
|
|
|
gen_database(action, column);
|
|
|
|
return;
|
|
|
|
case ACT_declare_filter:
|
|
|
|
case ACT_declare_udf:
|
|
|
|
gen_ddl(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_disconnect:
|
|
|
|
gen_finish(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_drop_database:
|
|
|
|
gen_drop_database(action, column);
|
|
|
|
break;
|
|
|
|
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, column);
|
|
|
|
break;
|
|
|
|
case ACT_dyn_close:
|
|
|
|
gen_dyn_close(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_dyn_cursor:
|
|
|
|
gen_dyn_declare(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_dyn_describe:
|
|
|
|
gen_dyn_describe(action, column, FALSE);
|
|
|
|
break;
|
|
|
|
case ACT_dyn_describe_input:
|
|
|
|
gen_dyn_describe(action, column, TRUE);
|
|
|
|
break;
|
|
|
|
case ACT_dyn_execute:
|
|
|
|
gen_dyn_execute(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_dyn_fetch:
|
|
|
|
gen_dyn_fetch(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_dyn_grant:
|
|
|
|
gen_ddl(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_dyn_immediate:
|
|
|
|
gen_dyn_immediate(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_dyn_insert:
|
|
|
|
gen_dyn_insert(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_dyn_open:
|
|
|
|
gen_dyn_open(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_dyn_prepare:
|
|
|
|
gen_dyn_prepare(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_dyn_revoke:
|
|
|
|
gen_ddl(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_endblob:
|
|
|
|
gen_blob_end(action, (USHORT) column);
|
|
|
|
return;
|
|
|
|
case ACT_enderror:{
|
|
|
|
column += INDENT;
|
|
|
|
END;
|
|
|
|
column -= INDENT;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ACT_endfor:
|
|
|
|
gen_endfor(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_endmodify:
|
|
|
|
gen_emodify(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_endstore:
|
|
|
|
gen_estore(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_erase:
|
|
|
|
gen_erase(action, column);
|
|
|
|
return;
|
|
|
|
case ACT_event_init:
|
|
|
|
gen_event_init(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_event_wait:
|
|
|
|
gen_event_wait(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_fetch:
|
|
|
|
gen_fetch(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_finish:
|
|
|
|
gen_finish(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_for:
|
|
|
|
gen_for(action, column);
|
|
|
|
return;
|
|
|
|
case ACT_form_display:
|
|
|
|
gen_form_display(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_form_end:
|
|
|
|
gen_form_end(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_form_for:
|
|
|
|
gen_form_for(action, column);
|
|
|
|
return;
|
|
|
|
case ACT_function:
|
|
|
|
gen_function(action, column);
|
|
|
|
return;
|
|
|
|
case ACT_get_segment:
|
|
|
|
gen_get_segment(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_get_slice:
|
|
|
|
gen_slice(action, 0, column);
|
|
|
|
break;
|
|
|
|
case ACT_hctef:
|
|
|
|
END;
|
|
|
|
break;
|
|
|
|
case ACT_insert:
|
|
|
|
gen_s_start(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_item_for:
|
|
|
|
case ACT_item_put:
|
|
|
|
gen_item_for(action, column);
|
|
|
|
return;
|
|
|
|
case ACT_item_end:
|
|
|
|
gen_item_end(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_loop:
|
|
|
|
gen_loop(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_menu:
|
|
|
|
gen_menu(action, column);
|
|
|
|
return;
|
|
|
|
case ACT_menu_display:
|
|
|
|
gen_menu_display(action, column);
|
|
|
|
return;
|
|
|
|
case ACT_menu_end:
|
|
|
|
gen_menu_end(action, column);
|
|
|
|
return;
|
|
|
|
case ACT_menu_entree:
|
|
|
|
gen_menu_entree(action, column);
|
|
|
|
return;
|
|
|
|
case ACT_menu_for:
|
|
|
|
gen_menu_for(action, column);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case ACT_title_text:
|
|
|
|
case ACT_title_length:
|
|
|
|
case ACT_terminator:
|
|
|
|
case ACT_entree_text:
|
|
|
|
case ACT_entree_length:
|
|
|
|
case ACT_entree_value:
|
|
|
|
gen_menu_entree_att(action, column);
|
|
|
|
return;
|
|
|
|
|
|
|
|
case ACT_on_error:
|
|
|
|
gen_on_error(action, (USHORT) column);
|
|
|
|
return;
|
|
|
|
case ACT_open:
|
|
|
|
gen_s_start(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_prepare:
|
|
|
|
gen_trans(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_procedure:
|
|
|
|
gen_procedure(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_put_segment:
|
|
|
|
gen_put_segment(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_put_slice:
|
|
|
|
gen_slice(action, 0, column);
|
|
|
|
break;
|
|
|
|
case ACT_ready:
|
|
|
|
gen_ready(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_release:
|
|
|
|
gen_release(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_rfinish:
|
|
|
|
gen_finish(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_rollback:
|
|
|
|
gen_trans(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_routine:
|
|
|
|
gen_routine(action, column);
|
|
|
|
return;
|
|
|
|
case ACT_s_end:
|
|
|
|
gen_s_end(action, column);
|
|
|
|
return;
|
|
|
|
case ACT_s_fetch:
|
|
|
|
gen_s_fetch(action, column);
|
|
|
|
return;
|
|
|
|
case ACT_s_start:
|
|
|
|
gen_s_start(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_segment:
|
|
|
|
gen_segment(action, column);
|
|
|
|
return;
|
|
|
|
case ACT_segment_length:
|
|
|
|
gen_segment(action, column);
|
|
|
|
return;
|
|
|
|
case ACT_select:
|
|
|
|
gen_select(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_sql_dialect:
|
|
|
|
sw_sql_dialect = ((SDT) action->act_object)->sdt_dialect;
|
|
|
|
return;
|
|
|
|
case ACT_start:
|
|
|
|
gen_t_start(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_statistics:
|
|
|
|
gen_ddl(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_store:
|
|
|
|
gen_store(action, column);
|
|
|
|
return;
|
|
|
|
case ACT_store2:
|
|
|
|
gen_return_value(action, column);
|
|
|
|
return;
|
|
|
|
case ACT_type:
|
|
|
|
gen_type(action, column);
|
|
|
|
return;
|
|
|
|
case ACT_update:
|
|
|
|
gen_update(action, column);
|
|
|
|
break;
|
|
|
|
case ACT_variable:
|
|
|
|
gen_variable(action, column);
|
|
|
|
return;
|
|
|
|
case ACT_window_create:
|
|
|
|
gen_window_create(action, column);
|
|
|
|
return;
|
|
|
|
case ACT_window_delete:
|
|
|
|
gen_window_delete(action, column);
|
|
|
|
return;
|
|
|
|
case ACT_window_suspend:
|
|
|
|
gen_window_suspend(action, column);
|
|
|
|
return;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Put in a trailing brace for those actions still with us
|
|
|
|
|
|
|
|
if (action->act_flags & ACT_sql)
|
|
|
|
gen_whenever(action->act_whenever, column);
|
|
|
|
|
|
|
|
if (action->act_error)
|
|
|
|
ib_fprintf(out_file, ";");
|
|
|
|
else
|
|
|
|
END;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Build an assignment from a host language variable to
|
|
|
|
// a port variable. The string assignments are a little
|
|
|
|
// hairy because the normal mode is varying (null
|
|
|
|
// terminated) strings, but the fixed subtype makes the
|
|
|
|
// string a byte stream. Furthering the complication, a
|
|
|
|
// single character byte stream is handled as a single byte,
|
|
|
|
// meaining that it is the byte, not the address of the
|
|
|
|
// byte.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void asgn_from( ACT action, REF reference, int column)
|
|
|
|
{
|
|
|
|
FLD field;
|
|
|
|
TEXT *value, name[64], variable[20], temp[20];
|
|
|
|
REF source;
|
|
|
|
ACT slice_action;
|
|
|
|
SSHORT slice_flag = FALSE;
|
|
|
|
|
|
|
|
for (; reference; reference = reference->ref_next) {
|
|
|
|
slice_flag = FALSE;
|
|
|
|
field = reference->ref_field;
|
|
|
|
if (field->fld_array_info) {
|
|
|
|
if ((source = reference->ref_friend) &&
|
|
|
|
(slice_action = (ACT) source->ref_slice) &&
|
|
|
|
slice_action->act_object) {
|
|
|
|
slice_flag = TRUE;
|
|
|
|
slice_action->act_type = ACT_put_slice;
|
|
|
|
gen_slice(slice_action, 0, column);
|
|
|
|
}
|
|
|
|
else if (!(reference->ref_flags & REF_array_elem)) {
|
|
|
|
printa(column, "%s = isc_blob_null;",
|
|
|
|
gen_name(name, reference, TRUE));
|
|
|
|
gen_get_or_put_slice(action, reference, FALSE, column);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!reference->ref_source && !reference->ref_value && !slice_flag)
|
|
|
|
continue;
|
|
|
|
align(column);
|
|
|
|
gen_name(variable, reference, TRUE);
|
|
|
|
if (slice_flag)
|
|
|
|
value = gen_name(temp, reference->ref_friend, TRUE);
|
|
|
|
else if (reference->ref_source)
|
|
|
|
value = gen_name(temp, reference->ref_source, TRUE);
|
|
|
|
else
|
|
|
|
value = reference->ref_value;
|
|
|
|
|
|
|
|
if (!slice_flag &&
|
|
|
|
reference->ref_value &&
|
|
|
|
(reference->ref_flags & REF_array_elem)) field = field->fld_array;
|
|
|
|
#if (! (defined JPN_SJIS || defined JPN_EUC) )
|
|
|
|
if (field && field->fld_dtype <= dtype_cstring)
|
|
|
|
if (field->fld_sub_type == 1)
|
|
|
|
if (field->fld_length == 1)
|
|
|
|
ib_fprintf(out_file, "%s = %s;", variable, value);
|
|
|
|
else
|
|
|
|
ib_fprintf(out_file,
|
|
|
|
"isc_ftof (%s, sizeof (%s), %s, %d);", value,
|
|
|
|
value, variable, field->fld_length);
|
|
|
|
else if (field->fld_flags & FLD_dbkey)
|
|
|
|
ib_fprintf(out_file, "isc_ftof (%s, %d, %s, %d);", value,
|
|
|
|
field->fld_length, variable, field->fld_length);
|
|
|
|
else if (sw_cstring)
|
2001-07-12 07:46:06 +02:00
|
|
|
ib_fprintf(out_file, "isc_vtov ((char*)%s, (char*)%s, %d);", value,
|
2001-05-23 15:26:42 +02:00
|
|
|
variable, field->fld_length);
|
|
|
|
else if (reference->ref_source)
|
|
|
|
ib_fprintf(out_file, "isc_ftof (%s, sizeof (%s), %s, %d);",
|
|
|
|
value, value, variable, field->fld_length);
|
|
|
|
else
|
|
|
|
ib_fprintf(out_file, "isc_vtof (%s, %s, %d);", value,
|
|
|
|
variable, field->fld_length);
|
|
|
|
#else
|
|
|
|
/* To avoid chopping off a double byte kanji character in between
|
|
|
|
the two bytes, generate calls to isc_ftof2 isc_vtof2 and
|
|
|
|
isc_vtov2 wherever necessary */
|
|
|
|
|
|
|
|
if (field && field->fld_dtype <= dtype_cstring)
|
|
|
|
if (field->fld_sub_type == 1)
|
|
|
|
if (field->fld_length == 1)
|
|
|
|
ib_fprintf(out_file, "%s = %s;", variable, value);
|
|
|
|
else
|
|
|
|
ib_fprintf(out_file,
|
|
|
|
"isc_ftof (%s, sizeof (%s), %s, %d);", value,
|
|
|
|
value, variable, field->fld_length);
|
|
|
|
else if (field->fld_flags & FLD_dbkey)
|
|
|
|
ib_fprintf(out_file, "isc_ftof (%s, %d, %s, %d);", value,
|
|
|
|
field->fld_length, variable, field->fld_length);
|
|
|
|
else if (sw_cstring)
|
|
|
|
ib_fprintf(out_file, "isc_vtov2 (%s, %s, %d, %d);", value,
|
|
|
|
variable, field->fld_length, sw_interp);
|
|
|
|
else if (reference->ref_source)
|
|
|
|
ib_fprintf(out_file,
|
|
|
|
"isc_ftof2 (%s, sizeof (%s), %s, %d, %d);", value,
|
|
|
|
value, variable, field->fld_length, sw_interp);
|
|
|
|
else
|
|
|
|
ib_fprintf(out_file, "isc_vtof2 (%s, %s, %d, %d);", value,
|
|
|
|
variable, field->fld_length, sw_interp);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
else if (!reference->ref_master
|
|
|
|
|| (reference->ref_flags & REF_literal)) ib_fprintf(out_file,
|
|
|
|
"%s = %s;",
|
|
|
|
variable,
|
|
|
|
value);
|
|
|
|
else {
|
|
|
|
ib_fprintf(out_file, "if (%s < 0)", value);
|
|
|
|
align(column + 4);
|
|
|
|
ib_fprintf(out_file, "%s = -1;", variable);
|
|
|
|
align(column);
|
|
|
|
ib_fprintf(out_file, "else");
|
|
|
|
align(column + 4);
|
|
|
|
ib_fprintf(out_file, "%s = 0;", variable);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef UNDEF
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Build an assignment from a host language variable to
|
|
|
|
// a sqlda variable.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void asgn_sqlda_from(
|
|
|
|
REF reference,
|
|
|
|
int number, SCHAR * string, int column)
|
|
|
|
{
|
|
|
|
SCHAR *value, temp[20];
|
|
|
|
|
|
|
|
for (; reference; reference = reference->ref_next) {
|
|
|
|
align(column);
|
|
|
|
if (reference->ref_source)
|
|
|
|
value = gen_name(temp, reference->ref_source, TRUE);
|
|
|
|
else
|
|
|
|
value = reference->ref_value;
|
|
|
|
ib_fprintf(out_file,
|
|
|
|
"isc_to_sqlda (isc_sqlda, %d, %s, sizeof(%s), %s);",
|
|
|
|
number, value, value, string);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Build an assignment to a host language variable from
|
|
|
|
// a port variable.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void asgn_to( ACT action, REF reference, int column)
|
|
|
|
{
|
|
|
|
FLD field;
|
|
|
|
REF source;
|
|
|
|
ACT slice_action;
|
|
|
|
char s[64];
|
|
|
|
|
|
|
|
source = reference->ref_friend;
|
|
|
|
field = source->ref_field;
|
|
|
|
|
|
|
|
if (field) {
|
|
|
|
if (field->fld_array_info && (slice_action = (ACT) source->ref_slice)) {
|
|
|
|
source->ref_value = reference->ref_value;
|
|
|
|
if (slice_action->act_object) {
|
|
|
|
slice_action->act_type = ACT_get_slice;
|
|
|
|
gen_slice(slice_action, source, column);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
gen_get_or_put_slice(action, source, TRUE, column);
|
|
|
|
|
|
|
|
/* Pick up NULL value if one is there */
|
|
|
|
|
|
|
|
if (reference = reference->ref_null) {
|
|
|
|
align(column);
|
|
|
|
ib_fprintf(out_file, "%s = %s;", reference->ref_value,
|
|
|
|
gen_name(s, reference, TRUE));
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
gen_name(s, source, TRUE);
|
|
|
|
if (field->fld_dtype > dtype_cstring)
|
|
|
|
ib_fprintf(out_file, "%s = %s;", reference->ref_value, s);
|
|
|
|
else if (field->fld_sub_type == 1 && field->fld_length == 1)
|
|
|
|
ib_fprintf(out_file, "%s = %s;", reference->ref_value, s);
|
|
|
|
#if (! (defined JPN_SJIS || defined JPN_EUC) )
|
|
|
|
else if (field->fld_flags & FLD_dbkey)
|
|
|
|
ib_fprintf(out_file, "isc_ftof (%s, %d, %s, %d);",
|
|
|
|
s, field->fld_length, reference->ref_value,
|
|
|
|
field->fld_length);
|
|
|
|
else if (!sw_cstring || field->fld_sub_type == 1)
|
|
|
|
ib_fprintf(out_file, "isc_ftof (%s, %d, %s, sizeof (%s));", s,
|
|
|
|
field->fld_length, reference->ref_value,
|
|
|
|
reference->ref_value);
|
|
|
|
else
|
2001-07-12 07:46:06 +02:00
|
|
|
ib_fprintf(out_file, "isc_vtov ((char*)%s, (char*)%s, sizeof (%s));", s,
|
2001-05-23 15:26:42 +02:00
|
|
|
reference->ref_value, reference->ref_value);
|
|
|
|
#else
|
|
|
|
/* To avoid chopping off a double byte kanji character in between
|
|
|
|
the two bytes, generate calls to isc_ftof2 isc_vtof2 and
|
|
|
|
isc_vtov2 wherever necessary */
|
|
|
|
|
|
|
|
else if (field->fld_flags & FLD_dbkey)
|
|
|
|
ib_fprintf(out_file, "isc_ftof (%s, %d, %s, %d);",
|
|
|
|
s, field->fld_length, reference->ref_value,
|
|
|
|
field->fld_length);
|
|
|
|
else if (!sw_cstring || field->fld_sub_type == 1)
|
|
|
|
ib_fprintf(out_file, "isc_ftof (%s, %d, %s, sizeof (%s));", s,
|
|
|
|
field->fld_length, reference->ref_value,
|
|
|
|
reference->ref_value);
|
|
|
|
else
|
|
|
|
ib_fprintf(out_file, "isc_vtov2 (%s, %s, sizeof (%s), %d);", s,
|
|
|
|
reference->ref_value, reference->ref_value, sw_interp);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
// Pick up NULL value if one is there
|
|
|
|
|
|
|
|
if (reference = reference->ref_null) {
|
|
|
|
align(column);
|
|
|
|
ib_fprintf(out_file, "%s = %s;", reference->ref_value,
|
|
|
|
gen_name(s, reference, TRUE));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Build an assignment to a host language variable from
|
|
|
|
// a port variable.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void asgn_to_proc( REF reference, int column)
|
|
|
|
{
|
|
|
|
FLD field;
|
|
|
|
char s[64];
|
|
|
|
|
|
|
|
for (; reference; reference = reference->ref_next) {
|
|
|
|
if (!reference->ref_value)
|
|
|
|
continue;
|
|
|
|
field = reference->ref_field;
|
|
|
|
gen_name(s, reference, TRUE);
|
|
|
|
align(column);
|
|
|
|
|
|
|
|
if (field->fld_dtype > dtype_cstring)
|
|
|
|
ib_fprintf(out_file, "%s = %s;", reference->ref_value, s);
|
|
|
|
else if (field->fld_sub_type == 1 && field->fld_length == 1)
|
|
|
|
ib_fprintf(out_file, "%s = %s;", reference->ref_value, s);
|
|
|
|
#if (! (defined JPN_SJIS || defined JPN_EUC) )
|
|
|
|
else if (field->fld_flags & FLD_dbkey)
|
|
|
|
ib_fprintf(out_file, "isc_ftof (%s, %d, %s, %d);",
|
|
|
|
s, field->fld_length, reference->ref_value,
|
|
|
|
field->fld_length);
|
|
|
|
else if (!sw_cstring || field->fld_sub_type == 1)
|
|
|
|
ib_fprintf(out_file, "isc_ftof (%s, %d, %s, sizeof (%s));", s,
|
|
|
|
field->fld_length, reference->ref_value,
|
|
|
|
reference->ref_value);
|
|
|
|
else
|
2001-07-12 07:46:06 +02:00
|
|
|
ib_fprintf(out_file, "isc_vtov ((char*)%s, (char*)%s, sizeof (%s));", s,
|
2001-05-23 15:26:42 +02:00
|
|
|
reference->ref_value, reference->ref_value);
|
|
|
|
#else
|
|
|
|
/* To avoid chopping off a double byte kanji character in between
|
|
|
|
the two bytes, generate calls to isc_ftof2 isc_vtof2 and
|
|
|
|
isc_vtov2 wherever necessary */
|
|
|
|
|
|
|
|
else if (field->fld_flags & FLD_dbkey)
|
|
|
|
ib_fprintf(out_file, "isc_ftof (%s, %d, %s, %d);",
|
|
|
|
s, field->fld_length, reference->ref_value,
|
|
|
|
field->fld_length);
|
|
|
|
else if (!sw_cstring || field->fld_sub_type == 1)
|
|
|
|
ib_fprintf(out_file, "isc_ftof (%s, %d, %s, sizeof (%s));", s,
|
|
|
|
field->fld_length, reference->ref_value,
|
|
|
|
reference->ref_value);
|
|
|
|
else
|
|
|
|
ib_fprintf(out_file, "isc_vtov2 (%s, %s, sizeof (%s), %d);", s,
|
|
|
|
reference->ref_value, reference->ref_value, sw_interp);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate a function call for free standing ANY. Somebody else
|
|
|
|
// will need to generate the actual function.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_any( ACT action, int column)
|
|
|
|
{
|
|
|
|
REQ request;
|
|
|
|
POR port;
|
|
|
|
REF reference;
|
|
|
|
|
|
|
|
align(column);
|
|
|
|
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, int column)
|
|
|
|
{
|
|
|
|
REQ request;
|
|
|
|
char s[20];
|
|
|
|
|
|
|
|
request = action->act_request;
|
|
|
|
printa(column, "if (!%s) {", gen_name(s, request->req_eof, TRUE));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Substitute for a BASED ON <field name> clause.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_based( ACT action, int column)
|
|
|
|
{
|
|
|
|
BAS based_on;
|
|
|
|
FLD field;
|
|
|
|
TEXT s[64], *variable, first_flag;
|
|
|
|
USHORT datatype;
|
|
|
|
SLONG length;
|
|
|
|
DIM dimension;
|
|
|
|
|
|
|
|
align(column);
|
|
|
|
based_on = (BAS) action->act_object;
|
|
|
|
field = based_on->bas_field;
|
|
|
|
|
|
|
|
if (based_on->bas_flags & BAS_segment) {
|
|
|
|
datatype = (sw_cstring) ? dtype_cstring : dtype_text;
|
|
|
|
if (!(length = field->fld_seg_length))
|
|
|
|
length = 256;
|
|
|
|
if (datatype == dtype_cstring)
|
|
|
|
length++;
|
|
|
|
}
|
|
|
|
else if (field->fld_array_info)
|
|
|
|
datatype = field->fld_array_info->ary_dtype;
|
|
|
|
else
|
|
|
|
datatype = field->fld_dtype;
|
|
|
|
|
|
|
|
switch (datatype) {
|
|
|
|
case dtype_short:
|
|
|
|
ib_fprintf(out_file, "short");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_long:
|
|
|
|
ib_fprintf(out_file, DCL_LONG);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_quad:
|
|
|
|
ib_fprintf(out_file, DCL_QUAD);
|
|
|
|
break;
|
|
|
|
|
|
|
|
// ** Begin date/time/timestamp *
|
|
|
|
case dtype_sql_date:
|
|
|
|
ib_fprintf(out_file, "ISC_DATE");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_sql_time:
|
|
|
|
ib_fprintf(out_file, "ISC_TIME");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_timestamp:
|
|
|
|
ib_fprintf(out_file, "ISC_TIMESTAMP");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_int64:
|
|
|
|
ib_fprintf(out_file, "ISC_INT64");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_blob:
|
|
|
|
ib_fprintf(out_file, "ISC_QUAD");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_cstring:
|
|
|
|
case dtype_text:
|
|
|
|
case dtype_varying:
|
|
|
|
ib_fprintf(out_file, "char");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_real:
|
|
|
|
ib_fprintf(out_file, "float");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_double:
|
|
|
|
ib_fprintf(out_file, "double");
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
sprintf(s, "datatype %d unknown\n", field->fld_dtype);
|
|
|
|
IBERROR(s);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// print the first variable, then precede the rest with commas
|
|
|
|
|
|
|
|
column += INDENT;
|
|
|
|
|
|
|
|
first_flag = TRUE;
|
|
|
|
|
|
|
|
while (based_on->bas_variables) {
|
|
|
|
variable = (TEXT *) POP(&based_on->bas_variables);
|
|
|
|
if (!first_flag)
|
|
|
|
ib_fprintf(out_file, ",");
|
|
|
|
first_flag = FALSE;
|
|
|
|
align(column);
|
|
|
|
ib_fprintf(out_file, "%s", variable);
|
|
|
|
if (based_on->bas_flags & BAS_segment) {
|
|
|
|
if (*variable != '*')
|
2002-09-24 14:57:10 +02:00
|
|
|
ib_fprintf(out_file, "[%ld]", length);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else if (field->fld_array_info) {
|
|
|
|
/* Print out the dimension part of the declaration */
|
|
|
|
|
|
|
|
for (dimension = field->fld_array_info->ary_dimension; dimension;
|
|
|
|
dimension = dimension->dim_next)
|
2002-09-24 14:57:10 +02:00
|
|
|
ib_fprintf(out_file, " [%ld]",
|
2001-05-23 15:26:42 +02:00
|
|
|
dimension->dim_upper - dimension->dim_lower + 1);
|
|
|
|
|
|
|
|
if (field->fld_array_info->ary_dtype <= dtype_varying &&
|
|
|
|
field->fld_length > 1)
|
2002-09-24 14:57:10 +02:00
|
|
|
ib_fprintf(out_file, " [%ld]", field->fld_array->fld_length);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
if (*variable != '*' &&
|
|
|
|
field->fld_dtype <= dtype_varying &&
|
|
|
|
(field->fld_sub_type != 1 || field->fld_length > 1))
|
|
|
|
// *???????
|
|
|
|
// if (*variable != '*' && field->fld_dtype <= dtype_varying &&
|
|
|
|
// field->fld_length > 1)
|
|
|
|
//
|
|
|
|
ib_fprintf(out_file, "[%d]", field->fld_length);
|
|
|
|
}
|
|
|
|
|
|
|
|
ib_fprintf(out_file, "%s\n", based_on->bas_terminator);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Make a blob FOR loop.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_blob_close( ACT action, USHORT column)
|
|
|
|
{
|
|
|
|
BLB blob;
|
|
|
|
PAT args;
|
|
|
|
TEXT *pattern1 = "isc_%IFcancel%ELclose%EN_blob (%V1, &%BH);";
|
|
|
|
|
|
|
|
if (action->act_error)
|
|
|
|
BEGIN;
|
|
|
|
|
|
|
|
if (action->act_flags & ACT_sql) {
|
|
|
|
column = gen_cursor_close(action, action->act_request, column);
|
|
|
|
blob = (BLB) action->act_request->req_blobs;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
blob = (BLB) action->act_object;
|
|
|
|
|
|
|
|
args.pat_blob = blob;
|
|
|
|
args.pat_vector1 = status_vector(action);
|
|
|
|
args.pat_condition = action->act_type == ACT_blob_cancel;
|
|
|
|
PATTERN_expand(column, pattern1, &args);
|
|
|
|
|
|
|
|
if (action->act_flags & ACT_sql) {
|
|
|
|
END;
|
|
|
|
column -= INDENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
SET_SQLCODE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// End a blob FOR loop.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_blob_end( ACT action, USHORT column)
|
|
|
|
{
|
|
|
|
BLB blob;
|
|
|
|
PAT args;
|
|
|
|
TEXT s1[32];
|
|
|
|
TEXT *pattern1 = "}\n\
|
|
|
|
isc_close_blob (%V1, &%BH);\n\
|
|
|
|
}";
|
|
|
|
|
|
|
|
args.pat_blob = blob = (BLB) action->act_object;
|
|
|
|
if (action->act_error) {
|
|
|
|
sprintf(s1, "%s2", status_name);
|
|
|
|
args.pat_vector1 = s1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
args.pat_vector1 = status_vector(0);
|
|
|
|
args.pat_condition = action->act_type == ACT_blob_cancel;
|
|
|
|
PATTERN_expand(column, pattern1, &args);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Make a blob FOR loop.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_blob_for( ACT action, USHORT column)
|
|
|
|
{
|
|
|
|
PAT args;
|
|
|
|
TEXT *pattern1 = "%IFif (!%S1 [1]) {\n\
|
|
|
|
%ENwhile (1)\n\
|
|
|
|
{";
|
|
|
|
|
|
|
|
gen_blob_open(action, column);
|
|
|
|
args.pat_condition = action->act_error != NULL;
|
|
|
|
args.pat_string1 = status_name;
|
|
|
|
PATTERN_expand(column, pattern1, &args);
|
|
|
|
column += INDENT;
|
|
|
|
gen_get_segment(action, column);
|
|
|
|
printa(column, "if (%s [1] && (%s [1] != isc_segment)) break;",
|
|
|
|
status_name, status_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate the call to open (or create) a blob.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_blob_open( ACT action, USHORT column)
|
|
|
|
{
|
|
|
|
BLB blob;
|
|
|
|
PAT args;
|
|
|
|
REF reference;
|
|
|
|
TEXT s[20];
|
|
|
|
TEXT *pattern1 =
|
|
|
|
"isc_%IFcreate%ELopen%EN_blob2 (%V1, &%DH, &%RT, &%BH, &%FR, (short) %N1, %I1);",
|
|
|
|
*pattern2 =
|
2001-07-12 07:46:06 +02:00
|
|
|
"isc_%IFcreate%ELopen%EN_blob2 (%V1, &%DH, &%RT, &%BH, &%FR, (short) 0, (%IFchar%ELunsigned char%EN*) 0);";
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (sw_auto && (action->act_flags & ACT_sql)) {
|
|
|
|
t_start_auto(action, action->act_request, status_vector(action),
|
|
|
|
column, TRUE);
|
|
|
|
printa(column, "if (%s)", request_trans(action, action->act_request));
|
|
|
|
column += INDENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((action->act_error && (action->act_type != ACT_blob_for)) ||
|
|
|
|
(action->act_flags & ACT_sql))
|
|
|
|
BEGIN;
|
|
|
|
|
|
|
|
if (action->act_flags & ACT_sql) {
|
|
|
|
column = gen_cursor_open(action, action->act_request, column);
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
if ((action->act_flags & ACT_sql) && action->act_type == ACT_blob_open) {
|
|
|
|
align(column);
|
|
|
|
ib_fprintf(out_file, "%s = %s;", s, reference->ref_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
|
|
END;
|
|
|
|
column -= INDENT;
|
|
|
|
END;
|
|
|
|
column -= INDENT;
|
|
|
|
END;
|
|
|
|
if (sw_auto)
|
|
|
|
column -= INDENT;
|
|
|
|
SET_SQLCODE;
|
|
|
|
if (action->act_type == ACT_blob_create) {
|
|
|
|
printa(column, "if (!SQLCODE)");
|
|
|
|
align(column + INDENT);
|
|
|
|
ib_fprintf(out_file, "%s = %s;", reference->ref_value, s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ((action->act_error && (action->act_type != ACT_blob_for)))
|
|
|
|
END;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Callback routine for BLR pretty printer.
|
|
|
|
//
|
|
|
|
|
2001-07-12 07:46:06 +02:00
|
|
|
static int gen_blr( int *user_arg, int offset, TEXT * string)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
int indent, length;
|
|
|
|
TEXT *p, *q, *p1, *q1, c, d, line[256];
|
|
|
|
BOOLEAN open_quote, first_line;
|
|
|
|
|
|
|
|
first_line = TRUE;
|
|
|
|
indent = 2 * INDENT;
|
|
|
|
p = string;
|
|
|
|
while (*p == ' ') {
|
|
|
|
p++;
|
|
|
|
indent++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Limit indentation to 192 characters
|
|
|
|
|
|
|
|
indent = MIN(indent, 192);
|
|
|
|
|
|
|
|
length = strlen(p);
|
|
|
|
do {
|
|
|
|
if (length + indent > 255) {
|
|
|
|
/* 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) < 255; q++) {
|
|
|
|
if ((q - p + indent) > 220 && *q == ',' && !open_quote)
|
|
|
|
break;
|
|
|
|
if (*q == '\'' && *(q - 1) != '\\')
|
|
|
|
open_quote = !open_quote;
|
|
|
|
}
|
|
|
|
c = *++q;
|
|
|
|
*q = 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
c = 0;
|
|
|
|
q = p + strlen(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Replace all occurrences of gds__ (or gds__) with isc_ */
|
|
|
|
|
|
|
|
for (q1 = line, p1 = p; *p1;)
|
|
|
|
if ((*q1++ = *p1++) == 'g')
|
|
|
|
if (*p1 && (*q1++ = *p1++) == 'd')
|
|
|
|
if (*p1 && (*q1++ = *p1++) == 's')
|
|
|
|
if (*p1 && (*q1++ = *p1++) == '_')
|
|
|
|
if (*p1 && ((d = *p1++) == '_' || d == '$'))
|
|
|
|
strncpy(q1 - 4, "isc", 3);
|
|
|
|
else
|
|
|
|
*q1++ = d;
|
|
|
|
*q1 = 0;
|
|
|
|
printa(indent, line);
|
|
|
|
*q = c;
|
|
|
|
length = length - (q - p);
|
|
|
|
p = q;
|
|
|
|
if (first_line) {
|
|
|
|
indent = MIN(indent + INDENT, 192);
|
|
|
|
first_line = FALSE;
|
|
|
|
}
|
|
|
|
} while (length > 0);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Zap all know handles.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_clear_handles( ACT action, int column)
|
|
|
|
{
|
|
|
|
REQ request;
|
|
|
|
|
|
|
|
for (request = requests; request; request = request->req_next) {
|
|
|
|
if (!(request->req_flags & REQ_exp_hand))
|
|
|
|
printa(column, "%s = 0;", request->req_handle);
|
|
|
|
if (request->req_form_handle &&
|
|
|
|
!(request->req_flags & REQ_exp_form_handle))
|
|
|
|
printa(column, "%s = 0;", request->req_form_handle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate a symbol to ease compatibility with V3.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_compatibility_symbol(
|
|
|
|
TEXT * symbol,
|
|
|
|
TEXT * v4_prefix, TEXT * trailer)
|
|
|
|
{
|
2001-07-12 07:46:06 +02:00
|
|
|
const char *v3_prefix;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2002-01-04 12:34:22 +01:00
|
|
|
v3_prefix = (isLangCpp(sw_language)) ? "gds_" : "gds__";
|
|
|
|
// v3_prefix = (sw_language == lang_cxx) ? "gds_" : "gds__";
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
ib_fprintf(out_file, "#define %s%s\t%s%s%s\n", v3_prefix, symbol,
|
|
|
|
v4_prefix, symbol, trailer);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate text to compile a request.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_compile( ACT action, int column)
|
|
|
|
{
|
|
|
|
REQ request;
|
|
|
|
DBB db;
|
|
|
|
BLB blob;
|
|
|
|
PAT args;
|
|
|
|
TEXT *pattern1 =
|
2001-07-12 07:46:06 +02:00
|
|
|
"isc_compile_request%IF2%EN (%V1, (void**) &%DH, (void**) &%RH, (short) sizeof (%RI), (char ISC_FAR *) %RI);",
|
2001-05-23 15:26:42 +02:00
|
|
|
*pattern2 = "if (!%RH%IF && %S1%EN)";
|
|
|
|
|
|
|
|
args.pat_request = request = action->act_request;
|
|
|
|
args.pat_database = db = request->req_database;
|
|
|
|
args.pat_vector1 = status_vector(action);
|
|
|
|
args.pat_string1 = request_trans(action, request);
|
|
|
|
args.pat_condition = (sw_auto
|
|
|
|
&& (action->act_error
|
|
|
|
|| (action->act_flags & ACT_sql)));
|
|
|
|
|
|
|
|
if (sw_auto)
|
|
|
|
t_start_auto(action, request, status_vector(action), column, TRUE);
|
|
|
|
|
|
|
|
PATTERN_expand((USHORT) column, pattern2, &args);
|
|
|
|
|
|
|
|
args.pat_condition = !(request->req_flags & REQ_exp_hand);
|
|
|
|
args.pat_value1 = request->req_length;
|
|
|
|
PATTERN_expand((USHORT) (column + INDENT), pattern1, &args);
|
|
|
|
|
|
|
|
// 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) {
|
|
|
|
ib_fprintf(out_file, "\n");
|
|
|
|
align(column - INDENT);
|
|
|
|
for (; blob; blob = blob->blb_next)
|
|
|
|
ib_fprintf(out_file, "isc_%d = ", blob->blb_ident);
|
|
|
|
ib_fprintf(out_file, "0;");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate a call to create a database.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_create_database( ACT action, int column)
|
|
|
|
{
|
|
|
|
REQ request;
|
|
|
|
DBB db;
|
|
|
|
PAT args;
|
|
|
|
TEXT *pattern1 =
|
|
|
|
"isc_create_database (%V1, %N1, \"%DF\", &%DH, %IF%S1, %S2%EL(short) 0, (char*) 0%EN, 0);";
|
|
|
|
TEXT s1[32], s2[32], trname[32];
|
|
|
|
|
|
|
|
request = ((MDBB) action->act_object)->mdbb_dpb_request;
|
|
|
|
db = (DBB) request->req_database;
|
|
|
|
|
|
|
|
sprintf(s1, "isc_%dl", request->req_ident);
|
|
|
|
sprintf(trname, "isc_%dt", request->req_ident);
|
|
|
|
|
|
|
|
if (request->req_flags & REQ_extend_dpb) {
|
|
|
|
sprintf(s2, "isc_%dp", request->req_ident);
|
|
|
|
if (request->req_length)
|
|
|
|
printa(column, "%s = isc_%d;", s2, request->req_ident);
|
|
|
|
else
|
|
|
|
printa(column, "%s = (char*) 0;", s2);
|
|
|
|
|
|
|
|
printa(column,
|
|
|
|
"isc_expand_dpb (&%s, &%s, isc_dpb_user_name, %s, isc_dpb_password, %s, isc_dpb_sql_role_name, %s, isc_dpb_lc_messages, %s, isc_dpb_lc_ctype, %s, 0);",
|
|
|
|
s2, s1,
|
|
|
|
db->dbb_r_user ? db->dbb_r_user : "(char*) 0",
|
|
|
|
db->dbb_r_password ? db->dbb_r_password : "(char*) 0",
|
|
|
|
db->dbb_r_sql_role ? db->dbb_r_sql_role : "(char*) 0",
|
|
|
|
db->dbb_r_lc_messages ? db->dbb_r_lc_messages : "(char*) 0",
|
|
|
|
db->dbb_r_lc_ctype ? db->dbb_r_lc_ctype : "(char*) 0");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
sprintf(s2, "isc_%d", request->req_ident);
|
|
|
|
|
|
|
|
args.pat_vector1 = status_vector(action);
|
|
|
|
args.pat_request = request;
|
|
|
|
args.pat_database = db;
|
|
|
|
args.pat_value1 = strlen(db->dbb_filename);
|
|
|
|
args.pat_condition = (request->req_length
|
|
|
|
|| (request->req_flags & REQ_extend_dpb));
|
|
|
|
args.pat_string1 = s1;
|
|
|
|
args.pat_string2 = s2;
|
|
|
|
|
|
|
|
PATTERN_expand((USHORT) column, pattern1, &args);
|
|
|
|
|
|
|
|
// if the dpb was extended, free it here
|
|
|
|
|
|
|
|
if (request->req_flags & REQ_extend_dpb) {
|
|
|
|
if (request->req_length)
|
|
|
|
printa(column, "if (%s != isc_%d)", s2, request->req_ident);
|
2001-07-12 07:46:06 +02:00
|
|
|
printa(column + (request->req_length ? INDENT : 0), "isc_free ((char*) %s);",
|
2001-05-23 15:26:42 +02:00
|
|
|
s2);
|
|
|
|
|
|
|
|
/* reset the length of the dpb */
|
|
|
|
|
|
|
|
printa(column, "%s = %d;", s1, request->req_length);
|
|
|
|
}
|
|
|
|
|
|
|
|
request = action->act_request;
|
|
|
|
printa(column, "if (!%s [1])", status_name);
|
|
|
|
column += INDENT;
|
|
|
|
BEGIN;
|
|
|
|
printa(column,
|
2001-07-12 07:46:06 +02:00
|
|
|
"isc_start_transaction (%s, (void**) &%s, (short) 1, &%s, (short) 0, (char*) 0);",
|
2001-05-23 15:26:42 +02:00
|
|
|
status_vector(action), trname, db->dbb_name->sym_string);
|
|
|
|
printa(column, "if (%s)", trname);
|
|
|
|
column += INDENT;
|
|
|
|
align(column);
|
|
|
|
ib_fprintf(out_file, "isc_ddl (%s, &%s, &%s, (short) %d, isc_%d);",
|
|
|
|
status_vector(action),
|
|
|
|
request->req_database->dbb_name->sym_string,
|
|
|
|
trname, request->req_length, request->req_ident);
|
|
|
|
column -= INDENT;
|
|
|
|
printa(column, "if (!%s [1])", status_name);
|
2001-07-12 07:46:06 +02:00
|
|
|
printa(column + INDENT, "isc_commit_transaction (%s, (void**) &%s);",
|
2001-05-23 15:26:42 +02:00
|
|
|
status_vector(action), trname);
|
|
|
|
printa(column, "if (%s [1])", status_name);
|
2001-07-12 07:46:06 +02:00
|
|
|
printa(column + INDENT, "isc_rollback_transaction (%s, (void**) &%s);",
|
2001-05-23 15:26:42 +02:00
|
|
|
status_vector(NULL), trname);
|
|
|
|
SET_SQLCODE;
|
|
|
|
END;
|
|
|
|
printa(column - INDENT, "else");
|
|
|
|
SET_SQLCODE;
|
|
|
|
column -= INDENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate substitution text for END_STREAM.
|
|
|
|
//
|
|
|
|
|
2001-07-12 07:46:06 +02:00
|
|
|
static int gen_cursor_close( ACT action, REQ request, int column)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
PAT args;
|
|
|
|
TEXT *pattern1 =
|
|
|
|
"if (%RIs && !isc_dsql_free_statement (%V1, &%RIs, %N1))";
|
|
|
|
|
|
|
|
args.pat_request = request;
|
|
|
|
args.pat_vector1 = status_vector(action);
|
|
|
|
args.pat_value1 = 1;
|
|
|
|
|
|
|
|
PATTERN_expand((USHORT) column, pattern1, &args);
|
|
|
|
column += INDENT;
|
|
|
|
BEGIN;
|
|
|
|
|
|
|
|
return column;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate text to initialize a cursor.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_cursor_init( ACT action, int column)
|
|
|
|
{
|
|
|
|
|
|
|
|
// 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(column,
|
|
|
|
"isc_%d = 0;",
|
|
|
|
action->
|
|
|
|
act_request->
|
|
|
|
req_blobs->
|
|
|
|
blb_ident);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate text to open an embedded SQL cursor.
|
|
|
|
//
|
|
|
|
|
2001-07-12 07:46:06 +02:00
|
|
|
static int gen_cursor_open( ACT action, REQ request, int column)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
PAT args;
|
|
|
|
TEXT s[64];
|
|
|
|
TEXT *pattern1 = "if (!%RIs && %RH%IF && %DH%EN)",
|
|
|
|
*pattern2 = "if (!%RIs%IF && %DH%EN)",
|
|
|
|
*pattern3 = "isc_dsql_alloc_statement2 (%V1, &%DH, &%RIs);",
|
|
|
|
*pattern4 = "if (%RIs%IF && %S3%EN)",
|
|
|
|
*pattern5 = "if (!isc_dsql_set_cursor_name (%V1, &%RIs, %S1, 0) &&",
|
|
|
|
*pattern6 =
|
|
|
|
"!isc_dsql_execute_m (%V1, &%S3, &%RIs, 0, %S2, %N2, 0, %S2))";
|
|
|
|
|
|
|
|
args.pat_request = request;
|
|
|
|
args.pat_database = request->req_database;
|
|
|
|
args.pat_vector1 = status_vector(action);
|
|
|
|
args.pat_condition = sw_auto && TRUE;
|
|
|
|
args.pat_string1 = make_name(s, ((OPN) action->act_object)->opn_cursor);
|
|
|
|
args.pat_string2 = NULL_STRING;
|
|
|
|
args.pat_string3 = request_trans(action, request);
|
|
|
|
args.pat_value2 = -1;
|
|
|
|
|
|
|
|
PATTERN_expand((USHORT) column,
|
|
|
|
(action->act_type == ACT_open) ? pattern1 : pattern2,
|
|
|
|
&args);
|
|
|
|
PATTERN_expand((USHORT) (column + INDENT), pattern3, &args);
|
|
|
|
PATTERN_expand((USHORT) column, pattern4, &args);
|
|
|
|
column += INDENT;
|
|
|
|
BEGIN;
|
|
|
|
PATTERN_expand((USHORT) column, pattern5, &args);
|
|
|
|
column += INDENT;
|
|
|
|
PATTERN_expand((USHORT) column, pattern6, &args);
|
|
|
|
BEGIN;
|
|
|
|
|
|
|
|
return column;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate insertion text for the database statement.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_database( ACT action, int column)
|
|
|
|
{
|
|
|
|
DBB db;
|
|
|
|
REQ request;
|
|
|
|
TPB tpb;
|
|
|
|
TEXT *scope;
|
|
|
|
FORM form;
|
|
|
|
BOOLEAN all_static, all_extern;
|
|
|
|
SSHORT count, max_count;
|
|
|
|
LLS stack_ptr;
|
|
|
|
REF reference;
|
|
|
|
POR port;
|
|
|
|
|
|
|
|
if (first_flag++ != 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
ib_fprintf(out_file, "\n/**** GDS Preprocessor Definitions ****/\n");
|
|
|
|
ib_fprintf(out_file, "#ifndef JRD_IBASE_H\n#include %s\n#endif\n",
|
|
|
|
GDS_INCLUDE);
|
|
|
|
|
|
|
|
printa(column, "static %sISC_QUAD", CONST_STR);
|
|
|
|
printa(column + INDENT,
|
|
|
|
"isc_blob_null = {0,0};\t/* initializer for blobs */");
|
|
|
|
|
|
|
|
for (db = isc_databases; db; db = db->dbb_next)
|
|
|
|
for (form = db->dbb_forms; form; form = form->form_next)
|
|
|
|
printa(column, "static isc_form_handle %s;\t\t/* form %s */",
|
|
|
|
form->form_handle, form->form_name->sym_string);
|
|
|
|
|
|
|
|
if (sw_language == lang_c)
|
|
|
|
printa(column,
|
|
|
|
"static %slong *gds__null = 0;\t/* dummy status vector */",
|
|
|
|
CONST_STR);
|
|
|
|
|
|
|
|
scope = "";
|
|
|
|
|
|
|
|
all_static = all_extern = TRUE;
|
|
|
|
for (db = isc_databases; db; db = db->dbb_next) {
|
|
|
|
all_static = all_static && (db->dbb_scope == DBB_STATIC);
|
|
|
|
all_extern = all_extern && (db->dbb_scope == DBB_EXTERN);
|
|
|
|
if (db->dbb_scope == DBB_STATIC)
|
|
|
|
scope = "static ";
|
|
|
|
else if (db->dbb_scope == DBB_EXTERN &&
|
|
|
|
TRUE)
|
|
|
|
scope = "extern ";
|
|
|
|
printa(column, "%sisc_db_handle", scope);
|
|
|
|
if (!all_extern)
|
|
|
|
printa(column + INDENT, "%s = 0;\t\t/* database handle */\n",
|
|
|
|
db->dbb_name->sym_string);
|
|
|
|
else
|
|
|
|
printa(column + INDENT, "%s;\t\t/* database handle */\n",
|
|
|
|
db->dbb_name->sym_string);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (all_static)
|
|
|
|
scope = "static ";
|
|
|
|
else if (all_extern)
|
|
|
|
scope = "extern ";
|
|
|
|
|
|
|
|
printa(column, "%sisc_tr_handle", scope);
|
|
|
|
if (!all_extern)
|
|
|
|
printa(column + INDENT, "%s = 0;\t\t/* default transaction handle */",
|
|
|
|
transaction_name);
|
|
|
|
else
|
|
|
|
printa(column + INDENT, "%s;\t\t/* default transaction handle */",
|
|
|
|
transaction_name);
|
|
|
|
|
|
|
|
printa(column, "%slong", scope);
|
|
|
|
column += INDENT;
|
|
|
|
printa(column, "%s [20],\t/* status vector */", status_name);
|
|
|
|
printa(column, "%s2 [20];\t/* status vector */", status_name);
|
|
|
|
printa(column - INDENT, "%s%s", scope, DCL_LONG);
|
|
|
|
printa(column, "isc_array_length, \t/* array return size */");
|
|
|
|
printa(column, "SQLCODE;\t\t/* SQL status code */");
|
|
|
|
|
|
|
|
#if (defined JPN_EUC || defined JPN_SJIS)
|
|
|
|
// Generate the default dpb to pass the users interpretation
|
|
|
|
|
|
|
|
ib_fprintf(out_file, "\n");
|
|
|
|
printa(column - INDENT, "static short");
|
|
|
|
printa(column, "isc_dpb_size = %d;", default_dpb_size);
|
|
|
|
printa(column - INDENT, "static char");
|
|
|
|
printa(column, "isc_dpb [] = {");
|
|
|
|
column += INDENT;
|
|
|
|
PRETTY_print_cdb(default_dpb, gen_blr, 0, 0);
|
|
|
|
column -= INDENT;
|
|
|
|
printa(column, "}; \t\t\t/* default dpb */");
|
|
|
|
ib_fprintf(out_file, "\n");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (sw_pyxis)
|
|
|
|
{
|
|
|
|
if (sw_window_scope == DBB_STATIC)
|
|
|
|
scope = "static ";
|
|
|
|
else if (sw_window_scope == DBB_EXTERN)
|
|
|
|
scope = "extern ";
|
|
|
|
else
|
|
|
|
scope = "";
|
|
|
|
printa(column - INDENT,
|
|
|
|
"%sisc_win_handle isc_window;\t/* window handle */", scope);
|
|
|
|
printa(column - INDENT, "%sshort", scope);
|
|
|
|
printa(column, "isc_width%s,\t/* window width */",
|
|
|
|
(sw_window_scope == DBB_EXTERN) ? "" : " = 80");
|
|
|
|
printa(column, "isc_height%s;\t/* window height */",
|
|
|
|
(sw_window_scope == DBB_EXTERN) ? "" : " = 24");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sw_dyn_using) {
|
|
|
|
printa(column - INDENT,
|
|
|
|
"static struct isc_sqlda { /* SQLDA for internal use */");
|
|
|
|
printa(column, "char sqldaid [8];");
|
|
|
|
printa(column, "%s sqldabc;", DCL_LONG);
|
|
|
|
printa(column, "short sqln;");
|
|
|
|
printa(column, "short sqld;");
|
|
|
|
printa(column, "SQLVAR sqlvar[%d];", sw_dyn_using);
|
|
|
|
printa(column, "}");
|
|
|
|
}
|
|
|
|
|
|
|
|
column -= INDENT;
|
|
|
|
|
|
|
|
for (db = isc_databases; db; db = db->dbb_next)
|
|
|
|
for (tpb = db->dbb_tpbs; tpb; tpb = tpb->tpb_dbb_next)
|
|
|
|
gen_tpb(tpb, column);
|
|
|
|
|
|
|
|
// generate event parameter block for each event in module
|
|
|
|
|
|
|
|
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(column, "%s%s isc_events [%d];\t/* event vector */", scope,
|
|
|
|
DCL_LONG, max_count);
|
|
|
|
|
|
|
|
for (request = requests; request; request = request->req_next) {
|
|
|
|
gen_request(request);
|
|
|
|
|
|
|
|
/* Array declarations */
|
|
|
|
|
|
|
|
if (port = request->req_primary)
|
|
|
|
for (reference = port->por_references; reference;
|
|
|
|
reference = reference->ref_next)
|
|
|
|
if (reference->ref_flags & REF_fetch_array)
|
|
|
|
make_array_declaration(reference);
|
|
|
|
}
|
|
|
|
|
|
|
|
ib_fprintf(out_file, "\n\n");
|
|
|
|
gen_compatibility_symbol("blob_null", "isc_",
|
|
|
|
"\t/* compatibility symbols */");
|
|
|
|
// ****
|
|
|
|
//gen_compatibility_symbol ("database", "isc_", "");
|
|
|
|
//gen_compatibility_symbol ("trans", "isc_", "");
|
|
|
|
//***
|
|
|
|
gen_compatibility_symbol("status", "isc_", "");
|
|
|
|
gen_compatibility_symbol("status2", "isc_", "");
|
|
|
|
gen_compatibility_symbol("array_length", "isc_", "");
|
|
|
|
if (max_count)
|
|
|
|
gen_compatibility_symbol("events", "isc_", "");
|
|
|
|
if (sw_pyxis) {
|
|
|
|
gen_compatibility_symbol("window", "isc_", "");
|
|
|
|
gen_compatibility_symbol("height", "isc_", "");
|
|
|
|
gen_compatibility_symbol("width", "isc_", "");
|
|
|
|
}
|
|
|
|
gen_compatibility_symbol("count", "isc_", "");
|
|
|
|
gen_compatibility_symbol("slack", "isc_", "");
|
|
|
|
gen_compatibility_symbol("utility", "isc_",
|
|
|
|
"\t/* end of compatibility symbols */");
|
|
|
|
|
|
|
|
ib_fprintf(out_file, "\n#ifndef isc_version4\n");
|
|
|
|
ib_fprintf(out_file, " Generate a compile-time error.\n");
|
|
|
|
ib_fprintf(out_file,
|
|
|
|
" Picking up a V3 include file after preprocessing with V4 GPRE.\n");
|
|
|
|
ib_fprintf(out_file, "#endif\n");
|
|
|
|
ib_fprintf(out_file, "\n/**** end of GPRE definitions ****/\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate a call to update metadata.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_ddl( ACT action, int column)
|
|
|
|
{
|
|
|
|
REQ request;
|
|
|
|
|
|
|
|
// Set up command type for call to RDB$DDL
|
|
|
|
|
|
|
|
request = action->act_request;
|
|
|
|
|
|
|
|
if (sw_auto) {
|
|
|
|
t_start_auto(action, 0, status_vector(action), column, TRUE);
|
|
|
|
printa(column, "if (%s)", transaction_name);
|
|
|
|
column += INDENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
align(column);
|
|
|
|
ib_fprintf(out_file, "isc_ddl (%s, &%s, &%s, (short) %d, isc_%d);",
|
|
|
|
status_vector(action),
|
|
|
|
request->req_database->dbb_name->sym_string,
|
|
|
|
transaction_name, request->req_length, request->req_ident);
|
|
|
|
|
|
|
|
if (sw_auto) {
|
|
|
|
column -= INDENT;
|
|
|
|
printa(column, "if (!%s [1])", status_name);
|
2001-07-12 07:46:06 +02:00
|
|
|
printa(column + INDENT, "isc_commit_transaction (%s, (void**) &%s);",
|
2001-05-23 15:26:42 +02:00
|
|
|
status_vector(action), transaction_name);
|
|
|
|
printa(column, "if (%s [1])", status_name);
|
2001-07-12 07:46:06 +02:00
|
|
|
printa(column + INDENT, "isc_rollback_transaction (%s, (void**) &%s);",
|
2001-05-23 15:26:42 +02:00
|
|
|
status_vector(NULL), transaction_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
SET_SQLCODE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate a call to create a database.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_drop_database( ACT action, int column)
|
|
|
|
{
|
|
|
|
DBB db;
|
|
|
|
|
|
|
|
db = (DBB) action->act_object;
|
|
|
|
align(column);
|
|
|
|
|
|
|
|
ib_fprintf(out_file,
|
|
|
|
"isc_drop_database (%s, %d, \"%s\", rdb$k_db_type_gds);",
|
|
|
|
status_vector(action),
|
|
|
|
strlen(db->dbb_filename), db->dbb_filename);
|
|
|
|
SET_SQLCODE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate a dynamic SQL statement.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_dyn_close( ACT action, int column)
|
|
|
|
{
|
|
|
|
DYN statement;
|
|
|
|
TEXT s[64];
|
|
|
|
|
|
|
|
statement = (DYN) action->act_object;
|
|
|
|
printa(column,
|
|
|
|
"isc_embed_dsql_close (%s, %s);",
|
|
|
|
status_name, make_name(s, statement->dyn_cursor_name));
|
|
|
|
SET_SQLCODE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate a dynamic SQL statement.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_dyn_declare( ACT action, int column)
|
|
|
|
{
|
|
|
|
DYN statement;
|
|
|
|
TEXT s1[64], s2[64];
|
|
|
|
|
|
|
|
statement = (DYN) action->act_object;
|
|
|
|
printa(column,
|
|
|
|
"isc_embed_dsql_declare (%s, %s, %s);",
|
|
|
|
status_name,
|
|
|
|
make_name(s1, statement->dyn_statement_name),
|
|
|
|
make_name(s2, statement->dyn_cursor_name));
|
|
|
|
SET_SQLCODE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate a dynamic SQL statement.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_dyn_describe( ACT action, int column, BOOLEAN bind_flag)
|
|
|
|
{
|
|
|
|
DYN statement;
|
|
|
|
TEXT s[64];
|
|
|
|
|
|
|
|
statement = (DYN) action->act_object;
|
|
|
|
printa(column,
|
|
|
|
"isc_embed_dsql_describe%s (%s, %s, %d, %s);",
|
|
|
|
bind_flag ? "_bind" : "",
|
|
|
|
status_name,
|
|
|
|
make_name(s, statement->dyn_statement_name),
|
|
|
|
sw_sql_dialect, statement->dyn_sqlda);
|
|
|
|
SET_SQLCODE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate a dynamic SQL statement.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_dyn_execute( ACT action, int column)
|
|
|
|
{
|
|
|
|
|
|
|
|
DYN statement = (DYN) action->act_object;
|
|
|
|
TEXT *transaction;
|
|
|
|
TEXT s[64];
|
|
|
|
struct req *request, req_const;
|
|
|
|
|
|
|
|
if (statement->dyn_trans) {
|
|
|
|
transaction = statement->dyn_trans;
|
|
|
|
request = &req_const;
|
|
|
|
request->req_trans = transaction;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
transaction = transaction_name;
|
|
|
|
request = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sw_auto) {
|
|
|
|
t_start_auto(action, request, status_vector(action), column, TRUE);
|
|
|
|
printa(column, "if (%s)", transaction);
|
|
|
|
column += INDENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (statement->dyn_sqlda2)
|
|
|
|
printa(column,
|
|
|
|
"isc_embed_dsql_execute2 (%s, &%s, %s, %d, %s, %s);",
|
|
|
|
status_name,
|
|
|
|
transaction,
|
|
|
|
make_name(s, statement->dyn_statement_name),
|
|
|
|
sw_sql_dialect,
|
|
|
|
(statement->dyn_sqlda) ? statement->dyn_sqlda : NULL_STRING,
|
|
|
|
statement->dyn_sqlda2);
|
|
|
|
else
|
|
|
|
printa(column,
|
|
|
|
"isc_embed_dsql_execute (%s, &%s, %s, %d, %s);",
|
|
|
|
status_name,
|
|
|
|
transaction,
|
|
|
|
make_name(s, statement->dyn_statement_name),
|
|
|
|
sw_sql_dialect,
|
|
|
|
(statement->dyn_sqlda) ? statement->dyn_sqlda : NULL_STRING);
|
|
|
|
|
|
|
|
if (sw_auto)
|
|
|
|
column -= INDENT;
|
|
|
|
|
|
|
|
SET_SQLCODE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate a dynamic SQL statement.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_dyn_fetch( ACT action, int column)
|
|
|
|
{
|
|
|
|
DYN statement;
|
|
|
|
TEXT s[64];
|
|
|
|
|
|
|
|
statement = (DYN) action->act_object;
|
|
|
|
printa(column,
|
|
|
|
"SQLCODE = isc_embed_dsql_fetch (%s, %s, %d, %s);",
|
|
|
|
status_name,
|
|
|
|
make_name(s, statement->dyn_cursor_name),
|
|
|
|
sw_sql_dialect,
|
|
|
|
(statement->dyn_sqlda) ? statement->dyn_sqlda : NULL_SQLDA);
|
|
|
|
|
|
|
|
printa(column, "if (SQLCODE != 100) SQLCODE = isc_sqlcode (%s);",
|
|
|
|
status_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate code for an EXECUTE IMMEDIATE dynamic SQL statement.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_dyn_immediate( ACT action, int column)
|
|
|
|
{
|
|
|
|
DYN statement;
|
|
|
|
DBB database;
|
|
|
|
TEXT *transaction;
|
|
|
|
struct req *request, 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 = transaction_name;
|
|
|
|
request = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sw_auto) {
|
|
|
|
t_start_auto(action, request, status_vector(action), column, TRUE);
|
|
|
|
printa(column, "if (%s)", transaction);
|
|
|
|
column += INDENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
printa(column,
|
|
|
|
(statement->dyn_sqlda2) ?
|
|
|
|
"isc_embed_dsql_execute_immed2 (%s, &%s, &%s, 0, %s, %d, %s, %s);"
|
|
|
|
: "isc_embed_dsql_execute_immed (%s, &%s, &%s, 0, %s, %d, %s);",
|
|
|
|
status_name, database->dbb_name->sym_string, transaction,
|
|
|
|
statement->dyn_string, sw_sql_dialect,
|
|
|
|
(statement->dyn_sqlda) ? statement->dyn_sqlda : NULL_SQLDA,
|
|
|
|
(statement->dyn_sqlda2) ? statement->dyn_sqlda2 : NULL_SQLDA);
|
|
|
|
|
|
|
|
if (sw_auto)
|
|
|
|
column -= INDENT;
|
|
|
|
|
|
|
|
SET_SQLCODE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate a dynamic SQL statement.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_dyn_insert( ACT action, int column)
|
|
|
|
{
|
|
|
|
DYN statement;
|
|
|
|
TEXT s[64];
|
|
|
|
|
|
|
|
statement = (DYN) action->act_object;
|
|
|
|
printa(column,
|
|
|
|
"isc_embed_dsql_insert (%s, %s, %d, %s);",
|
|
|
|
status_name,
|
|
|
|
make_name(s, statement->dyn_cursor_name),
|
|
|
|
sw_sql_dialect,
|
|
|
|
(statement->dyn_sqlda) ? statement->dyn_sqlda : NULL_SQLDA);
|
|
|
|
|
|
|
|
SET_SQLCODE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate a dynamic SQL statement.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_dyn_open( ACT action, int column)
|
|
|
|
{
|
|
|
|
DYN statement;
|
|
|
|
TEXT *transaction, s[64];
|
|
|
|
struct req *request, req_const;
|
|
|
|
|
|
|
|
statement = (DYN) action->act_object;
|
|
|
|
if (statement->dyn_trans) {
|
|
|
|
transaction = statement->dyn_trans;
|
|
|
|
request = &req_const;
|
|
|
|
request->req_trans = transaction;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
transaction = transaction_name;
|
|
|
|
request = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sw_auto) {
|
|
|
|
t_start_auto(action, request, status_vector(action), column, TRUE);
|
|
|
|
printa(column, "if (%s)", transaction);
|
|
|
|
column += INDENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
make_name(s, statement->dyn_cursor_name);
|
|
|
|
|
|
|
|
printa(column,
|
|
|
|
(statement->dyn_sqlda2) ?
|
|
|
|
"isc_embed_dsql_open2 (%s, &%s, %s, %d, %s, %s);" :
|
|
|
|
"isc_embed_dsql_open (%s, &%s, %s, %d, %s);",
|
|
|
|
status_name,
|
|
|
|
transaction,
|
|
|
|
s,
|
|
|
|
sw_sql_dialect,
|
|
|
|
(statement->dyn_sqlda) ? statement->dyn_sqlda : NULL_SQLDA,
|
|
|
|
(statement->dyn_sqlda2) ? statement->dyn_sqlda2 : NULL_SQLDA);
|
|
|
|
|
|
|
|
if (sw_auto)
|
|
|
|
column -= INDENT;
|
|
|
|
|
|
|
|
SET_SQLCODE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate a dynamic SQL statement.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_dyn_prepare( ACT action, int column)
|
|
|
|
{
|
|
|
|
DYN statement;
|
|
|
|
DBB database;
|
|
|
|
TEXT s[64], *transaction;
|
|
|
|
struct req *request, 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 = transaction_name;
|
|
|
|
request = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sw_auto) {
|
|
|
|
t_start_auto(action, request, status_vector(action), column, TRUE);
|
|
|
|
printa(column, "if (%s)", transaction);
|
|
|
|
column += INDENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
printa(column,
|
|
|
|
"isc_embed_dsql_prepare (%s, &%s, &%s, %s, 0, %s, %d, %s);",
|
|
|
|
status_name, database->dbb_name->sym_string, transaction,
|
|
|
|
make_name(s, statement->dyn_statement_name), statement->dyn_string,
|
|
|
|
sw_sql_dialect,
|
|
|
|
(statement->dyn_sqlda) ? statement->dyn_sqlda : NULL_SQLDA);
|
|
|
|
|
|
|
|
if (sw_auto)
|
|
|
|
column -= INDENT;
|
|
|
|
|
|
|
|
SET_SQLCODE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate substitution text for END_MODIFY.
|
|
|
|
//
|
|
|
|
// Trickier because a fixed subtype single character
|
|
|
|
// field is a single character, not a pointer to a
|
|
|
|
// single character.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_emodify( ACT action, int column)
|
|
|
|
{
|
|
|
|
UPD modify;
|
|
|
|
REF reference, source;
|
|
|
|
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;
|
|
|
|
align(column);
|
|
|
|
gen_name(s1, source, TRUE);
|
|
|
|
gen_name(s2, reference, TRUE);
|
|
|
|
if (field->fld_dtype > dtype_cstring ||
|
|
|
|
(field->fld_sub_type == 1 && field->fld_length == 1))
|
|
|
|
ib_fprintf(out_file, "%s = %s;", s2, s1);
|
|
|
|
#if (! (defined JPN_SJIS || defined JPN_EUC) )
|
|
|
|
else if (sw_cstring && !field->fld_sub_type)
|
2001-07-12 07:46:06 +02:00
|
|
|
ib_fprintf(out_file, "isc_vtov ((char*)%s, (char*)%s, %d);",
|
2001-05-23 15:26:42 +02:00
|
|
|
s1, s2, field->fld_length);
|
|
|
|
else
|
|
|
|
ib_fprintf(out_file, "isc_ftof (%s, %d, %s, %d);",
|
|
|
|
s1, field->fld_length, s2, field->fld_length);
|
|
|
|
#else
|
|
|
|
/* To avoid chopping off a double byte kanji character in between
|
|
|
|
the two bytes, generate calls to isc_ftof2 iscvtof2 and
|
|
|
|
iscvtov2 wherever necessary */
|
|
|
|
|
|
|
|
else if (sw_cstring && !field->fld_sub_type)
|
|
|
|
ib_fprintf(out_file, "isc_vtov2 (%s, %s, %d, %d);",
|
|
|
|
s1, s2, field->fld_length, sw_interp);
|
|
|
|
else
|
|
|
|
ib_fprintf(out_file, "isc_ftof2 (%s, %d, %s, %d, %d);",
|
|
|
|
s1, field->fld_length, s2, field->fld_length,
|
|
|
|
sw_interp);
|
|
|
|
#endif
|
|
|
|
if (field->fld_array_info)
|
|
|
|
gen_get_or_put_slice(action, reference, FALSE, column);
|
|
|
|
}
|
|
|
|
|
|
|
|
gen_send(action, modify->upd_port, column);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate substitution text for END_STORE.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_estore( ACT action, int column)
|
|
|
|
{
|
|
|
|
REQ request;
|
|
|
|
|
|
|
|
request = action->act_request;
|
|
|
|
|
|
|
|
// if we did a store ... returning_values aka store2
|
|
|
|
// just wrap up pending error and return
|
|
|
|
|
|
|
|
if (request->req_type == REQ_store2) {
|
|
|
|
if (action->act_error)
|
|
|
|
END;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (action->act_error)
|
|
|
|
column += INDENT;
|
|
|
|
|
|
|
|
align(column);
|
|
|
|
gen_start(action, request->req_primary, column, TRUE);
|
|
|
|
|
|
|
|
if (action->act_error)
|
|
|
|
END;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate definitions associated with a single request.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_endfor( ACT action, int column)
|
|
|
|
{
|
|
|
|
REQ request;
|
|
|
|
|
|
|
|
request = action->act_request;
|
|
|
|
column += INDENT;
|
|
|
|
|
|
|
|
if (request->req_sync)
|
|
|
|
gen_send(action, request->req_sync, column);
|
|
|
|
|
|
|
|
END;
|
|
|
|
|
|
|
|
if (action->act_error || (action->act_flags & ACT_sql))
|
|
|
|
END;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate substitution text for ERASE.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_erase( ACT action, int column)
|
|
|
|
{
|
|
|
|
UPD erase;
|
|
|
|
|
|
|
|
if (action->act_error || (action->act_flags & ACT_sql))
|
|
|
|
BEGIN;
|
|
|
|
|
|
|
|
erase = (UPD) action->act_object;
|
|
|
|
gen_send(action, erase->upd_port, column);
|
|
|
|
|
|
|
|
if (action->act_flags & ACT_sql)
|
|
|
|
END;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate event parameter blocks for use
|
|
|
|
// with a particular call to isc_event_wait.
|
|
|
|
//
|
|
|
|
|
|
|
|
static SSHORT gen_event_block( ACT action)
|
|
|
|
{
|
|
|
|
NOD init, list;
|
|
|
|
SYM event_name;
|
|
|
|
int ident;
|
|
|
|
|
|
|
|
init = (NOD) action->act_object;
|
|
|
|
event_name = (SYM) init->nod_arg[0];
|
|
|
|
|
|
|
|
ident = CMP_next_ident();
|
|
|
|
init->nod_arg[2] = (NOD) ident;
|
|
|
|
|
|
|
|
printa(0, "static %schar\n *isc_%da, *isc_%db;", CONST_STR, ident,
|
|
|
|
ident);
|
|
|
|
printa(0, "static short\n isc_%dl;", ident);
|
|
|
|
|
|
|
|
list = init->nod_arg[1];
|
|
|
|
return list->nod_count;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate substitution text for EVENT_INIT.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_event_init( ACT action, int column)
|
|
|
|
{
|
|
|
|
NOD init, event_list, *ptr, *end, node;
|
|
|
|
REF reference;
|
|
|
|
PAT args;
|
|
|
|
TEXT variable[20];
|
|
|
|
TEXT
|
|
|
|
* pattern1 =
|
|
|
|
"isc_%N1l = isc_event_block (&isc_%N1a, &isc_%N1b, (short) %N2",
|
|
|
|
*pattern2 =
|
|
|
|
"isc_wait_for_event (%V1, &%DH, isc_%N1l, isc_%N1a, isc_%N1b);",
|
|
|
|
*pattern3 =
|
|
|
|
"isc_event_counts (isc_events, isc_%N1l, isc_%N1a, isc_%N1b);";
|
|
|
|
|
|
|
|
if (action->act_error)
|
|
|
|
BEGIN;
|
|
|
|
BEGIN;
|
|
|
|
|
|
|
|
init = (NOD) action->act_object;
|
|
|
|
event_list = init->nod_arg[1];
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
// generate call to dynamically generate event blocks
|
|
|
|
|
|
|
|
PATTERN_expand((USHORT) column, pattern1, &args);
|
|
|
|
|
|
|
|
for (ptr = event_list->nod_arg, end = ptr + event_list->nod_count;
|
|
|
|
ptr < end; ptr++) {
|
|
|
|
node = *ptr;
|
|
|
|
if (node->nod_type == nod_field) {
|
|
|
|
reference = (REF) node->nod_arg[0];
|
|
|
|
gen_name(variable, reference, TRUE);
|
|
|
|
printb(", %s", variable);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
printb(", %s", node->nod_arg[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
printb(");");
|
|
|
|
|
|
|
|
// generate actual call to event_wait
|
|
|
|
|
|
|
|
PATTERN_expand((USHORT) column, pattern2, &args);
|
|
|
|
|
|
|
|
// get change in event counts, copying event parameter block for reuse
|
|
|
|
|
|
|
|
PATTERN_expand((USHORT) column, pattern3, &args);
|
|
|
|
|
|
|
|
if (action->act_error)
|
|
|
|
END;
|
|
|
|
SET_SQLCODE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate substitution text for EVENT_WAIT.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_event_wait( ACT action, int column)
|
|
|
|
{
|
|
|
|
PAT args;
|
|
|
|
NOD event_init;
|
|
|
|
SYM event_name, stack_name;
|
|
|
|
DBB database;
|
|
|
|
LLS stack_ptr;
|
|
|
|
ACT event_action;
|
|
|
|
int ident;
|
|
|
|
TEXT s[64];
|
|
|
|
TEXT
|
|
|
|
* pattern1 =
|
|
|
|
"isc_wait_for_event (%V1, &%DH, isc_%N1l, isc_%N1a, isc_%N1b);",
|
|
|
|
*pattern2 =
|
|
|
|
"isc_event_counts (isc_events, isc_%N1l, isc_%N1a, isc_%N1b);";
|
|
|
|
|
|
|
|
if (action->act_error)
|
|
|
|
BEGIN;
|
|
|
|
BEGIN;
|
|
|
|
|
|
|
|
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 = (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;
|
|
|
|
}
|
|
|
|
|
|
|
|
args.pat_database = database;
|
|
|
|
args.pat_vector1 = status_vector(action);
|
|
|
|
args.pat_value1 = (int) ident;
|
|
|
|
|
|
|
|
// generate calls to wait on the event and to fill out the events array
|
|
|
|
|
|
|
|
PATTERN_expand((USHORT) column, pattern1, &args);
|
|
|
|
PATTERN_expand((USHORT) column, pattern2, &args);
|
|
|
|
|
|
|
|
if (action->act_error)
|
|
|
|
END;
|
|
|
|
SET_SQLCODE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// 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, int column)
|
|
|
|
{
|
|
|
|
REQ request;
|
|
|
|
NOD var_list;
|
|
|
|
int i;
|
|
|
|
TEXT s[20];
|
|
|
|
|
|
|
|
#ifdef SCROLLABLE_CURSORS
|
|
|
|
POR port;
|
|
|
|
SCHAR *direction;
|
|
|
|
SCHAR *offset;
|
|
|
|
VAL value;
|
|
|
|
REF reference;
|
|
|
|
#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(column, "if (isc_%ddirection %% 2 != %s || %s != 1)",
|
|
|
|
request->req_ident, direction, offset);
|
|
|
|
column += INDENT;
|
|
|
|
BEGIN;
|
|
|
|
|
|
|
|
/* assign the direction and offset parameters to the appropriate message,
|
|
|
|
then send the message to the engine */
|
|
|
|
|
|
|
|
asgn_from(action, port->por_references, column);
|
|
|
|
gen_send(action, port, column);
|
|
|
|
printa(column, "isc_%ddirection = %s;", request->req_ident,
|
|
|
|
direction);
|
|
|
|
column -= INDENT;
|
|
|
|
END;
|
|
|
|
|
|
|
|
printa(column, "if (!SQLCODE)");
|
|
|
|
column += INDENT;
|
|
|
|
BEGIN;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (request->req_sync) {
|
|
|
|
gen_send(action, request->req_sync, column);
|
|
|
|
printa(column, "if (!SQLCODE)");
|
|
|
|
column += INDENT;
|
|
|
|
BEGIN;
|
|
|
|
}
|
|
|
|
|
|
|
|
gen_receive(action, column, request->req_primary);
|
|
|
|
printa(column, "if (!SQLCODE)");
|
|
|
|
column += INDENT;
|
|
|
|
printa(column, "if (%s)", gen_name(s, request->req_eof, TRUE));
|
|
|
|
column += INDENT;
|
|
|
|
BEGIN;
|
|
|
|
|
|
|
|
if (var_list = (NOD) action->act_object)
|
|
|
|
for (i = 0; i < var_list->nod_count; i++) {
|
|
|
|
align(column);
|
|
|
|
asgn_to(action, (REF) (var_list->nod_arg[i]), column);
|
|
|
|
}
|
|
|
|
END;
|
|
|
|
printa(column - INDENT, "else");
|
|
|
|
printa(column, "SQLCODE = 100;");
|
|
|
|
|
|
|
|
if (request->req_sync) {
|
|
|
|
column -= INDENT;
|
|
|
|
END;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef SCROLLABLE_CURSORS
|
|
|
|
if (port) {
|
|
|
|
column -= INDENT;
|
|
|
|
END;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate substitution text for FINISH
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_finish( ACT action, int column)
|
|
|
|
{
|
|
|
|
DBB db;
|
|
|
|
RDY ready;
|
|
|
|
PAT args;
|
|
|
|
TEXT *pattern1 = "if (%S2)\n\
|
2001-07-12 07:46:06 +02:00
|
|
|
isc_%S1_transaction (%V1, (void**) &%S2);";
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
args.pat_vector1 = status_vector(action);
|
|
|
|
args.pat_string2 = transaction_name;
|
|
|
|
|
|
|
|
if (sw_auto || ((action->act_flags & ACT_sql) &&
|
|
|
|
(action->act_type != ACT_disconnect))) {
|
2001-07-12 07:46:06 +02:00
|
|
|
args.pat_string1 = (TEXT*)
|
|
|
|
((action->act_type != ACT_rfinish) ? "commit" : "rollback");
|
2001-05-23 15:26:42 +02:00
|
|
|
PATTERN_expand((USHORT) column, pattern1, &args);
|
|
|
|
}
|
|
|
|
|
|
|
|
db = NULL;
|
|
|
|
|
|
|
|
// the user supplied one or more db_handles
|
|
|
|
|
|
|
|
for (ready = (RDY) action->act_object; ready; ready = ready->rdy_next) {
|
|
|
|
db = ready->rdy_database;
|
|
|
|
printa(column, "isc_detach_database (%s, &%s);",
|
|
|
|
status_vector(action), db->dbb_name->sym_string);
|
|
|
|
}
|
|
|
|
// no hanbdles, so we finish all known databases
|
|
|
|
|
|
|
|
if (!db)
|
|
|
|
for (db = isc_databases; db; db = db->dbb_next) {
|
|
|
|
if ((action->act_error || (action->act_flags & ACT_sql)) &&
|
|
|
|
(db != isc_databases))
|
|
|
|
printa(column, "if (%s && !%s [1]) ",
|
|
|
|
db->dbb_name->sym_string, status_name);
|
|
|
|
else
|
|
|
|
printa(column, "if (%s)", db->dbb_name->sym_string);
|
|
|
|
printa(column + INDENT, "isc_detach_database (%s, &%s);",
|
|
|
|
status_vector(action), db->dbb_name->sym_string);
|
|
|
|
}
|
|
|
|
|
|
|
|
SET_SQLCODE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate substitution text for FOR statement.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_for( ACT action, int column)
|
|
|
|
{
|
|
|
|
POR port;
|
|
|
|
REQ request;
|
|
|
|
TEXT s[20];
|
|
|
|
REF reference;
|
|
|
|
|
|
|
|
gen_s_start(action, column);
|
|
|
|
request = action->act_request;
|
|
|
|
|
|
|
|
if (action->act_error || (action->act_flags & ACT_sql))
|
|
|
|
printa(column, "if (!%s [1]) {", status_name);
|
|
|
|
|
|
|
|
printa(column, "while (1)");
|
|
|
|
column += INDENT;
|
|
|
|
BEGIN;
|
|
|
|
gen_receive(action, column, request->req_primary);
|
|
|
|
|
|
|
|
if (action->act_error || (action->act_flags & ACT_sql))
|
|
|
|
printa(column, "if (!%s || %s [1]) break;",
|
|
|
|
gen_name(s, request->req_eof, TRUE), status_name);
|
|
|
|
else
|
|
|
|
printa(column, "if (!%s) break;",
|
|
|
|
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, column);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate code for a form interaction.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_form_display( ACT action, int column)
|
|
|
|
{
|
|
|
|
FINT display;
|
|
|
|
REQ request;
|
|
|
|
REF reference, master;
|
|
|
|
POR port;
|
|
|
|
DBB dbb;
|
2001-07-12 07:46:06 +02:00
|
|
|
TEXT s[32], out[16];
|
|
|
|
const char *status;
|
2001-05-23 15:26:42 +02:00
|
|
|
int code;
|
|
|
|
|
|
|
|
display = (FINT) action->act_object;
|
|
|
|
request = display->fint_request;
|
|
|
|
dbb = request->req_database;
|
|
|
|
port = request->req_ports;
|
|
|
|
status = (action->act_error) ? status_name : NULL_STATUS;
|
|
|
|
|
|
|
|
// Initialize field options
|
|
|
|
|
|
|
|
for (reference = port->por_references; reference;
|
|
|
|
reference = reference->ref_next)
|
|
|
|
if ((master = reference->ref_master) &&
|
|
|
|
(code = CMP_display_code(display, master)) >= 0)
|
|
|
|
printa(column, "%s = %d;", gen_name(s, reference, TRUE), code);
|
|
|
|
|
|
|
|
if (display->fint_flags & FINT_no_wait)
|
|
|
|
strcpy(out, NULL_STRING);
|
|
|
|
else
|
|
|
|
sprintf(out, "&isc_%d", port->por_ident);
|
|
|
|
|
|
|
|
align(column);
|
|
|
|
ib_fprintf(out_file,
|
|
|
|
"isc_drive_form (%s, &%s, &%s, &isc_window, &%s, &isc_%d, %s);",
|
|
|
|
status,
|
|
|
|
dbb->dbb_name->sym_string,
|
|
|
|
request->req_trans, request->req_handle, port->por_ident, out);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate code for a form block.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_form_end( ACT action, int column)
|
|
|
|
{
|
|
|
|
|
|
|
|
printa(column, "isc_pop_window (%s, &isc_window);",
|
|
|
|
status_vector(action));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate code for a form block.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_form_for( ACT action, int column)
|
|
|
|
{
|
|
|
|
REQ request;
|
|
|
|
FORM form;
|
2001-07-12 07:46:06 +02:00
|
|
|
const char *status;
|
2001-05-23 15:26:42 +02:00
|
|
|
DBB dbb;
|
|
|
|
|
|
|
|
column += INDENT;
|
|
|
|
request = action->act_request;
|
|
|
|
form = request->req_form;
|
|
|
|
dbb = request->req_database;
|
|
|
|
status = (action->act_error) ? status_name : NULL_STATUS;
|
|
|
|
|
|
|
|
// Get database attach and transaction started
|
|
|
|
|
|
|
|
if (sw_auto)
|
|
|
|
t_start_auto(action, 0, status_vector(action), column, TRUE);
|
|
|
|
|
|
|
|
// Get form loaded first
|
|
|
|
|
|
|
|
printa(column, "if (!%s)", request->req_form_handle);
|
|
|
|
printa(column + INDENT,
|
|
|
|
"isc_load_form (%s, &%s, &%s, &%s, (short*) 0, \"%s\");", status,
|
|
|
|
dbb->dbb_name->sym_string, request->req_trans,
|
|
|
|
request->req_form_handle, form->form_name->sym_string);
|
|
|
|
|
|
|
|
// Get map compiled
|
|
|
|
|
|
|
|
printa(column, "if (!%s)", request->req_handle);
|
|
|
|
printa(column + INDENT,
|
|
|
|
"isc_compile_map (%s, &%s, &%s, &isc_%dl, isc_%d);", status,
|
|
|
|
request->req_form_handle, request->req_handle, request->req_ident,
|
|
|
|
request->req_ident);
|
|
|
|
|
|
|
|
// Reset form to known state
|
|
|
|
|
|
|
|
printa(column, "isc_reset_form (%s, &%s);", status, request->req_handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate a function for free standing ANY or statistical.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_function( ACT function, int column)
|
|
|
|
{
|
|
|
|
REQ request;
|
|
|
|
POR port;
|
|
|
|
REF reference;
|
|
|
|
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;
|
|
|
|
|
2002-09-24 14:57:10 +02:00
|
|
|
#pragma FB_COMPILER WARNING fix format string
|
|
|
|
ib_fprintf(out_file, "static %s_r (request, transaction ",
|
2001-05-23 15:26:42 +02:00
|
|
|
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",
|
|
|
|
gen_name(s, reference->ref_source, TRUE));
|
|
|
|
|
2002-09-24 14:57:10 +02:00
|
|
|
#pragma FB_COMPILER WARNING fix format string
|
2001-05-23 15:26:42 +02:00
|
|
|
ib_fprintf(out_file,
|
|
|
|
")\n isc_req_handle\trequest;\n isc_tr_handle\ttransaction;\n",
|
|
|
|
request->req_handle, request->req_trans);
|
|
|
|
|
|
|
|
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 = DCL_LONG;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_cstring:
|
|
|
|
case dtype_text:
|
|
|
|
dtype = "char*";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_quad:
|
|
|
|
dtype = DCL_QUAD;
|
|
|
|
break;
|
|
|
|
|
|
|
|
// ** Begin date/time/timestamp *
|
|
|
|
case dtype_sql_date:
|
|
|
|
dtype = "ISC_DATE";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_sql_time:
|
|
|
|
dtype = "ISC_TIME";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_timestamp:
|
|
|
|
dtype = "ISC_TIMESTAMP";
|
|
|
|
break;
|
|
|
|
// ** End date/time/timestamp *
|
|
|
|
|
|
|
|
case dtype_int64:
|
|
|
|
dtype = "ISC_INT64";
|
|
|
|
break;
|
|
|
|
|
|
|
|
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, column);
|
|
|
|
|
|
|
|
ib_fprintf(out_file, "\n\n");
|
|
|
|
gen_s_start(action, 0);
|
|
|
|
gen_receive(action, column, 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, column);
|
|
|
|
|
|
|
|
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, BOOLEAN get, int column)
|
|
|
|
{
|
|
|
|
PAT args;
|
|
|
|
TEXT s1[25], s2[10], s4[10];
|
|
|
|
TEXT *pattern1 =
|
|
|
|
"isc_get_slice (%V1, &%DH, &%RT, &%S2, (short) %N1, (char ISC_FAR *) %S3, 0, (%S6*) 0, (%S6) %L1, %S5, &isc_array_length);";
|
|
|
|
TEXT *pattern2 =
|
|
|
|
"isc_put_slice (%V1, &%DH, &%RT, &%S2, (short) %N1, (char ISC_FAR *) %S3, 0, (%S6*) 0, (%S6) %L1, (void ISC_FAR *)%S5);";
|
|
|
|
|
|
|
|
if (!(reference->ref_flags & REF_fetch_array))
|
|
|
|
return;
|
|
|
|
|
|
|
|
args.pat_request = action->act_request;
|
|
|
|
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 */
|
|
|
|
gen_name(s1, reference, TRUE); /* blob handle */
|
|
|
|
args.pat_string2 = s1;
|
|
|
|
args.pat_value1 = reference->ref_sdl_length; /* slice description length */
|
|
|
|
sprintf(s2, "isc_%d", reference->ref_sdl_ident); /* slice description */
|
|
|
|
args.pat_string3 = s2;
|
|
|
|
|
|
|
|
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, "isc_%d",
|
|
|
|
reference->ref_field->fld_array_info->ary_ident);
|
|
|
|
args.pat_string5 = s4; /* array name */
|
|
|
|
}
|
|
|
|
|
|
|
|
args.pat_string6 = DCL_LONG;
|
|
|
|
|
|
|
|
PATTERN_expand((USHORT) column, (get) ? pattern1 : pattern2, &args);
|
|
|
|
|
|
|
|
SET_SQLCODE;
|
|
|
|
if (action->act_flags & ACT_sql)
|
|
|
|
gen_whenever(action->act_whenever, column);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate the code to do a get segment.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_get_segment( ACT action, int column)
|
|
|
|
{
|
|
|
|
BLB blob;
|
|
|
|
PAT args;
|
|
|
|
REF into;
|
|
|
|
TEXT *pattern1 =
|
|
|
|
"%IF%S1 [1] = %ENisc_get_segment (%V1, &%BH, &%I1, (short) sizeof (%I2), %I2);";
|
|
|
|
|
|
|
|
if (action->act_error && (action->act_type != ACT_blob_for))
|
|
|
|
BEGIN;
|
|
|
|
|
|
|
|
if (action->act_flags & ACT_sql)
|
|
|
|
blob = (BLB) action->act_request->req_blobs;
|
|
|
|
else
|
|
|
|
blob = (BLB) action->act_object;
|
|
|
|
|
|
|
|
args.pat_blob = blob;
|
|
|
|
args.pat_vector1 = status_vector(action);
|
|
|
|
args.pat_condition = !(action->act_error
|
|
|
|
|| (action->act_flags & ACT_sql));
|
|
|
|
args.pat_ident1 = blob->blb_len_ident;
|
|
|
|
args.pat_ident2 = blob->blb_buff_ident;
|
|
|
|
args.pat_string1 = status_name;
|
|
|
|
PATTERN_expand((USHORT) column, pattern1, &args);
|
|
|
|
|
|
|
|
if (action->act_flags & ACT_sql) {
|
|
|
|
into = action->act_object;
|
|
|
|
SET_SQLCODE;
|
|
|
|
printa(column, "if (!SQLCODE || SQLCODE == 101)");
|
|
|
|
column += INDENT;
|
|
|
|
BEGIN;
|
|
|
|
align(column);
|
|
|
|
ib_fprintf(out_file, "isc_ftof (isc_%d, isc_%d, %s, isc_%d);",
|
|
|
|
blob->blb_buff_ident, blob->blb_len_ident,
|
|
|
|
into->ref_value, blob->blb_len_ident);
|
|
|
|
if (into->ref_null_value) {
|
|
|
|
align(column);
|
|
|
|
ib_fprintf(out_file, "%s = isc_%d;",
|
|
|
|
into->ref_null_value, blob->blb_len_ident);
|
|
|
|
}
|
|
|
|
END;
|
|
|
|
column -= INDENT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate end of block for PUT_ITEM and FOR_ITEM.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_item_end( ACT action, int column)
|
|
|
|
{
|
|
|
|
REQ request;
|
|
|
|
REF reference, master;
|
|
|
|
POR port;
|
|
|
|
DBB dbb;
|
2001-07-12 07:46:06 +02:00
|
|
|
TEXT s[32];
|
|
|
|
const char *status;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
request = action->act_request;
|
|
|
|
if (request->req_type == REQ_menu) {
|
|
|
|
gen_menu_item_end(action, column);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (action->act_pair->act_type == ACT_item_for) {
|
|
|
|
column += INDENT;
|
|
|
|
END;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
dbb = request->req_database;
|
|
|
|
port = request->req_ports;
|
|
|
|
status = (action->act_error) ? status_name : NULL_STATUS;
|
|
|
|
|
|
|
|
// Initialize field options
|
|
|
|
|
|
|
|
for (reference = port->por_references; reference;
|
|
|
|
reference = reference->ref_next) if (master = reference->ref_master)
|
|
|
|
printa(column, "%s = %d;", gen_name(s, reference, TRUE),
|
|
|
|
PYXIS_OPT_DISPLAY);
|
|
|
|
|
|
|
|
align(column);
|
|
|
|
ib_fprintf(out_file,
|
|
|
|
"isc_form_insert (%s, &%s, &%s, &%s, &isc_%d);",
|
|
|
|
status,
|
|
|
|
dbb->dbb_name->sym_string,
|
|
|
|
request->req_trans, request->req_handle, port->por_ident);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate insert text for FOR_ITEM and PUT_ITEM.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_item_for( ACT action, int column)
|
|
|
|
{
|
|
|
|
REQ request, parent;
|
|
|
|
FORM form;
|
|
|
|
TEXT *status, index[30];
|
|
|
|
|
|
|
|
request = action->act_request;
|
|
|
|
if (request->req_type == REQ_menu) {
|
|
|
|
gen_menu_item_for(action, column);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
column += INDENT;
|
|
|
|
form = request->req_form;
|
|
|
|
parent = form->form_parent;
|
|
|
|
|
|
|
|
status = status_vector(action);
|
|
|
|
|
|
|
|
// Get map compiled
|
|
|
|
|
|
|
|
printa(column, "if (!%s)", request->req_handle);
|
|
|
|
printa(column + INDENT,
|
|
|
|
"isc_compile_sub_map (%s, &%s, &%s, &isc_%dl, isc_%d);", status,
|
|
|
|
parent->req_handle, request->req_handle, request->req_ident,
|
|
|
|
request->req_ident);
|
|
|
|
|
|
|
|
if (action->act_type != ACT_item_for)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Build stuff for item loop
|
|
|
|
|
|
|
|
gen_name(index, request->req_index, TRUE);
|
|
|
|
printa(column, "for (%s = 1;; ++%s)", index, index);
|
|
|
|
column += INDENT;
|
|
|
|
BEGIN;
|
|
|
|
align(column);
|
|
|
|
ib_fprintf(out_file,
|
|
|
|
"isc_form_fetch (%s, &%s, &%s, &%s, &isc_%d);",
|
|
|
|
status,
|
|
|
|
request->req_database->dbb_name->sym_string,
|
|
|
|
request->req_trans,
|
|
|
|
request->req_handle, request->req_ports->por_ident);
|
|
|
|
printa(column, "if (!%s) break;", index);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate text to compile and start a SQL command
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_loop( ACT action, int column)
|
|
|
|
{
|
|
|
|
REQ request;
|
|
|
|
POR port;
|
|
|
|
TEXT name[20];
|
|
|
|
|
|
|
|
gen_s_start(action, column);
|
|
|
|
request = action->act_request;
|
|
|
|
port = request->req_primary;
|
|
|
|
printa(column, "if (!SQLCODE) ");
|
|
|
|
column += INDENT;
|
|
|
|
BEGIN;
|
|
|
|
gen_receive(action, column, port);
|
|
|
|
gen_name(name, port->por_references, TRUE);
|
|
|
|
printa(column, "if (!SQLCODE && !%s)", name);
|
|
|
|
printa(column + INDENT, "SQLCODE = 100;");
|
|
|
|
END;
|
|
|
|
column -= INDENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_menu( ACT action, int column)
|
|
|
|
{
|
|
|
|
REQ request;
|
|
|
|
|
|
|
|
request = action->act_request;
|
|
|
|
printa(column,
|
|
|
|
"switch (isc_menu (%s, &isc_window, &%s, &isc_%dl, isc_%d))",
|
|
|
|
status_vector(action), request->req_handle, request->req_ident,
|
|
|
|
request->req_ident);
|
|
|
|
printa(column + INDENT, "{");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate code for a menu interaction.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_menu_display( ACT action, int column)
|
|
|
|
{
|
|
|
|
MENU menu;
|
|
|
|
REQ request, display_request;
|
|
|
|
|
|
|
|
request = action->act_request;
|
|
|
|
display_request = (REQ) action->act_object;
|
|
|
|
|
|
|
|
menu = NULL;
|
|
|
|
|
|
|
|
for (action = request->req_actions; action; action = action->act_next)
|
|
|
|
if (action->act_type == ACT_menu_for) {
|
|
|
|
menu = (MENU) action->act_object;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
printa(column,
|
|
|
|
"isc_drive_menu (%s, &isc_window, &%s, &isc_%dl, isc_%d, &isc_%dl, isc_%d,",
|
|
|
|
status_vector(action),
|
|
|
|
request->req_handle,
|
|
|
|
display_request->req_ident,
|
|
|
|
display_request->req_ident, menu->menu_title, menu->menu_title);
|
|
|
|
|
|
|
|
printa(column,
|
|
|
|
"\t\t&isc_%d, &isc_%dl, isc_%d, &isc_%d);",
|
|
|
|
menu->menu_terminator,
|
|
|
|
menu->menu_entree_entree,
|
|
|
|
menu->menu_entree_entree, menu->menu_entree_value);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_menu_entree( ACT action, int column)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (!(action->act_flags & ACT_first_entree))
|
|
|
|
printa(column + INDENT, "break;");
|
|
|
|
|
|
|
|
printa(column, "case %d:", action->act_count);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// Generate code for a reference to a menu or entree attribute.
|
|
|
|
|
|
|
|
static void gen_menu_entree_att( ACT action, int column)
|
|
|
|
{
|
|
|
|
MENU menu;
|
|
|
|
SSHORT ident, length;
|
|
|
|
|
|
|
|
menu = (MENU) action->act_object;
|
|
|
|
|
|
|
|
length = FALSE;
|
|
|
|
switch (action->act_type) {
|
|
|
|
case ACT_entree_text:
|
|
|
|
ident = menu->menu_entree_entree;
|
|
|
|
break;
|
|
|
|
case ACT_entree_length:
|
|
|
|
ident = menu->menu_entree_entree;
|
|
|
|
length = TRUE;
|
|
|
|
break;
|
|
|
|
case ACT_entree_value:
|
|
|
|
ident = menu->menu_entree_value;
|
|
|
|
break;
|
|
|
|
case ACT_title_text:
|
|
|
|
ident = menu->menu_title;
|
|
|
|
break;
|
|
|
|
case ACT_title_length:
|
|
|
|
ident = menu->menu_title;
|
|
|
|
length = TRUE;
|
|
|
|
break;
|
|
|
|
case ACT_terminator:
|
|
|
|
ident = menu->menu_terminator;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ident = -1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (length)
|
|
|
|
printa(column, "isc_%dl", ident);
|
|
|
|
else
|
|
|
|
printa(column, "isc_%d", ident);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_menu_end( ACT action, int column)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (!(action->act_request->req_flags & REQ_menu_for))
|
|
|
|
printa(column + INDENT, "break;");
|
|
|
|
END;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate code for a menu block.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_menu_for( ACT action, int column)
|
|
|
|
{
|
|
|
|
REQ request;
|
|
|
|
|
|
|
|
request = action->act_request;
|
|
|
|
|
|
|
|
// Get menu created
|
|
|
|
|
|
|
|
if (!(request->req_flags & REQ_exp_hand))
|
|
|
|
printa(column, "isc_initialize_menu (%s, &%s);",
|
|
|
|
status_vector(action), request->req_handle);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate end of block for PUT_ITEM and FOR_ITEM
|
|
|
|
// for a dynamic menu.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_menu_item_end( ACT action, int column)
|
|
|
|
{
|
|
|
|
REQ request;
|
|
|
|
ENTREE entree;
|
|
|
|
|
|
|
|
if (action->act_pair->act_type == ACT_item_for) {
|
|
|
|
column += INDENT;
|
|
|
|
END;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
entree = (ENTREE) action->act_pair->act_object;
|
|
|
|
request = entree->entree_request;
|
|
|
|
|
|
|
|
align(column);
|
|
|
|
ib_fprintf(out_file,
|
|
|
|
"isc_put_entree (%s, &%s, &isc_%dl, isc_%d, &isc_%d);",
|
|
|
|
status_vector(action),
|
|
|
|
request->req_handle,
|
|
|
|
entree->entree_entree,
|
|
|
|
entree->entree_entree, entree->entree_value);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate insert text for FOR_ITEM and PUT_ITEM
|
|
|
|
// for a dynamic menu.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_menu_item_for( ACT action, int column)
|
|
|
|
{
|
|
|
|
ENTREE entree;
|
|
|
|
REQ request;
|
|
|
|
|
|
|
|
if (action->act_type != ACT_item_for)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Build stuff for item loop
|
|
|
|
|
|
|
|
entree = (ENTREE) action->act_object;
|
|
|
|
request = entree->entree_request;
|
|
|
|
|
|
|
|
printa(column, "while (1)");
|
|
|
|
column += INDENT;
|
|
|
|
BEGIN;
|
|
|
|
align(column);
|
|
|
|
printa(column,
|
|
|
|
"isc_get_entree (%s, &%s, &isc_%dl, isc_%d, &isc_%d, &isc_%d);",
|
|
|
|
status_vector(action), request->req_handle, entree->entree_entree,
|
|
|
|
entree->entree_entree, entree->entree_value, entree->entree_end);
|
|
|
|
|
|
|
|
printa(column, "if (isc_%d) break;", entree->entree_end);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate definitions associated with a dynamic menu request.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_menu_request( REQ request)
|
|
|
|
{
|
|
|
|
ACT action;
|
|
|
|
MENU menu;
|
|
|
|
ENTREE entree;
|
|
|
|
|
|
|
|
menu = NULL;
|
|
|
|
entree = NULL;
|
|
|
|
|
|
|
|
for (action = request->req_actions; action; action = action->act_next) {
|
|
|
|
if (action->act_type == ACT_menu_for) {
|
|
|
|
menu = (MENU) action->act_object;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else if (action->act_type == ACT_item_for
|
|
|
|
|| action->act_type == ACT_item_put) {
|
|
|
|
entree = (ENTREE) action->act_object;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (menu) {
|
|
|
|
menu->menu_title = CMP_next_ident();
|
|
|
|
menu->menu_terminator = CMP_next_ident();
|
|
|
|
menu->menu_entree_value = CMP_next_ident();
|
|
|
|
menu->menu_entree_entree = CMP_next_ident();
|
|
|
|
printa(0, "static short isc_%dl;\t\t/* TITLE_LENGTH */",
|
|
|
|
menu->menu_title);
|
|
|
|
printa(0, "static char isc_%d [81];\t\t/* TITLE_TEXT */",
|
|
|
|
menu->menu_title);
|
|
|
|
printa(0, "static short isc_%d;\t\t/* TERMINATOR */",
|
|
|
|
menu->menu_terminator);
|
|
|
|
printa(0, "static short isc_%dl;\t\t/* ENTREE_LENGTH */",
|
|
|
|
menu->menu_entree_entree);
|
|
|
|
printa(0, "static char isc_%d [81];\t/* ENTREE_TEXT */",
|
|
|
|
menu->menu_entree_entree);
|
|
|
|
printa(0, "static %s isc_%d;\t\t/* ENTREE_VALUE */\n",
|
|
|
|
DCL_LONG, menu->menu_entree_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (entree) {
|
|
|
|
entree->entree_entree = CMP_next_ident();
|
|
|
|
entree->entree_value = CMP_next_ident();
|
|
|
|
entree->entree_end = CMP_next_ident();
|
|
|
|
printa(0, "static short isc_%dl;\t\t/* ENTREE_LENGTH */",
|
|
|
|
entree->entree_entree);
|
|
|
|
printa(0, "static char isc_%d [81];\t/* ENTREE_TEXT */",
|
|
|
|
entree->entree_entree);
|
|
|
|
printa(0, "static %s isc_%d;\t\t/* ENTREE_VALUE */",
|
|
|
|
DCL_LONG, entree->entree_value);
|
|
|
|
if (request->req_flags & REQ_menu_for_item)
|
|
|
|
printa(0, "static short isc_%d;\t\t/* ENTREE_END */\n",
|
|
|
|
entree->entree_end);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate a name for a reference. Name is constructed from
|
|
|
|
// port and parameter idents.
|
|
|
|
//
|
|
|
|
|
|
|
|
static TEXT *gen_name( char *string, REF reference, BOOLEAN as_blob)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (reference->ref_field->fld_array_info && !as_blob)
|
|
|
|
sprintf(string, "isc_%d",
|
|
|
|
reference->ref_field->fld_array_info->ary_ident);
|
|
|
|
else if (reference->ref_port)
|
|
|
|
sprintf(string, "isc_%d.isc_%d",
|
|
|
|
reference->ref_port->por_ident, reference->ref_ident);
|
|
|
|
else
|
|
|
|
sprintf(string, "isc_%d", reference->ref_ident);
|
|
|
|
|
|
|
|
return string;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate a block to handle errors.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_on_error( ACT action, USHORT column)
|
|
|
|
{
|
|
|
|
ACT err_action;
|
|
|
|
|
|
|
|
err_action = (ACT) action->act_object;
|
|
|
|
if ((err_action->act_type == ACT_get_segment) ||
|
|
|
|
(err_action->act_type == ACT_put_segment) ||
|
|
|
|
(err_action->act_type == ACT_endblob))
|
|
|
|
printa(column,
|
|
|
|
"if (%s [1] && (%s [1] != isc_segment) && (%s [1] != isc_segstr_eof))",
|
|
|
|
status_name, status_name, status_name);
|
|
|
|
else
|
|
|
|
printa(column, "if (%s [1])", status_name);
|
|
|
|
column += INDENT;
|
|
|
|
BEGIN;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate code for an EXECUTE PROCEDURE.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_procedure( ACT action, int column)
|
|
|
|
{
|
|
|
|
PAT args;
|
|
|
|
TEXT *pattern;
|
|
|
|
REQ request;
|
|
|
|
POR in_port, out_port;
|
|
|
|
DBB dbb;
|
|
|
|
|
|
|
|
column += INDENT;
|
|
|
|
request = action->act_request;
|
|
|
|
in_port = request->req_vport;
|
|
|
|
out_port = request->req_primary;
|
|
|
|
|
|
|
|
dbb = request->req_database;
|
|
|
|
args.pat_database = dbb;
|
|
|
|
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;
|
|
|
|
if (in_port && in_port->por_length)
|
|
|
|
pattern =
|
|
|
|
"isc_transact_request (%V1, %RF%DH%RE, %RF%RT%RE, sizeof (%RI), %RI, (short) %PL, (char *) %RF%PI%RE, (short) %QL, (char *) %RF%QI%RE);";
|
|
|
|
else
|
|
|
|
pattern =
|
|
|
|
"isc_transact_request (%V1, %RF%DH%RE, %RF%RT%RE, sizeof (%RI), %RI, 0, 0, (short) %QL, (char *) %RF%QI%RE);";
|
|
|
|
|
|
|
|
// Get database attach and transaction started
|
|
|
|
|
|
|
|
if (sw_auto)
|
|
|
|
t_start_auto(action, 0, status_vector(action), column, TRUE);
|
|
|
|
|
|
|
|
// Move in input values
|
|
|
|
|
|
|
|
asgn_from(action, request->req_values, column);
|
|
|
|
|
|
|
|
// Execute the procedure
|
|
|
|
|
|
|
|
PATTERN_expand((USHORT) column, pattern, &args);
|
|
|
|
|
|
|
|
SET_SQLCODE;
|
|
|
|
|
|
|
|
printa(column, "if (!SQLCODE)");
|
|
|
|
column += INDENT;
|
|
|
|
BEGIN;
|
|
|
|
|
|
|
|
// Move out output values
|
|
|
|
|
|
|
|
asgn_to_proc(request->req_references, column);
|
|
|
|
END;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate the code to do a put segment.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_put_segment( ACT action, int column)
|
|
|
|
{
|
|
|
|
BLB blob;
|
|
|
|
PAT args;
|
|
|
|
REF from;
|
|
|
|
TEXT *pattern1 = "%IF%S1 [1] = %ENisc_put_segment (%V1, &%BH, %I1, %I2);";
|
|
|
|
|
|
|
|
if (!action->act_error)
|
|
|
|
BEGIN;
|
|
|
|
if (action->act_error || (action->act_flags & ACT_sql))
|
|
|
|
BEGIN;
|
|
|
|
|
|
|
|
if (action->act_flags & ACT_sql) {
|
|
|
|
blob = (BLB) action->act_request->req_blobs;
|
|
|
|
from = action->act_object;
|
|
|
|
align(column);
|
|
|
|
ib_fprintf(out_file, "isc_%d = %s;",
|
|
|
|
blob->blb_len_ident, from->ref_null_value);
|
|
|
|
align(column);
|
|
|
|
ib_fprintf(out_file, "isc_ftof (%s, isc_%d, isc_%d, isc_%d);",
|
|
|
|
from->ref_value, blob->blb_len_ident,
|
|
|
|
blob->blb_buff_ident, blob->blb_len_ident);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
blob = (BLB) action->act_object;
|
|
|
|
|
|
|
|
args.pat_blob = blob;
|
|
|
|
args.pat_vector1 = status_vector(action);
|
|
|
|
args.pat_condition = !(action->act_error
|
|
|
|
|| (action->act_flags & ACT_sql));
|
|
|
|
args.pat_ident1 = blob->blb_len_ident;
|
|
|
|
args.pat_ident2 = blob->blb_buff_ident;
|
|
|
|
args.pat_string1 = status_name;
|
|
|
|
PATTERN_expand((USHORT) column, pattern1, &args);
|
|
|
|
|
|
|
|
SET_SQLCODE;
|
|
|
|
|
|
|
|
if (action->act_flags & ACT_sql)
|
|
|
|
END;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate BLR/MBLR/etc. in raw, numeric form. Ugly but dense.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_raw( UCHAR * blr, int request_length)
|
|
|
|
{
|
|
|
|
TEXT c, buffer[80], *p, *limit;
|
|
|
|
int count;
|
|
|
|
|
|
|
|
p = buffer;
|
|
|
|
limit = buffer + 60;
|
|
|
|
|
|
|
|
for (count = request_length; count; count--) {
|
|
|
|
c = *blr++;
|
|
|
|
if ((c >= 'A' && c <= 'Z') || c == '$' || c == '_')
|
|
|
|
sprintf(p, "'%c'", c);
|
|
|
|
else
|
|
|
|
sprintf(p, "%d", c);
|
|
|
|
while (*p)
|
|
|
|
p++;
|
|
|
|
if (count - 1)
|
|
|
|
*p++ = ',';
|
|
|
|
if (p < limit)
|
|
|
|
continue;
|
|
|
|
*p = 0;
|
|
|
|
printa(INDENT, buffer);
|
|
|
|
p = buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
*p = 0;
|
|
|
|
printa(INDENT, buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate substitution text for READY
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_ready( ACT action, int column)
|
|
|
|
{
|
|
|
|
RDY ready;
|
|
|
|
DBB db;
|
|
|
|
TEXT *filename, *vector;
|
|
|
|
|
|
|
|
vector = status_vector(action);
|
|
|
|
|
|
|
|
for (ready = (RDY) action->act_object; ready; ready = ready->rdy_next) {
|
|
|
|
db = ready->rdy_database;
|
|
|
|
if (!(filename = ready->rdy_filename))
|
|
|
|
filename = db->dbb_runtime;
|
|
|
|
if ((action->act_error || (action->act_flags & ACT_sql)) &&
|
|
|
|
ready != (RDY) action->act_object)
|
|
|
|
printa(column, "if (!%s [1]) {", status_name);
|
|
|
|
make_ready(db, filename, vector, (USHORT) column, ready->rdy_request);
|
|
|
|
if ((action->act_error || (action->act_flags & ACT_sql)) &&
|
|
|
|
ready != (RDY) action->act_object)
|
|
|
|
END;
|
|
|
|
}
|
|
|
|
SET_SQLCODE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate a send or receive call for a port.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_receive( ACT action, int column, POR port)
|
|
|
|
{
|
|
|
|
PAT args;
|
|
|
|
TEXT *pattern =
|
2001-07-12 07:46:06 +02:00
|
|
|
"isc_receive (%V1, (void**) &%RH, (short) %PN, (short) %PL, &%PI, (short) %RL);";
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
args.pat_request = action->act_request;
|
|
|
|
args.pat_vector1 = status_vector(action);
|
|
|
|
args.pat_port = port;
|
|
|
|
PATTERN_expand((USHORT) column, pattern, &args);
|
|
|
|
|
|
|
|
SET_SQLCODE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// 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, int column)
|
|
|
|
{
|
|
|
|
DBB db, exp_db;
|
|
|
|
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 (db && request->req_handle && !(request->req_flags & REQ_exp_hand)) {
|
|
|
|
printa(column, "if (%s && %s)",
|
|
|
|
db->dbb_name->sym_string, request->req_handle);
|
|
|
|
printa(column + INDENT, "isc_release_request (%s, &%s);",
|
|
|
|
status_name, request->req_handle);
|
|
|
|
printa(column, "%s = 0;", request->req_handle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate definitions associated with a single request.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_request( REQ request)
|
|
|
|
{
|
|
|
|
POR port;
|
|
|
|
REF reference;
|
|
|
|
BLB blob;
|
|
|
|
TEXT *string_type;
|
|
|
|
|
|
|
|
if (!
|
|
|
|
(request->
|
|
|
|
req_flags & (REQ_exp_hand | REQ_menu_for_item | REQ_sql_blob_open |
|
|
|
|
REQ_sql_blob_create)) && request->req_type != REQ_slice
|
|
|
|
&& request->req_type != REQ_procedure)
|
|
|
|
printa(0,
|
|
|
|
"static isc_req_handle\n %s = 0;\t\t/* request handle */\n",
|
|
|
|
request->req_handle);
|
|
|
|
|
|
|
|
// 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(0, "static char\n *isc_%dp;", request->req_ident);
|
|
|
|
if (!request->req_length)
|
|
|
|
printa(0, "static short\n isc_%dl = %d;", request->req_ident,
|
|
|
|
request->req_length);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (request->req_type == REQ_create_database)
|
|
|
|
printa(0, "static %s\n *isc_%dt;", DCL_LONG, request->req_ident);
|
|
|
|
|
|
|
|
if (request->req_flags & (REQ_sql_blob_open | REQ_sql_blob_create))
|
|
|
|
printa(0,
|
|
|
|
"static isc_stmt_handle\n isc_%ds;\t\t/* sql statement handle */",
|
|
|
|
request->req_ident);
|
|
|
|
|
|
|
|
if (request->req_length) {
|
|
|
|
if (request->req_flags & REQ_sql_cursor)
|
|
|
|
printa(0,
|
|
|
|
"static isc_stmt_handle\n isc_%ds;\t\t/* sql statement handle */",
|
|
|
|
request->req_ident);
|
|
|
|
#ifdef SCROLLABLE_CURSORS
|
|
|
|
if (request->req_flags & REQ_scroll)
|
|
|
|
printa(0,
|
|
|
|
"static short\n isc_%ddirection;\t\t/* last direction sent to engine */",
|
|
|
|
request->req_ident);
|
|
|
|
#endif
|
|
|
|
printa(0, "static %sshort\n isc_%dl = %d;",
|
|
|
|
(request->req_flags & REQ_extend_dpb) ? "" : CONST_STR,
|
|
|
|
request->req_ident, request->req_length);
|
|
|
|
printa(0, "static %schar\n isc_%d [] = {",
|
|
|
|
CONST_STR, request->req_ident, request->req_length);
|
|
|
|
string_type = "blr";
|
|
|
|
if (sw_raw) {
|
|
|
|
gen_raw(request->req_blr, request->req_length);
|
|
|
|
switch (request->req_type) {
|
|
|
|
case REQ_create_database:
|
|
|
|
case REQ_ready:
|
|
|
|
string_type = "dpb";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case REQ_ddl:
|
|
|
|
string_type = "dyn";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case REQ_form:
|
|
|
|
string_type = "form_map";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case REQ_menu:
|
|
|
|
string_type = "blr";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case REQ_slice:
|
|
|
|
string_type = "sdl";
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
string_type = "blr";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
switch (request->req_type) {
|
|
|
|
case REQ_create_database:
|
|
|
|
case REQ_ready:
|
|
|
|
string_type = "dpb";
|
|
|
|
if (PRETTY_print_cdb
|
|
|
|
((SCHAR *) request->req_blr,
|
|
|
|
reinterpret_cast < PRETTY_print_cb_pfn > (gen_blr), 0,
|
|
|
|
0))
|
|
|
|
IBERROR("internal error during parameter generation");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case REQ_ddl:
|
|
|
|
string_type = "dyn";
|
|
|
|
if (PRETTY_print_dyn
|
|
|
|
((SCHAR *) request->req_blr,
|
|
|
|
reinterpret_cast < PRETTY_print_cb_pfn > (gen_blr), 0,
|
|
|
|
0))
|
|
|
|
IBERROR
|
|
|
|
("internal error during dynamic DDL generation");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case REQ_form:
|
|
|
|
string_type = "form map";
|
|
|
|
if (PRETTY_print_form_map
|
|
|
|
((SCHAR *) request->req_blr,
|
|
|
|
reinterpret_cast < PRETTY_print_cb_pfn > (gen_blr), 0,
|
|
|
|
0)) IBERROR("internal error during form map generation");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case REQ_menu:
|
|
|
|
string_type = "menu";
|
|
|
|
if (PRETTY_print_menu
|
|
|
|
((SCHAR *) request->req_blr,
|
|
|
|
reinterpret_cast < PRETTY_print_cb_pfn > (gen_blr), 0,
|
|
|
|
0)) IBERROR("internal error during menu generation");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case REQ_slice:
|
|
|
|
string_type = "sdl";
|
|
|
|
if (PRETTY_print_sdl
|
|
|
|
((SCHAR *) request->req_blr,
|
|
|
|
reinterpret_cast < PRETTY_print_cb_pfn > (gen_blr), 0,
|
|
|
|
0)) IBERROR("internal error during SDL generation");
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
string_type = "blr";
|
|
|
|
if (isc_print_blr
|
|
|
|
((char *) request->req_blr, (FPTR_VOID) gen_blr, 0, 0))
|
|
|
|
IBERROR("internal error during BLR generation");
|
|
|
|
}
|
|
|
|
printa(INDENT, "};\t/* end of %s string for request isc_%d */\n",
|
|
|
|
string_type, request->req_ident, request->req_length);
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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(0, "static %sshort\n isc_%dl = %d;", CONST_STR,
|
|
|
|
reference->ref_sdl_ident, reference->ref_sdl_length);
|
|
|
|
printa(0, "static %schar\n isc_%d [] = {", CONST_STR,
|
|
|
|
reference->ref_sdl_ident);
|
|
|
|
if (sw_raw)
|
|
|
|
gen_raw((UCHAR *) reference->ref_sdl,
|
|
|
|
reference->ref_sdl_length);
|
|
|
|
else
|
|
|
|
if (PRETTY_print_sdl
|
|
|
|
((SCHAR *) reference->ref_sdl,
|
|
|
|
reinterpret_cast < PRETTY_print_cb_pfn > (gen_blr),
|
|
|
|
0, 0))
|
|
|
|
IBERROR("internal error during SDL generation");
|
|
|
|
printa(INDENT,
|
|
|
|
"};\t/* end of sdl string for request isc_%d */\n",
|
|
|
|
reference->ref_sdl_ident);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Print out any blob parameter blocks required
|
|
|
|
|
|
|
|
for (blob = request->req_blobs; blob; blob = blob->blb_next)
|
|
|
|
if (blob->blb_bpb_length) {
|
|
|
|
printa(0, "static %schar\n isc_%d [] = {", CONST_STR,
|
|
|
|
blob->blb_bpb_ident);
|
|
|
|
gen_raw(blob->blb_bpb, blob->blb_bpb_length);
|
|
|
|
printa(INDENT, "};\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
// If this is a menu request, handle things
|
|
|
|
|
|
|
|
if (request->req_type == REQ_menu)
|
|
|
|
gen_menu_request(request);
|
|
|
|
|
|
|
|
// If this is a GET_SLICE/PUT_slice, allocate some variables
|
|
|
|
|
|
|
|
if (request->req_type == REQ_slice) {
|
|
|
|
printa(0, "static %s", DCL_LONG);
|
|
|
|
printa(INDENT, "isc_%dv [%d],", request->req_ident,
|
|
|
|
MAX(request->req_slice->slc_parameters, 1));
|
|
|
|
printa(INDENT, "isc_%ds;", request->req_ident);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate receive call for a port
|
|
|
|
// in a store2 statement.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_return_value( ACT action, int column)
|
|
|
|
{
|
|
|
|
UPD update;
|
|
|
|
REF reference;
|
|
|
|
REQ request;
|
|
|
|
|
|
|
|
request = action->act_request;
|
|
|
|
if (action->act_pair->act_error)
|
|
|
|
column += INDENT;
|
|
|
|
align(column);
|
|
|
|
gen_start(action, request->req_primary, column, TRUE);
|
|
|
|
update = (UPD) action->act_object;
|
|
|
|
reference = update->upd_references;
|
|
|
|
gen_receive(action, column, reference->ref_port);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Process routine head. If there are requests in the
|
|
|
|
// routine, insert local definitions.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_routine( ACT action, int column)
|
|
|
|
{
|
|
|
|
BLB blob;
|
|
|
|
REQ request;
|
|
|
|
POR port;
|
|
|
|
|
|
|
|
column += INDENT;
|
|
|
|
|
|
|
|
for (request = (REQ) action->act_object; request;
|
|
|
|
request = request->req_routine) {
|
|
|
|
if (request->req_type == REQ_any)
|
|
|
|
continue;
|
|
|
|
for (port = request->req_ports; port; port = port->por_next)
|
|
|
|
make_port(port, column);
|
|
|
|
for (blob = request->req_blobs; blob; blob = blob->blb_next) {
|
|
|
|
printa(column, "isc_blob_handle\t\tisc_%d;\t\t/* blob handle */",
|
|
|
|
blob->blb_ident);
|
|
|
|
printa(column, "char\t\t\tisc_%d [%d];\t/* blob segment */",
|
|
|
|
blob->blb_buff_ident, blob->blb_seg_length);
|
|
|
|
printa(column, "unsigned short\tisc_%d;\t\t/* segment length */",
|
|
|
|
blob->blb_len_ident);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate substitution text for END_STREAM.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_s_end( ACT action, int column)
|
|
|
|
{
|
|
|
|
REQ request;
|
|
|
|
|
|
|
|
if (action->act_error)
|
|
|
|
BEGIN;
|
|
|
|
request = action->act_request;
|
|
|
|
|
|
|
|
if (action->act_type == ACT_close)
|
|
|
|
column = gen_cursor_close(action, request, column);
|
|
|
|
|
|
|
|
printa(column, "isc_unwind_request (%s, &%s, %s);",
|
|
|
|
status_vector(action),
|
|
|
|
request->req_handle, request->req_request_level);
|
|
|
|
|
|
|
|
if (action->act_type == ACT_close) {
|
|
|
|
END;
|
|
|
|
column -= INDENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
SET_SQLCODE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate substitution text for FETCH.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_s_fetch( ACT action, int column)
|
|
|
|
{
|
|
|
|
REQ request;
|
|
|
|
|
|
|
|
request = action->act_request;
|
|
|
|
|
|
|
|
if (request->req_sync)
|
|
|
|
gen_send(action, request->req_sync, column);
|
|
|
|
|
|
|
|
gen_receive(action, column, request->req_primary);
|
|
|
|
|
|
|
|
if (!action->act_pair && !action->act_error)
|
|
|
|
END;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate text to compile and start a stream. This is
|
|
|
|
// used both by START_STREAM and FOR
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_s_start( ACT action, int column)
|
|
|
|
{
|
|
|
|
REQ request;
|
|
|
|
POR port;
|
|
|
|
|
|
|
|
request = action->act_request;
|
|
|
|
|
|
|
|
gen_compile(action, column);
|
|
|
|
|
|
|
|
if (port = request->req_vport)
|
|
|
|
asgn_from(action, port->por_references, column);
|
|
|
|
|
|
|
|
if (action->act_type == ACT_open)
|
|
|
|
column = gen_cursor_open(action, request, column);
|
|
|
|
|
|
|
|
if (action->act_error || (action->act_flags & ACT_sql)) {
|
|
|
|
make_ok_test(action, request, column);
|
|
|
|
column += INDENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
gen_start(action, port, column, FALSE);
|
|
|
|
|
|
|
|
if (action->act_error || (action->act_flags & ACT_sql))
|
|
|
|
column -= INDENT;
|
|
|
|
|
|
|
|
if (action->act_type == ACT_open) {
|
|
|
|
END;
|
|
|
|
column -= INDENT;
|
|
|
|
END;
|
|
|
|
column -= INDENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
SET_SQLCODE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Substitute for a segment, segment length, or blob handle.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_segment( ACT action, int column)
|
|
|
|
{
|
|
|
|
BLB blob;
|
|
|
|
|
|
|
|
blob = (BLB) action->act_object;
|
|
|
|
|
|
|
|
printa(column, "isc_%d",
|
|
|
|
(action->act_type == ACT_segment) ? blob->blb_buff_ident :
|
|
|
|
(action->act_type == ACT_segment_length) ? blob->blb_len_ident :
|
|
|
|
blob->blb_ident);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// generate code for a singleton select.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_select( ACT action, int column)
|
|
|
|
{
|
|
|
|
REQ request;
|
|
|
|
POR port;
|
|
|
|
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, column);
|
|
|
|
printa(column, "if (!SQLCODE) ");
|
|
|
|
column += INDENT;
|
|
|
|
BEGIN;
|
|
|
|
gen_receive(action, column, port);
|
|
|
|
printa(column, "if (!SQLCODE)");
|
|
|
|
column += INDENT;
|
|
|
|
printa(column, "if (%s)", name);
|
|
|
|
column += INDENT;
|
|
|
|
|
|
|
|
BEGIN;
|
|
|
|
if (var_list = (NOD) action->act_object)
|
|
|
|
for (i = 0; i < var_list->nod_count; i++) {
|
|
|
|
align(column);
|
|
|
|
asgn_to(action, (REF) var_list->nod_arg[i], column);
|
|
|
|
}
|
|
|
|
if (request->req_database->dbb_flags & DBB_v3) {
|
|
|
|
gen_receive(action, column, port);
|
|
|
|
printa(column, "if (!SQLCODE && %s)", name);
|
|
|
|
printa(column + INDENT, "SQLCODE = -1;");
|
|
|
|
}
|
|
|
|
END;
|
|
|
|
|
|
|
|
printa(column - INDENT, "else");
|
|
|
|
printa(column, "SQLCODE = 100;");
|
|
|
|
column -= INDENT;
|
|
|
|
column -= INDENT;
|
|
|
|
END;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate a send or receive call for a port.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_send( ACT action, POR port, int column)
|
|
|
|
{
|
|
|
|
PAT args;
|
|
|
|
TEXT *pattern =
|
2001-07-12 07:46:06 +02:00
|
|
|
"isc_send (%V1, (void**) &%RH, (short) %PN, (short) %PL, &%PI, (short) %RL);";
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
args.pat_request = action->act_request;
|
|
|
|
args.pat_vector1 = status_vector(action);
|
|
|
|
args.pat_port = port;
|
|
|
|
PATTERN_expand((USHORT) column, pattern, &args);
|
|
|
|
|
|
|
|
SET_SQLCODE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate support for get/put slice statement.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_slice( ACT action, REF var_reference, int column)
|
|
|
|
{
|
|
|
|
REQ request, parent_request;
|
|
|
|
REF reference, upper, lower;
|
|
|
|
SLC slice;
|
|
|
|
PAT args;
|
|
|
|
slc::slc_repeat * tail, *end;
|
|
|
|
TEXT *pattern1 = "isc_get_slice (%V1, &%DH, &%RT, &%FR, (short) %N1, \
|
|
|
|
(char ISC_FAR *) %I1, (short) %N2, %I1v, %I1s, %S5, &isc_array_length);";
|
|
|
|
TEXT *pattern2 = "isc_put_slice (%V1, &%DH, &%RT, &%FR, (short) %N1, \
|
|
|
|
(char ISC_FAR *) %I1, (short) %N2, %I1v, %I1s, %S5);";
|
|
|
|
|
|
|
|
request = action->act_request;
|
|
|
|
slice = (SLC) action->act_object;
|
|
|
|
parent_request = slice->slc_parent_request;
|
|
|
|
|
|
|
|
// Compute array size
|
|
|
|
|
|
|
|
printa(column, "isc_%ds = %d", 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, ";");
|
|
|
|
|
|
|
|
// Make assignments to variable vector
|
|
|
|
|
|
|
|
for (reference = request->req_values; reference;
|
|
|
|
reference =
|
|
|
|
reference->ref_next) printa(column, "isc_%dv [%d] = %s;",
|
|
|
|
request->req_ident, reference->ref_id,
|
|
|
|
reference->ref_value);
|
|
|
|
|
|
|
|
args.pat_reference =
|
|
|
|
(var_reference ? var_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 */
|
|
|
|
|
|
|
|
if (!(reference = var_reference))
|
|
|
|
reference = (REF) slice->slc_array->nod_arg[0];
|
|
|
|
args.pat_string5 = reference->ref_value; /* array name */
|
|
|
|
|
|
|
|
PATTERN_expand((USHORT) column,
|
|
|
|
(action->act_type == ACT_get_slice) ? pattern1 : pattern2,
|
|
|
|
&args);
|
|
|
|
|
|
|
|
SET_SQLCODE;
|
|
|
|
if (action->act_flags & ACT_sql)
|
|
|
|
gen_whenever(action->act_whenever, column);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate either a START or START_AND_SEND depending
|
|
|
|
// on whether or a not a port is present. If this START
|
|
|
|
// or START_AND_SEND is being generated for a STORE or a
|
|
|
|
// MODIFY statement, generate PUT_SLICE calls, as well.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_start( ACT action, POR port, int column, BOOLEAN sending)
|
|
|
|
{
|
|
|
|
PAT args;
|
|
|
|
TEXT *pattern1 =
|
2001-07-12 07:46:06 +02:00
|
|
|
"isc_start_and_send (%V1, (void**) &%RH, (void**) &%S1, (short) %PN, (short) %PL, &%PI, (short) %RL);";
|
|
|
|
TEXT *pattern2 = "isc_start_request (%V1, (void**) &%RH, (void**) &%S1, (short) %RL);";
|
2001-05-23 15:26:42 +02:00
|
|
|
REF reference;
|
|
|
|
|
|
|
|
if (port && sending) {
|
|
|
|
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, column);
|
|
|
|
}
|
|
|
|
|
|
|
|
args.pat_request = action->act_request;
|
|
|
|
args.pat_vector1 = status_vector(action);
|
|
|
|
args.pat_port = port;
|
|
|
|
args.pat_string1 = request_trans(action, action->act_request);
|
|
|
|
PATTERN_expand((USHORT) column, (port) ? pattern1 : pattern2, &args);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate text for STORE statement. This includes the compile
|
|
|
|
// call and any variable initialization required.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_store( ACT action, int column)
|
|
|
|
{
|
|
|
|
REQ request;
|
|
|
|
REF reference;
|
|
|
|
FLD field;
|
|
|
|
POR port;
|
|
|
|
TEXT name[64];
|
|
|
|
|
|
|
|
request = action->act_request;
|
|
|
|
align(column);
|
|
|
|
gen_compile(action, column);
|
|
|
|
|
|
|
|
if (action->act_error || (action->act_flags & ACT_sql)) {
|
|
|
|
make_ok_test(action, request, column);
|
|
|
|
column += INDENT;
|
|
|
|
if (action->act_error)
|
|
|
|
BEGIN;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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(column, "%s = isc_blob_null;",
|
|
|
|
gen_name(name, reference, TRUE));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate substitution text for START_TRANSACTION.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_t_start( ACT action, int column)
|
|
|
|
{
|
|
|
|
DBB db;
|
|
|
|
TRA trans;
|
|
|
|
TPB tpb;
|
|
|
|
TEXT *filename, *vector;
|
|
|
|
int remaining, length;
|
|
|
|
|
|
|
|
vector = status_vector(action);
|
|
|
|
|
|
|
|
// if this is a purely default transaction, just let it through
|
|
|
|
|
|
|
|
if (!action || !(trans = (TRA) action->act_object)) {
|
|
|
|
t_start_auto(action, 0, vector, column, FALSE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// build a complete statement, including tpb's. Ready db's
|
|
|
|
|
|
|
|
if (sw_auto)
|
|
|
|
for (tpb = trans->tra_tpb; tpb; tpb = tpb->tpb_tra_next) {
|
|
|
|
db = tpb->tpb_database;
|
|
|
|
if ((filename = db->dbb_runtime) || !(db->dbb_flags & DBB_sqlca)) {
|
|
|
|
printa(column, "if (!%s)", db->dbb_name->sym_string);
|
|
|
|
make_ready(db, filename, vector, (USHORT) (column + INDENT),
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-07-12 07:46:06 +02:00
|
|
|
printa(column, "isc_start_transaction (%s, (void**) &%s, (short) %d",
|
2001-05-23 15:26:42 +02:00
|
|
|
vector,
|
|
|
|
(trans->tra_handle) ? trans->tra_handle : transaction_name,
|
|
|
|
trans->tra_db_count);
|
|
|
|
|
|
|
|
// Some systems don't like infinitely long lines. Limit them to 256.
|
|
|
|
|
|
|
|
remaining = 256 - column - strlen(vector) -
|
|
|
|
strlen((trans->tra_handle) ? trans->tra_handle : transaction_name) -
|
|
|
|
31;
|
|
|
|
|
|
|
|
for (tpb = trans->tra_tpb; tpb; tpb = tpb->tpb_tra_next) {
|
|
|
|
if ((length = strlen(tpb->tpb_database->dbb_name->sym_string) + 22) >
|
|
|
|
remaining) {
|
|
|
|
align(column + INDENT);
|
|
|
|
remaining = 256 - column - INDENT;
|
|
|
|
}
|
|
|
|
remaining -= length;
|
|
|
|
ib_fprintf(out_file, ", &%s, (short) %d, isc_tpb_%d",
|
|
|
|
tpb->tpb_database->dbb_name->sym_string,
|
|
|
|
tpb->tpb_length, tpb->tpb_ident);
|
|
|
|
}
|
|
|
|
|
|
|
|
ib_fprintf(out_file, ");");
|
|
|
|
|
|
|
|
SET_SQLCODE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate a TPB in the output file
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_tpb( TPB tpb, int column)
|
|
|
|
{
|
|
|
|
TEXT *text, buffer[80], c, *p;
|
|
|
|
SSHORT length, tpb_length;
|
|
|
|
|
|
|
|
printa(column, "static %schar\n", CONST_STR);
|
|
|
|
column += INDENT;
|
|
|
|
p = buffer;
|
|
|
|
|
|
|
|
for (length = 0; length < column; length++)
|
|
|
|
*p++ = ' ';
|
|
|
|
|
|
|
|
sprintf(p, "isc_tpb_%d [%d] = {", tpb->tpb_ident, tpb->tpb_length);
|
|
|
|
while (*p)
|
|
|
|
p++;
|
|
|
|
|
|
|
|
tpb_length = tpb->tpb_length;
|
|
|
|
text = (TEXT *) tpb->tpb_string;
|
|
|
|
|
|
|
|
while (--tpb_length >= 0) {
|
|
|
|
c = *text++;
|
|
|
|
if ((c >= 'A' && c <= 'Z') || c == '$' || c == '_')
|
|
|
|
sprintf(p, "'%c'", c);
|
|
|
|
else
|
|
|
|
sprintf(p, "%d", c);
|
|
|
|
while (*p)
|
|
|
|
p++;
|
|
|
|
if (tpb_length)
|
|
|
|
*p++ = ',';
|
|
|
|
if (p - buffer > 60) {
|
|
|
|
*p = 0;
|
|
|
|
ib_fprintf(out_file, " %s\n", buffer);
|
|
|
|
p = buffer;
|
|
|
|
for (length = 0; length < column + INDENT; length++)
|
|
|
|
*p++ = ' ';
|
|
|
|
*p = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ib_fprintf(out_file, "%s};\n", buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate substitution text for COMMIT, ROLLBACK, PREPARE, and SAVE
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_trans( ACT action, int column)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (action->act_type == ACT_commit_retain_context)
|
2001-07-12 07:46:06 +02:00
|
|
|
printa(column, "isc_commit_retaining (%s, (void**) &%s);",
|
2001-05-23 15:26:42 +02:00
|
|
|
status_vector(action),
|
|
|
|
(action->act_object) ? (TEXT *) (action->
|
|
|
|
act_object) :
|
|
|
|
transaction_name);
|
|
|
|
else
|
2001-07-12 07:46:06 +02:00
|
|
|
printa(column, "isc_%s_transaction (%s, (void**) &%s);",
|
2001-05-23 15:26:42 +02:00
|
|
|
(action->act_type ==
|
|
|
|
ACT_commit) ? "commit" : (action->act_type ==
|
|
|
|
ACT_rollback) ? "rollback" :
|
|
|
|
"prepare", status_vector(action),
|
|
|
|
(action->act_object) ? (TEXT *) (action->
|
|
|
|
act_object) :
|
|
|
|
transaction_name);
|
|
|
|
|
|
|
|
SET_SQLCODE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Substitute for a variable reference.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_type( ACT action, int column)
|
|
|
|
{
|
|
|
|
|
|
|
|
printa(column, "%ld", action->act_object);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate substitution text for UPDATE ... WHERE CURRENT OF ...
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_update( ACT action, int column)
|
|
|
|
{
|
|
|
|
POR port;
|
|
|
|
UPD modify;
|
|
|
|
|
|
|
|
modify = (UPD) action->act_object;
|
|
|
|
port = modify->upd_port;
|
|
|
|
asgn_from(action, port->por_references, column);
|
|
|
|
gen_send(action, port, column);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Substitute for a variable reference.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_variable( ACT action, int column)
|
|
|
|
{
|
|
|
|
TEXT s[20];
|
|
|
|
|
|
|
|
printa(column, gen_name(s, action->act_object, FALSE));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate tests for any WHENEVER clauses that may have been declared.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_whenever( SWE label, int column)
|
|
|
|
{
|
|
|
|
TEXT *condition;
|
|
|
|
|
|
|
|
while (label) {
|
|
|
|
switch (label->swe_condition) {
|
|
|
|
case SWE_error:
|
|
|
|
condition = "SQLCODE < 0";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SWE_warning:
|
|
|
|
condition = "SQLCODE > 0 && SQLCODE != 100";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SWE_not_found:
|
|
|
|
condition = "SQLCODE == 100";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
align(column);
|
|
|
|
ib_fprintf(out_file, "if (%s) goto %s;", condition, label->swe_label);
|
|
|
|
label = label->swe_next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Create a new window.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_window_create( ACT action, int column)
|
|
|
|
{
|
|
|
|
|
|
|
|
printa(column,
|
|
|
|
"isc_create_window (%s, &isc_window, (short*) 0, (char*) 0, &isc_width, &isc_height)",
|
|
|
|
status_vector(action));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Delete a window.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_window_delete( ACT action, int column)
|
|
|
|
{
|
|
|
|
|
|
|
|
printa(column, "isc_delete_window (%s, &isc_window)",
|
|
|
|
status_vector(action));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Suspend a window.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void gen_window_suspend( ACT action, int column)
|
|
|
|
{
|
|
|
|
|
|
|
|
printa(column, "isc_suspend_window (%s, &isc_window)",
|
|
|
|
status_vector(action));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate a declaration of an array in the
|
|
|
|
// output file.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void make_array_declaration( REF reference)
|
|
|
|
{
|
|
|
|
|
|
|
|
FLD field = reference->ref_field;
|
|
|
|
TEXT *name = field->fld_symbol->sym_string;
|
|
|
|
TEXT s[64];
|
|
|
|
TEXT *dtype;
|
|
|
|
DIM dimension;
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
|
|
|
switch (field->fld_array_info->ary_dtype) {
|
|
|
|
case dtype_short:
|
|
|
|
dtype = "short";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_long:
|
|
|
|
dtype = DCL_LONG;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_cstring:
|
|
|
|
case dtype_text:
|
|
|
|
case dtype_varying:
|
|
|
|
dtype = "char ";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_quad:
|
|
|
|
dtype = DCL_QUAD;
|
|
|
|
break;
|
|
|
|
|
|
|
|
// ** Begin date/time/timestamp *
|
|
|
|
case dtype_sql_date:
|
|
|
|
dtype = "ISC_DATE";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_sql_time:
|
|
|
|
dtype = "ISC_TIME";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_timestamp:
|
|
|
|
dtype = "ISC_TIMESTAMP";
|
|
|
|
break;
|
|
|
|
// ** End date/time/timestamp *
|
|
|
|
|
|
|
|
case dtype_int64:
|
|
|
|
dtype = "ISC_INT64";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_float:
|
|
|
|
dtype = "float ";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_double:
|
|
|
|
dtype = "double";
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
sprintf(s, "datatype %d unknown for field %s",
|
|
|
|
field->fld_array_info->ary_dtype, name);
|
|
|
|
IBERROR(s);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ib_fprintf(out_file, "static %s isc_%d", dtype,
|
|
|
|
field->fld_array_info->ary_ident);
|
|
|
|
|
|
|
|
// Print out the dimension part of the declaration
|
|
|
|
|
|
|
|
for (dimension = field->fld_array_info->ary_dimension; dimension;
|
|
|
|
dimension = dimension->dim_next)
|
|
|
|
ib_fprintf(out_file, " [%d]",
|
|
|
|
dimension->dim_upper - dimension->dim_lower + 1);
|
|
|
|
|
|
|
|
if (field->fld_array_info->ary_dtype <= dtype_varying)
|
|
|
|
ib_fprintf(out_file, " [%d]", field->fld_array->fld_length);
|
|
|
|
|
|
|
|
// Print out the database field
|
|
|
|
|
|
|
|
ib_fprintf(out_file, ";\t/* %s */\n", name);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Turn a symbol into a varying string.
|
|
|
|
//
|
|
|
|
|
|
|
|
static TEXT *make_name( TEXT * string, SYM symbol)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (symbol->sym_type == SYM_delimited_cursor) {
|
|
|
|
/** All This elaborate code is just to put double quotes around
|
|
|
|
the cursor names and to escape any embeded quotes.
|
|
|
|
**/
|
|
|
|
int i = 0;
|
|
|
|
strcpy(string, "\"\\\"");
|
|
|
|
for (i = strlen(string); *symbol->sym_string; i++) {
|
|
|
|
if (*symbol->sym_string == '\"' || *symbol->sym_string == '\'') {
|
|
|
|
string[i++] = '\\';
|
|
|
|
string[i++] = *symbol->sym_string;
|
|
|
|
string[i++] = '\\';
|
|
|
|
}
|
|
|
|
string[i] = *symbol->sym_string++;
|
|
|
|
}
|
|
|
|
string[i] = 0;
|
|
|
|
strcat(string, "\\\"\"");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
sprintf(string, "\"%s\"", symbol->sym_string);
|
|
|
|
|
|
|
|
return string;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate code to test existence of compiled request with
|
|
|
|
// active transaction
|
|
|
|
//
|
|
|
|
|
|
|
|
static void make_ok_test( ACT action, REQ request, int column)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (sw_auto)
|
|
|
|
printa(column, "if (%s && %s)",
|
|
|
|
request_trans(action, request), request->req_handle);
|
|
|
|
else
|
|
|
|
printa(column, "if (%s)", request->req_handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Insert a port record description in output.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void make_port( POR port, int column)
|
|
|
|
{
|
|
|
|
FLD field;
|
|
|
|
REF reference;
|
|
|
|
SYM symbol;
|
|
|
|
TEXT *name;
|
|
|
|
TEXT s[80];
|
|
|
|
TEXT *dtype;
|
|
|
|
int fld_len;
|
|
|
|
|
|
|
|
printa(column, "struct {");
|
|
|
|
|
|
|
|
for (reference = port->por_references; reference;
|
|
|
|
reference = reference->ref_next) {
|
|
|
|
align(column + INDENT);
|
|
|
|
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;
|
|
|
|
fld_len = 0;
|
|
|
|
switch (field->fld_dtype) {
|
|
|
|
case dtype_short:
|
|
|
|
dtype = "short";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_long:
|
|
|
|
dtype = DCL_LONG;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_cstring:
|
|
|
|
case dtype_text:
|
|
|
|
dtype = "char ";
|
|
|
|
if (field->fld_sub_type != 1 || field->fld_length > 1)
|
|
|
|
fld_len = field->fld_length;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_quad:
|
|
|
|
dtype = DCL_QUAD;
|
|
|
|
break;
|
|
|
|
|
|
|
|
// ** Begin date/time/timestamp *
|
|
|
|
case dtype_sql_date:
|
|
|
|
dtype = "ISC_DATE";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_sql_time:
|
|
|
|
dtype = "ISC_TIME";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_timestamp:
|
|
|
|
dtype = "ISC_TIMESTAMP";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_int64:
|
|
|
|
dtype = "ISC_INT64";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_blob:
|
|
|
|
dtype = "ISC_QUAD";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_float:
|
|
|
|
dtype = "float ";
|
|
|
|
break;
|
|
|
|
|
|
|
|
case dtype_double:
|
|
|
|
dtype = "double";
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
sprintf(s, "datatype %d unknown for field %s, msg %d",
|
|
|
|
field->fld_dtype, name, port->por_msg_number);
|
|
|
|
IBERROR(s);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (fld_len)
|
|
|
|
ib_fprintf(out_file, " %s isc_%d [%d];\t/* %s */",
|
|
|
|
dtype, reference->ref_ident, fld_len, name);
|
|
|
|
else
|
|
|
|
ib_fprintf(out_file, " %s isc_%d;\t/* %s */",
|
|
|
|
dtype, reference->ref_ident, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
printa(column, "} isc_%d;", port->por_ident);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate the actual insertion text for a
|
|
|
|
// ready;
|
|
|
|
//
|
|
|
|
|
|
|
|
static void make_ready(
|
|
|
|
DBB db,
|
|
|
|
TEXT * filename,
|
|
|
|
TEXT * vector, USHORT column, REQ request)
|
|
|
|
{
|
|
|
|
TEXT s1[32], s2[32];
|
|
|
|
TEXT *dpb_size_ptr, *dpb_ptr;
|
|
|
|
|
|
|
|
if (request) {
|
|
|
|
sprintf(s1, "isc_%dl", request->req_ident);
|
|
|
|
|
|
|
|
if (request->req_flags & REQ_extend_dpb)
|
|
|
|
sprintf(s2, "isc_%dp", request->req_ident);
|
|
|
|
else
|
|
|
|
sprintf(s2, "isc_%d", 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)
|
|
|
|
printa(column, "%s = isc_%d;", s2, request->req_ident);
|
|
|
|
else
|
|
|
|
printa(column, "%s = (char*) 0;", s2);
|
|
|
|
|
|
|
|
printa(column,
|
|
|
|
"isc_expand_dpb (&%s, &%s, isc_dpb_user_name, %s, isc_dpb_password, %s, isc_dpb_sql_role_name, %s, isc_dpb_lc_messages, %s, isc_dpb_lc_ctype, %s, 0);",
|
|
|
|
s2, s1, db->dbb_r_user ? db->dbb_r_user : "(char*) 0",
|
|
|
|
db->dbb_r_password ? db->dbb_r_password : "(char*) 0",
|
|
|
|
db->dbb_r_sql_role ? db->dbb_r_sql_role : "(char*) 0",
|
|
|
|
db->dbb_r_lc_messages ? db->
|
|
|
|
dbb_r_lc_messages : "(char*) 0",
|
|
|
|
db->dbb_r_lc_ctype ? db->dbb_r_lc_ctype : "(char*) 0");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// generate the attach database itself
|
|
|
|
|
|
|
|
dpb_size_ptr = "0";
|
|
|
|
dpb_ptr = "(char*) 0";
|
|
|
|
|
|
|
|
align(column);
|
|
|
|
if (filename)
|
|
|
|
ib_fprintf(out_file,
|
|
|
|
"isc_attach_database (%s, 0, %s, &%s, %s, %s);",
|
|
|
|
vector,
|
|
|
|
filename,
|
|
|
|
db->dbb_name->sym_string,
|
|
|
|
(request ? s1 : dpb_size_ptr), (request ? s2 : dpb_ptr));
|
|
|
|
else
|
|
|
|
ib_fprintf(out_file,
|
|
|
|
"isc_attach_database (%s, 0, \"%s\", &%s, %s, %s);",
|
|
|
|
vector,
|
|
|
|
db->dbb_filename,
|
|
|
|
db->dbb_name->sym_string,
|
|
|
|
(request ? s1 : dpb_size_ptr), (request ? s2 : dpb_ptr));
|
|
|
|
|
|
|
|
// if the dpb was extended, free it here
|
|
|
|
|
|
|
|
if (request && request->req_flags & REQ_extend_dpb) {
|
|
|
|
if (request->req_length)
|
|
|
|
printa(column, "if (%s != isc_%d)", s2, request->req_ident);
|
2001-07-12 07:46:06 +02:00
|
|
|
printa(column + (request->req_length ? INDENT : 0), "isc_free ((char*) %s);",
|
2001-05-23 15:26:42 +02:00
|
|
|
s2);
|
|
|
|
|
|
|
|
/* reset the length of the dpb */
|
|
|
|
|
|
|
|
printa(column, "%s = %d;", s1, request->req_length);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Print a fixed string at a particular column.
|
|
|
|
//
|
|
|
|
|
2001-07-12 07:46:06 +02:00
|
|
|
static void printa( int column, const char * string, ...)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
va_list ptr;
|
|
|
|
|
|
|
|
VA_START(ptr, string);
|
|
|
|
align(column);
|
|
|
|
ib_vfprintf(out_file, string, ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate the appropriate transaction handle.
|
|
|
|
//
|
|
|
|
|
|
|
|
static TEXT *request_trans( ACT action, REQ request)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (action->act_type == ACT_open) {
|
|
|
|
TEXT *trname = ((OPN) action->act_object)->opn_trans;
|
|
|
|
if (!trname) {
|
|
|
|
trname = transaction_name;
|
|
|
|
}
|
|
|
|
return trname;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (request) ? request->req_trans : transaction_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// 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 status_name;
|
|
|
|
|
|
|
|
return NULL_STATUS;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//____________________________________________________________
|
|
|
|
//
|
|
|
|
// Generate substitution text for START_TRANSACTION.
|
|
|
|
// The complications include the fact that all databases
|
|
|
|
// must be readied, and that everything should stop if
|
|
|
|
// any thing fails so we don't trash the status vector.
|
|
|
|
//
|
|
|
|
|
|
|
|
static void t_start_auto(
|
|
|
|
ACT action,
|
|
|
|
REQ request, TEXT * vector, int column, SSHORT test)
|
|
|
|
{
|
|
|
|
DBB db;
|
|
|
|
int count, stat, remaining, length;
|
|
|
|
TEXT *filename, buffer[256], *trname;
|
|
|
|
|
|
|
|
trname = request_trans(action, request);
|
|
|
|
|
|
|
|
// find out whether we're using a status vector or not
|
|
|
|
|
|
|
|
stat = !strcmp(vector, status_name);
|
|
|
|
|
|
|
|
// this is a default transaction, make sure all databases are ready
|
|
|
|
|
|
|
|
BEGIN;
|
|
|
|
|
|
|
|
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)) {
|
|
|
|
align(column);
|
|
|
|
ib_fprintf(out_file, "if (!%s", db->dbb_name->sym_string);
|
|
|
|
if (stat && buffer[0])
|
|
|
|
ib_fprintf(out_file, " && !%s [1]", vector);
|
|
|
|
ib_fprintf(out_file, ")");
|
|
|
|
make_ready(db, filename, vector, (USHORT) (column + INDENT),
|
|
|
|
0);
|
|
|
|
if (buffer[0])
|
|
|
|
strcat(buffer, " && ");
|
|
|
|
strcat(buffer, db->dbb_name->sym_string);
|
|
|
|
}
|
|
|
|
if (!buffer[0])
|
|
|
|
strcpy(buffer, "1");
|
|
|
|
if (test)
|
|
|
|
printa(column, "if (%s && !%s)", buffer, trname);
|
|
|
|
else
|
|
|
|
printa(column, "if (%s)", buffer);
|
|
|
|
column += INDENT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
for (count = 0, db = isc_databases; db; db = db->dbb_next, count++);
|
|
|
|
|
2001-07-12 07:46:06 +02:00
|
|
|
printa(column, "isc_start_transaction (%s, (void**) &%s, (short) %d",
|
2001-05-23 15:26:42 +02:00
|
|
|
vector, trname, count);
|
|
|
|
|
|
|
|
// Some systems don't like infinitely long lines. Limit them to 256.
|
|
|
|
|
|
|
|
remaining = 256 - column - strlen(vector) - strlen(trname) - 31;
|
|
|
|
|
|
|
|
for (db = isc_databases; db; db = db->dbb_next) {
|
|
|
|
if ((length = strlen(db->dbb_name->sym_string) + 17) > remaining) {
|
|
|
|
align(column + INDENT);
|
|
|
|
remaining = 256 - column - INDENT;
|
|
|
|
}
|
|
|
|
remaining -= length;
|
|
|
|
ib_fprintf(out_file, ", &%s, (short) 0, (char*) 0",
|
|
|
|
db->dbb_name->sym_string);
|
|
|
|
}
|
|
|
|
|
|
|
|
ib_fprintf(out_file, ");");
|
|
|
|
|
|
|
|
if (sw_auto)
|
|
|
|
column -= INDENT;
|
|
|
|
|
|
|
|
END;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // extern "C"
|