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