//____________________________________________________________ // // PROGRAM: ADA preprocesser // MODULE: ada.cpp // DESCRIPTION: Inserted text generator for ADA // // 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): ______________________________________. // // //____________________________________________________________ // // $Id: ada.cpp,v 1.13 2003-02-12 12:44:17 brodsom Exp $ // #include "firebird.h" #ifdef HAVE_STRING_H #include #endif #include "../jrd/ib_stdio.h" #include "../jrd/common.h" #include #include "../jrd/gds.h" #include "../gpre/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" static void align (int); static void asgn_from (ACT, REF, 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_compatability_symbol (TEXT *, TEXT *, TEXT *); static void gen_compile (ACT, int); static void gen_create_database (ACT, int); static int gen_cursor_close (ACT, GPRE_REQ, int); static void gen_cursor_init (ACT, int); static int gen_cursor_open (ACT, GPRE_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_end (ACT, int); static void gen_menu_entree (ACT, int); static void gen_menu_entree_att (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 (GPRE_REQ, int); static TEXT *gen_name (TEXT *, 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 *, enum req_t, int, int); static void gen_ready (ACT, int); static void gen_receive (ACT, int, POR); static void gen_release (ACT, int); static void gen_request (GPRE_REQ, int); 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, int); static void gen_start (ACT, POR, int); 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, int); static void make_cursor_open_test (enum act_t, GPRE_REQ, int); static TEXT *make_name (TEXT *, SYM); static void make_ok_test (ACT, GPRE_REQ, int); static void make_port (POR, int); static void make_ready (DBB, TEXT *, TEXT *, USHORT, GPRE_REQ); static void printa (int, TEXT *, ...); static void printb (TEXT *, ...); static TEXT *request_trans (ACT, GPRE_REQ); static TEXT *status_vector (ACT); static void t_start_auto (ACT, GPRE_REQ, TEXT *, int, SSHORT); static TEXT output_buffer[512]; static int first_flag; #define COMMENT "--- " #define INDENT 3 #define ENDIF printa (column, "end if;") #define BEGIN printa (column, "begin") #define END printa (column, "end;") #define BYTE_DCL "interbase.isc_byte" #define BYTE_VECTOR_DCL "interbase.isc_vector_byte" #define SHORT_DCL "interbase.isc_short" #define USHORT_DCL "interbase.isc_ushort" #define LONG_DCL "interbase.isc_long" #define LONG_VECTOR_DCL "interbase.isc_vector_long" #define EVENT_LIST_DCL "interbase.event_list" #define FLOAT_DCL "interbase.isc_float" #define DOUBLE_DCL "interbase.isc_double" #define ADA_WINDOW_PACKAGE (sw_window_scope == DBB_EXTERN) ? ada_package : "" #define SET_SQLCODE if (action->act_flags & ACT_sql) printa (column, "SQLCODE := interbase.sqlcode (isc_status);") //____________________________________________________________ // // Code generator for ADA. Not to be confused with // // void ADA_action( ACT action, int column) { switch (action->act_type) { case ACT_alter_database: case ACT_alter_domain: case ACT_alter_table: case ACT_alter_index: case ACT_create_domain: case ACT_create_generator: case ACT_create_index: case ACT_create_shadow: case ACT_create_table: case ACT_create_view: case ACT_declare_filter: case ACT_declare_udf: case ACT_drop_domain: case ACT_drop_filter: case ACT_drop_index: case ACT_drop_shadow: case ACT_drop_table: case ACT_drop_udf: case ACT_statistics: case ACT_drop_view: 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_commit: gen_trans(action, column); break; case ACT_commit_retain_context: gen_trans(action, column); break; 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, column); return; case ACT_blob_close: gen_blob_close(action, column); return; case ACT_blob_create: gen_blob_open(action, column); return; case ACT_blob_for: gen_blob_for(action, column); return; case ACT_blob_handle: gen_segment(action, column); return; case ACT_blob_open: gen_blob_open(action, column); return; case ACT_clear_handles: gen_clear_handles(action, column); break; case ACT_close: gen_s_end(action, column); break; case ACT_create_database: gen_create_database(action, column); break; case ACT_cursor: gen_cursor_init(action, column); return; case ACT_database: gen_database(action, column); return; case ACT_disconnect: gen_finish(action, column); break; case ACT_drop_database: gen_drop_database(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_procedure: gen_procedure(action, column); break; case ACT_dyn_revoke: gen_ddl(action, column); break; case ACT_endblob: gen_blob_end(action, column); return; case ACT_enderror: ENDIF; 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); return; case ACT_get_slice: gen_slice(action, column); return; case ACT_hctef: ENDIF; 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_open: gen_s_start(action, column); break; case ACT_on_error: gen_on_error(action, column); return; case ACT_ready: gen_ready(action, column); break; case ACT_prepare: gen_trans(action, column); break; case ACT_put_segment: gen_put_segment(action, column); return; case ACT_put_slice: gen_slice(action, column); return; 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_select: gen_select(action, column); break; case ACT_segment_length: gen_segment(action, column); return; case ACT_segment: gen_segment(action, column); return; 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_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); } //____________________________________________________________ // // Print a statment, breaking it into // reasonable 120 character hunks. // void ADA_print_buffer( TEXT * output_buffer, int column) { TEXT s[121], *p, *q; int i; BOOLEAN multiline; p = s; multiline = FALSE; for (q = output_buffer; *q; q++) { *p++ = *q; if (((p - s) + column) > 119) { for (p--; (*p != ',') && (*p != ' '); p--) q--; *++p = 0; if (multiline) { for (i = column / 8; i; --i) ib_putc('\t', out_file); for (i = column % 8; i; --i) ib_putc(' ', out_file); } ib_fprintf(out_file, "%s\n", s); s[0] = 0; p = s; multiline = TRUE; } } *p = 0; if (multiline) { for (i = column / 8; i; --i) ib_putc('\t', out_file); for (i = column % 8; i; --i) ib_putc(' ', out_file); } ib_fprintf(out_file, "%s", s); output_buffer[0] = 0; } //____________________________________________________________ // // Align output to a specific column for output. // 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. // static void asgn_from( ACT action, REF reference, int column) { GPRE_FLD field; TEXT *value, name[64], variable[20], temp[20]; for (; reference; reference = reference->ref_next) { field = reference->ref_field; if (field->fld_array_info) if (!(reference->ref_flags & REF_array_elem)) { printa(column, "%s := interbase.null_blob;", gen_name(name, reference, TRUE)); gen_get_or_put_slice(action, reference, FALSE, column); continue; } if (!reference->ref_source && !reference->ref_value) continue; gen_name(variable, reference, TRUE); if (reference->ref_source) value = gen_name(temp, reference->ref_source, TRUE); else value = reference->ref_value; if (!reference->ref_master) printa(column, "%s := %s;", variable, value); else { printa(column, "if %s < 0 then", value); printa(column + INDENT, "%s := -1;", variable); printa(column, "else"); printa(column + INDENT, "%s := 0;", variable); ENDIF; } } } //____________________________________________________________ // // Build an assignment to a host language variable from // a port variable. // static void asgn_to( ACT action, REF reference, int column) { GPRE_FLD field; REF source; TEXT s[20]; source = reference->ref_friend; field = source->ref_field; if (field->fld_array_info) { source->ref_value = reference->ref_value; gen_get_or_put_slice(action, source, TRUE, column); return; } // //if (field && (field->fld_flags & FLD_text)) // printa (column, "interbase.isc_ftof (%s, %d, %s, sizeof (%s));", // gen_name (s, source, TRUE), // field->fld_length, // reference->ref_value, // reference->ref_value); //else // printa(column, "%s := %s;", reference->ref_value, gen_name(s, source, TRUE)); // Pick up NULL value if one is there if (reference = reference->ref_null) printa(column, "%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) { SCHAR s[64]; for (; reference; reference = reference->ref_next) { if (!reference->ref_value) continue; printa(column, "%s := %s;", reference->ref_value, gen_name(s, reference, TRUE)); } } //____________________________________________________________ // // 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) { GPRE_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) { GPRE_REQ request; SCHAR s[20]; request = action->act_request; printa(column, "if %s = 0 then", gen_name(s, request->req_eof, TRUE)); } //____________________________________________________________ // // Substitute for a BASED ON clause. // static void gen_based( ACT action, int column) { BAS based_on; GPRE_FLD field; SSHORT datatype, i, length; DIM dimension; SCHAR s[512], s2[128], *p, *q; based_on = (BAS) action->act_object; field = based_on->bas_field; q = s; if (field->fld_array_info) { datatype = field->fld_array->fld_dtype; sprintf(s, "array ("); for (q = s; *q; q++); /* Print out the dimension part of the declaration */ for (dimension = field->fld_array_info->ary_dimension, i = 1; i < field->fld_array_info->ary_dimension_count; dimension = dimension->dim_next, i++) { sprintf(s2, "%s range %d..%d,\n ", LONG_DCL, dimension->dim_lower, dimension->dim_upper); for (p = s2; *p; p++, q++) *q = *p; } sprintf(s2, "%s range %d..%d) of ", LONG_DCL, dimension->dim_lower, dimension->dim_upper); for (p = s2; *p; p++, q++) *q = *p; } else datatype = field->fld_dtype; switch (datatype) { case dtype_short: sprintf(s2, "%s", SHORT_DCL); break; case dtype_long: sprintf(s2, "%s", LONG_DCL); break; case dtype_date: case dtype_blob: case dtype_quad: sprintf(s2, "interbase.quad"); break; case dtype_text: length = (field->fld_array_info) ? field->fld_array->fld_length : field-> fld_length; if (field->fld_sub_type == 1) { if (length == 1) sprintf(s2, "%s", BYTE_DCL); else sprintf(s2, "%s (1..%d)", BYTE_VECTOR_DCL, length); } else if (length == 1) sprintf(s2, "interbase.isc_character"); else sprintf(s2, "string (1..%d)", length); break; case dtype_float: sprintf(s2, "%s", FLOAT_DCL); break; case dtype_double: sprintf(s2, "%s", DOUBLE_DCL); break; default: sprintf(s2, "datatype %d unknown\n", field->fld_dtype); return ; } for (p = s2; *p; p++, q++) *q = *p; if (!strcmp(based_on->bas_terminator, ";")) *q++ = ';'; *q = 0; printa(column, s); } //____________________________________________________________ // // Make a blob FOR loop. // static void gen_blob_close( ACT action, USHORT column) { TEXT *command; BLB blob; 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; command = (action->act_type == ACT_blob_cancel) ? (TEXT*)"CANCEL" : (TEXT*)"CLOSE"; printa(column, "interbase.%s_BLOB (%s isc_%d);", command, status_vector(action), blob->blb_ident); if (action->act_flags & ACT_sql) { ENDIF; column -= INDENT; } SET_SQLCODE; } //____________________________________________________________ // // End a blob FOR loop. // static void gen_blob_end( ACT action, USHORT column) { BLB blob; blob = (BLB) action->act_object; printa(column, "end loop;"); if (action->act_error) printa(column, "interbase.CLOSE_BLOB (isc_status2, isc_%d);", blob->blb_ident); else printa(column, "interbase.CLOSE_BLOB (%s isc_%d);", status_vector(0), blob->blb_ident); } //____________________________________________________________ // // Make a blob FOR loop. // static void gen_blob_for( ACT action, USHORT column) { gen_blob_open(action, column); if (action->act_error) printa(column, "if (isc_status(1) = 0) then"); printa(column, "loop"); gen_get_segment(action, column + INDENT); printa(column + INDENT, "exit when (isc_status(1) /= 0 and isc_status(1) /= interbase.isc_segment);"); } #ifdef NOT_USED_OR_REPLACED // This is the V4.0 version of the function prior to 18-January-95. // for unknown reasons it contains a core dump. The V3.3 version of // this function appears to work fine, so we are using it instead. // Ravi Kumar // //____________________________________________________________ // // Generate the call to open (or create) a blob. // static gen_blob_open( ACT action, USHORT column) { TEXT *command; BLB blob; PAT args; REF reference; TEXT s[20]; TEXT *pattern1 = "interbase.%IFCREATE%ELOPEN%EN_BLOB2 (%V1 %RF%DH, %RF%RT, %RF%BH, %RF%FR, %N1, %I1);", *pattern2 = "interbase.%IFCREATE%ELOPEN%EN_BLOB2 (%V1 %RF%DH, %RF%RT, %RF%BH, %RF%FR, 0, isc_null_bpb);"; 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; 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) printa(column, "%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) { ENDIF; column -= INDENT; ENDIF; column -= INDENT; SET_SQLCODE; if (action->act_type == ACT_blob_create) { printa(column, "if SQLCODE = 0 then"); printa(column + INDENT, "%s := %s;", reference->ref_value, s); ENDIF; } ENDIF; } } #else // This is the version 3.3 of this routine - the original V4.0 version // has a core drop. // Ravi Kumar // //____________________________________________________________ // // Generate the call to open (or create) a blob. // static void gen_blob_open( ACT action, USHORT column) { BLB blob; PAT args; TEXT *pattern1 = "interbase.%IFCREATE%ELOPEN%EN_BLOB2 (%V1 %RF%DH, %RF%RT, %RF%BH, %RF%FR, %N1, %I1);"; TEXT *pattern2 = "interbase.%IFCREATE%ELOPEN%EN_BLOB2 (%V1 %RF%DH, %RF%RT, %RF%BH, %RF%FR, 0, isc_null_bpb);"; blob = (BLB) action->act_object; 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 = blob->blb_reference; /* blob identifier */ args.pat_ident1 = blob->blb_bpb_ident; if (args.pat_value1 = blob->blb_bpb_length) PATTERN_expand(column, pattern1, &args); else PATTERN_expand(column, pattern2, &args); } #endif //____________________________________________________________ // // Callback routine for BLR pretty printer. // static int gen_blr( int *user_arg, int offset, TEXT * string) { int from, to, len, c_len; SCHAR c; c_len = strlen(COMMENT); len = strlen(string); from = 0; to = 120 - c_len; while (from < len) { if (to < len) { c = string[to]; string[to] = 0; } ib_fprintf(out_file, "%s%s\n", COMMENT, &string[from]); if (to < len) string[to] = c; from = to; to = to + 120 - c_len; } return TRUE; } //____________________________________________________________ // // Zap all know handles. // static void gen_clear_handles( ACT action, int column) { GPRE_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); } } #ifdef NOT_USED_OR_REPLACED //____________________________________________________________ // // Generate a symbol to ease compatibility with V3. // static void gen_compatibility_symbol( TEXT * symbol, TEXT * v4_prefix, TEXT * trailer) { TEXT *v3_prefix; v3_prefix = (isLangCpp(sw_language)) ? "gds_" : "gds__"; ib_fprintf(out_file, "#define %s%s\t%s%s%s\n", v3_prefix, symbol, v4_prefix, symbol, trailer); } #endif //____________________________________________________________ // // Generate text to compile a request. // static void gen_compile( ACT action, int column) { GPRE_REQ request; DBB db; SYM symbol; BLB blob; request = action->act_request; column += INDENT; db = request->req_database; symbol = db->dbb_name; if (sw_auto) t_start_auto(action, request, status_vector(action), column, TRUE); if ((action->act_error || (action->act_flags & ACT_sql)) && sw_auto) printa(column, "if (%s = 0) and (%s%s /= 0) then", request->req_handle, ada_package, request_trans(action, request)); else printa(column, "if %s = 0 then", request->req_handle); column += INDENT; #ifdef NOT_USED_OR_REPLACED printa(column, "interbase.COMPILE_REQUEST%s (%s %s%s, %s%s, %d, isc_%d);", (request->req_flags & REQ_exp_hand) ? "" : "2", status_vector(action), ada_package, symbol->sym_string, request_trans(action, request), (request->req_flags & REQ_exp_hand) ? "" : "'address", request->req_length, request->req_ident); #endif printa(column, "interbase.COMPILE_REQUEST%s (%s %s%s, %s%s, %d, isc_%d);", (request->req_flags & REQ_exp_hand) ? "" : "2", status_vector(action), ada_package, symbol->sym_string, request->req_handle, (request->req_flags & REQ_exp_hand) ? "" : "'address", request->req_length, request->req_ident); SET_SQLCODE; column -= INDENT; ENDIF; if (blob = request->req_blobs) for (; blob; blob = blob->blb_next) printa(column - INDENT, "isc_%d := 0;", blob->blb_ident); } //____________________________________________________________ // // Generate a call to create a database. // static void gen_create_database( ACT action, int column) { GPRE_REQ request; DBB db; USHORT save_sw_auto; TEXT s1[32], s2[32]; request = ((MDBB) action->act_object)->mdbb_dpb_request; db = (DBB) request->req_database; sprintf(s1, "isc_%dl", 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_to_dpb_ptr (isc_%d'address);", s2, request->req_ident); if (db->dbb_r_user) printa(column, "interbase.MODIFY_DPB (%s, %s, interbase.isc_dpb_user_name, %s, %d);\n", s2, s1, db->dbb_r_user, (strlen(db->dbb_r_user) - 2)); if (db->dbb_r_password) printa(column, "interbase.MODIFY_DPB (%s, %s, interbase.isc_dpb_password, %s, %d);\n", s2, s1, db->dbb_r_password, (strlen(db->dbb_r_password) - 2)); /* ** =========================================================== ** == ** == Process Role Name ** == ** =========================================================== */ if (db->dbb_r_sql_role) printa(column, "interbase.MODIFY_DPB (%s, %s, interbase.isc_dpb_sql_role_name, %s, %d);\n", s2, s1, db->dbb_r_sql_role, (strlen(db->dbb_r_sql_role) - 2)); if (db->dbb_r_lc_messages) printa(column, "interbase.MODIFY_DPB (%s, %s, interbase.isc_dpb_lc_messages, %s, %d);\n", s2, s1, db->dbb_r_lc_messages, (strlen(db->dbb_r_lc_messages) - 2)); if (db->dbb_r_lc_ctype) printa(column, "interbase.MODIFY_DPB (%s, %s, interbase.isc_dpb_lc_ctype, %s, %d);\n", s2, s1, db->dbb_r_lc_ctype, (strlen(db->dbb_r_lc_ctype) - 2)); } else sprintf(s2, "isc_to_dpb_ptr (isc_%d'address)", request->req_ident); if (request->req_length) printa(column, "interbase.CREATE_DATABASE (%s %d, \"%s\", %s%s, %s, %s, 0);", status_vector(action), strlen(db->dbb_filename), db->dbb_filename, ada_package, db->dbb_name->sym_string, s1, s2); else printa(column, "interbase.CREATE_DATABASE (%s %d, \"%s\", %s%s, 0, interbase.null_dpb, 0);", status_vector(action), strlen(db->dbb_filename), db->dbb_filename, ada_package, db->dbb_name->sym_string); if (request && request->req_flags & REQ_extend_dpb) { if (request->req_length) printa(column, "if (%s != isc_%d)", s2, request->req_ident); printa(column + (request->req_length ? 4 : 0), "interbase.FREE (%s);", s2); /* reset the length of the dpb */ if (request->req_length) printa(column, "%s = %d;", s1, request->req_length); } printa(column, "if %sisc_status(1) = 0 then", ada_package); column += INDENT; save_sw_auto = sw_auto; sw_auto = (USHORT) TRUE; gen_ddl(action, column); sw_auto = save_sw_auto; column -= INDENT; printa(column, "else"); column += INDENT; SET_SQLCODE; column -= INDENT; printa(column, "end if;"); } //____________________________________________________________ // // Generate substitution text for END_STREAM. // static int gen_cursor_close( ACT action, GPRE_REQ request, int column) { 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 //int, the handles are the user's responsibility if (action->act_request-> req_flags & (REQ_sql_blob_open | REQ_sql_blob_create)) printa(column, "gds_%d := 0;", action-> act_request-> req_blobs-> blb_ident); } //____________________________________________________________ // // Generate text to open an embedded SQL cursor. // static int gen_cursor_open( ACT action, GPRE_REQ request, int column) { return column; } //____________________________________________________________ // // Generate insertion text for the database statement, // including the definitions of all requests, and blob // and port declarations for requests in the main routine. // static void gen_database( ACT action, int column) { DBB db; GPRE_REQ request; POR port; BLB blob; USHORT count; SSHORT blob_subtype; USHORT event_count, max_count; FORM form; LLS stack_ptr; TPB tpb; REF reference; GPRE_FLD field; BOOLEAN array_flag; if (first_flag++ != 0) return; ib_fprintf(out_file, "\n----- GPRE Preprocessor Definitions -----\n"); for (request = requests; request; request = request->req_next) { if (request->req_flags & REQ_local) continue; for (port = request->req_ports; port; port = port->por_next) make_port(port, column); } ib_fprintf(out_file, "\n"); for (db = isc_databases; db; db = db->dbb_next) for (form = db->dbb_forms; form; form = form->form_next) printa(column, "%s\t: interbase.form_handle := 0;\t-- form %s --", form->form_handle, form->form_name->sym_string); for (request = requests; request; request = request->req_routine) { if (request->req_flags & REQ_local) continue; for (port = request->req_ports; port; port = port->por_next) printa(column, "isc_%d\t: isc_%dt;\t\t\t-- message --", port->por_ident, port->por_ident); for (blob = request->req_blobs; blob; blob = blob->blb_next) { printa(column, "isc_%d\t: interbase.blob_handle;\t-- blob handle --", blob->blb_ident); if (!(blob_subtype = blob->blb_const_to_type)) if (reference = blob->blb_reference) if (field = reference->ref_field) blob_subtype = field->fld_sub_type; if (blob_subtype != 0 && blob_subtype != 1) printa(column, "isc_%d\t: %s (1 .. %d);\t\t-- blob segment --", blob->blb_buff_ident, BYTE_VECTOR_DCL, blob->blb_seg_length); else printa(column, "isc_%d\t: string (1 .. %d);\t\t-- blob segment --", blob->blb_buff_ident, blob->blb_seg_length); printa(column, "isc_%d\t: %s;\t\t-- segment length --", blob->blb_len_ident, USHORT_DCL); } } // generate event parameter block for each event in module max_count = 0; for (stack_ptr = events; stack_ptr; stack_ptr = stack_ptr->lls_next) { event_count = gen_event_block((ACT) stack_ptr->lls_object); max_count = MAX(event_count, max_count); } if (max_count) printa(column, "isc_events: %s(1..%d);\t-- event vector --", EVENT_LIST_DCL, max_count); for (request = requests; request; request = request->req_next) { gen_request(request, column); /* 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, column); array_flag = TRUE; } } if (array_flag) { printa(column, "isc_array_length\t: %s;\t-- slice return value --", LONG_DCL); printa(column, "isc_null_vector_l\t: %s (1..1);\t-- null long vector --", LONG_VECTOR_DCL); } printa(column, "isc_null_bpb\t: interbase.blr (1..1);\t-- null blob parameter block --"); if (!ada_package[0]) printa(column, "gds_trans\t: interbase.transaction_handle := 0;\t-- default transaction --"); printa(column, "isc_status\t: interbase.status_vector;\t-- status vector --"); printa(column, "isc_status2\t: interbase.status_vector;\t-- status vector --"); printa(column, "SQLCODE\t: %s := 0;\t\t\t-- SQL status code --", LONG_DCL); if (sw_pyxis && ((sw_window_scope != DBB_EXTERN) || !ada_package[0])) { printa(column, "isc_window\t: interbase.window_handle := 0;\t-- window handle --"); printa(column, "isc_width\t: %s := 80;\t-- window width --", USHORT_DCL); printa(column, "isc_height\t: %s := 24;\t-- window height --", USHORT_DCL); } if (!ada_package[0]) for (db = isc_databases; db; db = db->dbb_next) printa(column, "%s\t\t: interbase.database_handle%s;-- database handle --", db->dbb_name->sym_string, (db->dbb_scope == DBB_EXTERN) ? "" : " := 0"); printa(column, " "); count = 0; for (db = isc_databases; db; db = db->dbb_next) { count++; for (tpb = db->dbb_tpbs; tpb; tpb = tpb->tpb_dbb_next) gen_tpb(tpb, column + INDENT); } printa(column, "isc_teb\t: array (1..%d) of interbase.isc_teb_t;\t-- transaction vector ", count); printa(column, "----- end of GPRE definitions "); } //____________________________________________________________ // // Generate a call to update metadata. // static void gen_ddl( ACT action, int column) { GPRE_REQ request; // Set up command type for call to RDB$DDL request = action->act_request; // Generate a call to RDB$DDL to perform action if (sw_auto) { t_start_auto(action, 0, status_vector(action), column, TRUE); printa(column, "if %sgds_trans /= 0 then", ada_package); column += INDENT; } printa(column, "interbase.DDL (%s %s%s, %s%s, %d, isc_%d'address);", status_vector(action), ada_package, request->req_database->dbb_name->sym_string, ada_package, request->req_trans, request->req_length, request->req_ident); if (sw_auto) { printa(column, "if %sisc_status(1) = 0 then", ada_package); printa(column + INDENT, "interbase.commit_TRANSACTION (%s %sgds_trans);", status_vector(action), ada_package); printa(column, "else", ada_package); printa(column + INDENT, "interbase.rollback_TRANSACTION (%sgds_trans);", ada_package); ENDIF; column -= INDENT; ENDIF; } SET_SQLCODE; } //____________________________________________________________ // // Generate a call to create a database. // static void gen_drop_database( ACT action, int column) { GPRE_REQ request; DBB db; db = (DBB) action->act_object; request = action->act_request; printa(column, "interbase.DROP_DATABASE (%s %d, \"%s\", RDBK_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, "interbase.embed_dsql_close (%s %s);", status_vector(action), 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, "interbase.embed_dsql_declare (%s %s, %s);", status_vector(action), 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 input_flag) { DYN statement; TEXT s[64]; statement = (DYN) action->act_object; printa(column, "interbase.embed_dsql_describe%s (%s %s, %d, %s'address);", input_flag ? "_bind" : "", status_vector(action), 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; TEXT *transaction, s[64]; struct gpre_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 = "gds_trans"; request = NULL; } if (sw_auto) { t_start_auto(action, request, status_vector(action), column, TRUE); printa(column, "if %s%s /= 0 then", ada_package, transaction); column += INDENT; } if (statement->dyn_sqlda2) printa(column, "interbase.embed_dsql_execute2 (isc_status, %s%s, %s, %d, %s'address);", ada_package, transaction, make_name(s, statement->dyn_statement_name), sw_sql_dialect, (statement->dyn_sqlda) ? ada_null_address : statement-> dyn_sqlda, statement->dyn_sqlda2); else if (statement->dyn_sqlda) printa(column, "interbase.embed_dsql_execute (isc_status, %s%s, %s, %d, %s'address);", ada_package, transaction, make_name(s, statement-> dyn_statement_name), sw_sql_dialect, statement->dyn_sqlda); else printa(column, "interbase.embed_dsql_execute (isc_status, %s%s, %s, %d);", ada_package, transaction, make_name(s, statement-> dyn_statement_name), sw_sql_dialect); if (sw_auto) { column -= INDENT; ENDIF; } 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; if (statement->dyn_sqlda) printa(column, "interbase.embed_dsql_fetch (isc_status, SQLCODE, %s, %d, %s'address);", make_name(s, statement->dyn_cursor_name), sw_sql_dialect, statement->dyn_sqlda); else printa(column, "interbase.embed_dsql_fetch (isc_status, SQLCODE, %s, %d);", make_name(s, statement->dyn_cursor_name), sw_sql_dialect); printa(column, "if SQLCODE /= 100 then"); printa(column + INDENT, "SQLCODE := interbase.sqlcode (isc_status);"); ENDIF; } //____________________________________________________________ // // 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 gpre_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 = "gds_trans"; request = NULL; } database = statement->dyn_database; if (sw_auto) { t_start_auto(action, request, status_vector(action), column, TRUE); printa(column, "if %s%s /= 0 then", ada_package, transaction); column += INDENT; } printa(column, "interbase.embed_dsql_execute_immed (isc_status, %s%s, %s%s, %s'length(1), %s, %d);", ada_package, database->dbb_name->sym_string, ada_package, transaction, statement->dyn_string, statement->dyn_string, sw_sql_dialect); if (sw_auto) { column -= INDENT; ENDIF; } 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; if (statement->dyn_sqlda) printa(column, "interbase.embed_dsql_insert (isc_status, %s, %d, %s'address);", make_name(s, statement->dyn_cursor_name), sw_sql_dialect, statement->dyn_sqlda); else printa(column, "interbase.embed_dsql_insert (isc_status, %s, %d);", make_name(s, statement->dyn_cursor_name), sw_sql_dialect); SET_SQLCODE; } //____________________________________________________________ // // Generate a dynamic SQL statement. // static void gen_dyn_open( ACT action, int column) { DYN statement; TEXT *transaction, s[64]; struct gpre_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 = "gds_trans"; request = NULL; } make_name(s, statement->dyn_cursor_name); if (sw_auto) { t_start_auto(action, request, status_vector(action), column, TRUE); printa(column, "if %s%s /= 0 then", ada_package, transaction); column += INDENT; } if (statement->dyn_sqlda) printa(column, "interbase.embed_dsql_open (isc_status, %s%s, %s, %d, %s'address);", ada_package, transaction, s, sw_sql_dialect, statement->dyn_sqlda); else printa(column, "interbase.embed_dsql_open (isc_status, %s%s, %s, %d);", ada_package, transaction, s, sw_sql_dialect); if (sw_auto) { column -= INDENT; ENDIF; } SET_SQLCODE; } //____________________________________________________________ // // Generate a dynamic SQL statement. // static void gen_dyn_prepare( ACT action, int column) { DYN statement; DBB database; TEXT *transaction, s[64]; struct gpre_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 = "gds_trans"; request = NULL; } if (sw_auto) { t_start_auto(action, request, status_vector(action), column, TRUE); printa(column, "if %s%s /= 0 then", ada_package, transaction); column += INDENT; } if (statement->dyn_sqlda) printa(column, "interbase.embed_dsql_prepare (isc_status, %s%s, %s%s, %s, %s'length(1), %s, %d, %s'address);", ada_package, database->dbb_name->sym_string, ada_package, transaction, make_name(s, statement->dyn_statement_name), statement->dyn_string, statement->dyn_string, sw_sql_dialect, statement->dyn_sqlda); else printa(column, "interbase.embed_dsql_prepare (isc_status, %s%s, %s%s, %s, %s'length(1), %s, %d);", ada_package, database->dbb_name->sym_string, ada_package, transaction, make_name(s, statement->dyn_statement_name), statement->dyn_string, statement->dyn_string, sw_sql_dialect); if (sw_auto) { column -= INDENT; ENDIF; } SET_SQLCODE; } //____________________________________________________________ // // Generate substitution text for END_MODIFY. // static void gen_emodify( ACT action, int column) { UPD modify; REF reference, source; GPRE_FLD field; TEXT s1[20], s2[20]; modify = (UPD) action->act_object; for (reference = modify->upd_port->por_references; reference; reference = reference->ref_next) { if (!(source = reference->ref_source)) continue; field = reference->ref_field; printa(column, "%s := %s;", gen_name(s1, reference, TRUE), gen_name(s2, source, TRUE)); 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) { GPRE_REQ request; request = action->act_request; // if we did a store ... returning_values aka store2 // just wrap up any dangling error handling if (request->req_type == REQ_store2) { if (action->act_error) ENDIF; return; } gen_start(action, request->req_primary, column); if (action->act_error) ENDIF; } //____________________________________________________________ // // Generate definitions associated with a single request. // static void gen_endfor( ACT action, int column) { GPRE_REQ request; request = action->act_request; if (request->req_sync) gen_send(action, request->req_sync, column + INDENT); printa(column, "end loop;"); if (action->act_error || (action->act_flags & ACT_sql)) ENDIF; } //____________________________________________________________ // // Generate substitution text for ERASE. // static void gen_erase( ACT action, int column) { UPD erase; erase = (UPD) action->act_object; gen_send(action, erase->upd_port, column); } //____________________________________________________________ // // Generate event parameter blocks for use // with a particular call to isc_event_wait. // For languages too dim to deal with variable // arg lists, set up a vector for the event names. // static SSHORT gen_event_block( ACT action) { GPRE_NOD init, list; SYM event_name; int ident; init = (GPRE_NOD) action->act_object; event_name = (SYM) init->nod_arg[0]; ident = CMP_next_ident(); init->nod_arg[2] = (GPRE_NOD) ident; list = init->nod_arg[1]; printa(0, "isc_%da\t\t: system.address;\t\t-- event parameter block --\n", ident); printa(0, "isc_%db\t\t: system.address;\t\t-- result parameter block --\n", ident); printa(0, "isc_%dc\t\t: %s;\t\t-- count of events --\n", ident, USHORT_DCL); printa(0, "isc_%dl\t\t: %s;\t\t-- length of event parameter block --\n", ident, USHORT_DCL); printa(0, "isc_%dv\t\t: interbase.isc_el_t (1..%d);\t\t-- vector for initialization --\n", ident, list->nod_count); return list->nod_count; } //____________________________________________________________ // // Generate substitution text for EVENT_INIT. // static void gen_event_init( ACT action, int column) { GPRE_NOD init, event_list, *ptr, *end, node; REF reference; PAT args; TEXT variable[32]; USHORT count; TEXT * pattern1 = "isc_%N1l := interbase.event_block (%RFisc_%N1a'address, %RFisc_%N1b'address, isc_%N1c, %RFisc_%N1v);", *pattern2 = "interbase.event_wait (%V1 %RF%DH, isc_%N1l, isc_%N1a, isc_%N1b);", *pattern3 = "interbase.event_counts (isc_events, isc_%N1l, isc_%N1a, isc_%N1b);"; if (action->act_error) BEGIN; BEGIN; init = (GPRE_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]; // generate call to dynamically generate event blocks for (ptr = event_list->nod_arg, count = 0, end = ptr + event_list->nod_count; ptr < end; ptr++) { count++; node = *ptr; if (node->nod_type == nod_field) { reference = (REF) node->nod_arg[0]; gen_name(variable, reference, TRUE); printa(column, "isc_%dv(%d) := %s'address;", args.pat_value1, count, variable); } else printa(column, "isc_%dv(%d) := %s'address;", args.pat_value1, count, node->nod_arg[0]); } printa(column, "isc_%dc := %d;", args.pat_value1, (int) event_list->nod_count); PATTERN_expand(column, pattern1, &args); // generate actual call to event_wait PATTERN_expand(column, pattern2, &args); // get change in event counts, copying event parameter block for reuse PATTERN_expand(column, pattern3, &args); END; SET_SQLCODE; } //____________________________________________________________ // // Generate substitution text for EVENT_WAIT. // static void gen_event_wait( ACT action, int column) { PAT args; GPRE_NOD event_init; SYM event_name, stack_name; DBB database; LLS stack_ptr; ACT event_action; int ident; TEXT s[64]; TEXT * pattern1 = "interbase.event_wait (%V1 %RF%DH, isc_%N1l, isc_%N1a, isc_%N1b);", *pattern2 = "interbase.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 = (GPRE_NOD) event_action->act_object; stack_name = (SYM) event_init->nod_arg[0]; if (!strcmp(event_name->sym_string, stack_name->sym_string)) { ident = (int) event_init->nod_arg[2]; database = (DBB) event_init->nod_arg[3]; } } if (ident < 0) { sprintf(s, "event handle \"%s\" not found", event_name->sym_string); IBERROR(s); return; } 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(column, pattern1, &args); PATTERN_expand(column, pattern2, &args); 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) { GPRE_REQ request; GPRE_NOD var_list; int i; SCHAR s[20]; #ifdef SCROLLABLE_CURSORS POR port; REF reference; VAL value; SCHAR *direction, *offset; #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 MOD 2 /= %s or %s /= 1 then", request->req_ident, direction, offset); column += INDENT; /* 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; ENDIF; printa(column, "if SQLCODE = 0 then"); column += INDENT; } #endif if (request->req_sync) { gen_send(action, request->req_sync, column); printa(column, "if SQLCODE = 0 then"); column += INDENT; } gen_receive(action, column, request->req_primary); printa(column, "if SQLCODE = 0 then"); column += INDENT; printa(column, "if %s /= 0 then", gen_name(s, request->req_eof, TRUE)); column += INDENT; if (var_list = (GPRE_NOD) action->act_object) { for (i = 0; i < var_list->nod_count; i++) asgn_to(action, (REF) var_list->nod_arg[i], column); } else { /* No WITH clause on the FETCH, so no assignments generated; fix for bug#940. mao 6/20/89 */ printa(column, "NULL;"); } column -= INDENT; printa(column, "else"); printa(column + INDENT, "SQLCODE := 100;"); ENDIF; column -= INDENT; ENDIF; column -= INDENT; if (request->req_sync) ENDIF; #ifdef SCROLLABLE_CURSORS if (port) { column -= INDENT; ENDIF; } #endif } //____________________________________________________________ // // Generate substitution text for FINISH. // static void gen_finish( ACT action, int column) { DBB db; GPRE_REQ request; RDY ready; db = NULL; if (sw_auto || ((action->act_flags & ACT_sql) && (action->act_type != ACT_disconnect))) { printa(column, "if %sgds_trans /= 0 then", ada_package); printa(column + INDENT, "interbase.%s_TRANSACTION (%s %sgds_trans);", (action->act_type != ACT_rfinish) ? "COMMIT" : "ROLLBACK", status_vector(action), ada_package); ENDIF; } // the user supplied one or more db_handles for (ready = (RDY) action->act_object; ready; ready = ready->rdy_next) { db = ready->rdy_database; if (action->act_error || (action->act_flags & ACT_sql)) printa(column, "if %s%s /= 0 then", ada_package, db->dbb_name->sym_string); printa(column, "interbase.DETACH_DATABASE (%s %s%s);", status_vector(action), ada_package, db->dbb_name->sym_string); if (action->act_error || (action->act_flags & ACT_sql)) ENDIF; } // no hanbdles, so we finish all known databases if (!db) { if (action->act_error || (action->act_flags & ACT_sql)) printa(column, "if %sgds_trans = 0 then", ada_package); 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 /= 0 and isc_status(1) = 0 then", ada_package, db->dbb_name->sym_string); else printa(column, "if %s%s /= 0 then", ada_package, db->dbb_name->sym_string); column += INDENT; printa(column, "interbase.DETACH_DATABASE (%s %s%s);", status_vector(action), ada_package, db->dbb_name->sym_string); for (request = requests; request; request = request->req_next) if (!(request->req_flags & REQ_exp_hand) && request->req_type != REQ_slice && request->req_type != REQ_procedure && request->req_database == db) printa(column, "%s := 0;", request->req_handle); column -= INDENT; ENDIF; } if (action->act_error || (action->act_flags & ACT_sql)) ENDIF; } SET_SQLCODE; } //____________________________________________________________ // // Generate substitution text for FOR statement. // static void gen_for( ACT action, int column) { POR port; GPRE_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 isc_status(1) = 0 then"); printa(column, "loop"); column += INDENT; gen_receive(action, column, request->req_primary); if (action->act_error || (action->act_flags & ACT_sql)) printa(column, "exit when (%s = 0) or (isc_status(1) /= 0);", gen_name(s, request->req_eof, TRUE)); else printa(column, "exit when %s = 0;", gen_name(s, request->req_eof, TRUE)); if (port = action->act_request->req_primary) for (reference = port->por_references; reference; reference = reference->ref_next) if (reference->ref_field-> fld_array_info) gen_get_or_put_slice(action, reference, TRUE, column); } //____________________________________________________________ // // Generate code for a form interaction. // static void gen_form_display( ACT action, int column) { FINT display; GPRE_REQ request; REF reference, master; POR port; DBB dbb; TEXT s[32], out[16]; int code; display = (FINT) action->act_object; request = display->fint_request; dbb = request->req_database; port = request->req_ports; // 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, "0"); else sprintf(out, "isc_%d", port->por_ident); printa(column, "interbase.drive_form (%s %s%s, %s%s, %sisc_window, %s, isc_%d'address, %s'address)", status_vector(action), ada_package, dbb->dbb_name->sym_string, ada_package, request->req_trans, ADA_WINDOW_PACKAGE, request->req_handle, port->por_ident, out); } //____________________________________________________________ // // Generate code for a form block. // static void gen_form_end( ACT action, int column) { printa(column, "interbase.pop_window (%sisc_window)", ADA_WINDOW_PACKAGE); } //____________________________________________________________ // // Generate code for a form block. // static void gen_form_for( ACT action, int column) { GPRE_REQ request; FORM form; TEXT *status; DBB dbb; int indent; indent = column + INDENT; request = action->act_request; form = request->req_form; dbb = request->req_database; status = status_vector(action); // Get database attach and transaction started if (sw_auto) t_start_auto(action, 0, status_vector(action), indent, TRUE); // Get form loaded first printa(column, "if %s = 0 then", request->req_form_handle); printa(column, "interbase.load_form (%s %s%s, %s%s, %s, %d, \"%s\");", status, ada_package, dbb->dbb_name->sym_string, ada_package, request->req_trans, request->req_form_handle, strlen(form->form_name->sym_string), form->form_name->sym_string); ENDIF; // Get map compiled printa(column, "if %s = 0 then", request->req_handle); printa(indent, "interbase.compile_map (%s %s, %s, %d, isc_%d);", status, request->req_form_handle, request->req_handle, request->req_length, request->req_ident); ENDIF; // Reset form to known state printa(column, "interbase.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) { GPRE_REQ request; POR port; REF reference; GPRE_FLD field; ACT action; TEXT *dtype, s[64]; action = (ACT) function->act_object; if (action->act_type != ACT_any) { IBERROR("can't generate function"); return; } request = action->act_request; ib_fprintf(out_file, "static %s_r (request, transaction", request->req_handle, 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)); 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 = "long"; break; case dtype_cstring: case dtype_text: dtype = "char*"; break; case dtype_quad: dtype = "long"; break; case dtype_date: case dtype_blob: dtype = "ISC_QUAD"; break; case dtype_real: dtype = "float"; break; case dtype_double: dtype = "double"; break; default: IBERROR("gen_function: unsupported datatype"); return; } ib_fprintf(out_file, " %s\t%s;\n", dtype, gen_name(s, reference->ref_source, TRUE)); } ib_fprintf(out_file, "{\n"); for (port = request->req_ports; port; port = port->por_next) make_port(port, 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[25], s3[25], s4[25]; TEXT *pattern1 = "interbase.GET_SLICE (%V1 %RF%DH%RE, %RF%S1%RE, %S2, %N1, %S3, %N2, %S4, %L1, %S5, %S6);"; TEXT *pattern2 = "interbase.PUT_SLICE (%V1 %RF%DH%RE, %RF%S1%RE, %S2, %N1, %S3, %N2, %S4, %L1, %S5);"; if (!(reference->ref_flags & REF_fetch_array)) return; args.pat_vector1 = status_vector(action); /* status vector */ args.pat_database = action->act_request->req_database; /* database handle */ args.pat_string1 = action->act_request->req_trans; /* transaction handle */ gen_name(s1, reference, TRUE); /* blob handle */ args.pat_string2 = s1; args.pat_value1 = reference->ref_sdl_length; /* slice descr. length */ sprintf(s2, "isc_%d", reference->ref_sdl_ident); /* slice description */ args.pat_string3 = s2; args.pat_value2 = 0; /* parameter length */ sprintf(s3, "isc_null_vector_l"); /* parameter block init */ args.pat_string4 = s3; args.pat_long1 = reference->ref_field->fld_array_info->ary_size; /* slice size */ if (action->act_flags & ACT_sql) { sprintf(s4, "%s'address", reference->ref_value); } else { sprintf(s4, "isc_%d'address", reference->ref_field->fld_array_info->ary_ident); } args.pat_string5 = s4; /* array name */ args.pat_string6 = "isc_array_length"; /* return length */ if (get) PATTERN_expand(column, pattern1, &args); else PATTERN_expand(column, pattern2, &args); } //____________________________________________________________ // // Generate the code to do a get segment. // static void gen_get_segment( ACT action, int column) { BLB blob; REF into; if (action->act_flags & ACT_sql) blob = (BLB) action->act_request->req_blobs; else blob = (BLB) action->act_object; if (action->act_error || (action->act_flags & ACT_sql)) printa(column, "interbase.ISC_GET_SEGMENT (isc_status, isc_%d, isc_%d, %d, isc_%d'address);", blob->blb_ident, blob->blb_len_ident, blob->blb_seg_length, blob->blb_buff_ident); else printa(column, "interbase.ISC_GET_SEGMENT (isc_status(1), isc_%d, isc_%d, %d, isc_%d'address);", blob->blb_ident, blob->blb_len_ident, blob->blb_seg_length, blob->blb_buff_ident); if (action->act_flags & ACT_sql) { into = action->act_object; SET_SQLCODE; printa(column, "if (SQLCODE = 0) or (SQLCODE = 101) then"); printa(column + INDENT, "%s := isc_%d;", into->ref_value, blob->blb_buff_ident); if (into->ref_null_value) printa(column + INDENT, "%s := isc_%d;", into->ref_null_value, blob->blb_len_ident); ENDIF; } } //____________________________________________________________ // // Generate end of block for PUT_ITEM and FOR_ITEM. // static void gen_item_end( ACT action, int column) { GPRE_REQ request; REF reference, master; POR port; DBB dbb; TEXT s[32], index[16]; 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; gen_name(index, request->req_index, TRUE); printa(column, "%s := %s + 1;", index, index); printa(column, "end loop"); return; } dbb = request->req_database; port = request->req_ports; // 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); printa(column, "interbase.insert_sub_form (%s %s%s, %s%s, %s, isc_%d'address)", status_vector(action), ada_package, dbb->dbb_name->sym_string, ada_package, 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) { GPRE_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 = 0 then", request->req_handle); printa(column + INDENT, "interbase.compile_sub_map (%s %s, %s, %d, isc_%d);", status, parent->req_handle, request->req_handle, request->req_length, request->req_ident); printa(column, "end if;"); if (action->act_type != ACT_item_for) return; // Build stuff for item loop gen_name(index, request->req_index, TRUE); printa(column, "%s := 1;", index); printa(column, "loop"); column += INDENT; printa(column, "interbase.fetch_sub_form (%s %s%s, %s%s, %s, isc_%d'address);", status, ada_package, request->req_database->dbb_name->sym_string, ada_package, request->req_trans, request->req_handle, request->req_ports->por_ident); printa(column, "exit when %s = 0;", index); } //____________________________________________________________ // // Generate code to drive a mass update. Just start a request // and get the result. // static void gen_loop( ACT action, int column) { GPRE_REQ request; POR port; TEXT name[20]; gen_s_start(action, column); request = action->act_request; port = request->req_primary; printa(column, "if SQLCODE = 0 then"); column += INDENT; gen_receive(action, column, port); gen_name(name, port->por_references, TRUE); printa(column, "if (SQLCODE = 0) and (%s = 0) then", name); printa(column + INDENT, "SQLCODE := 100;"); ENDIF; column -= INDENT; ENDIF; } //____________________________________________________________ // // static void gen_menu( ACT action, int column) { GPRE_REQ request; request = action->act_request; printa(column, "case interbase.menu (%sisc_window, %s, %d, isc_%d) is", ADA_WINDOW_PACKAGE, request->req_handle, request->req_length, request->req_ident); } //____________________________________________________________ // // Generate code for a menu interaction. // static void gen_menu_display( ACT action, int column) { MENU menu; GPRE_REQ request, display_request; request = action->act_request; display_request = (GPRE_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, "interbase.drive_menu (%sisc_window, %s, %d, isc_%d, isc_%dl, isc_%d,", ADA_WINDOW_PACKAGE, request->req_handle, display_request->req_length, display_request->req_ident, menu->menu_title, menu->menu_title); printa(column, "\n\t\t\tisc_%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_end( ACT action, int column) { GPRE_REQ request; request = action->act_request; if (request->req_flags & REQ_menu_for) return; printa(column, "when others =>"); printa(column + INDENT, "null ;"); printa(column, "end case"); } //____________________________________________________________ // // static void gen_menu_entree( ACT action, int column) { GPRE_REQ request; request = action->act_request; printa(column, "when %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); } //____________________________________________________________ // // Generate code for a menu block. // static void gen_menu_for( ACT action, int column) { GPRE_REQ request; request = action->act_request; // Get menu created if (!(request->req_flags & REQ_exp_hand)) printa(column, "interbase.initialize_menu (%s);", 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) { GPRE_REQ request; ENTREE entree; if (action->act_pair->act_type == ACT_item_for) { column += INDENT; printa(column, "end loop"); return; } entree = (ENTREE) action->act_pair->act_object; request = entree->entree_request; align(column); ib_fprintf(out_file, "interbase.put_entree (%s, isc_%dl, isc_%d, isc_%d);", 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; GPRE_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, "loop"); column += INDENT; align(column); printa(column, "interbase.get_entree (%s, isc_%dl, isc_%d, isc_%d, isc_%d);", request->req_handle, entree->entree_entree, entree->entree_entree, entree->entree_value, entree->entree_end); printa(column, "exit when isc_%d /= 0;", entree->entree_end); } //____________________________________________________________ // // Generate definitions associated with a dynamic menu request. // static void gen_menu_request( GPRE_REQ request, int column) { 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(column, "isc_%dl\t: %s;\t\t-- TITLE_LENGTH --", menu->menu_title, USHORT_DCL); printa(column, "isc_%d\t: string (1..81);\t\t-- TITLE_TEXT --", menu->menu_title); printa(column, "isc_%d\t: %s;\t\t-- TERMINATOR --", menu->menu_terminator, USHORT_DCL); printa(column, "isc_%dl\t: %s;\t\t-- ENTREE_LENGTH --", menu->menu_entree_entree, USHORT_DCL); printa(column, "isc_%d\t: string (1..81);\t\t-- ENTREE_TEXT --", menu->menu_entree_entree); printa(column, "isc_%d\t: %s;\t\t-- ENTREE_VALUE --", menu->menu_entree_value, LONG_DCL); } if (entree) { entree->entree_entree = CMP_next_ident(); entree->entree_value = CMP_next_ident(); entree->entree_end = CMP_next_ident(); printa(column, "isc_%dl\t: %s;\t\t-- ENTREE_LENGTH --", entree->entree_entree, USHORT_DCL); printa(column, "isc_%d\t: string (1..81);\t\t-- ENTREE_TEXT --", entree->entree_entree); printa(column, "isc_%d\t: %s;\t\t-- ENTREE_VALUE --", entree->entree_value, LONG_DCL); printa(column, "isc_%d\t: %s;\t\t-- --", entree->entree_end, USHORT_DCL); } } //____________________________________________________________ // // Generate a name for a reference. Name is constructed from // port and parameter idents. // static TEXT *gen_name( TEXT * 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 sprintf(string, "isc_%d.isc_%d", reference->ref_port->por_ident, 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 (isc_status (1) /= 0) and (isc_status(1) /= interbase.isc_segment) and (isc_status(1) /= interbase.isc_segstr_eof) then"); else printa(column, "if (isc_status (1) /= 0) then"); } //____________________________________________________________ // // Generate code for an EXECUTE PROCEDURE. // static void gen_procedure( ACT action, int column) { PAT args; TEXT *pattern; GPRE_REQ request; POR in_port, out_port; DBB dbb; 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_string2 = ada_null_address; args.pat_request = request; args.pat_port = in_port; args.pat_port2 = out_port; if (in_port && in_port->por_length) pattern = "interbase.gds_transact_request (%V1 %RF%DH%RE, %RF%RT%RE, %VF%RS%VE, %RF%RI%RE, %VF%PL%VE, %PI'address, %VF%QL%VE, %QI'address);\n"; else pattern = "interbase.gds_transact_request (%V1 %RF%DH%RE, %RF%RT%RE, %VF%RS%VE, %RF%RI%RE, %VF0%VE, %S2, %VF%QL%VE, %QI'address);\n"; // 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(column, pattern, &args); SET_SQLCODE; printa(column, "if SQLCODE = 0 then"); // Move out output values asgn_to_proc(request->req_references, column); ENDIF; } //____________________________________________________________ // // Generate the code to do a put segment. // static void gen_put_segment( ACT action, int column) { BLB blob; REF from; if (action->act_flags & ACT_sql) { blob = (BLB) action->act_request->req_blobs; from = action->act_object; printa(column, "isc_%d := %s;", blob->blb_len_ident, from->ref_null_value); printa(column, "isc_%d := %s;", blob->blb_buff_ident, from->ref_value); } else blob = (BLB) action->act_object; printa(column, "interbase.ISC_PUT_SEGMENT (%s isc_%d, isc_%d, isc_%d'address);", status_vector(action), blob->blb_ident, blob->blb_len_ident, blob->blb_buff_ident); SET_SQLCODE; } //____________________________________________________________ // // Generate BLR in raw, numeric form. Ughly but dense. // static void gen_raw( UCHAR * blr, enum req_t request_type, int request_length, int column) { UCHAR *end; SCHAR c; TEXT buffer[80], *p, *limit; p = buffer; limit = buffer + 60; for (end = blr + request_length - 1; blr <= end; blr++) { c = *blr; sprintf(p, "%d", c); while (*p) p++; if (blr != end) *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 isc_status(1) = 0 then"); make_ready(db, filename, vector, column, ready->rdy_request); if ((action->act_error || (action->act_flags & ACT_sql)) && ready != (RDY) action->act_object) ENDIF; } SET_SQLCODE; } //____________________________________________________________ // // Generate receive call for a port. // static void gen_receive( ACT action, int column, POR port) { GPRE_REQ request; request = action->act_request; printa(column, "interbase.RECEIVE (%s %s, %d, %d, isc_%d'address, %s);", status_vector(action), request->req_handle, port->por_msg_number, port->por_length, port->por_ident, request->req_request_level); 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; GPRE_REQ request; exp_db = (DBB) action->act_object; for (request = requests; request; request = request->req_next) { db = request->req_database; if (exp_db && db != exp_db) continue; if (!(request->req_flags & REQ_exp_hand)) { printa(column, "if %s%s /= 0 then", ada_package, db->dbb_name->sym_string); printa(column + INDENT, "interbase.release_request (isc_status, %s);", request->req_handle); printa(column, "end if;"); printa(column, "%s := 0;", request->req_handle); } } } //____________________________________________________________ // // Generate definitions associated with a single request. // static void gen_request( GPRE_REQ request, int column) { REF reference; BLB blob; POR port; SSHORT length; TEXT *string_type; // generate request handle, blob handles, and ports 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) { if (request->req_type == REQ_menu) printa(column, "%s\t: interbase.menu_handle := 0;-- menu handle --", request->req_handle); else if (request->req_type == REQ_form) printa(column, "%s\t: interbase.map_handle := 0;-- map handle --", request->req_handle); else printa(column, "%s\t: interbase.request_handle := 0;-- request handle --", request->req_handle); } if (request->req_flags & (REQ_sql_blob_open | REQ_sql_blob_create)) printa(column, "isc_%do\t: %s;\t\t-- SQL CURSOR FLAG --", request->req_ident, SHORT_DCL); // 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(column, "isc_%dp\t: interbase.dpb_ptr := 0;\t-- db parameter block --", request->req_ident); if (!request->req_length) printa(column, "isc_%dl\t: interbase.isc_ushort := 0;\t-- db parameter block --", request->req_ident); } // generate actual BLR string if (request->req_length) { length = request->req_length; switch (request->req_type) { case REQ_create_database: if (ada_flags & ADA_create_database) { printa(column, "function isc_to_dpb_ptr is new unchecked_conversion (system.address, interbase.dpb_ptr);"); ada_flags &= ~ADA_create_database; } /* fall into ... */ case REQ_ready: printa(column, "isc_%dl\t: interbase.isc_ushort := %d;\t-- db parameter block --", request->req_ident, length); printa(column, "isc_%d\t: CONSTANT interbase.dpb (1..%d) := (", request->req_ident, length); break; default: if (request->req_flags & REQ_sql_cursor) printa(column, "isc_%do\t: %s;\t\t-- SQL CURSOR FLAG --", request->req_ident, SHORT_DCL); #ifdef SCROLLABLE_CURSORS if (request->req_flags & REQ_scroll) printa(column, "isc_%ddirection\t: interbase.isc_ushort := 0;\t-- last direction sent to engine --", request->req_ident); #endif printa(column, "isc_%d\t: CONSTANT interbase.blr (1..%d) := (", request->req_ident, length); } gen_raw(request->req_blr, request->req_type, request->req_length, column); printa(column, ");\n"); if (!sw_raw) { printa(column, "---"); printa(column, "--- FORMATTED REQUEST BLR FOR GDS_%d = \n", request->req_ident); switch (request->req_type) { case REQ_create_database: case REQ_ready: string_type = "DPB"; if (PRETTY_print_cdb((SCHAR*) request->req_blr, (int (*)()) 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, ( int (*)()) 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, ( int (*)()) 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, (int (*)()) gen_blr, 0, 1)) IBERROR("internal error during menu generation"); break; case REQ_slice: string_type = "SDL"; if (PRETTY_print_sdl((SCHAR*) request->req_blr, ( int (*)() ) gen_blr, 0, 0)) IBERROR("internal error during SDL generation"); break; default: string_type = "BLR"; if (isc_print_blr((SCHAR*) request->req_blr, ( void (*)() ) gen_blr, 0, 0)) IBERROR("internal error during BLR generation"); } } else { switch (request->req_type) { case REQ_create_database: case REQ_ready: string_type = "DPB"; break; case REQ_ddl: string_type = "DYN"; break; case REQ_form: string_type = "form map"; break; case REQ_menu: string_type = "menu"; break; case REQ_slice: string_type = "SDL"; break; default: string_type = "BLR"; } } printa(column, "\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(column, "isc_%d\t: CONSTANT interbase.blr (1..%d) := (", reference->ref_sdl_ident, reference->ref_sdl_length); gen_raw((UCHAR*) reference->ref_sdl, REQ_slice, reference->ref_sdl_length, column); printa(column, "); \t--- end of SDL string for isc_%d\n", reference->ref_sdl_ident); if (!sw_raw) { printa(column, "---"); printa(column, "--- FORMATTED REQUEST SDL FOR GDS_%d = \n", reference->ref_sdl_ident); if (PRETTY_print_sdl(reference->ref_sdl, ( int(*)() ) gen_blr, 0, 1)) IBERROR("internal error during SDL generation"); } } // Print out any blob parameter blocks required for (blob = request->req_blobs; blob; blob = blob->blb_next) if (blob->blb_bpb_length) { printa(column, "isc_%d\t: CONSTANT interbase.blr (1..%d) := (", blob->blb_bpb_ident, blob->blb_bpb_length); gen_raw(blob->blb_bpb, request->req_type, blob->blb_bpb_length, column); printa(INDENT, ");\n"); } if (request->req_type == REQ_menu) gen_menu_request(request, column); // If this is a GET_SLICE/PUT_slice, allocate some variables if (request->req_type == REQ_slice) { printa(INDENT, "isc_%ds\t: %s;\t\t", request->req_ident, LONG_DCL); printa(INDENT, "isc_%dv: %s (1..%d);", request->req_ident, LONG_VECTOR_DCL, MAX(request->req_slice->slc_parameters, 1)); } } //____________________________________________________________ // // Generate receive call for a port // in a store2 statement. // static void gen_return_value( ACT action, int column) { UPD update; REF reference; GPRE_REQ request; request = action->act_request; if (action->act_pair->act_error) column += INDENT; align(column); gen_start(action, request->req_primary, column); 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; GPRE_REQ request; POR port; SSHORT blob_subtype; REF reference; GPRE_FLD field; column += INDENT; for (request = (GPRE_REQ) action->act_object; request; request = request->req_routine) { for (port = request->req_ports; port; port = port->por_next) make_port(port, column); for (port = request->req_ports; port; port = port->por_next) printa(column, "isc_%d\t: isc_%dt;\t\t\t-- message --", port->por_ident, port->por_ident); for (blob = request->req_blobs; blob; blob = blob->blb_next) { printa(column, "isc_%d\t: interbase.blob_handle;\t-- blob handle --", blob->blb_ident); if (!(blob_subtype = blob->blb_const_to_type)) if (reference = blob->blb_reference) if (field = reference->ref_field) blob_subtype = field->fld_sub_type; if (blob_subtype != 0 && blob_subtype != 1) printa(column, "isc_%d\t: %s (1..%d);\t-- blob segment --", blob->blb_buff_ident, BYTE_VECTOR_DCL, blob->blb_seg_length); else printa(column, "isc_%d\t: string (1..%d);\t-- blob segment --", blob->blb_buff_ident, blob->blb_seg_length); printa(column, "isc_%d\t: %s;\t\t\t-- segment length --", blob->blb_len_ident, USHORT_DCL); } } column -= INDENT; } //____________________________________________________________ // // Generate substitution text for END_STREAM. // static void gen_s_end( ACT action, int column) { GPRE_REQ request; request = action->act_request; if (action->act_type == ACT_close) { make_cursor_open_test(ACT_close, request, column); column += INDENT; } printa(column, "interbase.UNWIND_REQUEST (%s %s, %s);", status_vector(action), request->req_handle, request->req_request_level); SET_SQLCODE; if (action->act_type == ACT_close) { printa(column, "if (SQLCODE = 0) then"); printa(column + INDENT, "isc_%do := 0;", request->req_ident); ENDIF; column -= INDENT; ENDIF; } } //____________________________________________________________ // // Generate substitution text for FETCH. // static void gen_s_fetch( ACT action, int column) { GPRE_REQ request; request = action->act_request; if (request->req_sync) gen_send(action, request->req_sync, column); gen_receive(action, column, request->req_primary); } //____________________________________________________________ // // Generate text to compile and start a stream. This is // used both by START_STREAM and FOR // static void gen_s_start( ACT action, int column) { GPRE_REQ request; POR port; request = action->act_request; if ((action->act_type == ACT_open)) { make_cursor_open_test(ACT_open, request, column); column += INDENT; } gen_compile(action, column); if (port = request->req_vport) asgn_from(action, port->por_references, column); if (action->act_error || (action->act_flags & ACT_sql)) { make_ok_test(action, request, column); gen_start(action, port, column + INDENT); ENDIF; } else gen_start(action, port, column); if (action->act_type == ACT_open) { printa(column, "if (SQLCODE = 0) then"); printa(column + INDENT, "isc_%do := 1;", request->req_ident); ENDIF; column -= INDENT; ENDIF; } } //____________________________________________________________ // // 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 standalone SELECT statement. // static void gen_select( ACT action, int column) { GPRE_REQ request; POR port; GPRE_NOD var_list; int i; TEXT name[20]; request = action->act_request; port = request->req_primary; gen_name(name, request->req_eof, TRUE); gen_s_start(action, column); gen_receive(action, column, port); printa(column, "if SQLCODE = 0 then", name); column += INDENT; printa(column, "if %s /= 0 then", name); column += INDENT; if (var_list = (GPRE_NOD) action->act_object) for (i = 0; i < var_list->nod_count; i++) asgn_to(action, (REF) var_list->nod_arg[i], column); if (request->req_database->dbb_flags & DBB_v3) { gen_receive(action, column, port); printa(column, "if (SQLCODE = 0) AND (%s /= 0) then", name); printa(column + INDENT, "SQLCODE := -1;"); ENDIF; } printa(column - INDENT, "else"); printa(column, "SQLCODE := 100;"); column -= INDENT; ENDIF; column -= INDENT; ENDIF; } //____________________________________________________________ // // Generate a send or receive call for a port. // static void gen_send( ACT action, POR port, int column) { GPRE_REQ request; request = action->act_request; printa(column, "interbase.SEND (%s %s, %d, %d, isc_%d'address, %s);", status_vector(action), request->req_handle, port->por_msg_number, port->por_length, port->por_ident, request->req_request_level); SET_SQLCODE; } //____________________________________________________________ // // Generate support for get/put slice statement. // static void gen_slice( ACT action, int column) { GPRE_REQ request, parent_request; REF reference, upper, lower; SLC slice; PAT args; slc::slc_repeat *tail, *end; TEXT *pattern1 = "interbase.GET_SLICE (%V1 %RF%DH%RE, %RF%RT%RE, %RF%FR%RE, %N1, \ %I1, %N2, %I1v, %I1s, %RF%S5'address%RE, %RF%S6%RE);"; TEXT *pattern2 = "interbase.PUT_SLICE (%V1 %RF%DH%RE, %RF%RT%RE, %RF%FR%RE, %N1, \ %I1, %N2, %I1v, %I1s, %RF%S5'address%RE);"; 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 + 1, reference->ref_value); args.pat_reference = slice->slc_field_ref; args.pat_request = parent_request; /* blob id request */ args.pat_vector1 = status_vector(action); /* status vector */ args.pat_database = parent_request->req_database; /* database handle */ args.pat_value1 = request->req_length; /* slice descr. length */ args.pat_ident1 = request->req_ident; /* request name */ args.pat_value2 = slice->slc_parameters * sizeof(SLONG); /* parameter length */ reference = (REF) slice->slc_array->nod_arg[0]; args.pat_string5 = reference->ref_value; /* array name */ args.pat_string6 = "isc_array_length"; PATTERN_expand(column, (action->act_type == ACT_get_slice) ? pattern1 : pattern2, &args); } //____________________________________________________________ // // Generate either a START or START_AND_SEND depending // on whether or a not a port is present. // static void gen_start( ACT action, POR port, int column) { GPRE_REQ request; TEXT *vector; REF reference; request = action->act_request; vector = status_vector(action); column += INDENT; if (port) { for (reference = port->por_references; reference; reference = reference->ref_next) if (reference->ref_field-> fld_array_info) gen_get_or_put_slice(action, reference, FALSE, column); printa(column, "interbase.START_AND_SEND (%s %s, %s%s, %d, %d, isc_%d'address, %s);", vector, request->req_handle, ada_package, request_trans(action, request), port->por_msg_number, port->por_length, port->por_ident, request->req_request_level); } else printa(column, "interbase.START_REQUEST (%s %s, %s%s, %s);", vector, request->req_handle, ada_package, request_trans(action, request), request->req_request_level); SET_SQLCODE; } //____________________________________________________________ // // Generate text for STORE statement. This includes the compile // call and any variable initialization required. // static void gen_store( ACT action, int column) { GPRE_REQ request; REF reference; GPRE_FLD field; POR port; TEXT name[64]; request = action->act_request; gen_compile(action, column); if (action->act_error || (action->act_flags & ACT_sql)) make_ok_test(action, request, column); // 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 := interbase.null_blob;", gen_name(name, reference, TRUE)); } } //____________________________________________________________ // // Generate substitution text for START_TRANSACTION. // static void gen_t_start( ACT action, int column) { DBB db; GPRE_TRA trans; TPB tpb; int count; TEXT *filename; // for automatically generated transactions, and transactions that are // explicitly started, but don't have any arguments so don't get a TPB, // generate something plausible. if (!action || !(trans = (GPRE_TRA) action->act_object)) { t_start_auto(action, 0, status_vector(action), column, FALSE); return; } // build a complete statement, including tpb's. // first generate any appropriate ready statements, // and fill in the tpb vector (aka TEB). count = 0; for (tpb = trans->tra_tpb; tpb; tpb = tpb->tpb_tra_next) { count++; db = tpb->tpb_database; if (sw_auto) if ((filename = db->dbb_runtime) || !(db->dbb_flags & DBB_sqlca)) { printa(column, "if (%s%s = 0) then", ada_package, db->dbb_name->sym_string); align(column + INDENT); make_ready(db, filename, status_vector(action), column + INDENT, 0); printa(column, "end if;"); } printa(column, "isc_teb(%d).tpb_len := %d;", count, tpb->tpb_length); printa(column, "isc_teb(%d).tpb_ptr := isc_tpb_%d'address;", count, tpb->tpb_ident); printa(column, "isc_teb(%d).dbb_ptr := %s%s'address;", count, ada_package, db->dbb_name->sym_string); } printa(column, "interbase.start_multiple (%s %s%s, %d, isc_teb'address);", status_vector(action), ada_package, (trans->tra_handle) ? (SCHAR *) trans->tra_handle : "gds_trans", trans->tra_db_count); SET_SQLCODE; } //____________________________________________________________ // // Generate a TPB in the output file // static void gen_tpb( TPB tpb, int column) { TEXT *text, buffer[80], c, *p; int length; printa(column, "isc_tpb_%d\t: CONSTANT interbase.tpb (1..%d) := (", tpb->tpb_ident, tpb->tpb_length); length = tpb->tpb_length; text = (TEXT *) tpb->tpb_string; p = buffer; while (--length) { c = *text++; sprintf(p, "%d, ", c); while (*p) p++; if (p - buffer > 60) { printa(column + INDENT, " %s", buffer); p = buffer; *p = 0; } } // handle the last character c = *text++; sprintf(p, "%d", c); printa(column + INDENT, "%s", buffer); printa(column, ");"); } //____________________________________________________________ // // 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) printa(column, "interbase.COMMIT_RETAINING (%s %s%s);", status_vector(action), ada_package, (action->act_object) ? (TEXT *) action-> act_object : "gds_trans"); else printa(column, "interbase.%s_TRANSACTION (%s %s%s);", (action->act_type == ACT_commit) ? "COMMIT" : (action->act_type == ACT_rollback) ? "ROLLBACK" : "PREPARE", status_vector(action), ada_package, (action->act_object) ? (TEXT *) action-> act_object : "gds_trans"); 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, (REF) 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) AND (SQLCODE /= 100)"; break; case SWE_not_found: condition = "SQLCODE = 100"; break; } printa(column, "if %s then goto %s; end if;", condition, label->swe_label); label = label->swe_next; } } //____________________________________________________________ // // Create a new window. // static void gen_window_create( ACT action, int column) { printa(column, "interbase.create_window (%sisc_window, 0, \" \", %sisc_width, %sisc_height)", ADA_WINDOW_PACKAGE, ADA_WINDOW_PACKAGE, ADA_WINDOW_PACKAGE); } //____________________________________________________________ // // Delete a window. // static void gen_window_delete( ACT action, int column) { printa(column, "interbase.delete_window (%sisc_window)", ADA_WINDOW_PACKAGE); } //____________________________________________________________ // // Suspend a window. // static void gen_window_suspend( ACT action, int column) { printa(column, "interbase.suspend_window (%sisc_window)", ADA_WINDOW_PACKAGE); } //____________________________________________________________ // // Generate a declaration of an array in the // output file. // static void make_array_declaration( REF reference, int column) { GPRE_FLD field; SCHAR *name; DIM dimension; int i; field = reference->ref_field; name = field->fld_symbol->sym_string; // Don't generate multiple declarations for the array. V3 Bug 569. if (field->fld_array_info->ary_declared) return; field->fld_array_info->ary_declared = TRUE; if ((field->fld_array->fld_dtype <= dtype_varying) && (field->fld_array->fld_length != 1)) { if (field->fld_array->fld_sub_type == 1) ib_fprintf(out_file, "subtype isc_%d_byte is %s(1..%d);\n", field->fld_array_info->ary_ident, BYTE_VECTOR_DCL, field->fld_array->fld_length); else ib_fprintf(out_file, "subtype isc_%d_string is string(1..%d);\n", field->fld_array_info->ary_ident, field->fld_array->fld_length); } ib_fprintf(out_file, "type isc_%dt is array (", field->fld_array_info->ary_ident); // Print out the dimension part of the declaration for (dimension = field->fld_array_info->ary_dimension, i = 1; i < field->fld_array_info->ary_dimension_count; dimension = dimension->dim_next, i++) ib_fprintf(out_file, "%s range %d..%d,\n ", LONG_DCL, dimension->dim_lower, dimension->dim_upper); ib_fprintf(out_file, "%s range %d..%d) of ", LONG_DCL, dimension->dim_lower, dimension->dim_upper); switch (field->fld_array_info->ary_dtype) { case dtype_short: ib_fprintf(out_file, "%s", SHORT_DCL); break; case dtype_long: ib_fprintf(out_file, "%s", LONG_DCL); break; case dtype_cstring: case dtype_text: case dtype_varying: if (field->fld_array->fld_length == 1) { if (field->fld_array->fld_sub_type == 1) ib_fprintf(out_file, BYTE_DCL); else ib_fprintf(out_file, "interbase.isc_character"); } else { if (field->fld_array->fld_sub_type == 1) ib_fprintf(out_file, "isc_%d_byte", field->fld_array_info->ary_ident); else ib_fprintf(out_file, "isc_%d_string", field->fld_array_info->ary_ident); } break; case dtype_date: case dtype_quad: ib_fprintf(out_file, "interbase.quad"); break; case dtype_float: ib_fprintf(out_file, "%s", FLOAT_DCL); break; case dtype_double: ib_fprintf(out_file, "%s", DOUBLE_DCL); break; default: printa(column, "datatype %d unknown for field %s", field->fld_array_info->ary_dtype, name); return; } ib_fprintf(out_file, ";\n"); // Print out the database field ib_fprintf(out_file, "isc_%d : isc_%dt;\t--- %s\n\n", field->fld_array_info->ary_ident, field->fld_array_info->ary_ident, name); } //____________________________________________________________ // // Generate code to test existence // of open cursor and do the right thing: // if type == ACT_open && isc_nl, error // if type == ACT_close && !isc_nl, error // static void make_cursor_open_test( enum act_t type, GPRE_REQ request, int column) { if (type == ACT_open) { printa(column, "if (isc_%do = 1) then", request->req_ident); printa(column + INDENT, "SQLCODE := -502;"); } else if (type == ACT_close) { printa(column, "if (isc_%do = 0) then", request->req_ident); printa(column + INDENT, "SQLCODE := -501;"); } printa(column, "else"); } //____________________________________________________________ // // Turn a symbol into a varying string. // static TEXT *make_name( TEXT * string, SYM symbol) { 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, GPRE_REQ request, int column) { if (sw_auto) printa(column, "if (%s%s /= 0) and (%s /= 0) then", ada_package, request_trans(action, request), request->req_handle); else printa(column, "if (%s /= 0) then", request->req_handle); } //____________________________________________________________ // // Insert a port record description in output. // static void make_port( POR port, int column) { GPRE_FLD field; REF reference; SYM symbol; TEXT *name, s[80]; int pos; printa(column, "type isc_%dt is record", port->por_ident); for (reference = port->por_references; reference; reference = reference->ref_next) { field = reference->ref_field; if (symbol = field->fld_symbol) name = symbol->sym_string; else name = ""; if (reference->ref_value && (reference->ref_flags & REF_array_elem)) field = field->fld_array; switch (field->fld_dtype) { case dtype_float: printa(column + INDENT, "isc_%d\t: %s;\t-- %s --", reference->ref_ident, FLOAT_DCL, name); break; case dtype_double: printa(column + INDENT, "isc_%d\t: %s;\t-- %s --", reference->ref_ident, DOUBLE_DCL, name); break; case dtype_short: printa(column + INDENT, "isc_%d\t: %s;\t-- %s --", reference->ref_ident, SHORT_DCL, name); break; case dtype_long: printa(column + INDENT, "isc_%d\t: %s;\t-- %s --", reference->ref_ident, LONG_DCL, name); break; case dtype_date: case dtype_quad: case dtype_blob: printa(column + INDENT, "isc_%d\t: interbase.quad;\t-- %s --", reference->ref_ident, name); break; case dtype_text: if (strcmp(name, "isc_slack")) { if (field->fld_sub_type == 1) { if (field->fld_length == 1) printa(column + INDENT, "isc_%d\t: %s;\t-- %s --", reference->ref_ident, BYTE_DCL, name); else printa(column + INDENT, "isc_%d\t: %s (1..%d);\t-- %s --", reference->ref_ident, BYTE_VECTOR_DCL, field->fld_length, name); } else { if (field->fld_length == 1) printa(column + INDENT, "isc_%d\t: interbase.isc_character;\t-- %s --", reference->ref_ident, name); else printa(column + INDENT, "isc_%d\t: string (1..%d);\t-- %s --", reference->ref_ident, field->fld_length, name); } } break; default: sprintf(s, "datatype %d unknown for field %s, msg %d", field->fld_dtype, name, port->por_msg_number); IBERROR(s); return; } } printa(column, "end record;"); printa(column, "for isc_%dt use record at mod 4;", port->por_ident); pos = 0; for (reference = port->por_references; reference; reference = reference->ref_next) { field = reference->ref_field; if (reference->ref_value && field->fld_array_info) field = field->fld_array; printa(column + INDENT, "isc_%d at %d range 0..%d;", reference->ref_ident, pos, 8 * field->fld_length - 1); pos += field->fld_length; } printa(column, "end record;"); } //____________________________________________________________ // // Generate the actual insertion text for a // ready; // static void make_ready( DBB db, TEXT * filename, TEXT * vector, USHORT column, GPRE_REQ request) { TEXT s1[32], s2[32]; if (request) { sprintf(s1, "isc_%dl", request->req_ident); 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) { sprintf(s2, "isc_%dp", request->req_ident); if (request->req_length) printa(column, "%s = isc_%d;", s2, request->req_ident); if (db->dbb_r_user) printa(column, "interbase.MODIFY_DPB (%s, %s, interbase.isc_dpb_user_name, %s, %d);\n", s2, s1, db->dbb_r_user, (strlen(db->dbb_r_user) - 2)); if (db->dbb_r_password) printa(column, "interbase.MODIFY_DPB (%s, %s, interbase.isc_dpb_password, %s, %d);\n", s2, s1, db->dbb_r_password, (strlen(db->dbb_r_password) - 2)); /* ** =========================================================== ** == ** == Process Role Name ** == ** =========================================================== */ if (db->dbb_r_sql_role) printa(column, "interbase.MODIFY_DPB (%s, %s, interbase.isc_dpb_sql_role_name, %s, %d);\n", s2, s1, db->dbb_r_sql_role, (strlen(db->dbb_r_sql_role) - 2)); if (db->dbb_r_lc_messages) printa(column, "interbase.MODIFY_DPB (%s, %s, interbase.isc_dpb_lc_messages, %s, %d);\n", s2, s1, db->dbb_r_lc_messages, (strlen(db->dbb_r_lc_messages) - 2)); if (db->dbb_r_lc_ctype) printa(column, "interbase.MODIFY_DPB (%s, %s, interbase.isc_dpb_lc_ctype, %s, %d);\n", s2, s1, db->dbb_r_lc_ctype, (strlen(db->dbb_r_lc_ctype) - 2)); } } if (filename) if (*filename == '"') printa(column, "interbase.ATTACH_DATABASE (%s %d, %s, %s%s, %s, %s);", vector, strlen(filename) - 2, filename, ada_package, db->dbb_name->sym_string, (request ? s1 : "0"), (request ? s2 : "interbase.null_dpb")); else printa(column, "interbase.ATTACH_DATABASE (%s %s'length(1), %s, %s%s, %s, %s);", vector, filename, filename, ada_package, db->dbb_name->sym_string, (request ? s1 : "0"), (request ? s2 : "interbase.null_dpb")); else printa(column, "interbase.ATTACH_DATABASE (%s %d, \"%s\", %s%s, %s, %s);", vector, strlen(db->dbb_filename), db->dbb_filename, ada_package, db->dbb_name->sym_string, (request ? s1 : "0"), (request ? s2 : "interbase.null_dpb")); if (request && request->req_flags & REQ_extend_dpb) { if (request->req_length) printa(column, "if (%s != isc_%d)", s2, request->req_ident); printa(column + (request->req_length ? 4 : 0), "interbase.FREE (%s);", s2); /* reset the length of the dpb */ if (request->req_length) printa(column, "%s = %d;", s1, request->req_length); } } //____________________________________________________________ // // Print a fixed string at a particular column. // static void printa( int column, TEXT * string, ...) { va_list ptr; VA_START(ptr, string); align(column); vsprintf(output_buffer, string, ptr); ADA_print_buffer(output_buffer, column); } //____________________________________________________________ // // Generate the appropriate transaction handle. // static TEXT *request_trans( ACT action, GPRE_REQ request) { SCHAR *trname; if (action->act_type == ACT_open) { if (!(trname = ((OPN) action->act_object)->opn_trans)) trname = "gds_trans"; return trname; } else return (request) ? request->req_trans : (TEXT*) "gds_trans"; } //____________________________________________________________ // // 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 "isc_status,"; return ""; } //____________________________________________________________ // // Generate substitution text for START_TRANSACTION. // static void t_start_auto( ACT action, GPRE_REQ request, TEXT * vector, int column, SSHORT test) { DBB db; int count, stat; TEXT *filename, buffer[256], temp[40], *trname; trname = request_trans(action, request); stat = !strcmp(vector, "isc_status"); 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%s = 0", ada_package, db->dbb_name->sym_string); if (stat && buffer[0]) ib_fprintf(out_file, "and %s(1) = 0", vector); ib_fprintf(out_file, ") then"); make_ready(db, filename, vector, column + INDENT, 0); printa(column, "end if;"); if (buffer[0]) strcat(buffer, ") and ("); sprintf(temp, "%s%s /= 0", ada_package, db->dbb_name->sym_string); strcat(buffer, temp); } if (!buffer[0]) strcpy(buffer, "True"); if (test) printa(column, "if (%s) and (%s%s = 0) then", buffer, ada_package, trname); else printa(column, "if (%s) then", buffer); column += INDENT; } for (count = 0, db = isc_databases; db; db = db->dbb_next) { count++; printa(column, "isc_teb(%d).tpb_len:= 0;", count); printa(column, "isc_teb(%d).tpb_ptr := interbase.null_tpb'address;", count); printa(column, "isc_teb(%d).dbb_ptr := %s%s'address;", count, ada_package, db->dbb_name->sym_string); } printa(column, "interbase.start_multiple (%s %s%s, %d, isc_teb'address);", vector, ada_package, trname, count); if (sw_auto) { ENDIF; column -= INDENT; } END; }