Example #1
0
int read_transposition() {
    extern unsigned char transposition[];
    unsigned char input;
    int i = 0;

    printf("This part of the program requires user input\n");
    printf("Please, input below via your keyboard %d natural numbers without repetition\n", MATRIX_LENGTH);
    printf("Each number will be acquired by a single string of numbers without spaces, finishing with ENTER key\n");
    printf("Enter numbers: ");

    for( i = 0; i < MATRIX_LENGTH; i++) {
        input = getchar();

        if(convert_to_number(input) == ERROR) return ERROR;
        transposition[i] = (unsigned char)convert_to_number(input);
    }

    return 0;
}
Example #2
0
vm_value vm_execute(vm_instruction *program, int program_length, vm_value *ctable, int ctable_length) {
  ++invocation;

  vm_state state0;
  vm_state *state = &state0;
  reset(state);

  state->const_table = ctable;
  state->const_table_length = ctable_length;


  bool is_running = true;


restart:
  while(is_running && state->program_pointer < program_length) {

    is_running = true;
    vm_value instr = program[state->program_pointer];
    vm_opcode opcode = get_opcode(instr);
    ++state->program_pointer;

    switch (opcode) {

      case OP_LOAD_i: {
        int reg0 = get_arg_r0(instr);
        int val = get_arg_i(instr);
        check_reg(reg0);
        get_reg(reg0) = val;
      }
      break;


      case OP_LOAD_ps: {
        int reg0 = get_arg_r0(instr);
        int value = get_arg_i(instr);
        check_reg(reg0);
        get_reg(reg0) = make_tagged_val(value, vm_tag_plain_symbol);
      }
      break;


      case OP_LOAD_cs: {
        int reg0 = get_arg_r0(instr);
        int value = get_arg_i(instr);
        check_reg(reg0);
        get_reg(reg0) = make_tagged_val(value, vm_tag_compound_symbol);
      }
      break;

      case OP_LOAD_os: {
        int reg0 = get_arg_r0(instr);
        int value = get_arg_i(instr);
        check_reg(reg0);
        get_reg(reg0) = make_tagged_val(value, vm_tag_opaque_symbol);
      }
      break;

      case OP_LOAD_f: {
        int reg0 = get_arg_r0(instr);
        int value = get_arg_i(instr);
        check_reg(reg0);
        get_reg(reg0) = make_tagged_val(value, vm_tag_function);
      }
      break;


      case OP_LOAD_str: {
        int reg0 = get_arg_r0(instr);
        int value = get_arg_i(instr);
        check_reg(reg0);
        get_reg(reg0) = make_tagged_val(value, vm_tag_string);
      }
      break;


      case OP_ADD: {
        int reg1 = get_arg_r1(instr);
        int reg2 = get_arg_r2(instr);
        check_reg(reg1);
        int arg1 = get_reg(reg1);
        check_reg(reg2);
        int arg2 = get_reg(reg2);
        int reg0 = get_arg_r0(instr);
        if(get_tag(arg1) != vm_tag_number) {
          fail("Expected a number, but got %s", value_to_type_string(arg1));
        }

        else if(get_tag(arg2) != vm_tag_number) {
          fail("Expected a number, but got %s", value_to_type_string(arg2));
        }

        check_reg(reg0);
        int result = ((arg1 - int_bias) + (arg2 - int_bias)) + int_bias;
        if(result < min_biased_int || result > max_biased_int) {
          fail("Int overflow");
        }
        get_reg(reg0) = result;
      }
      break;


      case OP_SUB: {
        int reg1 = get_arg_r1(instr);
        int reg2 = get_arg_r2(instr);
        check_reg(reg1);
        int arg1 = get_reg(reg1);
        check_reg(reg2);
        int arg2 = get_reg(reg2);
        int reg0 = get_arg_r0(instr);
        if(get_tag(arg1) != vm_tag_number) {
          fail("Expected a number, but got %s", value_to_type_string(arg1));
        }

        if(get_tag(arg2) != vm_tag_number) {
          fail("Expected a number, but got %s ", value_to_type_string(arg2));
        }

        check_reg(reg0);
        int result = ((arg1 - int_bias) - (arg2 - int_bias)) + int_bias;
        if(result < min_biased_int || result > max_biased_int) {
          fail("Int overflow");
        }
        get_reg(reg0) = result;
      }
      break;


      case OP_MUL: {
        int reg1 = get_arg_r1(instr);
        int reg2 = get_arg_r2(instr);
        check_reg(reg1);
        int arg1 = get_reg(reg1);
        check_reg(reg2);
        int arg2 = get_reg(reg2);
        int reg0 = get_arg_r0(instr);
        if(get_tag(arg1) != vm_tag_number) {
          fail("Expected a number, but got %s ", value_to_type_string(arg1) );
        }

        if(get_tag(arg2) != vm_tag_number) {
          fail("Expected a number, but got %s ", value_to_type_string(arg2) );
        }

        check_reg(reg0);
        int result = ((arg1 - int_bias) * (arg2 - int_bias)) + int_bias;
        if(result < min_biased_int || result > max_biased_int) {
          panic_stop_vm_m("Int overflow");
        }
        get_reg(reg0) = result;
      }
      break;


      case OP_DIV: {
        int reg1 = get_arg_r1(instr);
        int reg2 = get_arg_r2(instr);
        check_reg(reg1);
        int arg1 = get_reg(reg1);
        check_reg(reg2);
        int arg2 = get_reg(reg2);
        if(arg2 == 0) {
          fail("Division by 0");
        }

        if(get_tag(arg1) != vm_tag_number) {
          fail("Expected a number, but got %s ", value_to_type_string(arg1) );
        }

        if(get_tag(arg2) != vm_tag_number) {
          fail("Expected a number, but got %s", value_to_type_string(arg2) );
        }


        int reg0 = get_arg_r0(instr);
        check_reg(reg0);
        int result = ((arg1 - int_bias) / (arg2 - int_bias)) + int_bias;
        if(result < min_biased_int || result > max_biased_int) {
          fail("Int overflow");
        }
        get_reg(reg0) = result;
      }
      break;


      case OP_MOVE: {
        int reg0 = get_arg_r0(instr);
        int reg1 = get_arg_r1(instr);
        check_reg(reg0);
        check_reg(reg1);
        get_reg(reg0) = get_reg(reg1);
      }
      break;


      case OP_AP: {
        if (state->stack_pointer + 1 == stack_size) {
          fail("(call)!");
        }

        // this macro will create `return_pointer`
        do_call((&next_frame), get_arg_r1(instr), instr);
        if (call_failed) {
          fail("call failed"); //TODO give a better error description
        }

        next_frame.return_address = return_pointer;
        next_frame.result_register = get_arg_r0(instr);
        ++state->stack_pointer;

      }
      break;


      case OP_TAIL_AP: {
        do_call((&current_frame), get_arg_r1(instr), instr);
        if (call_failed) {
          fail("call failed"); //TODO give a better error description
        }

      }
      break;


      case OP_GEN_AP: {
        if (state->stack_pointer + 1 == stack_size) {
          printf("Stack overflow (call cl)!");
          panic_stop_vm();
        }

        int return_pointer = do_gen_ap(state, (&next_frame), instr, program);

        if (return_pointer != -1) {
          next_frame.return_address = return_pointer;
          next_frame.result_register = get_arg_r0(instr);
          ++state->stack_pointer;
        }

      }
      break;


      // TODO It's not entirely clear yet what happens when this returns a new PAP
      case OP_TAIL_GEN_AP: {
        do_gen_ap(state, &current_frame, instr, program);
      }
      break;


op_ret:
      case OP_RET: {
        int return_val_reg = get_arg_r0(instr);
        if (state->stack_pointer == 0) {
          //We simply copy the result value to register 0, so that the runtime can find it
          current_frame.reg[0] = current_frame.reg[return_val_reg];
          is_running = false;
          break;
        }
        --state->stack_pointer;
        current_frame.reg[next_frame.result_register] = next_frame.reg[return_val_reg];
        state->program_pointer = next_frame.return_address;
      }
      break;


      case OP_JMP: {
        int offset = get_arg_i(instr) - int_bias;
        state->program_pointer += offset;
        if(state->program_pointer < 0 || state->program_pointer > program_length) {
          panic_stop_vm_m("Illegal address!");
        }
      }
      break;

      case OP_JMP_TRUE: {
        check_reg(get_arg_r0(instr));
        vm_value bool_value = get_reg(get_arg_r0(instr));

        if( is_equal(state, bool_value, make_tagged_val(symbol_id_true, vm_tag_plain_symbol) )) {
          int offset = get_arg_i(instr) - int_bias;
          state->program_pointer += offset;
          if(state->program_pointer < 0 || state->program_pointer > program_length) {
            panic_stop_vm_m("Illegal address: %i", state->program_pointer);
          }
        }
        // else: do nothing

      }
      break;

      case OP_MATCH: {
        check_reg(get_arg_r0(instr));
        int subject = get_reg(get_arg_r0(instr));
        check_reg(get_arg_r1(instr));
        int patterns_addr = get_reg(get_arg_r1(instr));
        int capture_reg = get_arg_r2(instr);
        check_reg(capture_reg);

        check_ctable_index(patterns_addr)
        vm_value match_header = state->const_table[patterns_addr];
        int number_of_patterns = from_match_value(match_header);
        int i = 0;

        for(i=0; i<number_of_patterns; ++i) {
          int rel_pat_addr = patterns_addr + 1 + i;

          check_ctable_index(rel_pat_addr)
          vm_value pat = state->const_table[rel_pat_addr];
          if(does_value_match(state, pat, subject, capture_reg)) {
            break;
          }
          else {
            continue;
          }
        }

        if(i == number_of_patterns) {
          throw("Pattern match failed!");
        }

        state->program_pointer += i;
      }
      break;


      case OP_SET_ARG: {
        int target_arg = get_arg_r0(instr);
        int source_reg = get_arg_r1(instr);
        int extra_amount = get_arg_r2(instr);
        memcpy(&next_frame.reg[target_arg], &current_frame.reg[source_reg], (1 + extra_amount) * sizeof(vm_value));
      }
      break;


      case OP_SET_CL_VAL: {
        int cl_reg = get_arg_r0(instr);
        check_reg(cl_reg);
        vm_value closure = get_reg(cl_reg);

        if( get_tag(closure) != vm_tag_pap ) {
          fail("Expected a closure, but got %s", value_to_type_string(closure));
        }

        heap_address cl_address = get_val(closure);
        check_reg(get_arg_r1(instr));
        vm_value new_value = get_reg(get_arg_r1(instr));
        int arg_index = get_arg_r2(instr);

        vm_value *cl_pointer = heap_get_pointer(cl_address);
        int header = *cl_pointer;
        int num_env_args = pap_var_count(header);
        if(arg_index >= num_env_args) {
          panic_stop_vm_m("Illegal closure modification (index: %i, num env vars: %i)", arg_index, num_env_args);
        }
        cl_pointer[pap_header_size + arg_index] = new_value;

      }
      break;


      case OP_PART_AP: {
        int reg0 = get_arg_r0(instr);
        int fun_reg = get_arg_r1(instr);
        check_reg(fun_reg);
        int func = get_reg(fun_reg);

        if( get_tag(func) != vm_tag_function ) {
          fail("Expected a function, but got %s", value_to_type_string(func));
        }

        int fun_address = get_val(func);
        int num_args = get_arg_r2(instr);

        vm_value fun_header = program[fun_address];
        //TODO check that it's actually a function
        int arity = get_arg_i(fun_header);

        // TODO this was >= earlier, which apparently gave false positives. Find out why, and find out if > is the correct choice
        if(num_args > arity) {
          panic_stop_vm_m("Illegal partial application (num args: %i, arity: %i)", num_args, arity);
        }

        int pap_arity = arity - num_args;

        build_pap(num_args, pap_arity, 0, num_args, fun_address);
        check_reg(reg0);
        get_reg(reg0) = pap_value;
      }
      break;


      case OP_EQ: {
        check_reg(get_arg_r1(instr));
        check_reg(get_arg_r2(instr));
        vm_value l = get_reg(get_arg_r1(instr));
        vm_value r = get_reg(get_arg_r2(instr));
        int result_reg = get_arg_r0(instr);
        check_reg(result_reg);

        if( is_equal(state, l, r)) {
          get_reg(result_reg) = make_tagged_val(symbol_id_true, vm_tag_plain_symbol);
        }
        else {
          get_reg(result_reg) = make_tagged_val(symbol_id_false, vm_tag_plain_symbol);
        }
      }
      break;

      case OP_LT: {
        check_reg(get_arg_r1(instr));
        check_reg(get_arg_r2(instr));
        vm_value l = get_reg(get_arg_r1(instr));
        vm_value r = get_reg(get_arg_r2(instr));
        int result_reg = get_arg_r0(instr);
        check_reg(result_reg);

        if(get_tag(l) != vm_tag_number) {
          fail("Expected a number, but got %s", value_to_type_string(l));
        }
        else if(get_tag(r) != vm_tag_number) {
          fail("Expected a number, but got %s", value_to_type_string(r));
        }

        if( l < r) {
          get_reg(result_reg) = make_tagged_val(symbol_id_true, vm_tag_plain_symbol);
        }
        else {
          get_reg(result_reg) = make_tagged_val(symbol_id_false, vm_tag_plain_symbol);
        }
      }
      break;

      case OP_GT: {
        check_reg(get_arg_r1(instr));
        check_reg(get_arg_r2(instr));
        vm_value l = get_reg(get_arg_r1(instr));
        vm_value r = get_reg(get_arg_r2(instr));
        int result_reg = get_arg_r0(instr);
        check_reg(result_reg);

        if(get_tag(l) != vm_tag_number) {
          fail("Expected a number, but got %s", value_to_type_string(l));
        }
        else if(get_tag(r) != vm_tag_number) {
          fail("Expected a number, but got %s", value_to_type_string(r));
        }

        if( l > r) {
          get_reg(result_reg) = make_tagged_val(symbol_id_true, vm_tag_plain_symbol);
        }
        else {
          get_reg(result_reg) = make_tagged_val(symbol_id_false, vm_tag_plain_symbol);
        }
      }
      break;


      case OP_COPY_SYM: {
        check_reg(get_arg_r0(instr));
        check_reg(get_arg_r1(instr));
        vm_value const_symbol = get_reg(get_arg_r1(instr));

        if ( get_tag(const_symbol) != vm_tag_compound_symbol ) {
          panic_stop_vm_m("Expected a const symbol, but got %s", value_to_type_string(const_symbol));
        }

        int c_addr = get_val(const_symbol);
        vm_value c_sym_header = state->const_table[c_addr];

        int count = compound_symbol_count(c_sym_header);

        size_t total_size = compound_symbol_header_size + count;
        heap_address dyn_sym_address = heap_alloc(total_size);
        vm_value *sym_pointer = heap_get_pointer(dyn_sym_address);  \
        memcpy(sym_pointer, &(state->const_table[c_addr]), total_size * sizeof(vm_value));

        get_reg(get_arg_r0(instr)) = make_tagged_val(dyn_sym_address, vm_tag_dynamic_compound_symbol);

      }
      break;

      case OP_SET_SYM_FIELD: {
        check_reg(get_arg_r0(instr));
        check_reg(get_arg_r1(instr));
        vm_value heap_symbol = get_reg(get_arg_r0(instr));

        if ( get_tag(heap_symbol) != vm_tag_dynamic_compound_symbol ) {
          panic_stop_vm_m("Expected a dynamic symbol, but got %s", value_to_type_string(heap_symbol));
        }

        int h_addr = get_val(heap_symbol);
        vm_value *p = heap_get_pointer(h_addr);
        vm_value h_sym_header = *p;

        int count = compound_symbol_count(h_sym_header);

        int index = get_arg_r2(instr);
        if(index < 0 || index >= count) {
          panic_stop_vm_m("Illegal index while setting symbol field: %d", index);
        }

        p[compound_symbol_header_size + index] = get_reg(get_arg_r1(instr));
      }
      break;


      case OP_STR_LEN: {
        check_reg(get_arg_r0(instr));
        check_reg(get_arg_r1(instr));

        vm_value str = get_reg(get_arg_r1(instr));
        int tag = get_tag(str);
        if (tag != vm_tag_string && tag != vm_tag_dynamic_string ) {
          fail("Expected a string, but got %s", value_to_type_string(str));
        }

        int str_addr = get_val(str);
        vm_value *str_pointer;

        if(tag == vm_tag_string) {
          str_pointer = state->const_table + str_addr;
        }
        else {
          str_pointer = heap_get_pointer(str_addr);
        }

        vm_value str_header = *str_pointer;

        int count = string_length(str_header);
        get_reg(get_arg_r0(instr)) = make_tagged_val(count + int_bias, vm_tag_number);
      }
      break;


      case OP_NEW_STR: {
        int result_reg = get_arg_r0(instr);
        check_reg(result_reg);
        check_reg(get_arg_r1(instr));

        vm_value length_value = get_reg(get_arg_r1(instr));
        if(get_tag(length_value) != vm_tag_number) {
          panic_stop_vm_m("Expected a number, but got %s", value_to_type_string(length_value));
        }

        int length = length_value - int_bias;
        if(length < 0) {
          panic_stop_vm_m("Negative length for new string, got: %d", length);
        }

        int adjusted_length = length + 1; // allow space for trailing '\0'
        int num_chunks = adjusted_length / char_per_string_chunk;
        if( (adjusted_length % char_per_string_chunk) != 0 ) {
          num_chunks += char_per_string_chunk - (adjusted_length % char_per_string_chunk);
        }

        size_t total_size = string_header_size + num_chunks;
        heap_address string_address = heap_alloc(total_size);
        vm_value *str_pointer = heap_get_pointer(string_address);

        memset(str_pointer, 0, total_size * sizeof(vm_value));
        *str_pointer = string_header(length, num_chunks);

        get_reg(result_reg) = make_tagged_val(string_address, vm_tag_dynamic_string);

      }
      break;


      case OP_GET_CHAR: {
        int result_reg = get_arg_r0(instr);
        check_reg(result_reg);
        check_reg(get_arg_r1(instr));
        check_reg(get_arg_r2(instr));

        vm_value str = get_reg(get_arg_r1(instr));
        vm_value str_tag = get_tag(str);
        if(str_tag != vm_tag_string && str_tag != vm_tag_dynamic_string) {
          panic_stop_vm_m("Expected a string, but got %s", value_to_type_string(str));
        }

        int str_addr = get_val(str);
        vm_value *str_pointer;

        if(str_tag == vm_tag_string) {
          str_pointer = state->const_table + str_addr;
        }
        else {
          str_pointer = heap_get_pointer(str_addr);
        }

        vm_value str_header = *str_pointer;

        int index = get_reg(get_arg_r2(instr)) - int_bias;
        int str_length = string_length(str_header);
        if(index < 0 || index > str_length) {
          panic_stop_vm_m("Illegal string index: %d", index);
        }

        char *char_pointer = (char *) (str_pointer + string_header_size);
        int character = char_pointer[index];

        get_reg(result_reg) = make_tagged_val(character, vm_tag_number);

      }
      break;


      case OP_PUT_CHAR: {
        check_reg(get_arg_r0(instr));
        check_reg(get_arg_r1(instr));
        check_reg(get_arg_r2(instr));

        vm_value str = get_reg(get_arg_r1(instr));
        vm_value str_tag = get_tag(str);
        if(str_tag != vm_tag_dynamic_string) {
          panic_stop_vm_m("Expected a dynamic string, but got %s", value_to_type_string(str));
        }

        int character = get_reg(get_arg_r0(instr));
        if(get_tag(character) != vm_tag_number) {
          panic_stop_vm_m("Expected a number, but got %s", value_to_type_string(character));
        }

        int str_addr = get_val(str);
        vm_value *str_pointer = heap_get_pointer(str_addr);

        vm_value str_header = *str_pointer;

        int index = get_reg(get_arg_r2(instr)) - int_bias;
        int str_length = string_length(str_header);
        if(index < 0 || index > str_length) {
          panic_stop_vm_m("Illegal string index: %d", index);
        }

        char *char_pointer = (char *) (str_pointer + string_header_size);
        char_pointer[index] = (char) character;
      }
      break;


      case OP_OR: {
        int reg1 = get_arg_r1(instr);
        int reg2 = get_arg_r2(instr);
        check_reg(reg1);
        int arg1 = get_reg(reg1);
        check_reg(reg2);
        int arg2 = get_reg(reg2);
        int reg0 = get_arg_r0(instr);
        check_reg(reg0);

        vm_value result = make_tagged_val(symbol_id_false, vm_tag_plain_symbol);
        vm_value true_sym = make_tagged_val(symbol_id_true, vm_tag_plain_symbol);
        if(arg1 == true_sym || arg2 == true_sym) {
          result = true_sym;
        }
        get_reg(reg0) = result;
      }
      break;


      case OP_AND: {
        int reg1 = get_arg_r1(instr);
        int reg2 = get_arg_r2(instr);
        check_reg(reg1);
        int arg1 = get_reg(reg1);
        check_reg(reg2);
        int arg2 = get_reg(reg2);
        int reg0 = get_arg_r0(instr);
        check_reg(reg0);

        vm_value result = make_tagged_val(symbol_id_false, vm_tag_plain_symbol);
        vm_value true_sym = make_tagged_val(symbol_id_true, vm_tag_plain_symbol);
        if(arg1 == true_sym && arg2 == true_sym) {
          result = true_sym;
        }
        get_reg(reg0) = result;
      }
      break;


      case OP_NOT: {
        int reg1 = get_arg_r1(instr);
        check_reg(reg1);
        int arg1 = get_reg(reg1);
        int reg0 = get_arg_r0(instr);
        check_reg(reg0);

        vm_value result = make_tagged_val(symbol_id_false, vm_tag_plain_symbol);
        vm_value true_sym = make_tagged_val(symbol_id_true, vm_tag_plain_symbol);
        if(arg1 != true_sym) {
          result = true_sym;
        }
        //else: result is already set to false
        get_reg(reg0) = result;
      }
      break;


      case OP_GET_FIELD: {
        int result_reg = get_arg_r0(instr);
        int obj_reg = get_arg_r1(instr);
        int sym_reg = get_arg_r2(instr);
        check_reg(result_reg);
        check_reg(obj_reg);
        check_reg(sym_reg);

        vm_value obj_ref = get_reg(obj_reg);
        vm_value requested_name = get_reg(sym_reg);

        if(get_tag(requested_name) != vm_tag_plain_symbol) {
          panic_stop_vm_m("Malformed lookup!");
        }

        vm_value obj_header = 0;
        vm_value *obj_fields = 0;

        if(get_tag(obj_ref) == vm_tag_opaque_symbol) {

          int obj_addr = get_val(obj_ref);
          vm_value *obj_pointer = state->const_table + obj_addr;

          vm_value obj_owner = obj_pointer[1];
          if(obj_owner != make_tagged_val(0, vm_tag_plain_symbol)) {
            panic_stop_vm_m("Malformed module!");
          }

          obj_header = obj_pointer[0];
          obj_fields = obj_pointer + 2;


        }
        // TODO this branch is untested, as records are apparently always dynamic in this case (?!)
        else if(get_tag(obj_ref) == vm_tag_compound_symbol) {

          int obj_addr = get_val(obj_ref);
          vm_value *obj_pointer = state->const_table + obj_addr;

          obj_header = obj_pointer[0];
          if(compound_symbol_id(obj_header) != symbol_id_record) {
            fail("Expected a module or record, got %s", value_to_type_string(obj_ref));
          }

          obj_fields = obj_pointer + 1;

        }
        else if(get_tag(obj_ref) == vm_tag_dynamic_compound_symbol) {


          int obj_addr = get_val(obj_ref);
          vm_value *obj_pointer = heap_get_pointer(obj_addr);

          //vm_value *obj_pointer = state->const_table + obj_addr;

          obj_header = obj_pointer[0];
          obj_fields = obj_pointer + 1;

          if(compound_symbol_id(obj_header) != symbol_id_record) {
            fail("Expected a module or record, got %s", value_to_type_string(obj_ref));
          }


        }

        else {
          // exits subroutine here
          fail("Expected a module or record, got %s", value_to_type_string(obj_ref));
        }


        int num_symbol_fields = compound_symbol_count(obj_header);

        bool found = false;
        for(int i=0; i < num_symbol_fields; i += 2) {
          vm_value name = obj_fields[i];

          if(name == requested_name) {
            get_reg(result_reg) = obj_fields[i+1];
            found = true;
            break;
          }
        }

        if(found == false) {
          //TODO change this to built-in nil type
          get_reg(result_reg) = make_tagged_val(symbol_id_nil, vm_tag_plain_symbol);
        }

      }
      break;


      case OP_CONVERT: {
        int result_reg = get_arg_r0(instr);
        int source_reg = get_arg_r1(instr);
        int type_reg = get_arg_r2(instr);
        check_reg(result_reg);
        check_reg(source_reg);
        check_reg(type_reg);

        vm_value source = get_reg(source_reg);
        vm_value target_type = get_reg(type_reg);
        if(get_tag(target_type) != vm_tag_plain_symbol) {
          fail("Expected a symbol, got %s", value_to_type_string(target_type));
        }
        vm_value target_type_id = get_val(target_type);
        vm_value result;

        switch(target_type_id) {

          case symbol_id_number:
            result = convert_to_number(state, source);
            break;

          case symbol_id_string:
            result = convert_to_string(state, source);
            break;

          default:
            result = make_str_error("Unable to convert value");

        }

        get_reg(result_reg) = result;
      }
      break;

      default:
        panic_stop_vm_m("UNKNOWN OPCODE: %04x", opcode);
    }


  }


  vm_value result = state->stack[state->stack_pointer].reg[0];


  vm_value io_result_value = 0;
  vm_value next_action;
  io_action_result action_result = check_io_action(state, result, program, &io_result_value, &next_action);

  switch(action_result) {
    case no_io_action:
      // do nothing
      break;

    case intermediary_io_action: {
        state->stack_pointer = 0;

        current_frame.reg[0] = next_action;
        next_frame.reg[0] = io_result_value; // argument for next_action
        vm_instruction instr = op_gen_ap(0, 0, 1);
        int return_pointer = do_gen_ap(state, &current_frame, instr, program);
        if (return_pointer != -1) {
          current_frame.return_address = return_pointer;
          current_frame.result_register = 0;
        }
        else {
          // TODO is this malformed?
          panic_stop_vm_m("malformed bound lambda in io action");
        }
        is_running = true;
      }
      goto restart;

    case final_io_action:
      result = io_result_value;
      break;

    default:
      panic_stop_vm_m("Unknown result of io action: %d", action_result);
  }


  return result;
}
Example #3
0
/************************************************************************
** Function: ProcessUsgDetail
**
** Purpose: Read a  detail usage record from usage file.
**
** returns:	SUCCESS - no errors, or "soft" (minor) error.  SUCCESS
**		          means that the record will be saved in either
**		          CDR_DATA or CDR_DATA_WORK.
**		FAILURE - serious parsing error. return FAILURE implies
**		          "hard" error.  Such records will be written to
**		          the bad image file.
**		          Note that records with hard errors will be
**		          written to bad image file as is.  This means
**		          error codes are NOT saved.  This is why we
**		          return immediately for FAILURE case.
**
** General idea is that missing data will be considered a "soft" error
** where as non-numeric data in a numeric field will be considered a
** hard error.
*************************************************************************
*/
int ProcessUsgDetail(CDR_DATA_STRUCT *cdr_data,
        RECORD_TYPE_STRUCT *rec_type,
        int  minimize,
        int  *checksum1,
        int  *checksum2,
        int  *checksum3)
{
   char *ptr;
   char tmpstr[1024];
   char gstrScratch1[1024];
   int  pos;	/* floating pointer into cdr_data->usg_rec */

   /* for time field, we need to convert to the usage time zone if
   ** it is provided. But sometime we do not have timezone in usage
   ** file, in this case we will convert to default timezone?
   ** To convert time, we need to wait after the whole usage record
   ** has been processed, then do conversion if necessary
   */

   short trans_dt_type = -1; /* -1 means not supplied in usg file,no op */
   short second_dt_type = -1;/* -1 means not supplied in usg file,no op */
   short rate_dt_type = -1;  /* -1 means not supplied in usg file,no op */
   short new_timezone = FALSE; /* to indicate whether there is a timezone
                               ** in the usage record 
                               */
   char usage_tz[szUnixTZ+1+3];
   char unix_tz[szUnixTZ+1];
   short size;     /* size of input field */
   tiny isdst;     /* ignored */

   int  i;
   int  j;

   pos = 0;
   ptr = gstrScratch1;

   if(mpsIsLogLevelHigh())
   {
      sprintf(tmpstr, "\nProcessing Record Type \'%s\'",
         rec_type->record_type);
      emit(ERRLOC,MPS_GENERIC_INFORM,tmpstr);
      sprintf(tmpstr, "===================================");
      emit(ERRLOC,MPS_GENERIC_INFORM,tmpstr);
      sprintf(tmpstr, "%-20.20s   %-20.20s   %-12.12s %-5.5s %-15.12s",
         "Field Name From", "Field Name To","Field Type", "Size","Field Value");
      emit(ERRLOC,MPS_GENERIC_INFORM,tmpstr);
      sprintf(tmpstr,
         "===============        ===============        ============ ===== ===========");
      emit(ERRLOC,MPS_GENERIC_INFORM,tmpstr);
   }

   for(i = rec_type->from_pos; i <= rec_type->to_pos; i++)
   {
      size = gsField_Mapping[i].field_from_size;
      /* Skip over some fields if in minimize / non-debug mode */
      if ( minimize && !mpsIsLogLevelHigh() )
      {
         switch(gsField_Mapping[i].field_to_id)
         {
         case to_type_id_usg:
         case to_point_origin:
         case to_point_target:
         case to_trans_dt:
         case to_timezone:
         case to_external_id:
         case to_external_id_type:
         case to_home_carrier_sid_bid:
         case to_num_tax_details:
            break;

         default:
            pos += size;
            continue;
         }
      }

      switch(gsField_Mapping[i].field_from_type)
      {
      case binary:
         j = ParseHex((char *)cdr_data->usg_rec+pos, (int) size);
         pos += size;
         if(mpsIsLogLevelHigh())
         {
            sprintf(tmpstr, 
               "%-20.20s   %-20.20s   %-12.12s %-6d%-12d",
               gsField_Mapping[i].field_from_name,
               gsField_Mapping[i].field_to_name,
               "(binary)",
               size,
               j);
            emit(ERRLOC,MPS_GENERIC_INFORM,tmpstr);
         }
         break;
      default:
         if((gsField_Mapping[i].field_to_id == to_annotation)   ||
            (gsField_Mapping[i].field_to_id == to_customer_tag) ||
            (gsField_Mapping[i].field_to_id == to_roaming_detail))
         {
            extract_field_no_strip(&ptr, (char *)cdr_data->usg_rec, &pos, (int) size);
         } else {
            extract_field(&ptr, (char *)cdr_data->usg_rec, &pos, (int) size);
         }
         if(mpsIsLogLevelHigh())
         {
            sprintf(tmpstr, 
               "%-20.20s   %-20.20s   %-12.12s %-6d%-s",
               gsField_Mapping[i].field_from_name,
               gsField_Mapping[i].field_to_name,
               "(a/n str)",
               size,
               ptr);
            emit(ERRLOC,MPS_GENERIC_INFORM,tmpstr);
         }
         break;
      } 
      if(gsField_Mapping[i].is_ignored)
      {
         continue;
      }
      if(gsField_Mapping[i].is_required && ptr[0] == '\0' &&
         gsField_Mapping[i].field_from_type != binary)
      {
         emit(ERRLOC,CAP_FIELD_MISSING_X,gsField_Mapping[i].field_from_name);
         set_cdr_error_code(cdr_data, CAP_FIELD_MISSING); 
         sprintf(tmpstr, "%d,Field: \"%s\"",
            CAP_FIELD_MISSING,gsField_Mapping[i].field_to_name);

         emit(ERRLOC,MPS_GEN_ERROR,tmpstr );
         set_mps_error_struct(tmpstr,""); 
      }

      /* if we need to convert from string to a numeric field *
      ** we need to check no digital char and overflow        */
      if(gsField_Mapping[i].field_to_type != to_string)
      {
         if(gsField_Mapping[i].field_from_type != binary)
         {
            if(numeric_string(ptr))
            {
               if(gsField_Mapping[i].field_to_type == to_numeric)
               {
               }
               else
               {
                  if(convert_to_number(ptr,&j, 
                     (short) gsField_Mapping[i].field_to_type) == FAILURE)
                  {
                     /* conversion caused overflow */
                     j = 0;
                     set_cdr_error_code(cdr_data, CAP_VALUE_OVERFLOW);
                     sprintf(tmpstr,
                        "%d,convert \"%s\" to \"%s\" caused overflow",
                        CAP_VALUE_OVERFLOW,
                        ptr,
                        gsField_Mapping[i].field_to_name);
                     set_mps_error_struct(tmpstr,"");
                  }
               }
            }
            else
            {
               /* some non-numeric characters for numeric field */
               j = 0;
               set_cdr_error_code(cdr_data, CAP_BAD_NUM_FIELD);
               sprintf(tmpstr,
                  "%d,Field value: \"%s\"",
                  CAP_BAD_NUM_FIELD,
                  ptr);
               emit(ERRLOC,CAP_BAD_NUM_FIELD );
               sprintf(tmpstr, "%-20.20s: \"%s\"",
                  gsField_Mapping[i].field_from_name,gstrScratch1);
               emit(ERRLOC,MPS_GEN_ERROR,tmpstr );
               set_mps_error_struct(tmpstr,""); 
            }
         }
         else
         {
            /* when we get a binary field, we need to check overflow
            ** since we may get the int and try to convert to a tiny */
            if(check_overflow(j, (short) gsField_Mapping[i].field_to_type) == FAILURE)
            {
               j = 0;
               /* conversion caused overflow */
               set_cdr_error_code(cdr_data, CAP_VALUE_OVERFLOW);
               sprintf(tmpstr,
                  "%d,convert %d to \"%s\" caused overflow",
                  CAP_VALUE_OVERFLOW,
                  j,
                  gsField_Mapping[i].field_to_name);
               emit(ERRLOC,MPS_GEN_ERROR,tmpstr );
               set_mps_error_struct(tmpstr,"");
            }
         } 
      } 

      switch(gsField_Mapping[i].field_to_id)
      {
      case to_ext_tracking_id:
         if(gsField_Mapping[i].field_from_type != binary)
         {
            strncpy(cdr_data->ext_tracking_id, ptr, szExtTrackingId);
            cdr_data->ext_tracking_id[szExtTrackingId] = '\0';
         }
         else
         {
            sprintf(tmpstr,"%d",j);
            strncpy(cdr_data->ext_tracking_id, tmpstr,szExtTrackingId);
            cdr_data->ext_tracking_id[szExtTrackingId] = '\0';
         }
         break;
      case to_trans_id:
         if(gsField_Mapping[i].field_from_type != binary)
         {
            strncpy(cdr_data->trans_id, ptr, szTransID);
            cdr_data->trans_id[szTransID] = '\0';
         }
         else
         {
            sprintf(cdr_data->trans_id,"%d",j);
            sprintf(tmpstr,"%d",j);
            strncpy(cdr_data->trans_id, tmpstr, szTransID);
            cdr_data->trans_id[szTransID] = '\0';
         }
         break;
      case to_element_id:
         cdr_data->element_id = j;
         break;
      case to_type_id_usg:
         cdr_data->type_id_usg = j;
         cdr_data->orig_type_id_usg = j;
         break;
      case to_rate_class:
         cdr_data->rate_class = j;
         break;
      case to_bill_class:
         cdr_data->bill_class = j;
         break;
      case to_num_tax_details:
         cdr_data->num_tax_details = j;
         break;
      case to_provider_id:
         cdr_data->provider_id = j;
         break;
      case to_provider_class:
         cdr_data->provider_class = j;
         break;
      case to_jurisdiction:
         cdr_data->jurisdiction = j;
         break;
      case to_rate_currency_code:
         cdr_data->rate_currency_code = j;
         break;
      case to_emf_create_date:
         break;
      case to_point_origin:
         if(gsField_Mapping[i].field_from_type != binary)
         {
            strncpy(cdr_data->point_origin, ptr, szUsagePoint);
            cdr_data->point_origin[szUsagePoint] = '\0';
         }
         else
         {
            sprintf(tmpstr,"%d",j);
            strncpy(cdr_data->point_origin, tmpstr, szUsagePoint);
            cdr_data->point_origin[szUsagePoint] = '\0';
         }
         break;
      case to_country_dial_code_origin:
         if(gsField_Mapping[i].field_from_type != binary)
         {
            strncpy(cdr_data->country_dial_code_origin, ptr, 
               szDialCode);
            cdr_data->country_dial_code_origin[szDialCode] = '\0';
         }
         else
         {
            sprintf(tmpstr,"%d",j);
            strncpy(cdr_data->country_dial_code_origin, tmpstr, szDialCode);
            cdr_data->country_dial_code_origin[szDialCode] = '\0';
         }
         break;
      case to_point_tax_code_origin:
         if(gsField_Mapping[i].field_from_type != binary)
         {
            strncpy(cdr_data->point_tax_code_origin, ptr, szTaxCode);
            cdr_data->point_tax_code_origin[szTaxCode] = '\0';
         }
         else
         {
            sprintf(tmpstr,"%d",j);
            strncpy(cdr_data->point_tax_code_origin, tmpstr, szTaxCode);
            cdr_data->point_tax_code_origin[szTaxCode] = '\0';
         }
         break;
      case to_point_tax_code_type_origin:
         cdr_data->point_tax_code_type_origin = j;
         break;
      case to_point_target:
         if(gsField_Mapping[i].field_from_type != binary)
         {
            strncpy(cdr_data->point_target, ptr, szUsagePoint);
            cdr_data->point_target[szUsagePoint] = '\0';
         }
         else
         {
            sprintf(tmpstr,"%d",j);
            strncpy(cdr_data->point_target, tmpstr, szUsagePoint);
            cdr_data->point_target[szUsagePoint] = '\0';
         }
         break;
      case to_point_tax_code_target:
         if(gsField_Mapping[i].field_from_type != binary)
         {
            strncpy(cdr_data->point_tax_code_target, ptr, szTaxCode);
            cdr_data->point_tax_code_target[szTaxCode] = '\0';
         }
         else
         {
            sprintf(tmpstr,"%d",j);
            strncpy(cdr_data->point_tax_code_target, tmpstr, szTaxCode);
            cdr_data->point_tax_code_target[szTaxCode] = '\0';
         }
         break;
      case to_point_tax_code_type_target:
         cdr_data->point_tax_code_type_target = j;
         break;
      case to_trans_dt:
         /* if time comes in as unix time save it in the trans_time field
         ** and do conversion later by using a timezone 
         */
         if(gsField_Mapping[i].field_to_type == to_int)
            cdr_data->trans_time = j;
         else
         {
            /* if time comes in as char string save the string and convert
            ** to YYYYMMDD HH:MM:SS according the input format
            */
            if(convert_date_string(cdr_data->trans_dt, gstrScratch1,
               gsField_Mapping[i].date_format_type) == FAILURE)
            {
               emit(ERRLOC, MPS_BAD_FIELD, "trans_dt", cdr_data->trans_dt);
               set_cdr_error_code(cdr_data, CAP_BAD_PRIMTIME);
               sprintf(tmpstr,
                  "%d,%s: \"%s\"",
                  CAP_BAD_PRIMTIME,gsField_Mapping[i].field_to_name,
                  cdr_data->trans_dt);
               emit(ERRLOC, MPS_GEN_ERROR, tmpstr );
               set_mps_error_struct(tmpstr,"");
               break;
            }
         }
         trans_dt_type = gsField_Mapping[i].field_to_type;
         break;
      case to_second_dt:
         /* if time comes in as unix time save it in the trans_time field
         ** and do conversion later by using a timezone 
         */
         if(gsField_Mapping[i].field_to_type == to_int)
            cdr_data->second_time = j;
         else
         {
            /* if time comes in as char string save the string and convert
            ** to YYYYMMDD HH:MM:SS according the input format later 
            */
            if(convert_date_string(cdr_data->second_dt, gstrScratch1,
               gsField_Mapping[i].date_format_type) == FAILURE)
            {
               emit(ERRLOC, MPS_BAD_FIELD,"second_dt",cdr_data->second_dt);
               set_cdr_error_code(cdr_data, CAP_BAD_SECONDTIME);
               sprintf(tmpstr,
                  "%d,%s: \"%s\"",
                  CAP_BAD_SECONDTIME,
                  gsField_Mapping[i].field_to_name,
                  cdr_data->second_dt);

               emit(ERRLOC, MPS_GEN_ERROR, tmpstr );
               set_mps_error_struct(tmpstr,"");
               break;
            }
         }
         second_dt_type = gsField_Mapping[i].field_to_type;
         break;
      case to_timezone:
         cdr_data->timezone = j;
         new_timezone = TRUE;
         break;
      case to_primary_units:
         if(gsField_Mapping[i].field_from_type == binary)
         {
            arb_numeric_from_int(&(cdr_data->primary_units), j);
         }
         else
         {
            arb_numeric_from_string(&(cdr_data->primary_units), ptr);
            if ( arb_numeric_to_int( &(cdr_data->primary_units), &j) == FAILURE)
            {
               j = cdr_data->primary_units.low;
            }
         }
         *checksum1 += j;
         break;
      case to_primary_type:
         cdr_data->primary_type = j;
         break;
      case to_second_units:
         if(gsField_Mapping[i].field_from_type == binary)
         {
            arb_numeric_from_int(&(cdr_data->second_units), j);
         }
         else
         {
            arb_numeric_from_string(&(cdr_data->second_units), ptr);
            if ( arb_numeric_to_int( &(cdr_data->second_units), &j) == FAILURE)
            {
               j = cdr_data->second_units.low;
            }
         }
         *checksum2 += j;
         break;
      case to_second_type:
         cdr_data->second_type = j;
         break;
      case to_third_units:
         if(gsField_Mapping[i].field_from_type == binary)
         {
            arb_numeric_from_int(&(cdr_data->third_units), j);
         }
         else
         {
            arb_numeric_from_string(&(cdr_data->third_units), ptr);
            if ( arb_numeric_to_int( &(cdr_data->third_units), &j) == FAILURE)
            {
               j = cdr_data->third_units.low;
            }
         }
         *checksum3 += j;
         break;
      case to_third_type:
         cdr_data->third_type = j;
         break;
      case to_federal_tax:
         if(gsField_Mapping[i].field_from_type == binary)
         {
            arb_numeric_from_int(&(cdr_data->federal_tax), j);
         }
         else
         {
            arb_numeric_from_string(&(cdr_data->federal_tax), ptr);
         }
         break;
      case to_state_tax:
         if(gsField_Mapping[i].field_from_type == binary)
         {
            arb_numeric_from_int(&(cdr_data->state_tax), j);
         }
         else
         {
            arb_numeric_from_string(&(cdr_data->state_tax), ptr);
         }
         break;
      case to_county_tax:
         if(gsField_Mapping[i].field_from_type == binary)
         {
            arb_numeric_from_int(&(cdr_data->county_tax), j);
         }
         else
         {
            arb_numeric_from_string(&(cdr_data->county_tax), ptr);
         }
         break;
      case to_city_tax:
         if(gsField_Mapping[i].field_from_type == binary)
         {
            arb_numeric_from_int(&(cdr_data->city_tax), j);
         }
         else
         {
            arb_numeric_from_string(&(cdr_data->city_tax), ptr);
         }
         break;
      case to_other_tax:
         if(gsField_Mapping[i].field_from_type == binary)
         {
            arb_numeric_from_int(&(cdr_data->other_tax), j);
         }
         else
         {
            arb_numeric_from_string(&(cdr_data->other_tax), ptr);
         }
         break;
      case to_units_currency_code:
         cdr_data->units_currency_code = j;
         break;
      case to_annotation:
         if(gsField_Mapping[i].field_from_type != binary)
         {
            strncpy(cdr_data->annotation, ptr, size);
            cdr_data->annotation[size] = '\0';
         }
         else
         {
            sprintf(tmpstr,"%d",j);
            strncpy(cdr_data->annotation, tmpstr, size);
            cdr_data->annotation[size] = '\0';
         }
         break;
      case to_customer_tag:
         if(gsField_Mapping[i].field_from_type != binary)
         {
            strncpy(cdr_data->customer_tag, ptr, szCustomerTag);
            cdr_data->customer_tag[szCustomerTag] = '\0';
         }
         else
         {
            sprintf(tmpstr,"%d",j);
            strncpy(cdr_data->customer_tag, tmpstr, szCustomerTag);
            cdr_data->customer_tag[szCustomerTag] = '\0';
         }
         break;
      case to_geocode:
         if(gsField_Mapping[i].field_from_type != binary)
         {
            strncpy(cdr_data->geocode, ptr, szTaxCode);
            cdr_data->geocode[szTaxCode] = '\0';
         }
         else
         {
            sprintf(tmpstr,"%d",j);
            strncpy(cdr_data->geocode, tmpstr, szTaxCode);
            cdr_data->geocode[szTaxCode] = '\0';
         }
         break;
      case to_roaming_detail:
         if(gsField_Mapping[i].field_from_type != binary)
         {
            strncpy(cdr_data->roaming_detail, ptr, size);
            cdr_data->roaming_detail[size] = '\0';
         }
         else
         {
            sprintf(tmpstr,"%d",j);
            strncpy(cdr_data->roaming_detail, tmpstr, size);
            cdr_data->roaming_detail[size] = '\0';
         }
         break;	    
      case to_rated_units:
         if(gsField_Mapping[i].field_from_type == binary)
         {
            arb_numeric_from_int(&(cdr_data->rated_units), j);
         }
         else
            arb_numeric_from_string(&(cdr_data->rated_units), ptr);
         break;
      case to_total_amt:
         if(gsField_Mapping[i].field_from_type == binary)
         {
            arb_numeric_from_int(&(cdr_data->total_amt), j);
         }
         else
            arb_numeric_from_string(&(cdr_data->total_amt), ptr);
         break;
      case to_base_amt:
         if(gsField_Mapping[i].field_from_type == binary)
         {
            arb_numeric_from_int(&(cdr_data->base_amt), j);
         }
         else
            arb_numeric_from_string(&(cdr_data->base_amt), ptr);

         break;
      case to_unrounded_amount:
         if(gsField_Mapping[i].field_from_type == binary)
         {
            arb_numeric_from_int(&(cdr_data->unrounded_amount), j);
         }
         else
            arb_numeric_from_string(&(cdr_data->unrounded_amount), ptr);
         break;
      case to_foreign_amount:
         if(gsField_Mapping[i].field_from_type == binary)
         {
            arb_numeric_from_int(&(cdr_data->foreign_amount), j);
         }
         else
            arb_numeric_from_string(&(cdr_data->foreign_amount), ptr);
         break;
      case to_rate_period:
         if(gsField_Mapping[i].field_from_type != binary)
         {
            strncpy(cdr_data->rate_period, ptr, szRatePeriod);
            cdr_data->rate_period[szRatePeriod] = '\0';
         }
         else
         {
            sprintf(tmpstr,"%d",j);
            strncpy(cdr_data->rate_period, tmpstr, szRatePeriod);
            cdr_data->rate_period[szRatePeriod] = '\0';
         }
         break;
      case to_rate_dt:
         /* if time comes in as unix time save it in the trans_time field
         ** and do conversion later by using a timezone 
         */
         if(gsField_Mapping[i].field_to_type == to_int)
            cdr_data->rate_time = j;
         else
         {
            if(convert_date_string(cdr_data->rate_dt, gstrScratch1,
               gsField_Mapping[i].date_format_type) == FAILURE)
            { 
               emit(ERRLOC, MPS_BAD_FIELD,"rate_dt",cdr_data->rate_dt);
               set_cdr_error_code(cdr_data, CAP_BAD_RATETIME);
               sprintf(tmpstr,
                  "%d,%s: \"%s\"",
                  CAP_BAD_RATETIME,
                  gsField_Mapping[i].field_to_name,
                  cdr_data->rate_dt);
               emit(ERRLOC, MPS_GEN_ERROR, tmpstr );
               set_mps_error_struct(tmpstr,"");
               break;
            }
         }
         rate_dt_type = gsField_Mapping[i].field_to_type;
         break;
      case to_no_bill:
         cdr_data->no_bill = j;
         break;
      case to_comp_status:
         cdr_data->comp_status = j;
         break;
      case to_cdr_status:
         cdr_data->cdr_status = j;
         break;
      case to_external_id:
         if(gsField_Mapping[i].field_from_type != binary)
         {
            strncpy(cdr_data->external_id, ptr, size);
            cdr_data->external_id[size] = '\0';
         }
         else
         {
            sprintf(tmpstr,"%d",j);
            strncpy(cdr_data->external_id, tmpstr, size);
            cdr_data->external_id[size] = '\0';
         }
         break;
      case to_external_id_type:
         cdr_data->external_id_type = j;
         break;
      case to_account_no:
         cdr_data->account_no = j;
         break;
      case to_kp_subscr_no:
         cdr_data->kp_subscr_no = j;
         break;
      case to_kp_subscr_no_resets:
         cdr_data->kp_subscr_no_resets = j;
         break;
      case to_kp_server_id:
         cdr_data->kp_server_id = j;
         break;
      case to_ccard_account:
         if(gsField_Mapping[i].field_from_type != binary)
         {
            strncpy(cdr_data->miu_ccard_account, ptr, szCCardAcct);
            cdr_data->miu_ccard_account[szCCardAcct] = '\0';
         }
         else
         {
            sprintf(tmpstr,"%d",j);
            strncpy(cdr_data->miu_ccard_account, tmpstr, szCCardAcct);
            cdr_data->miu_ccard_account[szCCardAcct] = '\0';
         }
         break;
      case to_ccard_carrier_code:
         cdr_data->miu_ccard_carrier_code = j;
         break;
      case to_ccard_ownr_fname:
         if(gsField_Mapping[i].field_from_type != binary)
         {
            strncpy(cdr_data->miu_ccard_ownr_fname, ptr, szCCardOwnr);
            cdr_data->miu_ccard_ownr_fname[szCCardOwnr] = '\0';
         }
         else
         {
            sprintf(tmpstr,"%d",j);
            strncpy(cdr_data->miu_ccard_ownr_fname, tmpstr, szCCardOwnr);
            cdr_data->miu_ccard_ownr_fname[szCCardOwnr] = '\0';
         }
         break;
      case to_ccard_ownr_lname:
         if(gsField_Mapping[i].field_from_type != binary)
         {
            strncpy(cdr_data->miu_ccard_ownr_lname, ptr, szCCardOwnr);
            cdr_data->miu_ccard_ownr_lname[szCCardOwnr] = '\0';
         }
         else
         {
            sprintf(tmpstr,"%d",j);
            strncpy(cdr_data->miu_ccard_ownr_lname, tmpstr, szCCardOwnr);
            cdr_data->miu_ccard_ownr_lname[szCCardOwnr] = '\0';
         }
         break;
      case to_ccard_expire:
         if(gsField_Mapping[i].field_from_type != binary)
         {
            strncpy(cdr_data->miu_ccard_expire, ptr, szCCardExpire);
            cdr_data->miu_ccard_expire[szCCardExpire] = '\0';
         }
         else
         {
            sprintf(tmpstr,"%d",j);
            strncpy(cdr_data->miu_ccard_expire, tmpstr, szCCardExpire);
            cdr_data->miu_ccard_expire[szCCardExpire] = '\0';
         }
         break;
      case to_ccard_carrier:
         if(gsField_Mapping[i].field_from_type != binary)
         {
            strncpy(cdr_data->miu_ccard_carrier, ptr, szCCCarrier);
            cdr_data->miu_ccard_carrier[szCCCarrier] = '\0';
         }
         else
         {
            sprintf(tmpstr,"%d",j);
            strncpy(cdr_data->miu_ccard_carrier, tmpstr, szCCCarrier);
            cdr_data->miu_ccard_carrier[szCCCarrier] = '\0';
         }
         break;
      case to_free_flag:
         cdr_data->free_flag = j;
         break;
      case to_home_carrier_sid_bid:
         cdr_data->home_carrier_sid_bid = j;
         break;
      case to_open_item_id:
         cdr_data->open_item_id = j;
         break;
      case to_cell_name_origin:
         if(gsField_Mapping[i].field_from_type != binary)
         {
            strncpy(cdr_data->cell_name_origin, ptr, szCellName);
            cdr_data->cell_name_origin[szCellName] = '\0';
         }
         else
         {
            sprintf(tmpstr,"%d",j);
            strncpy(cdr_data->cell_name_origin, tmpstr, szCellName);
            cdr_data->cell_name_origin[szCellName] = '\0';
         }
         break;
     }
   }

   if(new_timezone)
   {
      if(timezone_lookup(cdr_data->timezone,unix_tz,&isdst) != SUCCESS)
      {
         emit(ERRLOC, CAP_BAD_USG_TIMEZONE, cdr_data->timezone);
         set_cdr_error_code(cdr_data, CAP_BAD_TIMEZONE);
         sprintf(tmpstr,"%d,Timezone:%d",CAP_BAD_TIMEZONE,cdr_data->timezone);
         emit(ERRLOC, MPS_GEN_ERROR, tmpstr );
         set_mps_error_struct(tmpstr,"");
         return(SUCCESS);
      }
      /* if we get a unix time do conversion 
      ** from int to arbor/bp date format */

      if(trans_dt_type == to_int || second_dt_type == to_int || 
         rate_dt_type == to_int)
      {
         if(mpsGetGuideTZ() == TIMEZONE_NOT_USED) 
         {
            /* convert to input usage record's timezone
            ** (already saved in cdr_data)
            */
            strcpy(usage_tz, unix_tz);
         }
         else
         {
            /* Use guiding timezone instead.
            ** NOTE: in this case, the timezone from the usage record
            **       IS DISCARDED !!
            */
            strcpy(usage_tz, mpsGetGuideTZstr());
            cdr_data->timezone = mpsGetGuideTZ();  /* int version of mpsGetGuideTZstr() */
         }

         /* ----------------------------------------------------
         ** Convert trans_dt & second_dt to appropriate timezone
         ** since we are converting a unix time_t, the "from_tz" arg
         ** of convert_timezone (arg 3) is not used.
         */

         if(trans_dt_type == to_int)
         {
            if(convert_timezone(cdr_data->trans_time, cdr_data->trans_dt, "GMT0", usage_tz)
               == FAILURE)
            {
               emit(ERRLOC, CAP_BAD_USG_TIMEZONE, cdr_data->timezone);
               set_cdr_error_code(cdr_data, CAP_BAD_TIMEZONE);
               sprintf(tmpstr,
                  "%d,Timezone:%d",
                  CAP_BAD_TIMEZONE,cdr_data->timezone);
               emit(ERRLOC, MPS_GEN_ERROR, tmpstr );
               set_mps_error_struct(tmpstr,"");
               return(SUCCESS);
            }
         }
         if(second_dt_type == to_int)
         {
            if(convert_timezone(cdr_data->second_time, cdr_data->second_dt, "GMT0", usage_tz)
               == FAILURE)
            {
               emit(ERRLOC, CAP_BAD_USG_TIMEZONE, cdr_data->timezone);
               set_cdr_error_code(cdr_data, CAP_BAD_TIMEZONE);
               sprintf(tmpstr,
                  "%d,Timezone:%d",
                  CAP_BAD_TIMEZONE,cdr_data->timezone);
               emit(ERRLOC, MPS_GEN_ERROR, tmpstr );
               set_mps_error_struct(tmpstr,"");
               return(SUCCESS);
            }
         }
         if(rate_dt_type == to_int)
         {
            if(convert_timezone(cdr_data->rate_time, cdr_data->rate_dt, "GMT0", usage_tz)
               == FAILURE)
            {
               emit(ERRLOC, CAP_BAD_USG_TIMEZONE, cdr_data->timezone);
               set_cdr_error_code(cdr_data, CAP_BAD_TIMEZONE);
               sprintf(tmpstr,
                  "%d,Timezone:%d",
                  CAP_BAD_TIMEZONE,cdr_data->timezone);
               emit(ERRLOC, MPS_GEN_ERROR, tmpstr );
               set_mps_error_struct(tmpstr,"");
               return(SUCCESS);
            }
         }
      }
   }
   else
   {
      /* no timezone provided, get the default time zone later */
      if(trans_dt_type == to_int || second_dt_type == to_int ||
         rate_dt_type == to_int)
      {
         if(mpsGetGuideTZ() == TIMEZONE_NOT_USED)
         {
            /* no default set, do not know what to convert to, hard error */
            emit(ERRLOC,CAP_NO_TIMEZONE);
            sprintf(tmpstr,
               "%d,No timezone",
               CAP_NO_TIMEZONE);
            emit(ERRLOC,MPS_GEN_ERROR, tmpstr );
            set_mps_error_struct(tmpstr,"");
            return(SUCCESS);
         }
         else
         {
            /* Use guiding timezone */
            strcpy(usage_tz, mpsGetGuideTZstr());
            cdr_data->timezone = mpsGetGuideTZ();  /* int version of mpsGetGuideTZstr() */

            /* ----------------------------------------------------
            ** Convert trans_dt & second_dt to appropriate timezone
            */

            if(trans_dt_type == to_int)
            {
               if(convert_timezone(cdr_data->trans_time, cdr_data->trans_dt,
                  "GMT0", usage_tz) == FAILURE)
               {
                  emit(ERRLOC, CAP_BAD_USG_TIMEZONE, cdr_data->timezone);
                  set_cdr_error_code(cdr_data, CAP_BAD_TIMEZONE);
                  sprintf(tmpstr,
                     "%d,Timezone:%d",
                     CAP_BAD_TIMEZONE,cdr_data->timezone);
                  emit(ERRLOC,MPS_GEN_ERROR, tmpstr );
                  set_mps_error_struct(tmpstr,"");
                  return(SUCCESS);
               }
            }
            if(second_dt_type == to_int)
            {
               if(convert_timezone(cdr_data->second_time, cdr_data->second_dt,
                  "GMT0", usage_tz) == FAILURE)
               {
                  emit(ERRLOC, CAP_BAD_USG_TIMEZONE, cdr_data->timezone);
                  set_cdr_error_code(cdr_data, CAP_BAD_TIMEZONE);
                  sprintf(tmpstr,
                     "%d,Timezone:%d",
                     CAP_BAD_TIMEZONE,cdr_data->timezone);
                  emit(ERRLOC,MPS_GEN_ERROR, tmpstr );
                  set_mps_error_struct(tmpstr,"");
                  return(SUCCESS);
               }
            }
            if(rate_dt_type == to_int)
            {
               if(convert_timezone(cdr_data->rate_time, cdr_data->rate_dt,
                  "GMT0", usage_tz) == FAILURE)
               {
                  emit(ERRLOC, CAP_BAD_USG_TIMEZONE, cdr_data->timezone);
                  set_cdr_error_code(cdr_data, CAP_BAD_TIMEZONE);
                  sprintf(tmpstr,
                     "%d,Timezone:%d",
                     CAP_BAD_TIMEZONE,cdr_data->timezone);
                  emit(ERRLOC,MPS_GEN_ERROR, tmpstr );
                  set_mps_error_struct(tmpstr,"");
                  return(SUCCESS);
               }
            }
         }
      }
   }
   return(SUCCESS);

} /* ProcessUsgDetail() */