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; }
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; } }