void PIC_missing( qli_const* constant, pics* picture)
{
/**************************************
 *
 *	P I C _ m i s s i n g
 *
 **************************************
 *
 * Functional description
 *	Create a literal picture string from
 *	a descriptor for a missing value so
 *	we can print the missing value
 *
 **************************************/

	const dsc* desc = &constant->con_desc;

	const int l = MAX(desc->dsc_length, picture->pic_length);

	qli_str* scratch = (qli_str*) ALLOCDV(type_str, l + 3);
	TEXT* p = scratch->str_data;
	*p++ = '\"';

	PIC_edit(desc, picture, &p, l);
	*p++ = '\"';
	*p = 0;

    pics* missing_picture = PIC_analyze(scratch->str_data, desc);
	picture->pic_missing = missing_picture;
	picture->pic_length = MAX(picture->pic_print_length, missing_picture->pic_print_length);
	missing_picture->pic_length = picture->pic_length;
}
Exemple #2
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;
	}
}