void PIC_edit(const dsc* desc, pics* picture, TEXT** output, USHORT max_length)
{
/**************************************
 *
 *	P I C _ e d i t
 *
 **************************************
 *
 * Functional description
 *	Edit data from a descriptor through an edit string to a running
 *	output pointer.  For text strings, check that we don't overflow
 *	the output buffer.
 *
 **************************************/

	switch (picture->pic_type)
	{
	case pic_alpha:
		edit_alpha(desc, picture, output, max_length);
		return;
	case pic_numeric:
		edit_numeric(desc, picture, output);
		return;
	case pic_date:
		edit_date(desc, picture, output);
		return;
	case pic_float:
		edit_float(desc, picture, output);
		return;
	default:
		ERRQ_bugcheck(68);			// Msg 68 PIC_edit: class not yet implemented
	}
}
예제 #2
0
static void gen_expression(qli_nod* node, qli_req* request)
{
/**************************************
 *
 *	g e n _ e x p r e s s i o n
 *
 **************************************
 *
 * Functional description
 *	Generate the BLR for a boolean or value expression.
 *
 **************************************/
	USHORT operatr = 0;
	qli_rlb* rlb = 0;

	if (node->nod_flags & NOD_local)
	{
		request = NULL;
		//return;
	}
	else if (request)
		rlb = CHECK_RLB(request->req_blr);

	switch (node->nod_type)
	{
	case nod_any:
		gen_any(node, request);
		return;

	case nod_unique:
		if (request)
		{
			STUFF(blr_unique);
			gen_rse(node->nod_arg[e_any_rse], request);
		}
		return;

	case nod_constant:
		if (request)
			gen_literal(&node->nod_desc, request);
		return;

	case nod_field:
		gen_field(node, request);
		return;

	case nod_format:
		gen_expression(node->nod_arg[e_fmt_value], request);
		return;

	case nod_map:
		{
			qli_map* map = (qli_map*) node->nod_arg[e_map_map];
			const qli_ctx* context = (qli_ctx*) node->nod_arg[e_map_context];
			if (context->ctx_request != request && map->map_node->nod_type == nod_field)
			{
				gen_field(map->map_node, request);
				return;
			}
			STUFF(blr_fid);
			STUFF(context->ctx_context);
			STUFF_WORD(map->map_position);
			return;
		}

	case nod_eql:
		operatr = blr_eql;
		break;

	case nod_neq:
		operatr = blr_neq;
		break;

	case nod_gtr:
		operatr = blr_gtr;
		break;

	case nod_geq:
		operatr = blr_geq;
		break;

	case nod_leq:
		operatr = blr_leq;
		break;

	case nod_lss:
		operatr = blr_lss;
		break;

	case nod_containing:
		operatr = blr_containing;
		break;

	case nod_matches:
		operatr = blr_matching;
		break;

	case nod_sleuth:
		operatr = blr_matching2;
		break;

	case nod_like:
		operatr = (node->nod_count == 2) ? blr_like : blr_ansi_like;
		break;

	case nod_starts:
		operatr = blr_starting;
		break;

	case nod_missing:
		operatr = blr_missing;
		break;

	case nod_between:
		operatr = blr_between;
		break;

	case nod_and:
		operatr = blr_and;
		break;

	case nod_or:
		operatr = blr_or;
		break;

	case nod_not:
		operatr = blr_not;
		break;

	case nod_add:
		operatr = blr_add;
		break;

	case nod_subtract:
		operatr = blr_subtract;
		break;

	case nod_multiply:
		operatr = blr_multiply;
		break;

	case nod_divide:
		operatr = blr_divide;
		break;

	case nod_negate:
		operatr = blr_negate;
		break;

	case nod_concatenate:
		operatr = blr_concatenate;
		break;

	case nod_substr:
		operatr = blr_substring;
		break;

	case nod_function:
		gen_function(node, request);
		return;

	case nod_agg_average:
	case nod_agg_count:
	case nod_agg_max:
	case nod_agg_min:
	case nod_agg_total:

	case nod_average:
	case nod_count:
	case nod_max:
	case nod_min:
	case nod_total:
	case nod_from:
		gen_statistical(node, request);
		return;

	case nod_rpt_average:
	case nod_rpt_count:
	case nod_rpt_max:
	case nod_rpt_min:
	case nod_rpt_total:

	case nod_running_total:
	case nod_running_count:
		if (node->nod_arg[e_stt_value])
			gen_expression(node->nod_arg[e_stt_value], request);
		if (node->nod_export)
			gen_parameter(node->nod_export, request);
		request = NULL;
		break;

	case nod_prompt:
	case nod_variable:
		if (node->nod_export)
			gen_parameter(node->nod_export, request);
		return;

	case nod_edit_blob:
	case nod_reference:
		return;

	case nod_null:
		operatr = blr_null;
		break;

	case nod_user_name:
		operatr = blr_user_name;
		break;

	case nod_upcase:
		operatr = blr_upcase;
		break;

	case nod_lowcase:
		operatr = blr_lowcase;
		break;

	default:
		if (request && node->nod_export)
		{
			gen_parameter(node->nod_export, request);
			return;
		}
		ERRQ_bugcheck(353);			// Msg353 gen_expression: not understood
	}

	if (request)
	{
		rlb = CHECK_RLB(request->req_blr);
		STUFF(operatr);
	}

	qli_nod** ptr = node->nod_arg;
	for (qli_nod** const end = ptr + node->nod_count; ptr < end; ptr++)
		gen_expression(*ptr, request);

	if (!node->nod_desc.dsc_address && node->nod_desc.dsc_length)
		CMP_alloc_temp(node);
}
예제 #3
0
static void gen_descriptor(const dsc* desc, qli_req* request)
{
/**************************************
 *
 *	g e n _ d e s c r i p t o r
 *
 **************************************
 *
 * Functional description
 *	Generator a field descriptor.  This is used for generating both
 *	message declarations and literals.
 *
 **************************************/
	qli_rlb* rlb = CHECK_RLB(request->req_blr);

	switch (desc->dsc_dtype)
	{

	case dtype_text:
		STUFF(blr_text);
		STUFF_WORD(desc->dsc_length);
		break;

	case dtype_varying:
		STUFF(blr_varying);
		STUFF_WORD((desc->dsc_length - sizeof(SSHORT)));
		break;

	case dtype_cstring:
		STUFF(blr_cstring);
		STUFF_WORD(desc->dsc_length);
		break;

	case dtype_short:
		STUFF(blr_short);
		STUFF(desc->dsc_scale);
		break;

	case dtype_int64:
		STUFF(blr_int64);
		STUFF(desc->dsc_scale);
		break;

	case dtype_long:
		STUFF(blr_long);
		STUFF(desc->dsc_scale);
		break;

	case dtype_blob:
	case dtype_quad:
		STUFF(blr_quad);
		STUFF(desc->dsc_scale);
		break;

	case dtype_real:
		STUFF(blr_float);
		break;

	case dtype_double:
		STUFF(blr_double);
		break;

	case dtype_timestamp:
		STUFF(blr_timestamp);
		break;

	case dtype_sql_date:
		STUFF(blr_sql_date);
		break;

	case dtype_sql_time:
		STUFF(blr_sql_time);
		break;

	default:
		ERRQ_bugcheck(352);			// Msg352 gen_descriptor: dtype not recognized
	}
}
예제 #4
0
static void gen_statistical( qli_nod* node, qli_req* request)
{
/**************************************
 *
 *	g e n _ s t a t i s t i c a l
 *
 **************************************
 *
 * Functional description
 *	Generate the BLR for a statistical expresionn.
 *
 **************************************/
	USHORT operatr;

	switch (node->nod_type)
	{
	case nod_average:
		operatr = blr_average;
		break;

	case nod_count:
		// count2
		// operatr = node->nod_arg [e_stt_value] ? blr_count2 : blr_count;
		operatr = blr_count;
		break;

	case nod_max:
		operatr = blr_maximum;
		break;

	case nod_min:
		operatr = blr_minimum;
		break;

	case nod_total:
		operatr = blr_total;
		break;

	case nod_agg_average:
		operatr = blr_agg_average;
		break;

	case nod_agg_count:
		// count2
		// operatr = node->nod_arg [e_stt_value] ? blr_agg_count2 : blr_agg_count;
		operatr = blr_agg_count;
		break;

	case nod_agg_max:
		operatr = blr_agg_max;
		break;

	case nod_agg_min:
		operatr = blr_agg_min;
		break;

	case nod_agg_total:
		operatr = blr_agg_total;
		break;

	case nod_from:
		operatr = node->nod_arg[e_stt_default] ? blr_via : blr_from;
		break;

	default:
		ERRQ_bugcheck(355);			// Msg355 gen_statistical: not understood
	}

	// If there is a request associated with the statement, prepare to
	// generate BLR.  Otherwise assume that a request is alrealdy initialized.

	qli_rlb* rlb;
	qli_req* new_request = (qli_req*) node->nod_arg[e_stt_request];
	if (new_request)
	{
		request = new_request;
		gen_request(request);
		const qli_msg* receive = (qli_msg*) node->nod_arg[e_stt_send];
		if (receive)
			gen_send_receive(receive, blr_receive);
		const qli_msg* send = (qli_msg*) node->nod_arg[e_stt_receive];
		gen_send_receive(send, blr_send);
		rlb = CHECK_RLB(request->req_blr);
		STUFF(blr_assignment);
	}
	else
		rlb = CHECK_RLB(request->req_blr);

	STUFF(operatr);

	if (node->nod_arg[e_stt_rse])
		gen_rse(node->nod_arg[e_stt_rse], request);

	// count 2
	// if (node->nod_arg [e_stt_value])

	if (node->nod_arg[e_stt_value] && node->nod_type != nod_agg_count)
		gen_expression(node->nod_arg[e_stt_value], request);

	if (node->nod_arg[e_stt_default])
		gen_expression(node->nod_arg[e_stt_default], request);

	if (new_request)
	{
		gen_parameter(node->nod_import, request);
		gen_compile(request);
	}
}
예제 #5
0
static void gen_statement( qli_nod* node, qli_req* request)
{
/**************************************
 *
 *	g e n _ s t a t e m e n t
 *
 **************************************
 *
 * Functional description
 *	Generate BLR for statement.
 *
 **************************************/
	if (request)
		CHECK_RLB(request->req_blr);

	switch (node->nod_type)
	{
	case nod_abort:
		if (node->nod_count)
			gen_expression(node->nod_arg[0], 0);
		return;

	case nod_assign:
		gen_assignment(node, request);
		return;

	case nod_commit_retaining:
		return;

	case nod_erase:
		gen_erase(node, request);
		return;

	case nod_for:
	case nod_report_loop:
		gen_for(node, request);
		return;

	case nod_list:
	    {
	        qli_nod** ptr = node->nod_arg;
			for (const qli_nod* const* const end = ptr + node->nod_count; ptr < end; ++ptr)
			{
				gen_statement(*ptr, request);
			}
			return;
		}

	case nod_modify:
		gen_modify(node); //, request);
		return;

	case nod_output:
		gen_statement(node->nod_arg[e_out_statement], request);
		return;

	case nod_print:
		gen_print_list(node->nod_arg[e_prt_list], request);
		return;

	case nod_repeat:
		gen_statement(node->nod_arg[e_rpt_statement], request);
		return;

	case nod_report:
		gen_report(node, request);
		return;

	case nod_store:
		gen_store(node, request);
		return;

	case nod_if:
		gen_if(node, request);
		return;

	default:
		ERRQ_bugcheck(354);			// Msg354 gen_statement: not yet implemented
	}
}
예제 #6
0
int EVAL_boolean( qli_nod* node)
{
/**************************************
 *
 *	E V A L _ b o o l e a n
 *
 **************************************
 *
 * Functional description
 *	Evaluate a boolean expression.
 *
 **************************************/
	DSC *value1, *value2;
	int result;

	switch (node->nod_type)
	{
	case nod_eql:
	case nod_neq:
	case nod_gtr:
	case nod_geq:
	case nod_leq:
	case nod_lss:
	case nod_between:
		if (!(value1 = EVAL_value(node->nod_arg[0])) || (value1->dsc_missing & DSC_missing) ||
			!(value2 = EVAL_value(node->nod_arg[1])) || (value2->dsc_missing & DSC_missing))
		{
			return false;
		}
		if (node->nod_flags & nod_comparison)
			result = MOVQ_compare(value1, value2);
		break;

	case nod_and:
	case nod_or:
	case nod_not:
		result = EVAL_boolean(node->nod_arg[0]);
		break;

	case nod_containing:
	case nod_matches:
	case nod_like:
	case nod_starts:
	case nod_sleuth:
		result = string_boolean(node);
	}

	switch (node->nod_type)
	{
	case nod_eql:
		return (result == 0);
	case nod_neq:
		return (result != 0);
	case nod_gtr:
		return (result > 0);
	case nod_geq:
		return (result >= 0);
	case nod_leq:
		return (result <= 0);
	case nod_lss:
		return (result < 0);

	case nod_between:
		if (result < 0)
			return false;
		if (!(value2 = EVAL_value(node->nod_arg[2])) || (value2->dsc_missing & DSC_missing))
		{
			return false;
		}
		if (MOVQ_compare(value1, value2) > 0)
			return false;
		return true;

	case nod_missing:
		value1 = EVAL_value(node->nod_arg[0]);
		if (value1)
			return (value1->dsc_missing & DSC_missing) != 0;
		return true;

	case nod_and:
		if (!result)
			return false;
		return EVAL_boolean(node->nod_arg[1]);

	case nod_or:
		if (result)
			return true;
		return EVAL_boolean(node->nod_arg[1]);

	case nod_not:
		return !result;

	case nod_any:
	case nod_unique:
		return execute_any(node);

	case nod_sleuth:
	case nod_containing:
	case nod_matches:
	case nod_like:
	case nod_starts:
		return result;

	default:
		ERRQ_bugcheck(28);			// Msg28 EVAL_boolean: not finished
		return false;
	}
}
예제 #7
0
dsc* EVAL_value(qli_nod* node)
{
/**************************************
 *
 *	E V A L _ v a l u e
 *
 **************************************
 *
 * Functional description
 *	Evaluate a value node.
 *
 **************************************/
	DSC *values[4];

	// Start by evaluating sub-expressions (where appropriate)

	dsc* desc = &node->nod_desc;
	fb_assert(node->nod_count < 5);
	qli_nod** ptr = node->nod_arg;
	const qli_nod* const* const end_ptr = ptr + node->nod_count;

	for (dsc** value = values; ptr < end_ptr; ptr++, value++)
	{
		*value = EVAL_value(*ptr);
		if (node->nod_flags & nod_partial)
			break;
	}

	switch (node->nod_type)
	{
	case nod_edit_blob:
		return execute_edit(node);

	case nod_rpt_max:
	case nod_rpt_min:
	case nod_rpt_total:
	case nod_rpt_average:
		if (!(IPTR) node->nod_arg[e_stt_default])
			desc->dsc_missing = DSC_missing;

	case nod_rpt_count:
	case nod_constant:
		return desc;

	case nod_variable:
		{
			qli_fld* field = (qli_fld*) node->nod_arg[e_fld_field];
			desc->dsc_missing = (field->fld_flags & FLD_missing) ? DSC_missing : 0;
		}
		return desc;

	case nod_field:
		return EVAL_value(node->nod_arg[e_fld_reference]);

	case nod_reference:
		return EVAL_parameter(node->nod_import);

	case nod_null:
		return desc;

	case nod_add:
		if ((values[0]->dsc_missing & DSC_missing) || (values[1]->dsc_missing & DSC_missing))
		{
			desc->dsc_missing = DSC_missing;
			return desc;
		}
		desc->dsc_missing = FALSE;
		if (node->nod_flags & nod_date)
		{
			double d1 = MOVQ_date_to_double(values[0]) + MOVQ_get_double(values[1]);
			MOVQ_double_to_date(d1, (SLONG*) desc->dsc_address);
		}
		else if (desc->dsc_dtype == dtype_long)
		{
			*((SLONG*) desc->dsc_address) =
				MOVQ_get_long(values[0], desc->dsc_scale) + MOVQ_get_long(values[1], desc->dsc_scale);
		}
		else
			*((double*) desc->dsc_address) = MOVQ_get_double(values[0]) + MOVQ_get_double(values[1]);
		return desc;

	case nod_subtract:
		if ((values[0]->dsc_missing & DSC_missing) || (values[1]->dsc_missing & DSC_missing))
		{
			desc->dsc_missing = DSC_missing;
			return desc;
		}
		desc->dsc_missing = FALSE;
		if (node->nod_flags & nod_date)
		{
			*((double*) desc->dsc_address) =
				MOVQ_date_to_double(values[0]) - MOVQ_date_to_double(values[1]);
		}
		else if (desc->dsc_dtype == dtype_long)
		{
			*((SLONG*) desc->dsc_address) =
				MOVQ_get_long(values[0], desc->dsc_scale) - MOVQ_get_long(values[1], desc->dsc_scale);
		}
		else
			*((double*) desc->dsc_address) = MOVQ_get_double(values[0]) - MOVQ_get_double(values[1]);
		return desc;

	case nod_divide:
		if ((values[0]->dsc_missing & DSC_missing) || (values[1]->dsc_missing & DSC_missing))
		{
			desc->dsc_missing = DSC_missing;
			return desc;
		}
		desc->dsc_missing = FALSE;
		*((double*) desc->dsc_address) = MOVQ_get_double(values[0]) / MOVQ_get_double(values[1]);
		return desc;

	case nod_multiply:
		if ((values[0]->dsc_missing & DSC_missing) || (values[1]->dsc_missing & DSC_missing))
		{
			desc->dsc_missing = DSC_missing;
			return desc;
		}
		desc->dsc_missing = FALSE;
		if (desc->dsc_dtype == dtype_long)
		{
			*((SLONG*) desc->dsc_address) =
				MOVQ_get_long(values[0], values[0]->dsc_scale) *
				MOVQ_get_long(values[1], values[1]->dsc_scale);
		}
		else
			*((double*) desc->dsc_address) = MOVQ_get_double(values[0]) * MOVQ_get_double(values[1]);
		return desc;

	case nod_negate:
		if (values[0]->dsc_missing & DSC_missing)
		{
			desc->dsc_missing = DSC_missing;
			return desc;
		}
		desc->dsc_missing = FALSE;
		switch (desc->dsc_dtype)
		{
		case dtype_short:
			*((SSHORT*) desc->dsc_address) = -MOVQ_get_long(values[0], desc->dsc_scale);
			break;

		case dtype_long:
			*((SLONG*) desc->dsc_address) = -MOVQ_get_long(values[0], desc->dsc_scale);
			break;

		// lets throw arithmetic not supported until fixed
        //case dtype_int64:
		//	*((SINT64*) desc->dsc_address) = -MOVQ_get_long(values[0], desc->dsc_scale);
		//	break;

		case dtype_real:
			*((float*) desc->dsc_address) = -MOVQ_get_double(values[0]);
			break;

		case dtype_double:
			*((double*) desc->dsc_address) = -MOVQ_get_double(values[0]);
			break;

		default:
			IBERROR(30);		// Msg30 data type not supported for arithmetic
		}
		return desc;

	case nod_prompt:
		if (!prompt[0][0])
		{
			ERRQ_msg_get(499, prompt[0], sizeof(prompt[0]));	// Msg499 Re-enter
			ERRQ_msg_get(500, prompt[1], sizeof(prompt[1]));	// Msg500 Enter
		}
		return execute_prompt(node);

	case nod_concatenate:
		return execute_concatenate(node, values[0], values[1]);

	case nod_function:
		return execute_function(node);

	case nod_max:
	case nod_min:
	case nod_count:
	case nod_average:
	case nod_total:
	case nod_from:
		return execute_statistical(node);

	case nod_running_count:
		*(SLONG*) (desc->dsc_address) += 1;
		return desc;

	case nod_running_total:
		{
			dsc* desc2 = EVAL_value(node->nod_arg[e_stt_value]);
			if (desc2)
			{
				if (desc2->dsc_missing & DSC_missing)
					return desc;
				if (desc->dsc_dtype == dtype_long)
					*(SLONG*) desc->dsc_address += MOVQ_get_long(desc2, desc->dsc_scale);
				else
					*(double*) desc->dsc_address += MOVQ_get_double(desc2);
			}
		}
		return desc;

	case nod_format:
		{
			UCHAR* p = desc->dsc_address;
			PIC_edit(values[0], (pics*) node->nod_arg[e_fmt_picture], (TEXT**) &p, desc->dsc_length);
			desc->dsc_length = p - desc->dsc_address;
		}
		return desc;

	case nod_user_name:
		IBERROR(31);			// Msg31 user name is supported only in RSEs temporarily

	case nod_parameter:
	case nod_position:
	case nod_substr:
	case nod_via:

	default:
		ERRQ_bugcheck(29);			// Msg29 EVAL_value: not finished
		return NULL;
	}
}