/*
 *	PROGRAM:	JRD Command Oriented Query Language
 *	MODULE:		exe.h
 *	DESCRIPTION:	Execution struct definitions
 *
 * 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): ______________________________________.
 */

#ifndef QLI_EXE_H
#define QLI_EXE_H

// Request Language Block  -- used for BLR, DYN, SDL, etc. 

struct qli_rlb {
    blk		rlb_header;
    UCHAR	*rlb_data;		// Pointer to end of BLR/DYN/SDL 
    UCHAR	*rlb_base;		// Pointer to start of buffer 
    UCHAR	*rlb_limit;		// Upper limit of string 
    USHORT	rlb_length;		// Length of string 
};

// RLB manipulation macros 
const USHORT RLB_BUFFER_SIZE	= 2048;
const USHORT RLB_SAFETY_MARGIN	= 48;

#define CHECK_RLB(in)	(!in || (in->rlb_data > in->rlb_limit)) ? (in = GEN_rlb_extend (in)) : in;
/* Would need gener_proto.h visible here to use this macro.
inline qli_rlb* CHECK_RLB(qli_rlb*& in)
{
	if (!in || (in->rlb_data > in->rlb_limit))
		in = GEN_rlb_extend(in);
	return in;
}
*/

// If used to replace the macro shown above, this function should be declared
// in gener_proto.h and defined in gener.cpp or declared and defined in gener_proto.h
// if "inline" is preserved.
//static inline rlb* check_rlb(rlb*& in)
//{
//	if (!in || (in->rlb_data > in->rlb_limit))
//	    in = GEN_rlb_extend(in);
//	return in;
//}

#define STUFF(blr)	*rlb->rlb_data++ = blr
#define STUFF_WORD(blr)	{STUFF (blr); STUFF (blr >> 8);}

// Request block 

struct qli_req {
    blk				req_header;
    qli_req*		req_next;		// Next request in statement 
    dbb*			req_database;	// Database for request 
    FB_API_HANDLE	req_handle;		// Database request handle 
    qli_rlb*		req_blr;
    struct qli_msg*	req_messages;	// Messages associated with request 
    struct qli_msg*	req_receive;	// Current receive message, if any  
    struct qli_msg*	req_send;		// Current send message, if any  
    struct qli_msg*	req_continue;	// Message to continue FOR loop after optional actions 
    USHORT			req_flags;		// Flags for state of request compilation, etc. 
    USHORT			req_context;	// Next available context 
    USHORT			req_msg_number;	// Next available message number 
    USHORT			req_label;		// Next available label 
};

// req_flags
const USHORT REQ_rse_compiled	= 1;
const USHORT REQ_project		= 2;	// Set during generation of project clause 
const USHORT REQ_group_by		= 4;	// Set during generation of group by clause 


struct qli_nod;

// Context node 

typedef enum {
    CTX_RELATION,
    CTX_VARIABLE,
    CTX_AGGREGATE,
    CTX_UNION,
    CTX_STREAM
} CTX_T;

struct qli_ctx {
    blk				ctx_header;
    CTX_T			ctx_type;		// Type of context 
    qli_ctx*		ctx_source;		// Source context for MODIFY 
    qli_ctx*		ctx_primary;	// Primary context 
    qli_symbol*		ctx_symbol;		// Context symbol, if any 
    struct qli_rel*	ctx_relation;	// Relation of context 
    qli_nod*		ctx_stream;		// Stream of context 
    struct qli_fld*	ctx_variable;	// Variable reference 
    qli_req*		ctx_request;	// Request block 
    struct qli_msg*	ctx_message;	// Message for data 
    qli_nod*		ctx_rse;		// RSE node for root context 
    qli_nod*		ctx_sub_rse;	// RSE node aggregate 
    qli_ctx*		ctx_parent;		// Parent context for map 
    struct qli_map*	ctx_map;		// Map items, if any 
    USHORT			ctx_context;	// Context in request 
};

// Aggregate/union map block 

struct qli_map {
    blk			map_header;
	qli_map*	map_next;			// Next map in item 
    qli_nod*	map_node;			// Value for map item 
    USHORT		map_position;		// Position in map 
};

// Message block                                        

struct qli_msg {
    blk			msg_header;
    qli_req*	msg_request;		// Parent request 
    qli_ctx*	msg_context;		// Contexts in message 
    struct qli_msg* msg_next;		// Next message in request 
    struct qli_par* msg_parameters;	// Field instances 
    USHORT		msg_number;			// Message number 
    USHORT		msg_length;			// Message length 
    USHORT		msg_parameter;		// Next parameter number 
    UCHAR*		msg_buffer;			// Message buffer 
};

// Parameter block 

struct qli_par {
	blk			par_header;
	dsc			par_desc;			// Value descriptor 
	qli_par*	par_next;			// Next par block in context 
	qli_msg*	par_message;		// Parent message 
	qli_nod*	par_value;			// Value 
	USHORT		par_parameter;		// Parameter number 
	USHORT		par_offset;			// Offset of parameter in message 
	qli_par*	par_missing;		// Parameter block for missing value 
};

// Print item block 

typedef enum itm_t
    {
    item_value,
    item_skip,
    item_column,
    item_tab,
    item_space,
    item_new_page,
    item_column_header,
    item_report_header
} ITM_T;

struct qli_print_item {
    blk			itm_header;
    qli_nod*	itm_value;
    const TEXT*	itm_edit_string;
    struct pics*	itm_picture;	// picture string block 
    const TEXT*	itm_query_header;
    ITM_T		itm_type;
    USHORT		itm_flags;			// Misc flags and crud 
    UCHAR		itm_dtype;
    UCHAR		itm_sub_type;
    USHORT		itm_print_offset;
    USHORT		itm_print_length;
    USHORT		itm_header_offset;
    USHORT		itm_header_length;
    USHORT		itm_header_segments;
    USHORT		itm_count;			// Number of lines to skip 
    USHORT		itm_column;			// Logical column number 
    FB_API_HANDLE itm_stream;
    USHORT		itm_kanji_fragment;	// JPN: last kanji on line border 
    ISC_STATUS	itm_blob_status;	// JPN: status of the last blob fetch 
};

// itm_flags
const USHORT ITM_overlapped	= 1;			// Overlapped by another item 

// Print Control Block 

struct qli_prt {
    blk		prt_header;
    struct file*	prt_file;		// FILE pointer 
    struct qli_rpt*	prt_report;		// Report block (if report) 
    void	(*prt_new_page)(qli_prt*, bool);	// New page routine, if any 
    USHORT	prt_lines_per_page;
    SSHORT	prt_lines_remaining;
    USHORT	prt_page_number;
};

// General node blocks 

struct qli_nod {
    blk			nod_header;
    NOD_T		nod_type;		// Type of node 
    dsc			nod_desc;		// Descriptor 
    qli_par*	nod_import;		// To pass random value 
    qli_par*	nod_export;		// To pass random value 
    SSHORT		nod_count;		// Number of arguments 
    UCHAR		nod_flags;
    qli_nod* 	nod_arg[1];		// If you change this change blk.h too 
};

// nod_flags
const UCHAR NOD_local		= 1;	// locally computed expression 
const UCHAR NOD_remote		= 2;
const UCHAR NOD_parameter2	= 4;	// generate a parameter2 if field 
const UCHAR nod_partial		= 8;
const UCHAR nod_comparison	= 16;
const UCHAR nod_date		= 32;	// node is a date operation, regardless 

// Execution node positions 

const int e_fld_field		= 0;	// field block 
const int e_fld_context		= 1;	// context for field 
const int e_fld_reference	= 2;	// points to parameter 
const int e_fld_subs		= 3;	// subscripts 
const int e_fld_count		= 4;

const int e_for_request		= 0;	// Request to be started 
const int e_for_send		= 1;	// Message to be sent 
const int e_for_receive		= 2;	// Message to be received 
const int e_for_eof			= 3;	// End of file parameter 
const int e_for_rse			= 4;
const int e_for_statement	= 5;
const int e_for_count		= 6;

const int e_itm_value		= 0;	// Value of print item 
const int e_itm_edit_string = 1;	// Edit string, if any 
const int e_itm_header		= 2;	// Query header, if any 
const int e_itm_count		= 3;

const int e_rse_first		= 0;	// FIRST clause, if any 
const int e_rse_boolean		= 1;	// Boolean clause, if any 
const int e_rse_sort		= 2;	// Sort clause, if any 
const int e_rse_reduced		= 3;	// Reduced clause, if any 
const int e_rse_context		= 4;	// Context block 
const int e_rse_group_by	= 5;
const int e_rse_having		= 6;
const int e_rse_join_type	= 7;
#ifdef PC_ENGINE
const int e_rse_index		= 8;
#endif
const int e_rse_count		= 9;

const int e_prt_list		= 0;	// List of print items 
const int e_prt_file_name	= 1;	// Output file name 
const int e_prt_output		= 2;	// Output file 
const int e_prt_header		= 3;	// Header to be printed, if any 
const int e_prt_count		= 4;

const int e_prm_prompt		= 0;	// Prompt string, if any 
const int e_prm_string		= 1;	// String node for data 
const int e_prm_next		= 2;	// Next prompt in statement 
const int e_prm_field		= 3;	// Prototype field, if known 
const int e_prm_count		= 4;

const int e_sto_context		= 0;
const int e_sto_statement	= 1;
const int e_sto_request		= 2;
const int e_sto_send		= 3;
const int e_sto_count		= 4;

const int e_asn_to			= 0;
const int e_asn_from		= 1;
const int e_asn_initial		= 2;
const int e_asn_valid		= 3;	// Always second-to-last 
const int e_asn_count		= 4;

const int e_mod_send		= 0;
const int e_mod_statement	= 1;	// Sub-statement 
const int e_mod_request		= 2;	// Parent request for statement 
const int e_mod_count		= 3;

const int e_era_context		= 0;
const int e_era_request		= 1;	// Parent request for erase 
const int e_era_message		= 2;	// Message to be sent, if any 
const int e_era_count		= 3;

const int e_any_request		= 0;	// Request to be started 
const int e_any_send		= 1;	// Message to be sent 
const int e_any_receive		= 2;	// Message to be received 
const int e_any_rse			= 3;
const int e_any_count		= 4;

const int e_rpt_value		= 0;
const int e_rpt_statement	= 1;
const int e_rpt_count		= 2;

const int e_if_boolean		= 0;
const int e_if_true			= 1;
const int e_if_false		= 2;
const int e_if_count		= 3;

const int e_edt_input		= 0;
const int e_edt_dbb			= 1;
const int e_edt_id1			= 2;
const int e_edt_id2			= 3;
const int e_edt_name		= 4;
const int e_edt_count		= 5;

const int e_out_statement	= 0;
const int e_out_file		= 1;
const int e_out_pipe		= 2;
const int e_out_print		= 3;
const int e_out_count		= 4;

const int e_fmt_value		= 0;
const int e_fmt_edit		= 1;
const int e_fmt_picture		= 2;
const int e_fmt_count		= 3;

// Statistical expression 

const int e_stt_rse			= 0;
const int e_stt_value		= 1;
const int e_stt_default		= 2;
const int e_stt_request		= 3;	// Request to be started 
const int e_stt_send		= 4;	// Message to be sent 
const int e_stt_receive		= 5;	// Message to be received 
const int e_stt_count		= 6;

const int e_map_context		= 0;
const int e_map_map			= 1;
const int e_map_count		= 2;

const int e_ffr_form		= 0;
const int e_ffr_statement	= 1;
const int e_ffr_count		= 2;

const int e_fup_form		= 0;
const int e_fup_fields		= 1;
const int e_fup_tag			= 2;
const int e_fup_count		= 3;

const int e_ffl_form		= 0;
const int e_ffl_field		= 1;
const int e_ffl_string		= 2;
const int e_ffl_count		= 3;

const int e_men_statements	= 0;
const int e_men_labels		= 1;
const int e_men_string		= 2;
const int e_men_menu		= 4;
const int e_men_count		= 5;

const int e_fun_args		= 0;
const int e_fun_function	= 1;
const int e_fun_request		= 2;	// Request to be started 
const int e_fun_send		= 3;	// Message to be sent 
const int e_fun_receive		= 4;	// Message to be received 
const int e_fun_count		= 5;

const int e_syn_statement	= 0;
const int e_syn_send		= 1;
const int e_syn_count		= 2;

#endif // QLI_EXE_H

