
(********************************************************************)
(*                                                                  *)
(*  s7c.sd7       Seed7 compiler - Compiles Seed7 to C              *)
(*  Copyright (C) 1990 - 1994, 2004 - 2014  Thomas Mertes           *)
(*                                                                  *)
(*  This program is free software; you can redistribute it and/or   *)
(*  modify it under the terms of the GNU General Public License as  *)
(*  published by the Free Software Foundation; either version 2 of  *)
(*  the License, or (at your option) any later version.             *)
(*                                                                  *)
(*  This program is distributed in the hope that it will be useful, *)
(*  but WITHOUT ANY WARRANTY; without even the implied warranty of  *)
(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   *)
(*  GNU General Public License for more details.                    *)
(*                                                                  *)
(*  You should have received a copy of the GNU General Public       *)
(*  License along with this program; if not, write to the           *)
(*  Free Software Foundation, Inc., 51 Franklin Street,             *)
(*  Fifth Floor, Boston, MA  02110-1301, USA.                       *)
(*                                                                  *)
(********************************************************************)


$ message "Compiling the compiler ...";
$ include "seed7_05.s7i";
  include "stdio.s7i";
  include "osfiles.s7i";
  include "scanstri.s7i";
  include "unicode.s7i";
  include "bigint.s7i";
  include "float.s7i";
  include "keybd.s7i";
  include "progs.s7i";
  include "shell.s7i";
  include "cc_conf.s7i";

const string: temp_marker is "/* Seed7 compiler temp file */";

const integer: MAX_SHOWN_BIGINT_LITERAL_BITLENGTH is 256;
const integer: MAX_SHOWN_STRI_LITERAL_LENGTH is 256;

const bigInteger: INTTYPE_MAX is 2_ ** pred(ccConf.INTTYPE_SIZE) - 1_;

const type: option_hash is hash [string] string;

var option_hash: compiler_option is option_hash.value;
var boolean: compileLibrary is FALSE;

var array string: libraryDirs is 0 times "";

var boolean: array_range_check      is TRUE;
var boolean: conversion_range_check is TRUE;
var boolean: integer_shift_check    is FALSE;
var boolean: source_debug_info      is TRUE;
var boolean: trace_exception        is FALSE;
var boolean: trace_signal           is TRUE;
var boolean: signal_exception       is FALSE;
var integer: evaluate_const_expr    is 1;
var boolean: inlineFunctions        is TRUE;
var boolean: declare_with_extern_c  is FALSE;
var boolean: generate_c_plus_plus   is FALSE;

var boolean: consoleLibraryUsed  is FALSE;
var boolean: drawLibraryUsed     is FALSE;
var boolean: compilerLibraryUsed is FALSE;
var boolean: compDataLibraryUsed is FALSE;

var integer: countOptimizations is 0;
var integer: countEvaluations   is 0;

var program: prog is program.EMPTY;
var reference: main_object is NIL;
var file: c_prog is STD_NULL;

# Category values only used in the Compiler:
const category: BOOLOBJECT        is category conv 256;
const category: ENUMOBJECT        is category conv 257;
const category: VOIDOBJECT        is category conv 258;

# Type variables which hold types from the program being compiled
var type: proctype is void;
var type: voidtype is void;
var type: fileInterfaceType is void;

var ref_list: declared_types is ref_list.EMPTY;

const type: expr_type is new struct
    var string: currentFile is "";
    var integer: currentLine is 0;
    var integer: temp_num is 0;
    var string: temp_decls is "";
    var string: temp_assigns is "";
    var string: expr is "";
    var string: temp_frees is "";
    var string: temp_to_null is "";
    var string: result_temp is "";
    var string: result_decl is "";
    var string: result_free is "";
    var string: result_to_null is "";
    var string: result_intro is "";
    var string: result_expr is "";
    var string: result_finish is "";
  end struct;

var expr_type: global_c_expr is expr_type.value;

var integer: countDeclarations is 0;
var expr_type: global_init is expr_type.value;

const type: bigint_table_hash is hash [bigInteger] integer;
const type: bigint_index_hash is hash [integer] array bigInteger;

var bigint_table_hash: bigint_const_table is bigint_table_hash.EMPTY_HASH;

const type: stri_table_hash is hash [string] integer;
const type: stri_index_hash is hash [integer] array string;

var stri_table_hash: stri_const_table is stri_table_hash.EMPTY_HASH;

const type: bstri_table_hash is hash [bstring] integer;
const type: bstri_index_hash is hash [integer] array bstring;

var bstri_table_hash: bstri_const_table is bstri_table_hash.EMPTY_HASH;

const type: set_table_hash is hash [bitset] integer;
const type: set_index_hash is hash [integer] array bitset;

var set_table_hash: set_const_table is set_table_hash.EMPTY_HASH;

const type: type_table_hash is hash [type] integer;
const type: type_index_hash is hash [integer] array type;

var type_table_hash: type_const_table is type_table_hash.EMPTY_HASH;

const type: win_table_hash is hash [PRIMITIVE_WINDOW] integer;
const type: win_index_hash is hash [integer] array PRIMITIVE_WINDOW;
const type: win_bstri_hash is hash [integer] integer;

var win_table_hash: win_const_table is win_table_hash.EMPTY_HASH;
var win_bstri_hash: win_bstri_table is win_bstri_hash.EMPTY_HASH;

const type: const_table_hash is hash [reference] integer;
const type: const_index_hash is hash [integer] array reference;

var const_table_hash: const_table is const_table_hash.EMPTY_HASH;

const type: globalInitHash is hash [reference] string;

var globalInitHash: globalInitalisations is globalInitHash.EMPTY_HASH;

const type: typeCategoryHash is hash [type] category;
const type: type_hash is hash [type] type;
const type: element_number_hash is hash [reference] integer;
const type: number_element_hash is hash [integer] array reference;
const type: element_type_hash is hash [reference] type;
const type: struct_elements_hash is hash [type] element_number_hash;
const type: struct_element_type_hash is hash [type] element_type_hash;
const type: boolean_type_hash is hash [type] boolean;
const type: boolean_obj_hash is hash [reference] boolean;
const type: implements_hash is hash [type] array type;
const type: interface_hash is hash [type] array type;
const type: enum_literal_hash is hash [type] element_number_hash;
const type: string_type_hash is hash [type] string;
const type: act_to_form_param_hash is hash [reference] reference;
const type: params_added_hash is hash [reference] act_to_form_param_hash;
const type: setOfCategory is set of category;
const type: inline_param_value_hash is hash [reference] ref_list;
const type: inline_param_hash is hash [reference] array integer;
const type: funcparam_data_hash is hash [reference] string;
const type: element_repeat_count_hash is hash [reference] integer;
const type: typeReferenceHash is hash [type] reference;
const type: stringLengthHash is hash [integer] integer;
const type: lengthToStriNumHash is hash [integer] array integer;

var typeCategoryHash: typeCategory is typeCategoryHash.EMPTY_HASH;
var type_hash: array_element is type_hash.EMPTY_HASH;
var type_hash: array_type is type_hash.EMPTY_HASH;
var struct_elements_hash: struct_elements is struct_elements_hash.EMPTY_HASH;
var struct_element_type_hash: struct_element_type is struct_element_type_hash.EMPTY_HASH;
var boolean_type_hash: create_declared is boolean_type_hash.EMPTY_HASH;
var boolean_type_hash: destr_declared is boolean_type_hash.EMPTY_HASH;
var boolean_type_hash: cpy_declared is boolean_type_hash.EMPTY_HASH;
var boolean_type_hash: generic_cpy_declared is boolean_type_hash.EMPTY_HASH;
var boolean_type_hash: generic_create_declared is boolean_type_hash.EMPTY_HASH;
var boolean_type_hash: generic_destr_declared is boolean_type_hash.EMPTY_HASH;
var boolean_type_hash: generic_cmp_declared is boolean_type_hash.EMPTY_HASH;
var boolean_type_hash: create_prototype_declared is boolean_type_hash.EMPTY_HASH;
var boolean_type_hash: destr_prototype_declared is boolean_type_hash.EMPTY_HASH;
var boolean_obj_hash: prototype_declared is boolean_obj_hash.EMPTY_HASH;
var boolean_obj_hash: return_ref_to_value is boolean_obj_hash.EMPTY_HASH;
var boolean_obj_hash: function_declared is boolean_obj_hash.EMPTY_HASH;
var boolean_obj_hash: function_pointer_declared is boolean_obj_hash.EMPTY_HASH;
var ref_list: dynamic_functions is ref_list.EMPTY;
var implements_hash: implements is implements_hash.EMPTY_HASH;
var interface_hash: interfaceOfType is interface_hash.EMPTY_HASH;
var string_type_hash: parametersOfHshCreate is string_type_hash.EMPTY_HASH;
var string_type_hash: parametersOfHshDestr is string_type_hash.EMPTY_HASH;
var string_type_hash: parametersOfHshCpy is string_type_hash.EMPTY_HASH;
var enum_literal_hash: enum_literal is enum_literal_hash.EMPTY_HASH;
var params_added_hash: params_added is params_added_hash.EMPTY_HASH;
var inline_param_value_hash: inline_param_value is inline_param_value_hash.EMPTY_HASH;
var inline_param_hash: inline_param is inline_param_hash.EMPTY_HASH;
var funcparam_data_hash: funcparam_data is funcparam_data_hash.EMPTY_HASH;
var funcparam_data_hash: funcparam_reference is funcparam_data_hash.EMPTY_HASH;
var element_repeat_count_hash: element_repeat_count is element_repeat_count_hash.EMPTY_HASH;
var typeReferenceHash: createFunction is typeReferenceHash.EMPTY_HASH;
var typeReferenceHash: destrFunction is typeReferenceHash.EMPTY_HASH;
var typeReferenceHash: copyFunction is typeReferenceHash.EMPTY_HASH;

var boolean: write_object_declaration is TRUE;


const proc: process_action (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is forward;
const proc: process_expr (in reference: current_expression, inout expr_type: c_expr) is forward;


const proc: count_declarations is func

  begin
    incr(countDeclarations);
    write(OUT, countDeclarations);
    write(OUT, "\r");
    flush(OUT);
  end func;


const func boolean: isByteString (in string: stri) is func

  result
    var boolean: isByteString is TRUE;
  local
    var char: ch is ' ';
  begin
    for ch range stri do
      if ord(ch) > 255 then
        isByteString := FALSE;
      end if;
    end for;
  end func;


const func string: sourceNameString (in string: sourceName) is func

  result
    var string: stri is "";
  begin
    if ccConf.CC_SOURCE_UTF8 or not isByteString(sourceName) then
      stri := c_literal(striToUtf8(toOsPath(sourceName)));
    else
      stri := c_literal(toOsPath(sourceName));
    end if;
  end func;


const func string: noDiagnosticLine is func

  result
    var string: diagnosticLine is "";
  begin
    if source_debug_info then
      diagnosticLine &:= "#line 1 \"no_file\"\n";
    else
      diagnosticLine &:= "/* line 1 \"no_file\" */\n";
    end if;
  end func;


const func string: diagnosticLine (in reference: current_object) is func

  result
    var string: diagnosticLine is "";
  begin
    if source_debug_info and line(current_object) <> 0 then
      diagnosticLine &:= "#line ";
      diagnosticLine &:= str(line(current_object));
      diagnosticLine &:= " ";
      diagnosticLine &:= sourceNameString(file(current_object));
      diagnosticLine &:= "\n";
    else
      diagnosticLine &:= "/* line ";
      diagnosticLine &:= str(line(current_object));
      diagnosticLine &:= " ";
      diagnosticLine &:= sourceNameString(file(current_object));
      diagnosticLine &:= " */\n";
    end if;
  end func;


const proc: setDiagnosticLine (inout expr_type: c_expr) is func

  begin
    if source_debug_info and c_expr.currentLine <> 0 then
      c_expr.expr &:= "#line ";
      c_expr.expr &:= str(c_expr.currentLine);
      c_expr.expr &:= " ";
      c_expr.expr &:= sourceNameString(c_expr.currentFile);
      c_expr.expr &:= "\n";
    else
      c_expr.expr &:= "/* line ";
      c_expr.expr &:= str(c_expr.currentLine);
      c_expr.expr &:= " ";
      c_expr.expr &:= sourceNameString(c_expr.currentFile);
      c_expr.expr &:= " */\n";
    end if;
  end func;


const proc: AppendWithDiagnostic (in string: decls, inout expr_type: c_expr) is func

  local
    var string: line is "";
  begin
    for line range split(decls, '\n') do
      if line <> "" then
        setDiagnosticLine(c_expr);
        c_expr.expr &:= line;
        c_expr.expr &:= "\n";
      end if;
    end for;
  end func;


const proc: create_name (in reference: current_object, inout string: expr) is func

  local
    var string: raw_name is "";
    var string: name is "";
  begin
    raw_name := str(current_object);
    name := getName(raw_name);
    expr &:= str(objNumber(current_object));
    if name <> "" then
      expr &:= "_";
      expr &:= name;
    end if;
    if raw_name <> "" then
      expr &:= "/*";
      expr &:= raw_name;
      expr &:= "*/";
    end if;
  end func;


const proc: create_name2 (in reference: current_object, inout string: expr) is func

  local
    var string: raw_name is "";
    var string: name is "";
  begin
    raw_name := str(current_object);
    name := getName(raw_name);
    expr &:= str(objNumber(current_object));
    if name <> "" then
      expr &:= "_";
      expr &:= name;
    end if;
    if raw_name <> "" then
      expr &:= "/ ";
      expr &:= raw_name;
    end if;
  end func;


const proc: create_name (in reference: current_object, in integer: object_number,
    inout string: expr) is func

  local
    var string: raw_name is "";
    var string: name is "";
  begin
    raw_name := str(current_object);
    name := getName(raw_name);
    expr &:= str(object_number);
    if name <> "" then
      expr &:= "_";
      expr &:= name;
    end if;
    if raw_name <> "" then
      expr &:= "/*";
      expr &:= raw_name;
      expr &:= "*/";
    end if;
  end func;


const func string: raw_type_name (in type: object_type) is func

  result
    var string: typeName is "";
  begin
    if object_type in typeCategory then
      case typeCategory[object_type] of
        when {VOIDOBJECT}:      typeName := "void";
        when {BOOLOBJECT}:      typeName := "booltype";
        when {ENUMOBJECT}:      typeName := "enumtype";
        when {INTOBJECT}:       typeName := "inttype";
        when {BIGINTOBJECT}:    typeName := "biginttype";
        when {FLOATOBJECT}:     typeName := "floattype";
        when {CHAROBJECT}:      typeName := "chartype";
        when {STRIOBJECT}:      typeName := "stritype";
        when {BSTRIOBJECT}:     typeName := "bstritype";
        when {FILEOBJECT}:      typeName := "filetype";
        when {SOCKETOBJECT}:    typeName := "sockettype";
        when {POLLOBJECT}:      typeName := "polltype";
        when {SETOBJECT}:       typeName := "settype";
        when {WINOBJECT}:       typeName := "wintype";
        when {PROGOBJECT}:      typeName := "progtype";
        when {ARRAYOBJECT}:     typeName := "arraytype";
        when {HASHOBJECT}:      typeName := "hashtype";
        when {STRUCTOBJECT}:    typeName := "structtype";
        when {INTERFACEOBJECT}: typeName := "interfacetype";
        when {REFOBJECT}:       typeName := "objreftype";
        when {REFLISTOBJECT}:   typeName := "listtype";
        when {TYPEOBJECT}:      typeName := "typetype";
        when {ACTOBJECT}:       typeName := "acttype";
        otherwise:
          typeName := "t_";
          typeName &:= str(typeNumber(object_type));
      end case;
    else
      typeName := "t_";
      typeName &:= str(typeNumber(object_type));
    end if;
  end func;


const func string: type_name (in type: object_type) is func

  result
    var string: typeName is "";
  begin
    typeName := raw_type_name(object_type);
    typeName &:= "/*t_";
    typeName &:= str(typeNumber(object_type));
    typeName &:= "_";
    typeName &:= str(object_type);
    typeName &:= "*/";
  end func;


const func string: type_name2 (in type: object_type) is func

  result
    var string: typeName is "";
  begin
    typeName := raw_type_name(object_type);
    typeName &:= "/t_";
    typeName &:= str(typeNumber(object_type));
    typeName &:= "_";
    typeName &:= str(object_type);
  end func;


const func type: base_type (in type: array_type) is func

  result
    var type: baseType is void;
  local
    var ref_list: param_list is ref_list.EMPTY;
    var reference: matched_object is NIL;
  begin
    param_list := make_list(typeObject(array_type));
    param_list &:= make_list(syobject(prog, "base_type"));
    matched_object := match(prog, param_list);
    if matched_object <> NIL and category(matched_object) = TYPEOBJECT then
      baseType := getValue(matched_object, type);
    end if;
  end func;


const proc: defineVarFuncType (in type: functionType, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "typedef struct {\n";
    c_expr.expr &:= type_name(resultType(functionType));
    c_expr.expr &:= " (*func) (void *);\n";
    c_expr.expr &:= "struct {\n";
    c_expr.expr &:= "int dummy;\n";
    c_expr.expr &:= "} data;\n";
    c_expr.expr &:= "} struct_";
    c_expr.expr &:= type_name(functionType);
    c_expr.expr &:= ", *";
    c_expr.expr &:= type_name(functionType);
    c_expr.expr &:= ";\n\n";
  end func;


const proc: declare_type_if_necessary (in type: aType, inout expr_type: c_expr) is func

  local
    var reference: type_obj is NIL;
    var type: metaType is void;
    var type: baseType is void;
  begin
    type_obj := typeObject(aType);
    if not type_obj in declared_types then
      if aType not in typeCategory then
        if isDerived(aType) then
          metaType := meta(aType);
          if metaType in typeCategory then
            typeCategory @:= [aType] typeCategory[metaType];
          else
            c_expr.expr &:= "typedef generictype ";
            c_expr.expr &:= type_name(aType);
            c_expr.expr &:= ";\n\n";
          end if;
          if metaType in array_element then
            baseType := base_type(metaType);
            if baseType <> void then
              if aType not in array_element then
                array_element @:= [aType] baseType;
              end if;
              if baseType not in array_type then
                array_type @:= [baseType] aType;
              end if;
            end if;
          end if;
        elsif isFunc(aType) then
          declare_type_if_necessary(resultType(aType), c_expr);
          defineVarFuncType(aType, c_expr);
          typeCategory @:= [aType] BLOCKOBJECT;
        else
          c_expr.expr &:= "typedef generictype ";
          c_expr.expr &:= type_name(aType);
          c_expr.expr &:= ";\n\n";
        end if;
        incl(declared_types, type_obj);
      # else
      #   writeln(type_name2(aType) & " in typeCategory " & str(typeCategory[aType]));
      #   c_expr.expr &:= "/* " & type_name2(aType) & " in typeCategory " & str(typeCategory[aType]) & " */\n";
      end if;
    # else
    #   c_expr.expr &:= "/* " & type_name2(aType) & " in declared_types */\n";
    end if;
  end func;


const func type: getExprResultType (in reference: aReference) is func

  result
    var type: resultType is void;
  begin
    resultType := getType(aReference);
    while isFunc(resultType) or isVarfunc(resultType) do
      resultType := resultType(resultType);
    end while;
  end func;


const func string: raw_type_value (in type: object_type) is func

  result
    var string: valueName is "";
  begin
    if object_type in typeCategory then
      case typeCategory[object_type] of
        when {BOOLOBJECT}:      valueName := "boolvalue";
        when {ENUMOBJECT}:      valueName := "enumvalue";
        when {INTOBJECT}:       valueName := "intvalue";
        when {BIGINTOBJECT}:    valueName := "bigintvalue";
        when {FLOATOBJECT}:     valueName := "floatvalue";
        when {CHAROBJECT}:      valueName := "charvalue";
        when {STRIOBJECT}:      valueName := "strivalue";
        when {BSTRIOBJECT}:     valueName := "bstrivalue";
        when {FILEOBJECT}:      valueName := "filevalue";
        when {SOCKETOBJECT}:    valueName := "socketvalue";
        when {POLLOBJECT}:      valueName := "pollvalue";
        when {SETOBJECT}:       valueName := "setvalue";
        when {WINOBJECT}:       valueName := "winvalue";
        when {PROGOBJECT}:      valueName := "progvalue";
        when {ARRAYOBJECT}:     valueName := "arrayvalue";
        when {HASHOBJECT}:      valueName := "hashvalue";
        when {STRUCTOBJECT}:    valueName := "structvalue";
        when {INTERFACEOBJECT}: valueName := "interfacevalue";
        when {REFOBJECT}:       valueName := "objrefvalue";
        when {REFLISTOBJECT}:   valueName := "listvalue";
        when {TYPEOBJECT}:      valueName := "typevalue";
        when {ACTOBJECT}:       valueName := "actvalue";
        otherwise:              valueName := "genericvalue";
       end case;
    else
      valueName := "genericvalue";
    end if;
  end func;


const func string: select_value_from_rtlObjectstruct (in type: typeWanted) is
  return ".value." & raw_type_value(typeWanted);


const func string: select_value_from_rtlObjectptr (in type: typeWanted) is
  return "->value." & raw_type_value(typeWanted);


const func boolean: valueIsAtHeap (in type: aType) is func

  result
    var boolean: isAtHeap is FALSE;
  local
    const set of category: heapCategories is {
        BIGINTOBJECT, STRIOBJECT, BSTRIOBJECT, WINOBJECT, PROGOBJECT,
        ARRAYOBJECT, STRUCTOBJECT, SETOBJECT, HASHOBJECT, INTERFACEOBJECT};
  begin
    if aType in typeCategory and typeCategory[aType] in heapCategories then
      isAtHeap := TRUE;
    end if;
  end func;


const func boolean: valueIsAtHeap (in reference: a_param) is
  return valueIsAtHeap(getType(a_param));


const func boolean: useConstPrefix (in type: aType) is func

  result
    var boolean: useConstPrefix is FALSE;
  local
    const set of category: constPrefixCategories is {
        BIGINTOBJECT, STRIOBJECT, PROGOBJECT,
        ARRAYOBJECT, SETOBJECT, HASHOBJECT};
  begin
    if aType in typeCategory and typeCategory[aType] in constPrefixCategories then
      useConstPrefix := TRUE;
    end if;
  end func;


const func boolean: useConstPrefix (in reference: a_param) is
  return useConstPrefix(getType(a_param));


const func boolean: isNormalVariable (in reference: a_param) is
  return category(a_param) in {TYPEOBJECT, INTOBJECT, BIGINTOBJECT,
      CHAROBJECT, STRIOBJECT, BSTRIOBJECT, ARRAYOBJECT, HASHOBJECT,
      STRUCTOBJECT, INTERFACEOBJECT, SETOBJECT, FILEOBJECT,
      SOCKETOBJECT, POLLOBJECT, LISTOBJECT, FLOATOBJECT, WINOBJECT,
      REFOBJECT, REFLISTOBJECT, ACTOBJECT, VALUEPARAMOBJECT,
      REFPARAMOBJECT, RESULTOBJECT, LOCALVOBJECT, PROGOBJECT};


const func string: raiseError (in string: exceptionName) is func

  result
    var string: expr is "";
  begin
    expr &:= "int_raise_error(";
    expr &:= exceptionName;
    expr &:= ", __FILE__, __LINE__)";
  end func;


const proc: process_raise_error (in string: exceptionName, in reference: function, inout expr_type: c_expr) is func

  begin
    if function <> NIL then
      c_expr.expr &:= "int_raise_error(";
      c_expr.expr &:= exceptionName;
      c_expr.expr &:= ", ";
      c_expr.expr &:= sourceNameString(file(function));
      c_expr.expr &:= ", ";
      c_expr.expr &:= str(line(function));
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= raiseError(exceptionName);
    end if;
  end func;


const func string: stringInComment (in string: stri) is func

  result
    var string: expr is "";
  begin
    if length(stri) <= MAX_SHOWN_STRI_LITERAL_LENGTH then
      expr &:= " /* ";
      expr &:= replace(literal(stri), "*/", "*\\/");
      expr &:= " */";
    end if;
  end func;


const func string: stringLiteral (in string: stri) is func

  result
    var string: expr is "";
  begin
    if stri not in stri_const_table then
      stri_const_table @:= [stri] length(stri_const_table);
    end if;
    if ccConf.ALLOW_STRITYPE_SLICES then
      expr := "&";
    end if;
    expr &:= "str[";
    expr &:= str(stri_const_table[stri]);
    expr &:= "]";
    expr &:= stringInComment(stri);
  end func;


const func string: charLiteral (in char: ch) is
  return "(chartype) " & c_literal(ch);


const func string: integerLiteral (in integer: number) is func

  result
    var string: expr is "";
  begin
    if ccConf.INTTYPE_SIZE = 64 and ccConf.INTTYPE_LITERAL_SUFFIX = "" then
      if number < 0 then
        expr := "-(inttype) ";
        expr &:= str(-number);
      else
        expr := "(inttype) ";
        expr &:= str(number);
      end if;
    else
      expr := str(number);
      expr &:= ccConf.INTTYPE_LITERAL_SUFFIX;
    end if;
  end func;


const func string: bigIntegerLiteral (in bigInteger: number) is func

  result
    var string: expr is "";
  begin
    if number not in bigint_const_table then
      bigint_const_table @:= [number] length(bigint_const_table);
    end if;
    expr := "big[";
    expr &:= str(bigint_const_table[number]);
    expr &:= "]";
    if bitLength(number) <= MAX_SHOWN_BIGINT_LITERAL_BITLENGTH then
      expr &:= " /* ";
      expr &:= str(number);
      expr &:= " */";
    end if;
  end func;


const func string: bitsetLiteral (in bitset: aBitset) is func

  result
    var string: expr is "";
  begin
    if aBitset not in set_const_table then
      set_const_table @:= [aBitset] length(set_const_table);
    end if;
    expr := "set[";
    expr &:= str(set_const_table[aBitset]);
    expr &:= "]";
  end func;


const func string: floatLiteral (in float: aFloat) is func

  result
    var string: expr is "";
  begin
    if isNaN(aFloat) then
      expr := "NOT_A_NUMBER";
    elsif aFloat = Infinity then
      expr := "POSITIVE_INFINITY";
    elsif aFloat = -Infinity then
      expr := "NEGATIVE_INFINITY";
    elsif isNegativeZero(aFloat) then
      expr := "negativeZero";
    else
      expr := str(aFloat);
    end if;
  end func;


const func string: bstriLiteral (in bstring: bstri) is func

  result
    var string: expr is "";
  begin
    if bstri not in bstri_const_table then
      bstri_const_table @:= [bstri] length(bstri_const_table);
    end if;
    expr := "bst[";
    expr &:= str(bstri_const_table[bstri]);
    expr &:= "]";
  end func;


const func string: typeLiteral (in type: aType) is func

  result
    var string: expr is "";
  begin
    if aType not in type_const_table then
      type_const_table @:= [aType] length(type_const_table);
    end if;
    expr := "typ[";
    expr &:= str(type_const_table[aType]);
    expr &:= "] /* ";
    expr &:= type_name2(aType);
    expr &:= " */";
  end func;


const func string: windowLiteral (in PRIMITIVE_WINDOW: aWindow) is func

  result
    var string: expr is "";
  begin
    if aWindow = PRIMITIVE_WINDOW.value then
      expr := "(wintype) NULL";
    else
      if aWindow not in win_const_table then
        win_const_table @:= [aWindow] length(win_const_table);
      end if;
      expr := "win[";
      expr &:= str(win_const_table[aWindow]);
      expr &:= "]";
    end if;
  end func;


const func integer: bitset_pos (in integer: number) is
  return number >> log2(ccConf.INTTYPE_SIZE);


const func string: bitsetElemAsHex (in bitset: set1, in integer: start_num) is func

  result
    var string: hex_num is "";
  local
    var integer: hex_digit_num is 0;
    var integer: bit_num is 0;
    var integer: hex_digit is 0;
  begin
    for hex_digit_num range 0 to pred(ccConf.INTTYPE_SIZE div 4) do
      hex_digit := 0;
      for bit_num range 0 to 3 do
        if start_num + hex_digit_num * 4 + bit_num in set1 then
          hex_digit +:= 2 ** bit_num;
        end if;
      end for;
      hex_num := hex_digit radix 16 <& hex_num;
    end for;
    hex_num := "0x" & hex_num;
  end func;


const proc: doRshift (in string: number_name, in string: rshift_name,
    inout expr_type: c_expr) is func

  begin
    (* Formula used: a<0?~(~a>>b):a>>b *)
    c_expr.expr &:= number_name;
    c_expr.expr &:= "<0?~(~";
    c_expr.expr &:= number_name;
    c_expr.expr &:= " >> ";
    c_expr.expr &:= rshift_name;
    c_expr.expr &:= "):";
    c_expr.expr &:= number_name;
    c_expr.expr &:= " >> ";
    c_expr.expr &:= rshift_name;
  end func;


const proc: process_create_declaration (in type: object_type,
    inout expr_type: c_expr) is forward;


const proc: process_create_call (in type: object_type,
    in string: param_b, inout string: expr) is forward;


const proc: process_arr_create_declaration (in type: object_type,
    inout expr_type: c_expr) is func

  local
    var string: diagnosticLine is "";
    var string: select_value is "";
  begin
    if object_type in createFunction then
      diagnosticLine := diagnosticLine(createFunction[object_type]);
    end if;
    select_value := select_value_from_rtlObjectstruct(array_element[object_type]);
    process_create_declaration(array_element[object_type], c_expr);
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "static ";
    c_expr.expr &:= type_name(object_type);
    c_expr.expr &:= " create_";
    c_expr.expr &:= str(typeNumber(object_type));
    c_expr.expr &:= " (const_";
    c_expr.expr &:= type_name(object_type);
    c_expr.expr &:= " b)\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "{\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= type_name(object_type);
    c_expr.expr &:= " a;\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "memsizetype i;\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "memsizetype size = (uinttype)(b->max_position - b->min_position + 1);\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "a=(";
    c_expr.expr &:= type_name(object_type);
    c_expr.expr &:= ")(arrMalloc(b->min_position, b->max_position));\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "for (i = 0; i < size; i++) {\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "a->arr[i]";
    c_expr.expr &:= select_value;
    c_expr.expr &:= "=";
    process_create_call(array_element[object_type],
        "b->arr[i]" & select_value, c_expr.expr);
    c_expr.expr &:= ";\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "}\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "return a;\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "}\n";
    c_expr.expr &:= noDiagnosticLine;
    c_expr.expr &:= "\n";
    create_declared @:= [object_type] TRUE;
  end func;


const proc: process_sct_create_declaration (in type: object_type,
    inout expr_type: c_expr) is func

  local
    var string: diagnosticLine is "";
    var number_element_hash: elements is number_element_hash.EMPTY_HASH;
    var integer: number is 0;
    var reference: struct_elem is NIL;
    var string: select_value is "";
  begin
    if object_type in createFunction then
      diagnosticLine := diagnosticLine(createFunction[object_type]);
    end if;
    if object_type in struct_elements then
      elements := flip(struct_elements[object_type]);
    end if;
    for number range 0 to pred(length(elements)) do
      struct_elem := elements[number][1];
      process_create_declaration(struct_element_type[object_type][struct_elem], c_expr);
    end for;
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "static ";
    c_expr.expr &:= type_name(object_type);
    c_expr.expr &:= " create_";
    c_expr.expr &:= str(typeNumber(object_type));
    c_expr.expr &:= " (const_";
    c_expr.expr &:= type_name(object_type);
    c_expr.expr &:= " b)\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "{\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= type_name(object_type);
    c_expr.expr &:= " a;\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "a=(";
    c_expr.expr &:= type_name(object_type);
    c_expr.expr &:= ")(malloc(sizeof(struct rtlStructstruct) - sizeof(rtlObjecttype) + \n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "  ";
    c_expr.expr &:= str(length(elements));
    c_expr.expr &:= " * sizeof(rtlObjecttype)));\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "if (a == NULL) {\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "raise_error(MEMORY_ERROR);\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "} else {\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "a->usage_count = 1;\n";
    c_expr.expr &:= "a->type_num = b->type_num;\n";
    for number range 0 to pred(length(elements)) do
      c_expr.expr &:= diagnosticLine;
      struct_elem := elements[number][1];
      select_value := select_value_from_rtlObjectstruct(struct_element_type[object_type][struct_elem]);
      c_expr.expr &:= "a->stru[" & str(number) & "]" & select_value & "=";
      process_create_call(struct_element_type[object_type][struct_elem],
          "b->stru[" & str(number) & "]" & select_value, c_expr.expr);
      c_expr.expr &:= ";\n";
    end for;
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "}\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "return a;\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "}\n";
    c_expr.expr &:= noDiagnosticLine;
    c_expr.expr &:= "\n";
    create_declared @:= [object_type] TRUE;
  end func;


const proc: process_hsh_create_declaration (in type: object_type,
    inout expr_type: c_expr) is func

  local
    var string: diagnosticLine is "";
  begin
    if object_type in createFunction then
      diagnosticLine := diagnosticLine(createFunction[object_type]);
    end if;
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "static ";
    c_expr.expr &:= type_name(object_type);
    c_expr.expr &:= " create_";
    c_expr.expr &:= str(typeNumber(object_type));
    c_expr.expr &:= " (const_";
    c_expr.expr &:= type_name(object_type);
    c_expr.expr &:= " b)\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "{\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "return hshCreate(b";
    c_expr.expr &:= parametersOfHshCreate[object_type];
    c_expr.expr &:= ");\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "}\n";
    c_expr.expr &:= noDiagnosticLine;
    c_expr.expr &:= "\n";
    create_declared @:= [object_type] TRUE;
  end func;


const proc: declare_create_prototype (in type: object_type,
    inout expr_type: c_expr) is func

  begin
    if object_type not in create_prototype_declared then
      declare_type_if_necessary(object_type, c_expr);
      c_expr.expr &:= "static ";
      c_expr.expr &:= type_name(object_type);
      c_expr.expr &:= " create_";
      c_expr.expr &:= str(typeNumber(object_type));
      c_expr.expr &:= " (const_";
      c_expr.expr &:= type_name(object_type);
      c_expr.expr &:= ");\n\n";
      create_prototype_declared @:= [object_type] TRUE;
    end if;
  end func;


const proc: process_create_declaration (in type: object_type,
    inout expr_type: c_expr) is func

  begin
    if object_type not in create_declared then
      if object_type in typeCategory then
        case typeCategory[object_type] of
          when {ARRAYOBJECT}:
            if object_type in array_element then
              process_arr_create_declaration(object_type, c_expr);
            else
              declare_create_prototype(object_type, c_expr);
            end if;
          when {STRUCTOBJECT}:
            process_sct_create_declaration(object_type, c_expr);
          when {HASHOBJECT}:
            if object_type in parametersOfHshCreate then
              process_hsh_create_declaration(object_type, c_expr);
            else
              declare_create_prototype(object_type, c_expr);
            end if;
          otherwise:
            create_declared @:= [object_type] TRUE;
        end case;
      else
        declare_create_prototype(object_type, c_expr);
      end if;
    end if;
  end func;


const proc: declare_missing_create_declarations (inout expr_type: c_expr) is func

  local
    var type: object_type is void;
  begin
    for key object_type range create_prototype_declared do
      process_create_declaration(object_type, c_expr);
    end for;
  end func;


const proc: process_create_call (in type: object_type,
    in string: param_b, inout string: expr) is func

  begin
    if object_type in typeCategory then
      case typeCategory[object_type] of
        when {BOOLOBJECT, ENUMOBJECT, INTOBJECT, FLOATOBJECT, CHAROBJECT,
              FILEOBJECT, SOCKETOBJECT, REFOBJECT, TYPEOBJECT,
              ACTOBJECT, BLOCKOBJECT}:
                                expr &:= param_b;
        when {BIGINTOBJECT}:    expr &:= "bigCreate(" & param_b & ")";
        when {STRIOBJECT}:      expr &:= "strCreate(" & param_b & ")";
        when {BSTRIOBJECT}:     expr &:= "bstCreate(" & param_b & ")";
        when {SETOBJECT}:       expr &:= "setCreate(" & param_b & ")";
        when {POLLOBJECT}:      expr &:= "polCreate(" & param_b & ")";
        when {REFLISTOBJECT}:   expr &:= "rflCreate(" & param_b & ")";
        when {WINOBJECT}:       expr &:= "drwCreate(" & param_b & ")";
        when {PROGOBJECT}:      expr &:= "prgCreate(" & param_b & ")";
        when {INTERFACEOBJECT}: expr &:= "itfCreate(" & param_b & ")";
        when {ARRAYOBJECT, HASHOBJECT, STRUCTOBJECT}:
          expr &:= "create_";
          expr &:= str(typeNumber(object_type));
          expr &:= "(";
          expr &:= param_b;
          expr &:= ")";
      end case;
    else
      expr &:= "create_";
      expr &:= str(typeNumber(object_type));
      expr &:= "((";
      expr &:= type_name(object_type);
      expr &:= ")(";
      expr &:= param_b;
      expr &:= "))";
    end if;
  end func;


const proc: process_destr_declaration (in type: object_type,
    inout expr_type: c_expr) is forward;


const proc: process_destr_call (in type: object_type,
    in string: param_b, inout string: expr) is forward;


const proc: process_arr_destr_declaration (in type: object_type,
    inout expr_type: c_expr) is func

  local
    var string: diagnosticLine is "";
    var string: select_value is "";
  begin
    if object_type in destrFunction then
      diagnosticLine := diagnosticLine(destrFunction[object_type]);
    end if;
    select_value := select_value_from_rtlObjectstruct(array_element[object_type]);
    process_destr_declaration(array_element[object_type], c_expr);
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "static void destr_";
    c_expr.expr &:= str(typeNumber(object_type));
    c_expr.expr &:= " (const_";
    c_expr.expr &:= type_name(object_type);
    c_expr.expr &:= " b)\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "{\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "memsizetype i;\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "memsizetype size;\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "if (b != NULL) {\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "size = (uinttype)(b->max_position - b->min_position + 1);\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "for (i = 0; i < size; i++) {\n";
    c_expr.expr &:= diagnosticLine;
    process_destr_call(array_element[object_type],
        "b->arr[i]" & select_value, c_expr.expr);
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "}\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "arrFree((arraytype)(b));\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "}\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "}\n";
    c_expr.expr &:= noDiagnosticLine;
    c_expr.expr &:= "\n";
    destr_declared @:= [object_type] TRUE;
  end func;


const proc: process_sct_destr_declaration (in type: object_type,
    inout expr_type: c_expr) is func

  local
    var string: diagnosticLine is "";
    var number_element_hash: elements is number_element_hash.EMPTY_HASH;
    var integer: number is 0;
    var reference: struct_elem is NIL;
    var string: select_value is "";
  begin
    if object_type in destrFunction then
      diagnosticLine := diagnosticLine(destrFunction[object_type]);
    end if;
    if object_type in struct_elements then
      elements := flip(struct_elements[object_type]);
    end if;
    for number range 0 to pred(length(elements)) do
      struct_elem := elements[number][1];
      process_destr_declaration(struct_element_type[object_type][struct_elem], c_expr);
    end for;
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "static void destr_";
    c_expr.expr &:= str(typeNumber(object_type));
    c_expr.expr &:= " (";
    c_expr.expr &:= type_name(object_type);
    c_expr.expr &:= " b)\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "{\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "if (b != NULL && b->usage_count != 0) {\n";
    c_expr.expr &:= "b->usage_count--;\n";
    c_expr.expr &:= "if (b->usage_count == 0) {\n";
    for number range 0 to pred(length(elements)) do
      struct_elem := elements[number][1];
      select_value := select_value_from_rtlObjectstruct(struct_element_type[object_type][struct_elem]);
      c_expr.expr &:= diagnosticLine;
      process_destr_call(struct_element_type[object_type][struct_elem],
          "b->stru[" & str(number) & "]" & select_value, c_expr.expr);
    end for;
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "free((void *)(b));\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "}}\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "}\n";
    c_expr.expr &:= noDiagnosticLine;
    c_expr.expr &:= "\n";
    destr_declared @:= [object_type] TRUE;
  end func;


const proc: process_hsh_destr_declaration (in type: object_type,
    inout expr_type: c_expr) is func

  local
    var string: diagnosticLine is "";
  begin
    if object_type in destrFunction then
      diagnosticLine := diagnosticLine(destrFunction[object_type]);
    end if;
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "static void destr_";
    c_expr.expr &:= str(typeNumber(object_type));
    c_expr.expr &:= " (const_";
    c_expr.expr &:= type_name(object_type);
    c_expr.expr &:= " b)\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "{\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "hshDestr(b";
    c_expr.expr &:= parametersOfHshDestr[object_type];
    c_expr.expr &:= ");\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "}\n";
    c_expr.expr &:= noDiagnosticLine;
    c_expr.expr &:= "\n";
    destr_declared @:= [object_type] TRUE;
  end func;


const proc: process_itf_destr_declaration (in type: object_type,
    inout expr_type: c_expr) is func

  local
    var string: diagnosticLine is "";
    var type: implementationType is void;
  begin
    if object_type in destrFunction then
      diagnosticLine := diagnosticLine(destrFunction[object_type]);
    end if;
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "static void destr_";
    c_expr.expr &:= str(typeNumber(object_type));
    c_expr.expr &:= " (";
    c_expr.expr &:= type_name(object_type);
    c_expr.expr &:= " b)\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "{\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "if (b != NULL) {\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "if (b->usage_count >= 2) {\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "b->usage_count--;\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "} else if (b->usage_count != 0) {\n";
    c_expr.expr &:= diagnosticLine;
    for implementationType range implements[object_type] do
      c_expr.expr &:= "if (b->type_num == ";
      c_expr.expr &:= str(typeNumber(implementationType));
      c_expr.expr &:= "/*";
      c_expr.expr &:= str(implementationType);
      c_expr.expr &:= "*/";
      c_expr.expr &:= ") {\n";
      c_expr.expr &:= diagnosticLine;
      process_destr_declaration(implementationType, global_c_expr);
      process_destr_call(implementationType, "b", c_expr.expr);
      c_expr.expr &:= diagnosticLine;
      c_expr.expr &:= "} else ";
    end for;
    c_expr.expr &:= "{\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "raise_error(ACTION_ERROR);\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "}\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "}\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "}\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "}\n";
    c_expr.expr &:= noDiagnosticLine;
    c_expr.expr &:= "\n";
    destr_declared @:= [object_type] TRUE;
  end func;


const proc: process_itf_destr_prototype (in type: object_type,
    inout expr_type: c_expr) is func

  begin
    if object_type not in destr_prototype_declared then
      c_expr.expr &:= "static void destr_";
      c_expr.expr &:= str(typeNumber(object_type));
      c_expr.expr &:= " (";
      c_expr.expr &:= type_name(object_type);
      c_expr.expr &:= ");\n\n";
      destr_prototype_declared @:= [object_type] TRUE;
    end if;
  end func;


const proc: declare_destr_prototype (in type: object_type,
    inout expr_type: c_expr) is func

  begin
    if object_type not in destr_prototype_declared then
      declare_type_if_necessary(object_type, c_expr);
      c_expr.expr &:= "static void destr_";
      c_expr.expr &:= str(typeNumber(object_type));
      c_expr.expr &:= " (const_";
      c_expr.expr &:= type_name(object_type);
      c_expr.expr &:= ");\n\n";
      destr_prototype_declared @:= [object_type] TRUE;
    end if;
  end func;


const proc: process_destr_declaration (in type: object_type,
    inout expr_type: c_expr) is func

  begin
    if object_type not in destr_declared then
      if object_type in typeCategory then
        case typeCategory[object_type] of
          when {ARRAYOBJECT}:
            if object_type in array_element then
              process_arr_destr_declaration(object_type, c_expr);
            else
              declare_destr_prototype(object_type, c_expr);
            end if;
          when {STRUCTOBJECT}:
            process_sct_destr_declaration(object_type, c_expr);
          when {HASHOBJECT}:
            if object_type in parametersOfHshDestr then
              process_hsh_destr_declaration(object_type, c_expr);
            else
              declare_destr_prototype(object_type, c_expr);
            end if;
          when {INTERFACEOBJECT}:
            process_itf_destr_prototype(object_type, c_expr);
          otherwise:
            destr_declared @:= [object_type] TRUE;
        end case;
      else
        declare_destr_prototype(object_type, c_expr);
      end if;
    end if;
  end func;


const proc: declare_missing_destr_declarations (inout expr_type: c_expr) is func

  local
    var type: object_type is void;
  begin
    for key object_type range destr_prototype_declared do
      process_destr_declaration(object_type, c_expr);
    end for;
    for key object_type range destr_prototype_declared do
      if object_type in typeCategory and typeCategory[object_type] = INTERFACEOBJECT then
        process_itf_destr_declaration(object_type, c_expr);
      end if;
    end for;
  end func;


const set of category: destrNecessary is {
    BIGINTOBJECT, STRIOBJECT, BSTRIOBJECT, SETOBJECT, REFLISTOBJECT,
    WINOBJECT, PROGOBJECT, ARRAYOBJECT, HASHOBJECT, STRUCTOBJECT};


const proc: process_destr_call (in type: object_type,
    in string: param_b, inout string: expr) is func

  begin
    if object_type in typeCategory then
      case typeCategory[object_type] of
        when {BOOLOBJECT, ENUMOBJECT, INTOBJECT, FLOATOBJECT, CHAROBJECT,
              FILEOBJECT, SOCKETOBJECT, REFOBJECT, TYPEOBJECT,
              ACTOBJECT, BLOCKOBJECT}:
                                noop;
        when {BIGINTOBJECT}:    expr &:= "bigDestr(" & param_b & ");\n";
        when {STRIOBJECT}:      expr &:= "strDestr(" & param_b & ");\n";
        when {BSTRIOBJECT}:     expr &:= "bstDestr(" & param_b & ");\n";
        when {SETOBJECT}:       expr &:= "setDestr(" & param_b & ");\n";
        when {POLLOBJECT}:      expr &:= "polDestr(" & param_b & ");\n";
        when {REFLISTOBJECT}:   expr &:= "rflDestr(" & param_b & ");\n";
        when {WINOBJECT}:       expr &:= "drwDestr(" & param_b & ");\n";
        when {PROGOBJECT}:      expr &:= "prgDestr(" & param_b & ");\n";
        when {ARRAYOBJECT, HASHOBJECT, STRUCTOBJECT, INTERFACEOBJECT}:
          expr &:= "destr_";
          expr &:= str(typeNumber(object_type));
          expr &:= "(";
          expr &:= param_b;
          expr &:= ");\n";
      end case;
    else
      expr &:= "destr_";
      expr &:= str(typeNumber(object_type));
      expr &:= "((";
      expr &:= type_name(object_type);
      expr &:= ")(";
      expr &:= param_b;
      expr &:= "));\n";
    end if;
  end func;


const proc: process_cpy_declaration (in type: object_type,
    inout expr_type: c_expr) is forward;


const proc: process_cpy_call (in type: object_type,
    in string: param_a, in string: param_b, inout string: expr) is forward;


const proc: process_arr_cpy_declaration (in type: object_type,
    inout expr_type: c_expr) is func

  local
    var string: diagnosticLine is "";
    var string: select_value is "";
  begin
    if object_type in copyFunction then
      diagnosticLine := diagnosticLine(copyFunction[object_type]);
    end if;
    select_value := select_value_from_rtlObjectstruct(array_element[object_type]);
    process_create_declaration(array_element[object_type], c_expr);
    process_destr_declaration(array_element[object_type], c_expr);
    process_cpy_declaration(array_element[object_type], c_expr);
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "static void cpy_";
    c_expr.expr &:= str(typeNumber(object_type));
    c_expr.expr &:= " (";
    c_expr.expr &:= type_name(object_type);
    c_expr.expr &:= " *a, ";
    c_expr.expr &:= type_name(object_type);
    c_expr.expr &:= " b)\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "{\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "memsizetype i;\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "memsizetype size_a = (uinttype)((*a)->max_position - (*a)->min_position + 1);\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "memsizetype size_b = (uinttype)(b->max_position - b->min_position + 1);\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "memsizetype size;\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "(*a)->min_position = b->min_position;\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "(*a)->max_position = b->max_position;\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "if (size_a == size_b) {\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "size = size_a;\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "} else {\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "if (size_a < size_b) {\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "*a=(";
    c_expr.expr &:= type_name(object_type);
    c_expr.expr &:= ")(arrRealloc((arraytype)(*a), size_a, size_b));\n";
    c_expr.expr &:= "size = size_a;\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "for (i = size_a; i < size_b; i++) {\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "(*a)->arr[i]";
    c_expr.expr &:= select_value;
    c_expr.expr &:= "=";
    process_create_call(array_element[object_type],
        "b->arr[i]" & select_value, c_expr.expr);
    c_expr.expr &:= ";\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "}\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "} else /* size_a > size_b */ {\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "size = size_b;\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "for (i = size_b; i < size_a; i++) {\n";
    c_expr.expr &:= diagnosticLine;
    process_destr_call(array_element[object_type],
        "(*a)->arr[i]" & select_value, c_expr.expr);
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "}\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "*a=(";
    c_expr.expr &:= type_name(object_type);
    c_expr.expr &:= ")(arrRealloc((arraytype)(*a), size_a, size_b));\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "}\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "}\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "for (i = 0; i < size; i++) {\n";
    c_expr.expr &:= diagnosticLine;
    process_cpy_call(array_element[object_type],
        "(*a)->arr[i]" & select_value,
        "b->arr[i]" & select_value, c_expr.expr);
    c_expr.expr &:= ";\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "}\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "}\n";
    c_expr.expr &:= noDiagnosticLine;
    c_expr.expr &:= "\n";
    cpy_declared @:= [object_type] TRUE;
  end func;


const proc: process_sct_cpy_declaration (in type: object_type,
    inout expr_type: c_expr) is func

  local
    var string: diagnosticLine is "";
    var number_element_hash: elements is number_element_hash.EMPTY_HASH;
    var integer: number is 0;
    var reference: struct_elem is NIL;
    var string: select_value is "";
  begin
    if object_type in copyFunction then
      diagnosticLine := diagnosticLine(copyFunction[object_type]);
    end if;
    if object_type in struct_elements then
      elements := flip(struct_elements[object_type]);
    end if;
    for number range 0 to pred(length(elements)) do
      struct_elem := elements[number][1];
      process_cpy_declaration(struct_element_type[object_type][struct_elem], c_expr);
    end for;
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "static void cpy_";
    c_expr.expr &:= str(typeNumber(object_type));
    c_expr.expr &:= " (";
    c_expr.expr &:= type_name(object_type);
    c_expr.expr &:= " a, ";
    c_expr.expr &:= type_name(object_type);
    c_expr.expr &:= " b)\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "{\n";
    # The usage_count is currently left unchanged for a deep copy.
    # c_expr.expr &:= "a->usage_count = b->usage_count;\n";
    # The dynamic type of a struct cannot change with a deep copy.
    # c_expr.expr &:= "a->type_num = b->type_num;\n";
    for number range 0 to pred(length(elements)) do
      struct_elem := elements[number][1];
      select_value := select_value_from_rtlObjectstruct(struct_element_type[object_type][struct_elem]);
      c_expr.expr &:= diagnosticLine;
      process_cpy_call(struct_element_type[object_type][struct_elem],
          "a->stru[" & str(number) & "]" & select_value,
          "b->stru[" & str(number) & "]" & select_value, c_expr.expr);
      c_expr.expr &:= ";\n";
    end for;
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "}\n";
    c_expr.expr &:= noDiagnosticLine;
    c_expr.expr &:= "\n";
    cpy_declared @:= [object_type] TRUE;
  end func;


const proc: process_hsh_cpy_declaration (in type: object_type,
    inout expr_type: c_expr) is func

  local
    var string: diagnosticLine is "";
  begin
    if object_type in copyFunction then
      diagnosticLine := diagnosticLine(copyFunction[object_type]);
    end if;
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "static void cpy_";
    c_expr.expr &:= str(typeNumber(object_type));
    c_expr.expr &:= " (";
    c_expr.expr &:= type_name(object_type);
    c_expr.expr &:= " *a, ";
    c_expr.expr &:= type_name(object_type);
    c_expr.expr &:= " b)\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "{\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "hshCpy(a, b";
    c_expr.expr &:= parametersOfHshCpy[object_type];
    c_expr.expr &:= ");\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "}\n";
    c_expr.expr &:= noDiagnosticLine;
    c_expr.expr &:= "\n";
    cpy_declared @:= [object_type] TRUE;
  end func;


const proc: process_itf_cpy_declaration (in type: object_type,
    inout expr_type: c_expr) is func

  local
    var string: diagnosticLine is "";
  begin
    if object_type in copyFunction then
      diagnosticLine := diagnosticLine(copyFunction[object_type]);
    end if;
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "static void cpy_";
    c_expr.expr &:= str(typeNumber(object_type));
    c_expr.expr &:= " (";
    c_expr.expr &:= type_name(object_type);
    c_expr.expr &:= " *a, ";
    c_expr.expr &:= type_name(object_type);
    c_expr.expr &:= " b)\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "{\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "interfacetype old_value = *a;\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "*a=b;\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "if ((*a)->usage_count != 0) { (*a)->usage_count++; }\n";
    process_destr_declaration(object_type, global_c_expr);
    c_expr.expr &:= diagnosticLine;
    process_destr_call(object_type, "old_value", c_expr.expr);
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "}\n";
    c_expr.expr &:= noDiagnosticLine;
    c_expr.expr &:= "\n";
    cpy_declared @:= [object_type] TRUE;
  end func;


const proc: process_cpy_declaration (in type: object_type,
    inout expr_type: c_expr) is func

  begin
    if object_type not in cpy_declared then
      if object_type in typeCategory then
        case typeCategory[object_type] of
          when {ARRAYOBJECT}:
            process_arr_cpy_declaration(object_type, c_expr);
          when {STRUCTOBJECT}:
            process_sct_cpy_declaration(object_type, c_expr);
          when {HASHOBJECT}:
            process_hsh_cpy_declaration(object_type, c_expr);
          when {INTERFACEOBJECT}:
            process_itf_cpy_declaration(object_type, c_expr);
          otherwise:
            cpy_declared @:= [object_type] TRUE;
        end case;
      else
        c_expr.expr &:= "/* cpy_";
        c_expr.expr &:= str(typeNumber(object_type));
        c_expr.expr &:= " declaration for type ";
        c_expr.expr &:= type_name2(object_type);
        c_expr.expr &:= " */\n\n";
      end if;
    end if;
  end func;


const proc: process_cpy_call (in type: object_type,
    in string: param_a, in string: param_b, inout string: expr) is func

  begin
    if object_type in typeCategory then
      case typeCategory[object_type] of
        when {BOOLOBJECT, ENUMOBJECT, INTOBJECT, FLOATOBJECT, CHAROBJECT,
              FILEOBJECT, SOCKETOBJECT, REFOBJECT, TYPEOBJECT,
              ACTOBJECT, BLOCKOBJECT}:
                                expr &:= param_a & "=" & param_b;
        when {BIGINTOBJECT}:    expr &:= "bigCpy(&(" & param_a & "), " & param_b & ")";
        when {STRIOBJECT}:      expr &:= "strCopy(&(" & param_a & "), " & param_b & ")";
        when {BSTRIOBJECT}:     expr &:= "bstCpy(&(" & param_a & "), " & param_b & ")";
        when {SETOBJECT}:       expr &:= "setCpy(&(" & param_a & "), " & param_b & ")";
        when {POLLOBJECT}:      expr &:= "polCpy(" & param_a & ", " & param_b & ")";
        when {REFLISTOBJECT}:   expr &:= "rflCpy(&(" & param_a & "), " & param_b & ")";
        when {WINOBJECT}:       expr &:= "drwCpy(&(" & param_a & "), " & param_b & ")";
        when {PROGOBJECT}:      expr &:= "prgCpy(&(" & param_a & "), " & param_b & ")";
        when {ARRAYOBJECT, HASHOBJECT, INTERFACEOBJECT}:
          expr &:= "cpy_";
          expr &:= str(typeNumber(object_type));
          expr &:= "((";
          expr &:= type_name(object_type);
          expr &:= " *)(&(";
          expr &:= param_a;
          expr &:= ")), (";
          expr &:= type_name(object_type);
          expr &:= ")(";
          expr &:= param_b;
          expr &:= "))";
        when {STRUCTOBJECT}:
          expr &:= "cpy_";
          expr &:= str(typeNumber(object_type));
          expr &:= "((";
          expr &:= type_name(object_type);
          expr &:= ")(";
          expr &:= param_a;
          expr &:= "), (";
          expr &:= type_name(object_type);
          expr &:= ")(";
          expr &:= param_b;
          expr &:= "))";
      end case;
    else
      expr &:= param_b & " /* cpy_";
      expr &:= str(typeNumber(object_type));
      expr &:= " for type ";
      expr &:= type_name2(object_type);
      expr &:= " */";
    end if;
  end func;


const proc: process_generic_cpy_declaration (in type: object_type,
    inout expr_type: c_expr) is func

  begin
    if object_type not in generic_cpy_declared then
      process_cpy_declaration(object_type, c_expr);
      c_expr.expr &:= "static void generic_cpy_";
      c_expr.expr &:= str(typeNumber(object_type));
      c_expr.expr &:= " (generictype *a, const generictype b)\n";
      c_expr.expr &:= "{\n";
      process_cpy_call(object_type,
          "((const_rtlObjecttype *) a)->value." & raw_type_value(object_type),
          "((const_rtlObjecttype *) &b)->value." & raw_type_value(object_type),
          c_expr.expr);
      c_expr.expr &:= ";\n";
      c_expr.expr &:= "}\n\n";
      generic_cpy_declared @:= [object_type] TRUE;
    end if;
  end func;


const proc: process_generic_create_declaration (in type: object_type,
    inout expr_type: c_expr) is func

  begin
    if object_type not in generic_create_declared then
      process_create_declaration(object_type, c_expr);
      c_expr.expr &:= "static generictype generic_create_";
      c_expr.expr &:= str(typeNumber(object_type));
      c_expr.expr &:= " (const generictype b)\n";
      c_expr.expr &:= "{\n";
      c_expr.expr &:= "rtlObjecttype result;\n";
      c_expr.expr &:= "result.value.";
      c_expr.expr &:= raw_type_value(object_type);
      c_expr.expr &:= "=";
      process_create_call(object_type,
          "((const_rtlObjecttype *) &b)->value." & raw_type_value(object_type),
          c_expr.expr);
      c_expr.expr &:= ";\n";
      c_expr.expr &:= "return result.value.genericvalue;\n";
      c_expr.expr &:= "}\n\n";
      generic_create_declared @:= [object_type] TRUE;
    end if;
  end func;


const proc: process_generic_destr_declaration (in type: object_type,
    inout expr_type: c_expr) is func

  begin
    if object_type not in generic_destr_declared then
      process_destr_declaration(object_type, c_expr);
      c_expr.expr &:= "static void generic_destr_";
      c_expr.expr &:= str(typeNumber(object_type));
      c_expr.expr &:= " (const generictype b)\n";
      c_expr.expr &:= "{\n";
      process_destr_call(object_type,
          "((const_rtlObjecttype *) &b)->value." & raw_type_value(object_type),
          c_expr.expr);
      c_expr.expr &:= "}\n\n";
      generic_destr_declared @:= [object_type] TRUE;
    end if;
  end func;


const proc: process_generic_cmp_declaration (in reference: function,
    in type: object_type, inout expr_type: c_expr) is func

  begin
    if object_type not in generic_cmp_declared then
      process_cpy_declaration(object_type, c_expr);
      c_expr.expr &:= "static inttype generic_cmp_";
      c_expr.expr &:= str(typeNumber(object_type));
      c_expr.expr &:= " (const generictype a, const generictype b)\n";
      c_expr.expr &:= "{\n";
      c_expr.expr &:= "return o_";
      create_name(function, c_expr.expr);
      c_expr.expr &:= "(((const_rtlObjecttype *) &a)->value.";
      c_expr.expr &:= raw_type_value(object_type);
      c_expr.expr &:= ", ((const_rtlObjecttype *) &b)->value.";
      c_expr.expr &:= raw_type_value(object_type);
      c_expr.expr &:= ");\n";
      c_expr.expr &:= "}\n\n";
      generic_cmp_declared @:= [object_type] TRUE;
    end if;
  end func;


const func boolean: useFunctype (in reference: current_object) is func

  result
    var boolean: okay is FALSE;
  local
    var reference: curr_expr is NIL;
    var category: exprCategory is category.value;
  begin
    curr_expr := getValue(current_object, reference);
    if curr_expr <> NIL then
      exprCategory := category(curr_expr);
      okay := exprCategory = ACTOBJECT or
              exprCategory = BLOCKOBJECT;
    end if;
  end func;


const proc: declare_prototype_if_necessary (in reference: function,
    inout expr_type: c_expr) is func

  local
    var ref_list: params is ref_list.EMPTY;
    var type: result_type is void;
    var type: object_type is void;
  begin
    if function not in prototype_declared then
      result_type := resultType(getType(function));
      params := formalParams(function);
      object_type := getType(params[3]);
      process_create_declaration(object_type, c_expr);
      # c_expr.expr &:= type_name(result_type);
      c_expr.expr &:= "static arraytype times_";
      c_expr.expr &:= str(typeNumber(result_type));
      c_expr.expr &:= " (inttype, const ";
      if useConstPrefix(object_type) then
        c_expr.expr &:= "const_";
      end if;
      c_expr.expr &:= type_name(object_type);
      c_expr.expr &:= ");\n\n";
      prototype_declared @:= [function] TRUE;
    end if;
  end func;



const proc: declare_func_pointer_if_necessary (in reference: current_object,
    inout expr_type: c_expr) is func

  local
    var ref_list: params is ref_list.EMPTY;
    var reference: func_pointer is NIL;
  begin
    if category(current_object) = CALLOBJECT then
      params := getValue(current_object, ref_list);
      if length(params) >= 1 then
        func_pointer := params[1];
        if category(func_pointer) = REFOBJECT then
          if func_pointer not in function_pointer_declared then
            if useFunctype(func_pointer) then
              c_expr.expr &:= "extern intfunctype o_";
            else
              c_expr.expr &:= "extern objreftype o_";
            end if;
            create_name(func_pointer, c_expr.expr);
            c_expr.expr &:= ";\n\n";
            function_pointer_declared @:= [func_pointer] TRUE;
          end if;
        end if;
      end if;
    end if;
  end func;


const proc: process_big_create_call (in bigInteger: number, inout string: expr) is func

  begin
    if number = 0_ then
      incr(countOptimizations);
      expr &:= "bigZero(); /* 0_ */\n";
    else
      expr &:= "bigCreate(";
      expr &:= bigIntegerLiteral(number);
      expr &:= ");\n";
    end if;
  end func;


const proc: process_str_create_call (in string: stri, inout string: expr) is func

  begin
    if stri = "" then
      incr(countOptimizations);
      expr &:= "strEmpty(); /* \"\" */\n";
    elsif length(stri) = 1 then
      incr(countOptimizations);
      expr &:= "chrStr(";
      expr &:= charLiteral(stri[1]);
      expr &:= "); /* ";
      expr &:= literal(stri);
      expr &:= " */\n";
    else
      expr &:= "strCreate(";
      expr &:= stringLiteral(stri);
      expr &:= ");\n";
    end if;
  end func;


const func boolean: has_temp_values (in expr_type: c_expr) is
  return c_expr.temp_num >= 2 or
      (c_expr.temp_num = 1 and c_expr.result_expr = "");


const proc: prepare_typed_result (in type: aType, inout expr_type: c_expr) is func

  begin
    incr(c_expr.temp_num);
    c_expr.result_temp := "tmp_";
    c_expr.result_temp &:= str(c_expr.temp_num);
    c_expr.result_decl := type_name(aType);
    c_expr.result_decl &:= " tmp_";
    c_expr.result_decl &:= str(c_expr.temp_num);
    c_expr.result_decl &:= " = (";
    c_expr.result_decl &:= type_name(aType);
    c_expr.result_decl &:= ")(NULL);\n";
    process_destr_declaration(aType, global_c_expr);
    process_destr_call(aType, c_expr.result_temp, c_expr.result_free);
    c_expr.result_to_null := c_expr.result_temp;
    c_expr.result_to_null &:= " = (";
    c_expr.result_to_null &:= type_name(aType);
    c_expr.result_to_null &:= ")(NULL);\n";
    c_expr.result_intro := "(tmp_";
    c_expr.result_intro &:= str(c_expr.temp_num);
    c_expr.result_intro &:= "=(";
    c_expr.result_intro &:= type_name(aType);
    c_expr.result_intro &:= ")(";
    c_expr.result_finish := "))";
  end func;


const proc: prepare_bigint_result (inout expr_type: c_expr) is func

  begin
    incr(c_expr.temp_num);
    c_expr.result_temp := "tmp_";
    c_expr.result_temp &:= str(c_expr.temp_num);
    c_expr.result_decl := "biginttype tmp_";
    c_expr.result_decl &:= str(c_expr.temp_num);
    c_expr.result_decl &:= " = NULL;\n";
    c_expr.result_free := "bigDestr(tmp_";
    c_expr.result_free &:= str(c_expr.temp_num);
    c_expr.result_free &:= ");\n";
    c_expr.result_to_null := c_expr.result_temp;
    c_expr.result_to_null &:= " = NULL;\n";
    c_expr.result_intro := "(tmp_";
    c_expr.result_intro &:= str(c_expr.temp_num);
    c_expr.result_intro &:= "=";
    c_expr.result_finish := ")";
  end func;


const proc: prepare_list_result (in type: list_type, inout expr_type: c_expr) is func

  begin
    incr(c_expr.temp_num);
    c_expr.result_temp := "tmp_";
    c_expr.result_temp &:= str(c_expr.temp_num);
    c_expr.result_decl := type_name(list_type);
    c_expr.result_decl &:= " tmp_";
    c_expr.result_decl &:= str(c_expr.temp_num);
    c_expr.result_decl &:= " = (";
    c_expr.result_decl &:= type_name(list_type);
    c_expr.result_decl &:= ")(NULL);\n";
    c_expr.result_free := "rflDestr(tmp_";
    c_expr.result_free &:= str(c_expr.temp_num);
    c_expr.result_free &:= ");\n";
    c_expr.result_to_null := c_expr.result_temp;
    c_expr.result_to_null &:= " = (";
    c_expr.result_to_null &:= type_name(list_type);
    c_expr.result_to_null &:= ")(NULL);\n";
    c_expr.result_intro := "(tmp_";
    c_expr.result_intro &:= str(c_expr.temp_num);
    c_expr.result_intro &:= "=(";
    c_expr.result_intro &:= type_name(list_type);
    c_expr.result_intro &:= ")(";
    c_expr.result_finish := "))";
  end func;


const proc: prepare_set_result (in type: set_type, inout expr_type: c_expr) is func

  begin
    incr(c_expr.temp_num);
    c_expr.result_temp := "tmp_";
    c_expr.result_temp &:= str(c_expr.temp_num);
    c_expr.result_decl := type_name(set_type);
    c_expr.result_decl &:= " tmp_";
    c_expr.result_decl &:= str(c_expr.temp_num);
    c_expr.result_decl &:= " = (";
    c_expr.result_decl &:= type_name(set_type);
    c_expr.result_decl &:= ")(NULL);\n";
    c_expr.result_free := "setDestr(tmp_";
    c_expr.result_free &:= str(c_expr.temp_num);
    c_expr.result_free &:= ");\n";
    c_expr.result_to_null := c_expr.result_temp;
    c_expr.result_to_null &:= " = (";
    c_expr.result_to_null &:= type_name(set_type);
    c_expr.result_to_null &:= ")(NULL);\n";
    c_expr.result_intro := "(tmp_";
    c_expr.result_intro &:= str(c_expr.temp_num);
    c_expr.result_intro &:= "=(";
    c_expr.result_intro &:= type_name(set_type);
    c_expr.result_intro &:= ")(";
    c_expr.result_finish := "))";
  end func;


const proc: prepare_stri_result (inout expr_type: c_expr) is func

  begin
    incr(c_expr.temp_num);
    c_expr.result_temp := "tmp_";
    c_expr.result_temp &:= str(c_expr.temp_num);
    c_expr.result_decl := "stritype tmp_";
    c_expr.result_decl &:= str(c_expr.temp_num);
    c_expr.result_decl &:= " = NULL;\n";
    c_expr.result_free := "strDestr(tmp_";
    c_expr.result_free &:= str(c_expr.temp_num);
    c_expr.result_free &:= ");\n";
    c_expr.result_to_null := c_expr.result_temp;
    c_expr.result_to_null &:= " = NULL;\n";
    c_expr.result_intro := "(tmp_";
    c_expr.result_intro &:= str(c_expr.temp_num);
    c_expr.result_intro &:= "=";
    c_expr.result_finish := ")";
  end func;


const proc: prepare_bstri_result (inout expr_type: c_expr) is func

  begin
    incr(c_expr.temp_num);
    c_expr.result_temp := "tmp_";
    c_expr.result_temp &:= str(c_expr.temp_num);
    c_expr.result_decl := "bstritype tmp_";
    c_expr.result_decl &:= str(c_expr.temp_num);
    c_expr.result_decl &:= " = NULL;\n";
    c_expr.result_free := "bstDestr(tmp_";
    c_expr.result_free &:= str(c_expr.temp_num);
    c_expr.result_free &:= ");\n";
    c_expr.result_to_null := c_expr.result_temp;
    c_expr.result_to_null &:= " = NULL;\n";
    c_expr.result_intro := "(tmp_";
    c_expr.result_intro &:= str(c_expr.temp_num);
    c_expr.result_intro &:= "=";
    c_expr.result_finish := ")";
  end func;


const proc: prepare_prog_result (inout expr_type: c_expr) is func

  begin
    incr(c_expr.temp_num);
    c_expr.result_temp := "tmp_";
    c_expr.result_temp &:= str(c_expr.temp_num);
    c_expr.result_decl := "progtype tmp_";
    c_expr.result_decl &:= str(c_expr.temp_num);
    c_expr.result_decl &:= " = NULL;\n";
    c_expr.result_free := "prgDestr(tmp_";
    c_expr.result_free &:= str(c_expr.temp_num);
    c_expr.result_free &:= ");\n";
    c_expr.result_to_null := c_expr.result_temp;
    c_expr.result_to_null &:= " = NULL;\n";
    c_expr.result_intro := "(tmp_";
    c_expr.result_intro &:= str(c_expr.temp_num);
    c_expr.result_intro &:= "=";
    c_expr.result_finish := ")";
  end func;


const proc: prepare_win_result (inout expr_type: c_expr) is func

  begin
    incr(c_expr.temp_num);
    c_expr.result_temp := "tmp_";
    c_expr.result_temp &:= str(c_expr.temp_num);
    c_expr.result_decl := "wintype tmp_";
    c_expr.result_decl &:= str(c_expr.temp_num);
    c_expr.result_decl &:= " = NULL;\n";
    c_expr.result_free := "winDestr(tmp_";
    c_expr.result_free &:= str(c_expr.temp_num);
    c_expr.result_free &:= ");\n";
    c_expr.result_to_null := c_expr.result_temp;
    c_expr.result_to_null &:= " = NULL;\n";
    c_expr.result_intro := "(tmp_";
    c_expr.result_intro &:= str(c_expr.temp_num);
    c_expr.result_intro &:= "=";
    c_expr.result_finish := ")";
  end func;


const proc: prepareAnyParamTemporarys (in reference: aParam,
    inout expr_type: c_param, inout expr_type: c_expr) is func

  begin
    c_param.temp_num := c_expr.temp_num;
    process_expr(aParam, c_param);
    c_expr.temp_num := c_param.temp_num;
    c_expr.temp_decls &:= c_param.temp_decls;
    c_expr.temp_assigns &:= c_param.temp_assigns;
    c_expr.temp_frees &:= c_param.temp_frees;
    c_expr.temp_to_null &:= c_param.temp_to_null;
  end func;


const proc: getAnyParamToExpr (in expr_type: c_param, inout expr_type: c_expr) is func

  begin
    if c_param.result_expr <> "" then
      c_expr.temp_decls &:= c_param.result_decl;
      c_expr.temp_frees &:= c_param.result_free;
      c_expr.temp_to_null &:= c_param.result_to_null;
      c_expr.expr &:= c_param.result_intro;
      c_expr.expr &:= c_param.result_expr;
      c_expr.expr &:= c_param.result_finish;
    else
      c_expr.expr &:= c_param.expr;
    end if;
  end func;


const proc: getAnyParamToExpr (in reference: aParam, inout expr_type: c_expr) is func

  local
    var expr_type: c_param is expr_type.value;
  begin
    prepareAnyParamTemporarys(aParam, c_param, c_expr);
    getAnyParamToExpr(c_param, c_expr);
  end func;


const proc: getAnyParamToResultExpr (in expr_type: c_param, inout expr_type: c_expr) is func

  begin
    if c_param.result_expr <> "" then
      c_expr.temp_decls &:= c_param.result_decl;
      c_expr.temp_frees &:= c_param.result_free;
      c_expr.temp_to_null &:= c_param.result_to_null;
      c_expr.result_expr &:= c_param.result_intro;
      c_expr.result_expr &:= c_param.result_expr;
      c_expr.result_expr &:= c_param.result_finish;
    else
      c_expr.result_expr &:= c_param.expr;
    end if;
  end func;


const proc: getAnyParamToResultExpr (in reference: aParam, inout expr_type: c_expr) is func

  local
    var expr_type: c_param is expr_type.value;
  begin
    prepareAnyParamTemporarys(aParam, c_param, c_expr);
    getAnyParamToResultExpr(c_param, c_expr);
  end func;


const proc: getStdParamToResultExpr (in reference: aParam, inout expr_type: c_expr) is func

  local
    var expr_type: c_param is expr_type.value;
  begin
    prepareAnyParamTemporarys(aParam, c_param, c_expr);
    c_expr.result_expr &:= c_param.expr;
  end func;


const proc: getGenericValue (in reference: current_expression,
    inout expr_type: c_expr) is func

  local
    var type: result_type is void;
    var string: temp_name is "";
  begin
    result_type := getExprResultType(current_expression);
    if result_type in typeCategory and typeCategory[result_type] = FLOATOBJECT or
        not ccConf.LITTLE_ENDIAN_INTTYPE then
      incr(c_expr.temp_num);
      temp_name := "tmp_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "const_rtlValueunion ";
      c_expr.temp_decls &:= temp_name;
      c_expr.temp_decls &:= ";\n";
      c_expr.expr &:= "(";
      c_expr.expr &:= temp_name;
      c_expr.expr &:= ".";
      c_expr.expr &:= raw_type_value(result_type);
      c_expr.expr &:= "=";
      process_expr(current_expression, c_expr);
      c_expr.expr &:= ",";
      c_expr.expr &:= temp_name;
      c_expr.expr &:= ".genericvalue)";
    else
      c_expr.expr &:= "(generictype)(";
      process_expr(current_expression, c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: getGenericValueToResultExpr (in reference: current_expression,
    inout expr_type: c_expr) is func

  local
    var type: result_type is void;
    var string: temp_name is "";
  begin
    result_type := getExprResultType(current_expression);
    if result_type in typeCategory and typeCategory[result_type] = FLOATOBJECT or
        not ccConf.LITTLE_ENDIAN_INTTYPE then
      incr(c_expr.temp_num);
      temp_name := "tmp_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "const_rtlValueunion ";
      c_expr.temp_decls &:= temp_name;
      c_expr.temp_decls &:= ";\n";
      c_expr.result_expr &:= "(";
      c_expr.result_expr &:= temp_name;
      c_expr.result_expr &:= ".";
      c_expr.result_expr &:= raw_type_value(result_type);
      c_expr.result_expr &:= "=";
      getAnyParamToResultExpr(current_expression, c_expr);
      c_expr.result_expr &:= ",";
      c_expr.result_expr &:= temp_name;
      c_expr.result_expr &:= ".genericvalue)";
    else
      c_expr.result_expr &:= "(generictype)(";
      getAnyParamToResultExpr(current_expression, c_expr);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: getGenericTemporaryToResultExpr (in type: param_type, in expr_type: c_param,
    inout expr_type: c_expr) is func

  local
    var string: temp_name is "";
  begin
    if param_type in typeCategory and typeCategory[param_type] = FLOATOBJECT or
        not ccConf.LITTLE_ENDIAN_INTTYPE then
      incr(c_expr.temp_num);
      temp_name := "tmp_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "rtlValueunion ";
      c_expr.temp_decls &:= temp_name;
      c_expr.temp_decls &:= ";\n";
      c_expr.result_expr &:= "(";
      c_expr.result_expr &:= temp_name;
      c_expr.result_expr &:= ".";
      c_expr.result_expr &:= raw_type_value(param_type);
      c_expr.result_expr &:= "=";
      if c_param.result_expr <> "" then
        c_expr.result_expr &:= c_param.result_expr;
      else
        process_create_declaration(param_type, global_c_expr);
        process_create_call(param_type, c_param.expr, c_expr.result_expr);
      end if;
      c_expr.result_expr &:= ",";
      c_expr.result_expr &:= temp_name;
      c_expr.result_expr &:= ".genericvalue)";
    elsif c_param.result_expr <> "" then
      c_expr.result_expr &:= c_param.result_expr;
    else
      process_create_declaration(param_type, global_c_expr);
      process_create_call(param_type, c_param.expr, c_expr.result_expr);
    end if;
  end func;


const proc: getGenericTemporaryToResultExpr (in reference: aParam, inout expr_type: c_expr) is func

  local
    var expr_type: c_param is expr_type.value;
    var type: param_type is void;
  begin
    param_type := getExprResultType(aParam);
    prepareAnyParamTemporarys(aParam, c_param, c_expr);
    getGenericTemporaryToResultExpr(param_type, c_param, c_expr);
  end func;


const proc: getTemporaryToResultExpr (in type: param_type, in expr_type: c_param,
    inout expr_type: c_expr) is func

  local
    var string: temp_name is "";
  begin
    if param_type in typeCategory and typeCategory[param_type] = FLOATOBJECT then
      incr(c_expr.temp_num);
      temp_name := "tmp_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "rtlValueunion ";
      c_expr.temp_decls &:= temp_name;
      c_expr.temp_decls &:= ";\n";
      c_expr.result_expr &:= "(";
      c_expr.result_expr &:= temp_name;
      c_expr.result_expr &:= ".floatvalue=";
      c_expr.result_expr &:= c_param.expr;
      c_expr.result_expr &:= ",";
      c_expr.result_expr &:= temp_name;
      c_expr.result_expr &:= ".genericvalue)";
    elsif c_param.result_expr <> "" then
      c_expr.result_expr &:= c_param.result_expr;
    else
      process_create_declaration(param_type, global_c_expr);
      process_create_call(param_type, c_param.expr, c_expr.result_expr);
    end if;
  end func;


const proc: getTemporaryToResultExpr (in reference: aParam, inout expr_type: c_expr) is func

  local
    var expr_type: c_param is expr_type.value;
    var type: param_type is void;
  begin
    param_type := getExprResultType(aParam);
    prepareAnyParamTemporarys(aParam, c_param, c_expr);
    getTemporaryToResultExpr(param_type, c_param, c_expr);
  end func;


const func string: beginCastGeneric (in type: dest_type, inout expr_type: c_expr) is func

  result
    var string: temp_name is "";
  begin
    c_expr.expr &:= "(";
    if dest_type in typeCategory and typeCategory[dest_type] = FLOATOBJECT or
        not ccConf.LITTLE_ENDIAN_INTTYPE then
      incr(c_expr.temp_num);
      temp_name := "tmp_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "rtlValueunion ";
      c_expr.temp_decls &:= temp_name;
      c_expr.temp_decls &:= ";\n";
      c_expr.expr &:= temp_name;
      c_expr.expr &:= ".genericvalue=";
    else
      c_expr.expr &:= type_name(dest_type);
      c_expr.expr &:= ")(";
    end if;
  end func;


const proc: endCastGeneric (in type: dest_type, in string: temp_name, inout expr_type: c_expr) is func

  begin
    if dest_type in typeCategory and typeCategory[dest_type] = FLOATOBJECT or
        not ccConf.LITTLE_ENDIAN_INTTYPE then
      c_expr.expr &:= ",";
      c_expr.expr &:= temp_name;
      c_expr.expr &:= ".";
      c_expr.expr &:= raw_type_value(dest_type);
    end if;
    c_expr.expr &:= ")";
  end func;


const func string: beginCastGenericToResultExpr (in type: dest_type, inout expr_type: c_expr) is func

  result
    var string: temp_name is "";
  begin
    c_expr.result_expr &:= "(";
    if dest_type in typeCategory and typeCategory[dest_type] = FLOATOBJECT or
        not ccConf.LITTLE_ENDIAN_INTTYPE then
      incr(c_expr.temp_num);
      temp_name := "tmp_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "rtlValueunion ";
      c_expr.temp_decls &:= temp_name;
      c_expr.temp_decls &:= ";\n";
      c_expr.result_expr &:= temp_name;
      c_expr.result_expr &:= ".genericvalue=";
    else
      c_expr.result_expr &:= type_name(dest_type);
      c_expr.result_expr &:= ")(";
    end if;
  end func;


const proc: endCastGenericToResultExpr (in type: dest_type, in string: temp_name, inout expr_type: c_expr) is func

  begin
    if dest_type in typeCategory and typeCategory[dest_type] = FLOATOBJECT or
        not ccConf.LITTLE_ENDIAN_INTTYPE then
      c_expr.result_expr &:= ",";
      c_expr.result_expr &:= temp_name;
      c_expr.result_expr &:= ".";
      c_expr.result_expr &:= raw_type_value(dest_type);
    end if;
    c_expr.result_expr &:= ")";
  end func;


const proc: getAnyParamToTempAssigns (in expr_type: c_param, inout expr_type: c_expr) is func

  begin
    if c_param.result_expr <> "" then
      c_expr.temp_decls &:= c_param.result_decl;
      c_expr.temp_frees &:= c_param.result_free;
      c_expr.temp_to_null &:= c_param.result_to_null;
      c_expr.temp_assigns &:= c_param.result_intro;
      c_expr.temp_assigns &:= c_param.result_expr;
      c_expr.temp_assigns &:= c_param.result_finish;
    else
      c_expr.temp_assigns &:= c_param.expr;
    end if;
  end func;


const proc: getAnyParamToTempAssigns (in reference: aParam, inout expr_type: c_expr) is func

  local
    var expr_type: c_param is expr_type.value;
  begin
    prepareAnyParamTemporarys(aParam, c_param, c_expr);
    getAnyParamToTempAssigns(c_param, c_expr);
  end func;


const proc: doLocalDeclsOfStatement (in expr_type: statement, inout expr_type: c_expr) is func

  begin
    if statement.temp_num > 0 then
      c_expr.expr &:= "{\n";
      AppendWithDiagnostic(statement.temp_decls, c_expr);
      AppendWithDiagnostic(statement.temp_assigns, c_expr);
      AppendWithDiagnostic(statement.expr, c_expr);
      AppendWithDiagnostic(statement.temp_frees, c_expr);
      AppendWithDiagnostic(statement.result_free, c_expr);
      c_expr.expr &:= "}\n";
    else
      AppendWithDiagnostic(statement.expr, c_expr);
    end if;
  end func;


const func string: normalVariable (in reference: aParam, inout expr_type: c_expr) is func

  result
    var string: varName is "";
  local
    var expr_type: c_param is expr_type.value;
  begin
    prepareAnyParamTemporarys(aParam, c_param, c_expr);
    varName := "(" & c_param.expr & ")";
  end func;


const func string: getTempVariable (in string: typeName, in string: namePrefix,
    in reference: param1, inout expr_type: c_expr) is func

  result
    var string: variableName is "";
  begin
    incr(c_expr.temp_num);
    variableName := namePrefix & str(c_expr.temp_num);
    c_expr.temp_decls &:= typeName;
    c_expr.temp_decls &:= " ";
    c_expr.temp_decls &:= variableName;
    c_expr.temp_decls &:= ";\n";
    c_expr.expr &:= variableName;
    c_expr.expr &:= "=";
    getAnyParamToExpr(param1, c_expr);
    c_expr.expr &:= ",";
  end func;


const func string: getParameterAsVariable (in string: typeName, in string: namePrefix,
    in reference: param1, inout expr_type: c_expr) is func

  result
    var string: variableName is "";
  begin
    if isNormalVariable(param1) then
      variableName := normalVariable(param1, c_expr);
    else
      variableName := getTempVariable(typeName, namePrefix, param1, c_expr);
    end if;
  end func;


const func string: enum_value (in reference: current_object) is func

  result
    var string: enumValue is "";
  local
    var type: enum_type is void;
    var string: object_name is "";
  begin
    enum_type := getType(current_object);
    if enum_type in typeCategory and typeCategory[enum_type] = BOOLOBJECT then
      object_name := str(current_object);
      if object_name = "FALSE" then
        enumValue := "0/*FALSE*/";
      elsif object_name = "TRUE" then
        enumValue := "1/*TRUE*/";
      end if;
    else
      enumValue := "/*" & str(current_object) & "*/";
      if enum_type in enum_literal and
          current_object in enum_literal[enum_type] then
        enumValue &:= str(enum_literal[enum_type][current_object]);
      else
        enumValue &:= str(objNumber(current_object));
      end if;
    end if;
  end func;


const proc: reference_value (in reference: current_value,
    inout expr_type: c_expr) is func

  begin
    if current_value = NIL then
      c_expr.expr &:= "NULL";
    else
      c_expr.expr &:= "&(";
      process_expr(current_value, c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: ref_list_value (in ref_list: current_value,
    inout expr_type: c_expr) is func

  local
    var reference: element is NIL;
    var boolean: first_element is TRUE;
  begin
    if length(current_value) = 0 then
      c_expr.expr &:= "NULL";
    else
      c_expr.expr &:= "{";
      for element range current_value do
        if first_element then
          first_element := FALSE;
        else
          c_expr.expr &:= ", ";
        end if;
        c_expr.expr &:= "&(";
        process_expr(element, c_expr);
        c_expr.expr &:= ")";
      end for;
      c_expr.expr &:= "}";
    end if;
  end func;


const func boolean: isActionExpression (in reference: current_expression, in string: actionName) is func

  result
    var boolean: isActionExpression is FALSE;
  local
    var ref_list: params is ref_list.EMPTY;
  begin
    if category(current_expression) = CALLOBJECT then
      params := getValue(current_expression, ref_list);
      if category(params[1]) = ACTOBJECT and str(getValue(params[1], ACTION)) = actionName then
        isActionExpression := TRUE;
      end if;
    end if;
  end func;


const func reference: getActionParameter (in reference: current_expression, in integer: number) is func

  result
    var reference: actionParameter is NIL;
  local
    var ref_list: params is ref_list.EMPTY;
  begin
    if category(current_expression) = CALLOBJECT then
      params := getValue(current_expression, ref_list);
      actionParameter := params[succ(number)];
    end if;
  end func;


const set of category: constantExpressionCategories is {
    TYPEOBJECT, INTOBJECT, BIGINTOBJECT, CHAROBJECT,
    STRIOBJECT, BSTRIOBJECT, ARRAYOBJECT, HASHOBJECT, STRUCTOBJECT,
    SETOBJECT, FILEOBJECT, SOCKETOBJECT, LISTOBJECT, FLOATOBJECT,
    WINOBJECT, ENUMLITERALOBJECT, REFLISTOBJECT, SYMBOLOBJECT};


const func boolean: isPureFunction (in reference: function) is forward;


const func boolean: isConstant (in reference: current_expression,
    in boolean_obj_hash: local_objects) is forward;


const func boolean: isConstantCall (in reference: current_expression,
    in boolean_obj_hash: local_objects) is func

  result
    var boolean: isConstantCall is FALSE;
  local
    var ref_list: params is ref_list.EMPTY;
    var reference: function is NIL;
    var reference: obj is NIL;
  begin
    params := getValue(current_expression, ref_list);
    function := params[1];
    params := params[2 ..];
    if category(function) in constantExpressionCategories then
      isConstantCall := TRUE;
    elsif isPureFunction(function) then
      # write(" {isPureFunction(" <& str(function) <& ")}");
      isConstantCall := TRUE;
      for obj range params until not isConstantCall do
        if not isConstant(obj, local_objects) then
          # write(" [not isConstant(" <& str(obj) <& ") " <& str(category(obj)) <& "]");
          isConstantCall := FALSE;
        end if;
      end for;
(*
    else
      # write(" [not isPureFunction(" <& str(function) <& ") " <& str(category(function)) <& "]");
      if category(function) = ACTOBJECT then
        # write(" [" <& str(getValue(function, ACTION)) <& "]");
      end if;
*)
    end if;
  end func;


const func boolean: isConstant (in reference: current_expression,
    in boolean_obj_hash: local_objects) is func

  result
    var boolean: isConstant is FALSE;
  local
    var category: exprCategory is category.value;
  begin
    if current_expression in local_objects then
      # write(" [local " <& str(current_expression) <& "]");
      isConstant := TRUE;
    elsif not isVar(current_expression) then
      exprCategory := category(current_expression);
      if exprCategory = MATCHOBJECT or exprCategory = CALLOBJECT then
        isConstant := isConstantCall(current_expression, local_objects);
      elsif exprCategory in constantExpressionCategories then
        isConstant := TRUE;
      end if;
    end if;
  end func;


const func boolean: isPureBlockFunction (in reference: function) is func

  result
    var boolean: isPureBlockFunction is FALSE;
  local
    var type: function_type is void;
    var reference: result_object is NIL;
    var ref_list: local_object_list is ref_list.EMPTY;
    var reference: obj is NIL;
    var boolean_obj_hash: local_objects is boolean_obj_hash.value;
  begin
    # write(str(function));
    function_type := getType(function);
    result_object := resultVar(function);
    if not isVarfunc(function_type) then
      if result_object <> NIL then
        local_object_list := make_list(result_object);
      end if;
      local_object_list &:= formalParams(function) & localVars(function);
      for obj range local_object_list do
        # write(" " <& str(obj));
        local_objects @:= [obj] TRUE;
      end for;
      isPureBlockFunction := isConstant(body(function), local_objects);
    end if;
    # writeln(" " <& isPureBlockFunction);
  end func;


const func boolean: isPureFunction (in reference: function) is func

  result
    var boolean: isPureFunction is FALSE;
  local
    const set of string: pureFunctionActions is
        {"ARR_ARRLIT", "ARR_ARRLIT2", "ARR_BASELIT", "ARR_BASELIT2", "ARR_CAT",
         "ARR_CONV", "ARR_EMPTY", "ARR_EXTEND", "ARR_GEN", "ARR_HEAD", "ARR_IDX",
         "ARR_LNG", "ARR_MAXIDX", "ARR_MINIDX", "ARR_RANGE", "ARR_SORT",
         "ARR_SUBARR", "ARR_TAIL", "ARR_TIMES",
         "BIG_ABS", "BIG_ADD", "BIG_BIT_LENGTH", "BIG_CLIT", "BIG_CMP", "BIG_CONV",
         "BIG_DIV", "BIG_EQ", "BIG_FROM_BSTRI_BE", "BIG_FROM_BSTRI_LE", "BIG_GCD",
         "BIG_GE", "BIG_GT", "BIG_HASHCODE", "BIG_ICONV", "BIG_IPOW", "BIG_LE",
         "BIG_LOG2", "BIG_LOWEST_SET_BIT", "BIG_LSHIFT", "BIG_LT", "BIG_MDIV",
         "BIG_MOD", "BIG_MULT", "BIG_NE", "BIG_NEGATE", "BIG_ODD", "BIG_ORD",
         "BIG_PARSE", "BIG_PLUS", "BIG_PRED", "BIG_REM", "BIG_RSHIFT", "BIG_SBTR",
         "BIG_STR", "BIG_SUCC", "BIG_TO_BSTRI_BE", "BIG_TO_BSTRI_LE", "BIG_VALUE",
         "BLN_AND", "BLN_EQ", "BLN_GE", "BLN_GT", "BLN_ICONV", "BLN_LE", "BLN_LT",
         "BLN_NE", "BLN_NOT", "BLN_OR", "BLN_ORD", "BLN_VALUE",
         "BST_CAT", "BST_CMP", "BST_EMPTY", "BST_EQ", "BST_HASHCODE", "BST_IDX",
         "BST_LNG", "BST_NE", "BST_PARSE", "BST_STR", "BST_VALUE",
         "CHR_CHR", "CHR_CLIT", "CHR_CMP", "CHR_CONV", "CHR_EQ", "CHR_GE",
         "CHR_GT", "CHR_HASHCODE", "CHR_ICONV", "CHR_LE", "CHR_LOW", "CHR_LT",
         "CHR_NE", "CHR_ORD", "CHR_PRED", "CHR_STR", "CHR_SUCC", "CHR_UP",
         "CHR_VALUE", "CMD_CONFIG_VALUE", "DRW_VALUE",
         "ENU_CONV", "ENU_EQ", "ENU_ICONV2", "ENU_NE", "ENU_ORD2", "ENU_VALUE",
         "FIL_EQ", "FIL_NE", "FIL_VALUE",
         "FLT_A2TAN", "FLT_ABS", "FLT_ACOS", "FLT_ADD", "FLT_ASIN", "FLT_ATAN",
         "FLT_CEIL", "FLT_CMP", "FLT_COS", "FLT_COSH", "FLT_DGTS", "FLT_DIV",
         "FLT_EQ", "FLT_EXP", "FLT_FLOOR", "FLT_GE", "FLT_GT", "FLT_HASHCODE",
         "FLT_ICONV", "FLT_IFLT", "FLT_IPOW", "FLT_ISNAN", "FLT_ISNEGATIVEZERO",
         "FLT_LE", "FLT_LOG", "FLT_LOG10", "FLT_LT", "FLT_MULT", "FLT_NE",
         "FLT_NEGATE", "FLT_PARSE", "FLT_PLUS", "FLT_POW", "FLT_ROUND", "FLT_SBTR",
         "FLT_SCI", "FLT_SIN", "FLT_SINH", "FLT_SQRT", "FLT_STR", "FLT_TAN",
         "FLT_TANH", "FLT_TRUNC", "FLT_VALUE",
         "HSH_CONTAINS", "HSH_EMPTY", "HSH_IDX", "HSH_KEYS", "HSH_LNG",
         "HSH_VALUES",
         "INT_ABS", "INT_ADD", "INT_AND", "INT_BINOM", "INT_BIT_LENGTH", "INT_CMP",
         "INT_CONV", "INT_DIV", "INT_EQ", "INT_FACT", "INT_GE", "INT_GT",
         "INT_HASHCODE", "INT_LE", "INT_LOG2", "INT_LOWEST_SET_BIT", "INT_LPAD0",
         "INT_LSHIFT", "INT_LT", "INT_MDIV", "INT_MOD", "INT_MULT", "INT_NE",
         "INT_NEGATE", "INT_ODD", "INT_OR", "INT_ORD", "INT_PARSE", "INT_PLUS",
         "INT_POW", "INT_PRED", "INT_radix", "INT_RADIX", "INT_REM", "INT_RSHIFT",
         "INT_SBTR", "INT_SQRT", "INT_STR", "INT_SUCC", "INT_TO_BSTRI_BE",
         "INT_TO_BSTRI_LE", "INT_URSHIFT", "INT_VALUE", "INT_XOR",
         "ITF_CMP", "ITF_EQ", "ITF_HASHCODE", "ITF_NE",
         "LST_CAT", "LST_ELEM", "LST_EMPTY", "LST_HEAD", "LST_IDX", "LST_LNG",
         "LST_RANGE", "LST_TAIL",
         "PRG_EQ", "PRG_NE",
         "REF_CMP", "REF_EQ", "REF_NE", "REF_NIL",
         "RFL_CAT", "RFL_ELEM", "RFL_EMPTY", "RFL_EQ", "RFL_HEAD", "RFL_IDX",
         "RFL_IPOS", "RFL_LNG", "RFL_NE", "RFL_NOT_ELEM", "RFL_POS", "RFL_RANGE",
         "RFL_TAIL", "RFL_VALUE",
         "SCT_LNG", "SCT_SELECT",
         "SET_ARRLIT", "SET_BASELIT", "SET_CARD", "SET_CMP", "SET_CONV",
         "SET_DIFF", "SET_ELEM", "SET_EMPTY", "SET_EQ", "SET_GE", "SET_GT",
         "SET_HASHCODE", "SET_ICONV", "SET_INTERSECT", "SET_LE", "SET_LT",
         "SET_MAX", "SET_MIN", "SET_NE", "SET_NEXT", "SET_NOT_ELEM",
         "SET_SCONV", "SET_SYMDIFF", "SET_UNION", "SET_VALUE",
         "SOC_EQ", "SOC_NE",
         "STR_CAT", "STR_CHIPOS", "STR_CHPOS", "STR_CHSPLIT", "STR_CLIT",
         "STR_CMP", "STR_EQ", "STR_GE", "STR_GT", "STR_HASHCODE", "STR_HEAD",
         "STR_IDX","STR_IPOS", "STR_LE", "STR_LIT", "STR_LNG", "STR_LOW",
         "STR_LPAD", "STR_LPAD0", "STR_LT", "STR_LTRIM", "STR_MULT", "STR_NE",
         "STR_POS", "STR_RANGE", "STR_RCHIPOS", "STR_RCHPOS", "STR_REPL",
         "STR_RIPOS", "STR_RPAD", "STR_RPOS", "STR_RTRIM", "STR_SPLIT", "STR_STR",
         "STR_SUBSTR", "STR_TAIL", "STR_TOUTF8", "STR_TRIM", "STR_UP",
         "STR_UTF8TOSTRI", "STR_VALUE",
         "TYP_CMP", "TYP_EQ", "TYP_NE"};
    const set of string: specialFunctionActions is
        {"PRC_FOR_DOWNTO", "PRC_FOR_TO", "SET_INCL", "TYP_VARCONV"};
    var category: functionCategory is category.value;
    var string: action_name is "";
    var reference: obj is NIL;
  begin
    functionCategory := category(function);
    if functionCategory = ACTOBJECT then
      action_name := str(getValue(function, ACTION));
      isPureFunction := action_name in pureFunctionActions or action_name in specialFunctionActions;
    elsif functionCategory = BLOCKOBJECT then
      isPureFunction := isPureBlockFunction(function);
    end if;
  end func;


const func boolean: isConstant (in reference: current_expression) is forward;


const func boolean: isConstantCall (in reference: current_expression) is func

  result
    var boolean: isConstantCall is FALSE;
  local
    var ref_list: params is ref_list.EMPTY;
    var reference: function is NIL;
    var reference: obj is NIL;
  begin
    params := getValue(current_expression, ref_list);
    function := params[1];
    params := params[2 ..];
    if isPureFunction(function) then
      isConstantCall := TRUE;
      for obj range params until not isConstantCall do
        if not isConstant(obj) then
          isConstantCall := FALSE;
        end if;
      end for;
    end if;
  end func;


const func boolean: isConstant (in reference: current_expression) is func

  result
    var boolean: isConstant is FALSE;
  local
    var category: exprCategory is category.value;
  begin
    if not isVar(current_expression) then
      exprCategory := category(current_expression);
      if exprCategory = MATCHOBJECT or exprCategory = CALLOBJECT then
        isConstant := isConstantCall(current_expression);
      elsif exprCategory in constantExpressionCategories then
        isConstant := TRUE;
      elsif exprCategory = BLOCKOBJECT then
        isConstant := TRUE;
      elsif exprCategory = ACTOBJECT then
        isConstant := TRUE;
      end if;
    end if;
  end func;


const func boolean: isConstantExpr (in reference: current_expression) is func

  result
    var boolean: isConstantExpr is FALSE;
  local
    var category: exprCategory is category.value;
  begin
    if not isVar(current_expression) then
      exprCategory := category(current_expression);
      if exprCategory = MATCHOBJECT or exprCategory = CALLOBJECT then
        isConstantExpr := isConstantCall(current_expression);
      end if;
    end if;
  end func;


const func boolean: getConstant (in reference: currExpr, in category: exprCategory,
    inout reference: evaluatedExpr) is func
  result
    var boolean: okay is FALSE;
  begin
    if evaluate_const_expr = 1 and category(currExpr) = exprCategory and not isVar(currExpr) then
      evaluatedExpr := currExpr;
      incr(countEvaluations);
      okay := TRUE;
    elsif evaluate_const_expr >= 2 and isConstant(currExpr) then
      block
        evaluatedExpr := evaluate(prog, currExpr);
        if evaluatedExpr <> NIL then
          if category(evaluatedExpr) = exprCategory then
            incr(countEvaluations);
            okay := TRUE;
          end if;
        end if;
      exception
        catch NUMERIC_ERROR: noop;
        catch RANGE_ERROR:   noop;
        catch FILE_ERROR:    noop;
      end block;
    end if;
  end func;


const func string: getExprValue (in reference: current_expression, attr string) is func
  result
    var string: exprValue is "";
  local
    var reference: evaluated_expression is NIL;
  begin
    if category(current_expression) = STRIOBJECT then
      exprValue := getValue(current_expression, string);
    else
      evaluated_expression := evaluate(prog, current_expression);
      if evaluated_expression <> NIL then
        exprValue := getValue(evaluated_expression, string);
      end if;
    end if;
  end func;


const proc: process_statements (in expr_type: statements, inout expr_type: c_expr) is func

  begin
    c_expr.currentFile := statements.currentFile;
    c_expr.currentLine := statements.currentLine;
    if statements.temp_num <> 0 then
      AppendWithDiagnostic(statements.temp_decls, c_expr);
      AppendWithDiagnostic(statements.temp_assigns, c_expr);
      c_expr.expr &:= statements.expr;
      AppendWithDiagnostic(statements.temp_frees, c_expr);
    else
      c_expr.expr &:= statements.expr;
    end if;
  end func;


const proc: process_statements (in expr_type: condition, in expr_type: statements, inout expr_type: c_expr) is func

  begin
    c_expr.currentFile := statements.currentFile;
    c_expr.currentLine := statements.currentLine;
    if statements.temp_num <> 0 then
      AppendWithDiagnostic(statements.temp_decls, c_expr);
      if condition.temp_num <> 0 then
        AppendWithDiagnostic(condition.temp_frees, c_expr);
        AppendWithDiagnostic(condition.temp_to_null, c_expr);
      end if;
      AppendWithDiagnostic(statements.temp_assigns, c_expr);
      c_expr.expr &:= statements.expr;
      AppendWithDiagnostic(statements.temp_frees, c_expr);
    else
      c_expr.expr &:= statements.expr;
    end if;
  end func;


const proc: process_else (in reference: else_part, in boolean: insertKeyword,
    inout expr_type: c_expr) is func

  local
    var category: functionCategory is category.value;
    var ref_list: params is ref_list.EMPTY;
    var reference: function is NIL;
    var expr_type: c_param2 is expr_type.value;
    var string: action_name is "";
  begin
    if category(else_part) = MATCHOBJECT then
      params := getValue(else_part, ref_list);
      function := params[1];
      params := params[2 ..];
      functionCategory := category(function);
      if functionCategory = CONSTENUMOBJECT then
        process_expr(params[2], c_param2);
        if insertKeyword then
          c_expr.expr &:= "else {\n";
        end if;
        process_statements(c_param2, c_expr);
        if insertKeyword then
          c_expr.expr &:= "}\n";
        end if;
      elsif functionCategory = ACTOBJECT then
        if insertKeyword then
          c_expr.expr &:= "else\n";
        end if;
        c_expr.currentFile := file(else_part);
        c_expr.currentLine := line(else_part);
        process_action(function, params, c_expr);
      else
        c_expr.expr &:= "/*!!! ";
        c_expr.expr &:= str(functionCategory);
        c_expr.expr &:= " ";
        c_expr.expr &:= str(function);
        c_expr.expr &:= " !!!*/";
      end if;
    else
      c_expr.expr &:= "/*!! ";
      c_expr.expr &:= str(category(else_part));
      c_expr.expr &:= " ";
      c_expr.expr &:= str(else_part);
      c_expr.expr &:= " !!*/";
    end if
  end func;


const proc: process_const_prc_if (in boolean: condition, in reference: statement,
    inout expr_type: c_expr) is func
  local
    var expr_type: c_statement is expr_type.value;
  begin
    incr(countOptimizations);
    if condition then
      c_expr.expr &:= "/* Optimized: if TRUE */ {\n";
      process_expr(statement, c_statement);
      process_statements(c_statement, c_expr);
      c_expr.expr &:= "}\n";
    else
      c_expr.expr &:= "/* Optimized: if FALSE */\n";
    end if;
  end func;


const proc: process_prc_if (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var expr_type: c_condition is expr_type.value;
    var expr_type: c_statement is expr_type.value;
    var string: statementFile is "";
    var integer: statementLine is 0;
  begin
    if getConstant(params[2], ENUMLITERALOBJECT, evaluatedParam) then
      process_const_prc_if(getValue(evaluatedParam, boolean), params[4], c_expr);
    else
      process_expr(params[2], c_condition);
      process_expr(params[4], c_statement);
      if c_condition.temp_num <> 0 then
        c_expr.expr &:= "{\n";
        AppendWithDiagnostic(c_condition.temp_decls, c_expr);
        AppendWithDiagnostic(c_condition.temp_assigns, c_expr);
      end if;
      statementFile := c_expr.currentFile;
      statementLine := c_expr.currentLine;
      setDiagnosticLine(c_expr);
      c_expr.expr &:= "if (";
      c_expr.expr &:= c_condition.expr;
      c_expr.expr &:= ") {\n";
      process_statements(c_statement, c_expr);
      c_expr.expr &:= "}\n";
      if c_condition.temp_num <> 0 then
        c_expr.currentFile := statementFile;
        c_expr.currentLine := statementLine;
        AppendWithDiagnostic(c_condition.temp_frees, c_expr);
        c_expr.expr &:= "}\n";
      end if;
    end if;
  end func;


const proc: process_const_prc_if_elsif (in boolean: condition, in reference: thenPart,
    in reference: elsePart, inout expr_type: c_expr) is func
  local
    var expr_type: c_then_part is expr_type.value;
    var expr_type: c_else_part is expr_type.value;
  begin
    incr(countOptimizations);
    c_expr.expr &:= "/* Optimized: if ";
    c_expr.expr &:= str(condition);
    c_expr.expr &:= " */ {\n";
    if condition then
      process_expr(thenPart, c_then_part);
      process_statements(c_then_part, c_expr);
    else
      process_else(elsePart, FALSE, c_else_part);
      process_statements(c_else_part, c_expr);
    end if;
    c_expr.expr &:= "}\n";
  end func;


const proc: process_prc_if_elsif (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var expr_type: c_condition is expr_type.value;
    var expr_type: c_then_part is expr_type.value;
    var expr_type: c_else_part is expr_type.value;
    var string: statementFile is "";
    var integer: statementLine is 0;
  begin
    if getConstant(params[2], ENUMLITERALOBJECT, evaluatedParam) then
      process_const_prc_if_elsif(getValue(evaluatedParam, boolean),
          params[4], params[5], c_expr);
    else
      process_expr(params[2], c_condition);
      process_expr(params[4], c_then_part);
      c_else_part.temp_num := c_condition.temp_num;
      process_else(params[5], TRUE, c_else_part);
      if c_else_part.temp_num <> 0 then
        c_expr.expr &:= "{\n";
        AppendWithDiagnostic(c_condition.temp_decls, c_expr);
        AppendWithDiagnostic(c_else_part.temp_decls, c_expr);
        AppendWithDiagnostic(c_condition.temp_assigns, c_expr);
        AppendWithDiagnostic(c_else_part.temp_assigns, c_expr);
      end if;
      statementFile := c_expr.currentFile;
      statementLine := c_expr.currentLine;
      setDiagnosticLine(c_expr);
      c_expr.expr &:= "if (";
      c_expr.expr &:= c_condition.expr;
      c_expr.expr &:= ") {\n";
      process_statements(c_then_part, c_expr);
      c_expr.expr &:= "} ";
      c_expr.expr &:= c_else_part.expr;
      if c_else_part.temp_num <> 0 then
        c_expr.currentFile := statementFile;
        c_expr.currentLine := statementLine;
        AppendWithDiagnostic(c_condition.temp_frees, c_expr);
        AppendWithDiagnostic(c_else_part.temp_frees, c_expr);
        c_expr.expr &:= "}\n";
      end if;
    end if;
  end func;


const proc: process_prc_while (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: c_condition is expr_type.value;
    var expr_type: c_statement is expr_type.value;
    var string: statementFile is "";
    var integer: statementLine is 0;
  begin
    process_expr(params[2], c_condition);
    c_statement.temp_num := c_condition.temp_num;
    process_expr(params[4], c_statement);
    if c_condition.temp_num <> 0 then
      c_expr.expr &:= "{\n";
      AppendWithDiagnostic(c_condition.temp_decls, c_expr);
      AppendWithDiagnostic(c_condition.temp_assigns, c_expr);
    end if;
    statementFile := c_expr.currentFile;
    statementLine := c_expr.currentLine;
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "while (";
    c_expr.expr &:= c_condition.expr;
    c_expr.expr &:= ") {\n";
    process_statements(c_condition, c_statement, c_expr);
    c_expr.expr &:= "}\n";
    if c_condition.temp_num <> 0 then
      c_expr.currentFile := statementFile;
      c_expr.currentLine := statementLine;
      AppendWithDiagnostic(c_condition.temp_frees, c_expr);
      c_expr.expr &:= "}\n";
    end if;
  end func;


const proc: process_prc_repeat (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: c_condition is expr_type.value;
    var expr_type: c_statement is expr_type.value;
  begin
    process_expr(params[4], c_condition);
    c_statement.temp_num := c_condition.temp_num;
    process_expr(params[2], c_statement);
    if c_condition.temp_num <> 0 then
      c_expr.expr &:= "{\n";
      AppendWithDiagnostic(c_condition.temp_decls, c_expr);
      AppendWithDiagnostic(c_condition.temp_assigns, c_expr);
    end if;
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "do {\n";
    process_statements(c_condition, c_statement, c_expr);
    c_expr.expr &:= diagnosticLine(params[4]);
    c_expr.expr &:= "} while (!(";
    c_expr.expr &:= c_condition.expr;
    c_expr.expr &:= "));\n";
    if c_condition.temp_num <> 0 then
      c_expr.currentFile := file(params[4]);
      c_expr.currentLine := line(params[4]);
      AppendWithDiagnostic(c_condition.temp_frees, c_expr);
      c_expr.expr &:= "}\n";
    end if;
  end func;


const proc: process_const_prc_for (in reference: variable, in reference: startExpr,
    in integer: endValue, in reference: statement, in boolean: for_to,
    inout expr_type: c_expr) is func

  local
    var expr_type: c_start_expr is expr_type.value;
    var expr_type: c_statement is expr_type.value;
    var string: start_name is "";
    var integer: temp_num is 0;
  begin
    incr(countOptimizations);
    process_expr(startExpr, c_start_expr);
    c_statement.temp_num := c_start_expr.temp_num;
    process_expr(statement, c_statement);
    temp_num := c_statement.temp_num;
    incr(temp_num);
    if c_start_expr.temp_decls <> "" then
      c_expr.expr &:= "{\n";
      AppendWithDiagnostic(c_start_expr.temp_decls, c_expr);
    end if;
    if c_start_expr.temp_frees <> "" then
      start_name := "tmp_s_" & str(temp_num);
      setDiagnosticLine(c_expr);
      c_expr.expr &:= "inttype ";
      c_expr.expr &:= start_name;
      if c_start_expr.temp_assigns <> "" then
        c_expr.expr &:= ";\n";
        AppendWithDiagnostic(c_start_expr.temp_assigns, c_expr);
        setDiagnosticLine(c_expr);
        c_expr.expr &:= start_name;
      end if;
      c_expr.expr &:= "=";
      c_expr.expr &:= c_start_expr.expr;
      c_expr.expr &:= ";\n";
      AppendWithDiagnostic(c_start_expr.temp_frees, c_expr);
    else
      start_name := c_start_expr.expr;
      AppendWithDiagnostic(c_start_expr.temp_assigns, c_expr);
    end if;
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "for (";
    process_expr(variable, c_expr);
    c_expr.expr &:= "=";
    c_expr.expr &:= start_name;
    c_expr.expr &:= "; ";
    process_expr(variable, c_expr);
    if for_to then
      c_expr.expr &:= "<=";
    else
      c_expr.expr &:= ">=";
    end if;
    c_expr.expr &:= integerLiteral(endValue);
    c_expr.expr &:= "; (";
    process_expr(variable, c_expr);
    if for_to then
      c_expr.expr &:= ")++) {\n";
    else
      c_expr.expr &:= ")--) {\n";
    end if;
    process_statements(c_statement, c_expr);
    c_expr.expr &:= "}\n";
    if c_start_expr.temp_decls <> "" then
      c_expr.expr &:= "}\n";
    end if;
  end func;


const proc: process_prc_for (in reference: variable, in reference: startExpr,
    in reference: endExpr, in reference: statement, in boolean: for_to,
    inout expr_type: c_expr) is func

  local
    var expr_type: c_start_expr is expr_type.value;
    var expr_type: c_end_expr is expr_type.value;
    var expr_type: c_statement is expr_type.value;
    var string: start_name is "";
    var string: end_name is "";
    var integer: temp_num is 0;
  begin
    process_expr(startExpr, c_start_expr);
    c_end_expr.temp_num := c_start_expr.temp_num;
    process_expr(endExpr, c_end_expr);
    c_statement.temp_num := c_end_expr.temp_num;
    process_expr(statement, c_statement);
    temp_num := c_statement.temp_num;
    incr(temp_num);
    c_expr.expr &:= "{\n";
    AppendWithDiagnostic(c_start_expr.temp_decls, c_expr);
    AppendWithDiagnostic(c_end_expr.temp_decls, c_expr);
    if c_start_expr.temp_frees <> "" then
      start_name := "tmp_s_" & str(temp_num);
      setDiagnosticLine(c_expr);
      c_expr.expr &:= "inttype ";
      c_expr.expr &:= start_name;
      c_expr.expr &:= ";\n";
    else
      start_name := c_start_expr.expr;
    end if;
    end_name := "tmp_e_" & str(temp_num);
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "inttype ";
    c_expr.expr &:= end_name;
    if  c_start_expr.temp_assigns <> "" or
        c_start_expr.temp_frees <> "" or
        c_end_expr.temp_assigns <> "" then
      c_expr.expr &:= ";\n";
      AppendWithDiagnostic(c_start_expr.temp_assigns, c_expr);
      AppendWithDiagnostic(c_end_expr.temp_assigns, c_expr);
      if c_start_expr.temp_frees <> "" then
        setDiagnosticLine(c_expr);
        c_expr.expr &:= start_name;
        c_expr.expr &:= "=";
        c_expr.expr &:= c_start_expr.expr;
        c_expr.expr &:= ";\n";
        AppendWithDiagnostic(c_start_expr.temp_frees, c_expr);
      end if;
      setDiagnosticLine(c_expr);
      c_expr.expr &:= end_name;
    end if;
    c_expr.expr &:= "=";
    c_expr.expr &:= c_end_expr.expr;
    c_expr.expr &:= ";\n";
    AppendWithDiagnostic(c_end_expr.temp_frees, c_expr);
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "for (";
    process_expr(variable, c_expr);
    c_expr.expr &:= "=";
    c_expr.expr &:= start_name;
    c_expr.expr &:= "; ";
    process_expr(variable, c_expr);
    if for_to then
      c_expr.expr &:= "<=";
    else
      c_expr.expr &:= ">=";
    end if;
    c_expr.expr &:= end_name;
    c_expr.expr &:= "; (";
    process_expr(variable, c_expr);
    if for_to then
      c_expr.expr &:= ")++) {\n";
    else
      c_expr.expr &:= ")--) {\n";
    end if;
    process_statements(c_statement, c_expr);
    c_expr.expr &:= "}\n}\n";
  end func;


const proc: process_prc_for (in ref_list: params, in boolean: for_to,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[6], INTOBJECT, evaluatedParam) then
      process_const_prc_for(params[2], params[4], getValue(evaluatedParam, integer),
          params[8], for_to, c_expr);
    else
      process_prc_for(params[2], params[4], params[6], params[8], for_to, c_expr);
    end if;
  end func;


const proc: process_prc_for_downto (in ref_list: params, inout expr_type: c_expr) is func

  begin
    process_prc_for(params, FALSE, c_expr);
  end func;


const proc: process_prc_for_to (in ref_list: params, inout expr_type: c_expr) is func

  begin
    process_prc_for(params, TRUE, c_expr);
  end func;


const proc: process_bitset (in bitset: currentSet, in string: diagnosticLine,
    inout expr_type: c_expr) is func

  local
    var integer: number is 0;
  begin
    for number range min(currentSet) to max(currentSet) do
      if number in currentSet then
        c_expr.expr &:= diagnosticLine;
        c_expr.expr &:= "case ";
        c_expr.expr &:= str(number);
        c_expr.expr &:= ":\n";
      end if;
    end for;
  end func;


const proc: process_case_labels (in reference: current_expression, inout expr_type: c_expr) is func

  local
    var reference: case_labels is NIL;
    var category: labelCategory is category.value;
  begin
    case_labels := evaluate(prog, current_expression);
    labelCategory := category(case_labels);
    if labelCategory = SETOBJECT then
      process_bitset(getValue(case_labels, bitset),
          diagnosticLine(current_expression), c_expr);
    else
      c_expr.expr &:= "/* case ";
      c_expr.expr &:= str(labelCategory);
      c_expr.expr &:= " */";
    end if;
  end func;


const proc: process_when (in reference: when_expr, inout expr_type: c_expr) is func

  local
    var ref_list: params is ref_list.EMPTY;
    var reference: function is NIL;
  begin
    params := getValue(when_expr, ref_list);
    function := params[1];
    params := params[2 ..];
    process_case_labels(params[2], c_expr);
    process_expr(params[4], c_expr);
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "break;\n";
    if length(params) >= 5 then
      process_when(params[5], c_expr);
    end if;
  end func;


const proc: process_prc_case (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "switch (";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ") {\n";
    process_when(params[4], c_expr);
    c_expr.expr &:= "}\n";
  end func;


const proc: process_prc_case_def (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "switch (";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ") {\n";
    process_when(params[4], c_expr);
    c_expr.expr &:= "default:\n";
    process_expr(params[7], c_expr);
    c_expr.expr &:= "break;\n";
    c_expr.expr &:= "}\n";
  end func;


const proc: process_prc_block (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: current_catch is NIL;
    var ref_list: catch_expr is ref_list.EMPTY;
    var reference: catch_value is NIL;
  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "{\n";
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "int fail_value;\n";
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "catch_stack_pos++;\n";
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "if (catch_stack_pos >= max_catch_stack) {\n";
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "  resize_catch_stack();\n";
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "}\n";
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "if ((fail_value = do_setjmp(catch_stack[catch_stack_pos])) == 0) {\n";
    process_expr(params[2], c_expr);
    current_catch := params[4];
    catch_expr := getValue(current_catch, ref_list);
    c_expr.expr &:= diagnosticLine(current_catch);
    c_expr.expr &:= "} else {\n";
    # c_expr.expr &:= "printf(\"catch %d\\n\", fail_value);\n";
    while current_catch <> NIL and
        category(current_catch) = MATCHOBJECT and
        length(catch_expr) >= 5 do
      catch_value := catch_expr[3];
      c_expr.expr &:= diagnosticLine(current_catch);
      c_expr.expr &:= "if (";
      process_expr(catch_value, c_expr);
      c_expr.expr &:= " == fail_value - 1) {\n";
      process_expr(catch_expr[5], c_expr);
      if length(catch_expr) >= 6 then
        c_expr.expr &:= diagnosticLine(current_catch);
        c_expr.expr &:= "} else\n";
        current_catch := catch_expr[6];
        catch_expr := getValue(current_catch, ref_list);
      else
        incr(c_expr.currentLine);
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "} else {\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "  catch_stack_pos--;\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "  raise_error(fail_value);\n";
        current_catch := NIL;
      end if;
    end while;
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "}\n";
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "}\n";
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "catch_stack_pos--;\n";
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "}\n";
  end func;


const proc: process_func_call (in reference: function,
    in ref_list: actual_params, inout expr_type: c_expr) is forward;


const proc: process_prc_dynamic (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  begin
    process_func_call(function, params, c_expr);
  end func;


const proc: process_prc_exit (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "exit(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_prc_hsize (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "heapsize()";
  end func;


const proc: process_prc_semicol (in ref_list: params, inout expr_type: c_expr) is func

  begin
    process_expr(params[1], c_expr);
    process_expr(params[3], c_expr);
  end func;


const proc: do_noop_param(in reference: formal_param, in reference: actual_param,
    inout expr_type: c_expr) is func

  local
    var category: paramCategory is category.value;
    var type: object_type is void;
  begin
    paramCategory := category(actual_param);
    if paramCategory <> SYMBOLOBJECT and
        category(formal_param) <> SYMBOLOBJECT then
      object_type := getType(formal_param);
      if isFunc(object_type) or isVarfunc(object_type) then
        c_expr.expr &:= "/*expression*/";
(*
        if getType(formal_param) <> getType(actual_param) then
          PRINT("***###***\n");
        end if;
        object_type := resultType(object_type);
        TRACE(object_type); PRINT("\n");
        TRACE_OBJ(actual_param); PRINT("\n\n");
*)
      else
        c_expr.expr &:= "/* ";
        c_expr.expr &:= str(paramCategory);
        if paramCategory = CALLOBJECT then
          paramCategory := category(getValue(actual_param, ref_list)[1]);
          c_expr.expr &:= " ";
          c_expr.expr &:= str(paramCategory);
          if paramCategory = ACTOBJECT then
            c_expr.expr &:= " ";
            c_expr.expr &:= str(getValue(getValue(actual_param, ref_list)[1], ACTION));
          end if
        end if;
        c_expr.expr &:= " */";
        getAnyParamToExpr(actual_param, c_expr);
        c_expr.expr &:= ";";
      end if;
    else
      c_expr.expr &:= "/*";
      c_expr.expr &:= str(actual_param);
      c_expr.expr &:= "*/";
    end if;
  end func;


const proc: noop_params (in ref_list: formal_params,
    in ref_list: actual_params, inout expr_type: c_expr) is func

  local
    var integer: number is 0;
  begin
    for number range 1 to length(formal_params) do
      if number <= length(actual_params) then
        do_noop_param(formal_params[number], actual_params[number], c_expr);
      end if;
    end for;
  end func;


const proc: process_prc_other_noop (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "/*noop*/";
    noop_params(formalParams(function), params, c_expr);
    c_expr.expr &:= "\n";
  end func;


const proc: process_prc_noop (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  begin
    if length(params) = 3 and str(params[2]) = ";" then
      process_prc_semicol(params, c_expr);
    else
      process_prc_other_noop(function, params, c_expr);
    end if;
  end func;


const proc: process_prc_args (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    c_expr.expr &:= type_name(resultType(getType(function)));
    c_expr.expr &:= ")(arg_v)";
  end func;


const proc: processFuncValue (in string: valueName, in type: genericFuncType,
    in reference: closure, inout expr_type: c_expr) is forward;


const proc: process_prc_cpy (in ref_list: params, inout expr_type: c_expr) is func

  local
    var category: paramCategory is category.value;
    var string: valueName is "";
  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "/* prc_cpy */ ";
    if isVar(params[3]) then
      # c_expr.expr &:= "o_";
      # create_name(params[1], c_expr.expr);
      process_expr(params[1], c_expr);
      c_expr.expr &:= " = o_";
      create_name(params[3], c_expr.expr);
      c_expr.expr &:= ";\n";
    elsif isFunc(getType(params[3])) and getType(params[1]) = resultType(getType(params[3])) then
      c_expr.expr &:= "/* call func */ ";
      process_expr(params[1], c_expr);
      c_expr.expr &:= " = ";
      process_expr(params[3], c_expr);
      c_expr.expr &:= ";\n";
    else
      paramCategory := category(params[3]);
      if paramCategory = MATCHOBJECT or paramCategory = CALLOBJECT or
          paramCategory = BLOCKOBJECT then
        # c_expr.expr &:= "o_";
        # create_name(params[1], c_expr.expr);
        process_expr(params[1], c_expr);
        c_expr.expr &:= " = ";
        create_name(params[3], objNumber(params[3]), valueName);
        processFuncValue(valueName, getType(params[3]), params[3], c_expr);
        c_expr.expr &:= ";\n";
      else
        # c_expr.expr &:= "o_";
        # create_name(params[1], c_expr.expr);
        process_expr(params[1], c_expr);
        c_expr.expr &:= " = o_";
        create_name(params[3], c_expr.expr);
        c_expr.expr &:= ";\n";
      end if;
    end if;
  end func;


const proc: process_prc_raise (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "raise_error2(";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= "+1, ";
    c_expr.expr &:= sourceNameString(c_expr.currentFile);
    c_expr.expr &:= ", ";
    c_expr.expr &:= str(c_expr.currentLine);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_act_cpy (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: c_param1 is expr_type.value;
    var expr_type: c_param3 is expr_type.value;
  begin
    process_expr(params[1], c_param1);
    c_param3.temp_num := c_param1.temp_num;
    process_expr(params[3], c_param3);
    if c_param3.temp_num <> 0 then
      c_expr.expr &:= "{\n";
      AppendWithDiagnostic(c_param1.temp_decls, c_expr);
      AppendWithDiagnostic(c_param3.temp_decls, c_expr);
      AppendWithDiagnostic(c_param1.temp_assigns, c_expr);
      AppendWithDiagnostic(c_param3.temp_assigns, c_expr);
    end if;
    setDiagnosticLine(c_expr);
    c_expr.expr &:= c_param1.expr;
    c_expr.expr &:= "=";
    if c_param3.result_expr <> "" then
      c_expr.expr &:= c_param3.result_expr;
    else
      c_expr.expr &:= c_param3.expr;
    end if;
    c_expr.expr &:= ";\n";
    if c_param3.temp_num <> 0 then
      AppendWithDiagnostic(c_param1.temp_frees, c_expr);
      AppendWithDiagnostic(c_param3.temp_frees, c_expr);
      c_expr.expr &:= "}\n";
    end if;
  end func;


const proc: process_act_eq (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") == (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_act_iconv (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "actIConv(";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_act_ne (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") != (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_act_ord (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compilerLibraryUsed := TRUE;
    c_expr.expr := "actOrd(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_act_str (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compilerLibraryUsed := TRUE;
    prepare_stri_result(c_expr);
    c_expr.result_expr := "actStr(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_act_value (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "actValue(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_arr_append (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: c_param1 is expr_type.value;
    var expr_type: c_param3 is expr_type.value;
  begin
    process_expr(params[1], c_param1);
    c_param3.temp_num := c_param1.temp_num;
    getTemporaryToResultExpr(params[3], c_param3);
    incr(c_param3.temp_num);
    if has_temp_values(c_param3) then
      c_expr.expr &:= "{\n";
      AppendWithDiagnostic(c_param1.temp_decls, c_expr);
      AppendWithDiagnostic(c_param3.temp_decls, c_expr);
      AppendWithDiagnostic(c_param1.temp_assigns, c_expr);
      AppendWithDiagnostic(c_param3.temp_assigns, c_expr);
    end if;
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "arrAppend(&(";
    c_expr.expr &:= c_param1.expr;
    c_expr.expr &:= "), ";
    c_expr.expr &:= c_param3.result_expr;
    c_expr.expr &:= ");\n";
    if has_temp_values(c_param3) then
      AppendWithDiagnostic(c_param1.temp_frees, c_expr);
      AppendWithDiagnostic(c_param3.temp_frees, c_expr);
      c_expr.expr &:= "}\n";
    end if;
  end func;


const proc: process_arr_arrlit (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: anArray is NIL;
    var expr_type: c_param is expr_type.value;
  begin
    if isConstant(params[3]) then
      anArray := evaluate(prog, params[3]);
      if category(anArray) = ARRAYOBJECT then
        if anArray not in const_table then
          const_table @:= [anArray] length(const_table);
        end if;
        c_expr.expr &:= "arr[";
        c_expr.expr &:= str(const_table[anArray]);
        c_expr.expr &:= "]";
      end if;
    else
      prepareAnyParamTemporarys(params[3], c_param, c_expr);
      if c_param.result_expr <> "" then
        prepare_typed_result(getExprResultType(params[3]), c_expr);
        c_expr.result_expr := "/*arrArrlit()*/";
        c_expr.result_expr &:= c_param.result_expr;
      else
        c_expr.expr &:= "/*arrArrlit()*/";
        c_expr.expr &:= c_param.expr;
      end if;
    end if;
  end func;


const proc: process_arr_arrlit2 (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_typed_result(getExprResultType(params[4]), c_expr);
    c_expr.result_expr := "arrArrlit2(";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= ", ";
    getTemporaryToResultExpr(params[4], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_arr_baselit (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  begin
    if resultType(getType(function)) not in array_element then
      array_element @:= [resultType(getType(function))] getType(params[3]);
    end if;
    prepare_typed_result(resultType(getType(function)), c_expr);
    c_expr.result_expr := "arrBaselit((generictype)(";
    getGenericTemporaryToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= "))";
  end func;


const proc: process_arr_baselit2 (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  begin
    if resultType(getType(function)) not in array_element then
      array_element @:= [resultType(getType(function))] getType(params[4]);
    end if;
    prepare_typed_result(resultType(getType(function)), c_expr);
    c_expr.result_expr := "arrBaselit2(";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= ", (generictype)(";
    getGenericTemporaryToResultExpr(params[4], c_expr);
    c_expr.result_expr &:= "))";
  end func;


const proc: process_arr_cat (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_typed_result(getExprResultType(params[1]), c_expr);
    c_expr.result_expr := "arrCat(";
    getTemporaryToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getTemporaryToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_arr_conv (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: c_param is expr_type.value;
  begin
    prepareAnyParamTemporarys(params[3], c_param, c_expr);
    if c_param.result_expr <> "" then
      prepare_typed_result(getExprResultType(params[3]), c_expr);
      c_expr.result_expr := "/*arrConv()*/";
      c_expr.result_expr &:= c_param.result_expr;
    else
      c_expr.expr &:= "/*arrConv()*/";
      c_expr.expr &:= c_param.expr;
    end if;
  end func;


const proc: process_arr_cpy (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: c_param1 is expr_type.value;
    var expr_type: c_param3 is expr_type.value;
  begin
    process_expr(params[1], c_param1);
    c_param3.temp_num := c_param1.temp_num;
    process_expr(params[3], c_param3);
    if has_temp_values(c_param3) then
      c_expr.expr &:= "{\n";
      AppendWithDiagnostic(c_param1.temp_decls, c_expr);
      AppendWithDiagnostic(c_param3.temp_decls, c_expr);
      AppendWithDiagnostic(c_param1.temp_assigns, c_expr);
      AppendWithDiagnostic(c_param3.temp_assigns, c_expr);
    end if;
    if c_param3.result_expr <> "" then
      c_expr.expr &:= "{\n";
      setDiagnosticLine(c_expr);
      if isNormalVariable(params[1]) then
        c_expr.expr &:= "arraytype old_array=";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ";\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= "=";
      else
        c_expr.expr &:= "arraytype *array_ptr=&(";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ");\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "arraytype old_array=*array_ptr;\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "*array_ptr=";
      end if;
      c_expr.expr &:= c_param3.result_expr;
      c_expr.expr &:= ";\n";
      process_destr_declaration(getExprResultType(params[1]), global_c_expr);
      setDiagnosticLine(c_expr);
      process_destr_call(getExprResultType(params[1]),
          "old_array", c_expr.expr);
      c_expr.expr &:= "}\n";
    else
      process_cpy_declaration(getExprResultType(params[1]), global_c_expr);
      setDiagnosticLine(c_expr);
      process_cpy_call(getExprResultType(params[1]),
          c_param1.expr, c_param3.expr, c_expr.expr);
      c_expr.expr &:= ";\n";
    end if;
    if has_temp_values(c_param3) then
      AppendWithDiagnostic(c_param1.temp_frees, c_expr);
      AppendWithDiagnostic(c_param3.temp_frees, c_expr);
      c_expr.expr &:= "}\n";
    end if;
  end func;


const proc: process_arr_create (in ref_list: params, inout expr_type: c_expr) is func

  local
    var type: param_type is void;
  begin
    param_type := getExprResultType(params[3]);
    typeCategory @:= [param_type] ARRAYOBJECT;
    process_create_declaration(param_type, global_c_expr);
    process_expr(params[1], c_expr);
    c_expr.expr &:= "=create_";
    c_expr.expr &:= str(typeNumber(param_type));
    c_expr.expr &:= "(";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_arr_destr (in ref_list: params, inout expr_type: c_expr) is func

  local
    var type: param_type is void;
  begin
    param_type := getExprResultType(params[1]);
    process_destr_declaration(param_type, global_c_expr);
    c_expr.expr &:= "destr_";
    c_expr.expr &:= str(typeNumber(param_type));
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_arr_extend (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_typed_result(getExprResultType(params[1]), c_expr);
    c_expr.result_expr := "arrExtend(";
    getTemporaryToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", (generictype)(";
    getGenericTemporaryToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= "))";
  end func;


const proc: process_arr_gen (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  begin
    prepare_typed_result(resultType(getType(function)), c_expr);
    c_expr.result_expr := "arrGen((generictype)(";
    getGenericTemporaryToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= "), (generictype)(";
    getGenericTemporaryToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= "))";
  end func;


const proc: process_arr_head (in ref_list: params, inout expr_type: c_expr) is func

  local
    var type: param_type is void;
    var expr_type: c_param is expr_type.value;
    var string: array_name is "";
  begin
    param_type := getExprResultType(params[1]);
    prepare_typed_result(param_type, c_expr);
    prepareAnyParamTemporarys(params[1], c_param, c_expr);
    if c_param.result_expr <> "" then
      c_expr.temp_decls &:= c_param.result_decl;
      c_expr.temp_frees &:= c_param.result_free;
      c_expr.temp_to_null &:= c_param.result_to_null;
      c_expr.result_expr := "(";
      c_expr.result_expr &:= c_param.result_intro;
      c_expr.result_expr &:= c_param.result_expr;
      c_expr.result_expr &:= c_param.result_finish;
      c_expr.result_expr &:= ", arrHeadTemp(&(";
      c_expr.result_expr &:= c_param.result_temp;
      c_expr.result_expr &:= "), ";
      getStdParamToResultExpr(params[4], c_expr);
      c_expr.result_expr &:= "))";
    elsif valueIsAtHeap(array_element[param_type]) then
      incr(c_expr.temp_num);
      array_name := "tmp_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "arraytype ";
      c_expr.temp_decls &:= array_name;
      c_expr.temp_decls &:= "=NULL;\n";
      c_expr.temp_frees &:= "if (";
      c_expr.temp_frees &:= array_name;
      c_expr.temp_frees &:= " != NULL) {arrFree(";
      c_expr.temp_frees &:= array_name;
      c_expr.temp_frees &:= ");}\n";
      c_expr.temp_to_null &:= array_name;
      c_expr.temp_to_null &:= "=NULL;\n";
      c_expr.result_expr := "(";
      c_expr.result_expr &:= array_name;
      c_expr.result_expr &:= "=arrHead(";
      c_expr.result_expr &:= c_param.expr;
      c_expr.result_expr &:= ", ";
      getStdParamToResultExpr(params[4], c_expr);
      c_expr.result_expr &:= "), ";
      typeCategory @:= [param_type] ARRAYOBJECT;
      process_create_declaration(param_type, global_c_expr);
      process_create_call(param_type, array_name, c_expr.result_expr);
      c_expr.result_expr &:= ")";
    else
      c_expr.result_expr := "arrHead(";
      c_expr.result_expr &:= c_param.expr;
      c_expr.result_expr &:= ", ";
      getStdParamToResultExpr(params[4], c_expr);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_const_arr_idx (in reference: function, in reference: anArray,
    in reference: param3, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var integer: index is 0;
    var string: index_name is "";
  begin
    incr(countOptimizations);
    if anArray not in const_table then
      const_table @:= [anArray] length(const_table);
    end if;
    if getConstant(param3, INTOBJECT, evaluatedParam) then
      index := getValue(evaluatedParam, integer);
      if index < arrayMinIdx(anArray) or index > arrayMaxIdx(anArray) then
        process_raise_error("RANGE_ERROR", function, c_expr);
      else
        c_expr.expr &:= "arr[";
        c_expr.expr &:= str(const_table[anArray]);
        c_expr.expr &:= "]->arr[";
        c_expr.expr &:= str(index - arrayMinIdx(anArray));
        c_expr.expr &:= "]";
        c_expr.expr &:= select_value_from_rtlObjectstruct(resultType(getType(function)));
      end if;
    else
      c_expr.expr &:= "arr[";
      c_expr.expr &:= str(const_table[anArray]);
      c_expr.expr &:= "]->arr[";
      if array_range_check then
        incr(c_expr.temp_num);
        index_name := "idx_" & str(c_expr.temp_num);
        if ccConf.TWOS_COMPLEMENT_INTTYPE then
          c_expr.temp_decls &:= "uinttype ";
        else
          c_expr.temp_decls &:= "inttype ";
        end if;
        c_expr.temp_decls &:= index_name;
        c_expr.temp_decls &:= ";\n";
        c_expr.expr &:= "(";
        c_expr.expr &:= index_name;
        c_expr.expr &:= "=(";
        process_expr(param3, c_expr);
        c_expr.expr &:= ")-";
        c_expr.expr &:= str(arrayMinIdx(anArray));
        c_expr.expr &:= ", ";
        if not ccConf.TWOS_COMPLEMENT_INTTYPE then
          c_expr.expr &:= index_name;
          c_expr.expr &:= "<0 || ";
        end if;
        c_expr.expr &:= index_name;
        c_expr.expr &:= ">=";
        c_expr.expr &:= str(succ(arrayMaxIdx(anArray) - arrayMinIdx(anArray)));
        c_expr.expr &:= " ? ";
        process_raise_error("RANGE_ERROR", function, c_expr);
        c_expr.expr &:= " : 0, ";
        c_expr.expr &:= index_name;
        c_expr.expr &:= ")";
      else
        c_expr.expr &:= "(";
        process_expr(param3, c_expr);
        c_expr.expr &:= ")-";
        c_expr.expr &:= str(arrayMinIdx(anArray));
      end if;
      c_expr.expr &:= "]";
      c_expr.expr &:= select_value_from_rtlObjectstruct(resultType(getType(function)));
    end if;
  end func;


const proc: process_const_arr_idx (in reference: function, in reference: param1,
    in integer: index, inout expr_type: c_expr) is func

  local
    var expr_type: c_param is expr_type.value;
    var string: array_name is "";
    var string: result_name is "";
  begin
    prepareAnyParamTemporarys(param1, c_param, c_expr);
    if c_param.result_expr <> "" then
      incr(c_expr.temp_num);
      result_name := "help_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "rtlObjecttype ";
      c_expr.temp_decls &:= result_name;
      c_expr.temp_decls &:= ";\n";
      c_expr.temp_decls &:= c_param.result_decl;
      c_expr.temp_frees &:= c_param.result_free;
      c_expr.temp_to_null &:= c_param.result_to_null;
      if resultType(getType(function)) in typeCategory and
          typeCategory[resultType(getType(function))] in destrNecessary then
        prepare_typed_result(resultType(getType(function)), c_expr);
        c_expr.result_expr &:= "(";
        c_expr.result_expr &:= c_param.result_intro;
        c_expr.result_expr &:= c_param.result_expr;
        c_expr.result_expr &:= c_param.result_finish;
        c_expr.result_expr &:= ", ";
        c_expr.result_expr &:= result_name;
        c_expr.result_expr &:= ".value.genericvalue=arrIdxTemp(&(";
        c_expr.result_expr &:= c_param.result_temp;
        c_expr.result_expr &:= "), ";
        c_expr.result_expr &:= str(index);
        c_expr.result_expr &:= "), ";
        c_expr.result_expr &:= result_name;
        c_expr.result_expr &:= select_value_from_rtlObjectstruct(resultType(getType(function)));
        c_expr.result_expr &:= ")";
      else
        c_expr.expr &:= "(";
        c_expr.expr &:= c_param.result_intro;
        c_expr.expr &:= c_param.result_expr;
        c_expr.expr &:= c_param.result_finish;
        c_expr.expr &:= ", ";
        c_expr.expr &:= result_name;
        c_expr.expr &:= ".value.genericvalue=arrIdxTemp(&(";
        c_expr.expr &:= c_param.result_temp;
        c_expr.expr &:= "), ";
        c_expr.expr &:= str(index);
        c_expr.expr &:= "), ";
        c_expr.expr &:= result_name;
        c_expr.expr &:= select_value_from_rtlObjectstruct(resultType(getType(function)));
        c_expr.expr &:= ")";
      end if;
    else
      incr(countOptimizations);
      if isNormalVariable(param1) then
        array_name := "(" & c_param.expr & ")";
      else
        incr(c_expr.temp_num);
        array_name := "tmp_" & str(c_expr.temp_num);
        if not isVarfunc(getType(function)) then
          c_expr.temp_decls &:= "const_";
        end if;
        c_expr.temp_decls &:= "arraytype ";
        c_expr.temp_decls &:= array_name;
        c_expr.temp_decls &:= ";\n";
        c_expr.expr &:= "(*(";
        c_expr.expr &:= array_name;
        c_expr.expr &:= "=";
        c_expr.expr &:= c_param.expr;
        c_expr.expr &:= ", &";
      end if;
      c_expr.expr &:= array_name;
      c_expr.expr &:= "->arr[";
      if array_range_check then
        c_expr.expr &:= "(";
        c_expr.expr &:= str(index);
        c_expr.expr &:= "<";
        c_expr.expr &:= array_name;
        c_expr.expr &:= "->min_position || ";
        c_expr.expr &:= str(index);
        c_expr.expr &:= ">";
        c_expr.expr &:= array_name;
        c_expr.expr &:= "->max_position ? ";
        process_raise_error("RANGE_ERROR", function, c_expr);
        c_expr.expr &:= " : 0, ";
        c_expr.expr &:= str(index);
        c_expr.expr &:= "-";
        c_expr.expr &:= array_name;
        c_expr.expr &:= "->min_position)";
      else
        c_expr.expr &:= str(index);
        c_expr.expr &:= "-";
        c_expr.expr &:= array_name;
        c_expr.expr &:= "->min_position";
      end if;
      c_expr.expr &:= "]";
      c_expr.expr &:= select_value_from_rtlObjectstruct(resultType(getType(function)));
      if not isNormalVariable(param1) then
        c_expr.expr &:= "))";
      end if;
    end if;
  end func;


const proc: process_arr_idx (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var expr_type: c_param is expr_type.value;
    var string: array_name is "";
    var string: index_name is "";
    var string: result_name is "";
  begin
    if getType(params[1]) not in array_element then
      array_element @:= [getType(params[1])] resultType(getType(function));
    end if;
    if getConstant(params[1], ARRAYOBJECT, evaluatedParam) then
      process_const_arr_idx(function, evaluatedParam, params[3], c_expr);
    elsif getConstant(params[3], INTOBJECT, evaluatedParam) then
      process_const_arr_idx(function, params[1], getValue(evaluatedParam, integer), c_expr);
    else
      prepareAnyParamTemporarys(params[1], c_param, c_expr);
      if c_param.result_expr <> "" then
        incr(c_expr.temp_num);
        result_name := "help_" & str(c_expr.temp_num);
        c_expr.temp_decls &:= "rtlObjecttype ";
        c_expr.temp_decls &:= result_name;
        c_expr.temp_decls &:= ";\n";
        c_expr.temp_decls &:= c_param.result_decl;
        c_expr.temp_frees &:= c_param.result_free;
        c_expr.temp_to_null &:= c_param.result_to_null;
        if resultType(getType(function)) in typeCategory and
            typeCategory[resultType(getType(function))] in destrNecessary then
          prepare_typed_result(resultType(getType(function)), c_expr);
          c_expr.result_expr &:= "(";
          c_expr.result_expr &:= c_param.result_intro;
          c_expr.result_expr &:= c_param.result_expr;
          c_expr.result_expr &:= c_param.result_finish;
          c_expr.result_expr &:= ", ";
          c_expr.result_expr &:= result_name;
          c_expr.result_expr &:= ".value.genericvalue=arrIdxTemp(&(";
          c_expr.result_expr &:= c_param.result_temp;
          c_expr.result_expr &:= "), ";
          getAnyParamToResultExpr(params[3], c_expr);
          c_expr.result_expr &:= "), ";
          c_expr.result_expr &:= result_name;
          c_expr.result_expr &:= select_value_from_rtlObjectstruct(resultType(getType(function)));
          c_expr.result_expr &:= ")";
        else
          c_expr.expr &:= "(";
          c_expr.expr &:= c_param.result_intro;
          c_expr.expr &:= c_param.result_expr;
          c_expr.expr &:= c_param.result_finish;
          c_expr.expr &:= ", ";
          c_expr.expr &:= result_name;
          c_expr.expr &:= ".value.genericvalue=arrIdxTemp(&(";
          c_expr.expr &:= c_param.result_temp;
          c_expr.expr &:= "), ";
          process_expr(params[3], c_expr);
          c_expr.expr &:= "), ";
          c_expr.expr &:= result_name;
          c_expr.expr &:= select_value_from_rtlObjectstruct(resultType(getType(function)));
          c_expr.expr &:= ")";
        end if;
      else
        if isNormalVariable(params[1]) then
          array_name := "(" & c_param.expr & ")";
        else
          incr(c_expr.temp_num);
          array_name := "tmp_" & str(c_expr.temp_num);
          if not isVarfunc(getType(function)) then
            c_expr.temp_decls &:= "const_";
          end if;
          c_expr.temp_decls &:= "arraytype ";
          c_expr.temp_decls &:= array_name;
          c_expr.temp_decls &:= ";\n";
          c_expr.expr &:= "(*(";
          c_expr.expr &:= array_name;
          c_expr.expr &:= "=";
          c_expr.expr &:= c_param.expr;
          c_expr.expr &:= ", &";
        end if;
        c_expr.expr &:= array_name;
        c_expr.expr &:= "->arr[";
        if array_range_check then
          c_expr.expr &:= "(";
          index_name := getParameterAsVariable("inttype", "idx_", params[3], c_expr);
          c_expr.expr &:= index_name;
          c_expr.expr &:= " < ";
          c_expr.expr &:= array_name;
          c_expr.expr &:= "->min_position || ";
          c_expr.expr &:= index_name;
          c_expr.expr &:= " > ";
          c_expr.expr &:= array_name;
          c_expr.expr &:= "->max_position ? ";
          process_raise_error("RANGE_ERROR", function, c_expr);
          c_expr.expr &:= " : 0, ";
          c_expr.expr &:= index_name;
          c_expr.expr &:= "-";
          c_expr.expr &:= array_name;
          c_expr.expr &:= "->min_position)";
        else
          c_expr.expr &:= "(";
          process_expr(params[3], c_expr);
          c_expr.expr &:= ")-";
          c_expr.expr &:= array_name;
          c_expr.expr &:= "->min_position";
        end if;
        c_expr.expr &:= "]";
        c_expr.expr &:= select_value_from_rtlObjectstruct(resultType(getType(function)));
        if not isNormalVariable(params[1]) then
          c_expr.expr &:= "))";
        end if;
      end if;
    end if;
  end func;


const proc: process_arr_lng (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: array_name is "";
  begin
    if getConstant(params[1], ARRAYOBJECT, evaluatedParam) then
      incr(countOptimizations);
      c_expr.expr &:= str(arrayMaxIdx(evaluatedParam) - arrayMinIdx(evaluatedParam) + 1);
      if evaluatedParam in const_table then
        c_expr.expr &:= " /* length(arr[";
        c_expr.expr &:= str(const_table[evaluatedParam]);
        c_expr.expr &:= "]) */";
      else
        c_expr.expr &:= " /* length(array) */";
      end if;
    else
      c_expr.expr &:= "(";
      array_name := getParameterAsVariable("const_arraytype", "tmp_", params[1], c_expr);
      c_expr.expr &:= array_name;
      c_expr.expr &:= "->max_position - ";
      c_expr.expr &:= array_name;
      c_expr.expr &:= "->min_position + 1)";
    end if;
  end func;


const proc: process_arr_maxidx (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[1], ARRAYOBJECT, evaluatedParam) then
      incr(countOptimizations);
      c_expr.expr &:= str(arrayMaxIdx(evaluatedParam));
      if evaluatedParam in const_table then
        c_expr.expr &:= " /* maxIdx(arr[";
        c_expr.expr &:= str(const_table[evaluatedParam]);
        c_expr.expr &:= "]) */";
      else
        c_expr.expr &:= " /* maxIdx(array) */";
      end if;
    else
      c_expr.expr &:= "(";
      getAnyParamToExpr(params[1], c_expr);
      c_expr.expr &:= ")->max_position";
    end if;
  end func;


const proc: process_arr_minidx (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[1], ARRAYOBJECT, evaluatedParam) then
      incr(countOptimizations);
      c_expr.expr &:= str(arrayMinIdx(evaluatedParam));
      if evaluatedParam in const_table then
        c_expr.expr &:= " /* minIdx(arr[";
        c_expr.expr &:= str(const_table[evaluatedParam]);
        c_expr.expr &:= "]) */";
      else
        c_expr.expr &:= " /* minIdx(array) */";
      end if;
    else
      c_expr.expr &:= "(";
      getAnyParamToExpr(params[1], c_expr);
      c_expr.expr &:= ")->min_position";
    end if;
  end func;


const proc: process_arr_push (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: c_param1 is expr_type.value;
    var expr_type: c_param3 is expr_type.value;
  begin
    if getType(params[1]) not in array_element then
      array_element @:= [getType(params[1])] getType(params[3]);
    end if;
    process_expr(params[1], c_param1);
    c_param3.temp_num := c_param1.temp_num;
    getGenericTemporaryToResultExpr(params[3], c_param3);
    incr(c_param3.temp_num);
    if has_temp_values(c_param3) then
      c_expr.expr &:= "{\n";
      AppendWithDiagnostic(c_param1.temp_decls, c_expr);
      AppendWithDiagnostic(c_param3.temp_decls, c_expr);
      AppendWithDiagnostic(c_param1.temp_assigns, c_expr);
      AppendWithDiagnostic(c_param3.temp_assigns, c_expr);
    end if;
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "arrPush(&(";
    c_expr.expr &:= c_param1.expr;
    c_expr.expr &:= "), (generictype)(";
    c_expr.expr &:= c_param3.result_expr;
    c_expr.expr &:= "));\n";
    if has_temp_values(c_param3) then
      AppendWithDiagnostic(c_param1.temp_frees, c_expr);
      AppendWithDiagnostic(c_param3.temp_frees, c_expr);
      c_expr.expr &:= "}\n";
    end if;
  end func;


const proc: process_arr_range (in ref_list: params, inout expr_type: c_expr) is func

  local
    var type: param_type is void;
    var expr_type: c_param is expr_type.value;
    var string: array_name is "";
  begin
    param_type := getExprResultType(params[1]);
    prepare_typed_result(param_type, c_expr);
    prepareAnyParamTemporarys(params[1], c_param, c_expr);
    if c_param.result_expr <> "" then
      c_expr.temp_decls &:= c_param.result_decl;
      c_expr.temp_frees &:= c_param.result_free;
      c_expr.temp_to_null &:= c_param.result_to_null;
      c_expr.result_expr := "(";
      c_expr.result_expr &:= c_param.result_intro;
      c_expr.result_expr &:= c_param.result_expr;
      c_expr.result_expr &:= c_param.result_finish;
      c_expr.result_expr &:= ", arrRangeTemp(&(";
      c_expr.result_expr &:= c_param.result_temp;
      c_expr.result_expr &:= "), ";
      getStdParamToResultExpr(params[3], c_expr);
      c_expr.result_expr &:= ", ";
      getStdParamToResultExpr(params[5], c_expr);
      c_expr.result_expr &:= "))";
    elsif valueIsAtHeap(array_element[param_type]) then
      incr(c_expr.temp_num);
      array_name := "tmp_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "arraytype ";
      c_expr.temp_decls &:= array_name;
      c_expr.temp_decls &:= "=NULL;\n";
      c_expr.temp_frees &:= "if (";
      c_expr.temp_frees &:= array_name;
      c_expr.temp_frees &:= " != NULL) {arrFree(";
      c_expr.temp_frees &:= array_name;
      c_expr.temp_frees &:= ");}\n";
      c_expr.temp_to_null &:= array_name;
      c_expr.temp_to_null &:= "=NULL;\n";
      c_expr.result_expr := "(";
      c_expr.result_expr &:= array_name;
      c_expr.result_expr &:= "=arrRange(";
      c_expr.result_expr &:= c_param.expr;
      c_expr.result_expr &:= ", ";
      getStdParamToResultExpr(params[3], c_expr);
      c_expr.result_expr &:= ", ";
      getStdParamToResultExpr(params[5], c_expr);
      c_expr.result_expr &:= "), ";
      typeCategory @:= [param_type] ARRAYOBJECT;
      process_create_declaration(param_type, global_c_expr);
      process_create_call(param_type, array_name, c_expr.result_expr);
      c_expr.result_expr &:= ")";
    else
      c_expr.result_expr := "arrRange(";
      c_expr.result_expr &:= c_param.expr;
      c_expr.result_expr &:= ", ";
      getStdParamToResultExpr(params[3], c_expr);
      c_expr.result_expr &:= ", ";
      getStdParamToResultExpr(params[5], c_expr);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_arr_remove (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  local
    var type: proc_type is void;
    var type: result_type is void;
    var string: temp_name is "";
  begin
    proc_type := getType(function);
    result_type := resultType(proc_type);
    if valueIsAtHeap(result_type) then
      prepare_typed_result(result_type, c_expr);
      temp_name := beginCastGenericToResultExpr(result_type, c_expr);
      c_expr.result_expr &:= "arrRemove(&(";
      getStdParamToResultExpr(params[1], c_expr);
      c_expr.result_expr &:= "), ";
      getStdParamToResultExpr(params[2], c_expr);
      c_expr.result_expr &:= ")";
      endCastGenericToResultExpr(result_type, temp_name, c_expr);
    else
      temp_name := beginCastGeneric(result_type, c_expr);
      c_expr.expr &:= "arrRemove(&(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= "), ";
      process_expr(params[2], c_expr);
      c_expr.expr &:= ")";
      endCastGeneric(result_type, temp_name, c_expr);
    end if;
  end func;


const proc: process_arr_sort (in ref_list: params, inout expr_type: c_expr) is func

  begin
    declare_func_pointer_if_necessary(params[2], global_c_expr);
    prepare_typed_result(getExprResultType(params[1]), c_expr);
    c_expr.result_expr := "arrSort(";
    getTemporaryToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", (comparetype)(";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= "))";
  end func;


const proc: process_arr_subarr (in ref_list: params, inout expr_type: c_expr) is func

  local
    var type: param_type is void;
    var expr_type: c_param is expr_type.value;
    var string: array_name is "";
  begin
    param_type := getExprResultType(params[1]);
    prepare_typed_result(param_type, c_expr);
    prepareAnyParamTemporarys(params[1], c_param, c_expr);
    if c_param.result_expr <> "" then
      c_expr.temp_decls &:= c_param.result_decl;
      c_expr.temp_frees &:= c_param.result_free;
      c_expr.temp_to_null &:= c_param.result_to_null;
      c_expr.result_expr := "(";
      c_expr.result_expr &:= c_param.result_intro;
      c_expr.result_expr &:= c_param.result_expr;
      c_expr.result_expr &:= c_param.result_finish;
      c_expr.result_expr &:= ", arrSubarrTemp(&(";
      c_expr.result_expr &:= c_param.result_temp;
      c_expr.result_expr &:= "), ";
      getStdParamToResultExpr(params[3], c_expr);
      c_expr.result_expr &:= ", ";
      getStdParamToResultExpr(params[5], c_expr);
      c_expr.result_expr &:= "))";
    elsif valueIsAtHeap(array_element[param_type]) then
      incr(c_expr.temp_num);
      array_name := "tmp_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "arraytype ";
      c_expr.temp_decls &:= array_name;
      c_expr.temp_decls &:= "=NULL;\n";
      c_expr.temp_frees &:= "if (";
      c_expr.temp_frees &:= array_name;
      c_expr.temp_frees &:= " != NULL) {arrFree(";
      c_expr.temp_frees &:= array_name;
      c_expr.temp_frees &:= ");}\n";
      c_expr.temp_to_null &:= array_name;
      c_expr.temp_to_null &:= "=NULL;\n";
      c_expr.result_expr := "(";
      c_expr.result_expr &:= array_name;
      c_expr.result_expr &:= "=arrSubarr(";
      c_expr.result_expr &:= c_param.expr;
      c_expr.result_expr &:= ", ";
      getStdParamToResultExpr(params[3], c_expr);
      c_expr.result_expr &:= ", ";
      getStdParamToResultExpr(params[5], c_expr);
      c_expr.result_expr &:= "), ";
      typeCategory @:= [param_type] ARRAYOBJECT;
      process_create_declaration(param_type, global_c_expr);
      process_create_call(param_type, array_name, c_expr.result_expr);
      c_expr.result_expr &:= ")";
    else
      c_expr.result_expr := "arrSubarr(";
      c_expr.result_expr &:= c_param.expr;
      c_expr.result_expr &:= ", ";
      getStdParamToResultExpr(params[3], c_expr);
      c_expr.result_expr &:= ", ";
      getStdParamToResultExpr(params[5], c_expr);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_arr_tail (in ref_list: params, inout expr_type: c_expr) is func

  local
    var type: param_type is void;
    var expr_type: c_param is expr_type.value;
    var string: array_name is "";
  begin
    param_type := getExprResultType(params[1]);
    prepare_typed_result(param_type, c_expr);
    prepareAnyParamTemporarys(params[1], c_param, c_expr);
    if c_param.result_expr <> "" then
      c_expr.temp_decls &:= c_param.result_decl;
      c_expr.temp_frees &:= c_param.result_free;
      c_expr.temp_to_null &:= c_param.result_to_null;
      c_expr.result_expr := "(";
      c_expr.result_expr &:= c_param.result_intro;
      c_expr.result_expr &:= c_param.result_expr;
      c_expr.result_expr &:= c_param.result_finish;
      c_expr.result_expr &:= ", arrTailTemp(&(";
      c_expr.result_expr &:= c_param.result_temp;
      c_expr.result_expr &:= "), ";
      getStdParamToResultExpr(params[3], c_expr);
      c_expr.result_expr &:= "))";
    elsif valueIsAtHeap(array_element[param_type]) then
      incr(c_expr.temp_num);
      array_name := "tmp_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "arraytype ";
      c_expr.temp_decls &:= array_name;
      c_expr.temp_decls &:= "=NULL;\n";
      c_expr.temp_frees &:= "if (";
      c_expr.temp_frees &:= array_name;
      c_expr.temp_frees &:= " != NULL) {arrFree(";
      c_expr.temp_frees &:= array_name;
      c_expr.temp_frees &:= ");}\n";
      c_expr.temp_to_null &:= array_name;
      c_expr.temp_to_null &:= "=NULL;\n";
      c_expr.result_expr := "(";
      c_expr.result_expr &:= array_name;
      c_expr.result_expr &:= "=arrTail(";
      c_expr.result_expr &:= c_param.expr;
      c_expr.result_expr &:= ", ";
      getStdParamToResultExpr(params[3], c_expr);
      c_expr.result_expr &:= "), ";
      typeCategory @:= [param_type] ARRAYOBJECT;
      process_create_declaration(param_type, global_c_expr);
      process_create_call(param_type, array_name, c_expr.result_expr);
      c_expr.result_expr &:= ")";
    else
      c_expr.result_expr := "arrTail(";
      c_expr.result_expr &:= c_param.expr;
      c_expr.result_expr &:= ", ";
      getStdParamToResultExpr(params[3], c_expr);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_arr_times (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  local
    var type: result_type is void;
  begin
    result_type := resultType(getType(function));
    typeCategory @:= [result_type] ARRAYOBJECT;
    declare_prototype_if_necessary(function, global_c_expr);
    prepare_typed_result(result_type, c_expr);
    c_expr.result_expr := "times_";
    c_expr.result_expr &:= str(typeNumber(result_type));
    c_expr.result_expr &:= "(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getAnyParamToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_big_abs (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bigint_result(c_expr);
    c_expr.result_expr := "bigAbs(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_const_big_add (in reference: param1, in bigInteger: number,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var expr_type: c_param1 is expr_type.value;
  begin
    if getConstant(param1, BIGINTOBJECT, evaluatedParam) then
      incr(countOptimizations);
      c_expr.expr &:= bigIntegerLiteral(getValue(evaluatedParam, bigInteger) + number);
    elsif number = 0_ then
      incr(countOptimizations);
      process_expr(param1, c_expr);
    elsif number = 1_ then
      incr(countOptimizations);
      prepare_bigint_result(c_expr);
      prepareAnyParamTemporarys(param1, c_param1, c_expr);
      if c_param1.result_expr <> "" then
        c_expr.result_expr := "bigSuccTemp(";
        c_expr.result_expr &:= c_param1.result_expr;
      else
        c_expr.result_expr := "bigSucc(";
        c_expr.result_expr &:= c_param1.expr;
      end if;
      c_expr.result_expr &:= ")";
    elsif number = -1_ then
      incr(countOptimizations);
      prepare_bigint_result(c_expr);
      prepareAnyParamTemporarys(param1, c_param1, c_expr);
      if c_param1.result_expr <> "" then
        c_expr.result_expr := "bigPredTemp(";
        c_expr.result_expr &:= c_param1.result_expr;
      else
        c_expr.result_expr := "bigPred(";
        c_expr.result_expr &:= c_param1.expr;
      end if;
      c_expr.result_expr &:= ")";
    elsif number > 0_ then
      prepare_bigint_result(c_expr);
      prepareAnyParamTemporarys(param1, c_param1, c_expr);
      if c_param1.result_expr <> "" then
        c_expr.result_expr := "bigAddTemp(";
        c_expr.result_expr &:= c_param1.result_expr;
      else
        c_expr.result_expr := "bigAdd(";
        c_expr.result_expr &:= c_param1.expr;
      end if;
      c_expr.result_expr &:= ", ";
      c_expr.result_expr &:= bigIntegerLiteral(number);
      c_expr.result_expr &:= ")";
    else # number < 0_
      prepare_bigint_result(c_expr);
      prepareAnyParamTemporarys(param1, c_param1, c_expr);
      if c_param1.result_expr <> "" then
        c_expr.result_expr := "bigSbtrTemp(";
        c_expr.result_expr &:= c_param1.result_expr;
      else
        c_expr.result_expr := "bigSbtr(";
        c_expr.result_expr &:= c_param1.expr;
      end if;
      c_expr.result_expr &:= ", ";
      c_expr.result_expr &:= bigIntegerLiteral(-number);
      c_expr.result_expr &:= ")";
    end if;
  end func;


(**
 *  Produces code for the big integer addition.
 *  When the first or the second parameter is a temporary value
 *  the addition is done with bigAddTemp. The bigAddTemp function
 *  returns the first parameter as result of the addition. That
 *  way the temporary value of a parameter must not be freed.
 *)
const proc: process_big_add (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var expr_type: c_param1 is expr_type.value;
    var expr_type: c_param3 is expr_type.value;
  begin
    if getConstant(params[3], BIGINTOBJECT, evaluatedParam) then
      process_const_big_add(params[1], getValue(evaluatedParam, bigInteger), c_expr);
    elsif getConstant(params[1], BIGINTOBJECT, evaluatedParam) then
      process_const_big_add(params[3], getValue(evaluatedParam, bigInteger), c_expr);
    elsif params[1] = params[3] then
      incr(countOptimizations);
      prepare_bigint_result(c_expr);
      c_expr.result_expr := "bigLShift(";
      getAnyParamToResultExpr(params[1], c_expr);
      c_expr.result_expr &:= ", 1)";
    else
      prepare_bigint_result(c_expr);
      if isActionExpression(params[1], "BIG_NEGATE") then
        incr(countOptimizations);
        prepareAnyParamTemporarys(params[3], c_param3, c_expr);
        if c_param3.result_expr <> "" then
          c_expr.result_expr := "bigSbtrTemp(";
          c_expr.result_expr &:= c_param3.result_expr;
        else
          c_expr.result_expr := "bigSbtr(";
          c_expr.result_expr &:= c_param3.expr;
        end if;
        c_expr.result_expr &:= ", ";
        getAnyParamToResultExpr(getValue(params[1], ref_list)[3], c_expr);
      else
        prepareAnyParamTemporarys(params[1], c_param1, c_expr);
        if c_param1.result_expr <> "" then
          c_expr.result_expr := "bigAddTemp(";
          c_expr.result_expr &:= c_param1.result_expr;
          c_expr.result_expr &:= ", ";
          getAnyParamToResultExpr(params[3], c_expr);
        else
          prepareAnyParamTemporarys(params[3], c_param3, c_expr);
          if c_param3.result_expr <> "" then
            c_expr.result_expr := "bigAddTemp(";
            c_expr.result_expr &:= c_param3.result_expr;
            c_expr.result_expr &:= ", ";
            c_expr.result_expr &:= c_param1.expr;
          else
            c_expr.result_expr := "bigAdd(";
            c_expr.result_expr &:= c_param1.expr;
            c_expr.result_expr &:= ", ";
            c_expr.result_expr &:= c_param3.expr;
          end if;
        end if;
      end if;
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_big_bit_length (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "bigBitLength(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_big_clit (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "bigCLit(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_const_big_cmp (in reference: param1, in bigInteger: number,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(param1, BIGINTOBJECT, evaluatedParam) then
      incr(countOptimizations);
      c_expr.expr &:= str(compare(getValue(evaluatedParam, bigInteger), number));
    elsif abs(number) <= 127_ then
      incr(countOptimizations);
      c_expr.expr &:= "bigCmpSignedDigit(";
      getAnyParamToExpr(param1, c_expr);
      c_expr.expr &:= ", ";
      c_expr.expr &:= integerLiteral(ord(number));
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= "bigCmp(";
      getAnyParamToExpr(param1, c_expr);
      c_expr.expr &:= ", ";
      c_expr.expr &:= bigIntegerLiteral(number);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_const_big_cmp (in bigInteger: number, in reference: param2,
    inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "-";
    process_const_big_cmp(param2, number, c_expr);
  end func;


const proc: process_big_cmp (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[2], BIGINTOBJECT, evaluatedParam) then
      process_const_big_cmp(params[1], getValue(evaluatedParam, bigInteger), c_expr);
    elsif getConstant(params[1], BIGINTOBJECT, evaluatedParam) then
      process_const_big_cmp(getValue(evaluatedParam, bigInteger), params[2], c_expr);
    else
      c_expr.expr &:= "bigCmp(";
      getAnyParamToExpr(params[1], c_expr);
      c_expr.expr &:= ", ";
      getAnyParamToExpr(params[2], c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_big_conv (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_big_cpy (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: c_param1 is expr_type.value;
    var expr_type: c_param3 is expr_type.value;
  begin
    process_expr(params[1], c_param1);
    c_param3.temp_num := c_param1.temp_num;
    process_expr(params[3], c_param3);
    if has_temp_values(c_param3) then
      c_expr.expr &:= "{\n";
      AppendWithDiagnostic(c_param1.temp_decls, c_expr);
      AppendWithDiagnostic(c_param3.temp_decls, c_expr);
      AppendWithDiagnostic(c_param1.temp_assigns, c_expr);
      AppendWithDiagnostic(c_param3.temp_assigns, c_expr);
    end if;
    if c_param3.result_expr <> "" then
      c_expr.expr &:= "{\n";
      setDiagnosticLine(c_expr);
      if isNormalVariable(params[1]) then
        c_expr.expr &:= "biginttype old_big=";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ";\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= "=";
      else
        c_expr.expr &:= "biginttype *big_ptr=&(";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ");\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "biginttype old_big=*big_ptr;\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "*big_ptr=";
      end if;
      c_expr.expr &:= c_param3.result_expr;
      c_expr.expr &:= ";\n";
      setDiagnosticLine(c_expr);
      c_expr.expr &:= "bigDestr(old_big);\n";
      c_expr.expr &:= "}\n";
    else
      setDiagnosticLine(c_expr);
      c_expr.expr &:= "bigCpy(&(";
      c_expr.expr &:= c_param1.expr;
      c_expr.expr &:= "), ";
      c_expr.expr &:= c_param3.expr;
      c_expr.expr &:= ");\n";
    end if;
    if has_temp_values(c_param3) then
      AppendWithDiagnostic(c_param1.temp_frees, c_expr);
      AppendWithDiagnostic(c_param3.temp_frees, c_expr);
      c_expr.expr &:= "}\n";
    end if;
  end func;


const proc: process_big_decr (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "bigDecr(&(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= "));\n";
  end func;


const proc: process_const_big_div (in reference: param1, in bigInteger: divisor,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var bigInteger: bigNumber is 0_;
  begin
    if divisor = 0_ then
      incr(countOptimizations);
      c_expr.expr &:= "(biginttype)(raise_error(NUMERIC_ERROR),NULL)";
    elsif getConstant(param1, BIGINTOBJECT, evaluatedParam) then
      incr(countOptimizations);
      bigNumber := getValue(evaluatedParam, bigInteger) div divisor;
      c_expr.expr &:= bigIntegerLiteral(bigNumber);
    elsif divisor = 1_ then
      incr(countOptimizations);
      c_expr.expr &:= "(";
      process_expr(param1, c_expr);
      c_expr.expr &:= ")";
    elsif divisor = -1_ then
      incr(countOptimizations);
      prepare_bigint_result(c_expr);
      c_expr.result_expr := "bigNegate(";
      getAnyParamToResultExpr(param1, c_expr);
      c_expr.result_expr &:= ")";
    else
      prepare_bigint_result(c_expr);
      c_expr.result_expr := "bigDiv(";
      getAnyParamToResultExpr(param1, c_expr);
      c_expr.result_expr &:= ", ";
      c_expr.result_expr &:= bigIntegerLiteral(divisor);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_big_div (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[3], BIGINTOBJECT, evaluatedParam) then
      process_const_big_div(params[1], getValue(evaluatedParam, bigInteger), c_expr);
    else
      prepare_bigint_result(c_expr);
      c_expr.result_expr := "bigDiv(";
      getAnyParamToResultExpr(params[1], c_expr);
      c_expr.result_expr &:= ", ";
      getAnyParamToResultExpr(params[3], c_expr);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_const_big_eq (in reference: param1, in bigInteger: number,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(param1, BIGINTOBJECT, evaluatedParam) then
      incr(countOptimizations);
      c_expr.expr &:= str(ord(getValue(evaluatedParam, bigInteger) = number));
      c_expr.expr &:= "/*";
      c_expr.expr &:= str(getValue(evaluatedParam, bigInteger) = number);
      c_expr.expr &:= "*/";
    elsif abs(number) <= 127_ then
      incr(countOptimizations);
      c_expr.expr &:= "bigEqSignedDigit(";
      getAnyParamToExpr(param1, c_expr);
      c_expr.expr &:= ", ";
      c_expr.expr &:= integerLiteral(ord(number));
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= "bigEq(";
      getAnyParamToExpr(param1, c_expr);
      c_expr.expr &:= ", ";
      c_expr.expr &:= bigIntegerLiteral(number);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_big_eq (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[3], BIGINTOBJECT, evaluatedParam) then
      process_const_big_eq(params[1], getValue(evaluatedParam, bigInteger), c_expr);
    elsif getConstant(params[1], BIGINTOBJECT, evaluatedParam) then
      process_const_big_eq(params[3], getValue(evaluatedParam, bigInteger), c_expr);
    else
      c_expr.expr &:= "bigEq(";
      getAnyParamToExpr(params[1], c_expr);
      c_expr.expr &:= ", ";
      getAnyParamToExpr(params[3], c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_big_from_bstri_be (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bigint_result(c_expr);
    c_expr.result_expr := "bigFromBStriBe(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_big_from_bstri_le (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bigint_result(c_expr);
    c_expr.result_expr := "bigFromBStriLe(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_big_gcd (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bigint_result(c_expr);
    c_expr.result_expr := "bigGcd(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getAnyParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_big_ge (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[3], BIGINTOBJECT, evaluatedParam) then
      process_const_big_cmp(params[1], getValue(evaluatedParam, bigInteger), c_expr);
    elsif getConstant(params[1], BIGINTOBJECT, evaluatedParam) then
      process_const_big_cmp(getValue(evaluatedParam, bigInteger), params[3], c_expr);
    else
      c_expr.expr &:= "bigCmp(";
      getAnyParamToExpr(params[1], c_expr);
      c_expr.expr &:= ", ";
      getAnyParamToExpr(params[3], c_expr);
      c_expr.expr &:= ")";
    end if;
    c_expr.expr &:= " >= 0";
  end func;


const proc: process_const_big_grow (in reference: param1, in bigInteger: number,
    inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    if number = -1_ then
      incr(countOptimizations);
      statement.expr := "bigDecr(&(";
      process_expr(param1, statement);
      statement.expr &:= "));\n";
      doLocalDeclsOfStatement(statement, c_expr);
    elsif number = 0_ then
      incr(countOptimizations);
      c_expr.expr &:= "/* ignore bigInteger +:= 0_; */\n";
    elsif number = 1_ then
      incr(countOptimizations);
      statement.expr := "bigIncr(&(";
      process_expr(param1, statement);
      statement.expr &:= "));\n";
      doLocalDeclsOfStatement(statement, c_expr);
    else
      statement.expr := "bigGrow(&(";
      process_expr(param1, statement);
      statement.expr &:= "), ";
      statement.expr &:= bigIntegerLiteral(number);
      statement.expr &:= ");\n";
      doLocalDeclsOfStatement(statement, c_expr);
    end if;
  end func;


const proc: process_big_grow (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var expr_type: statement is expr_type.value;
  begin
    if getConstant(params[3], BIGINTOBJECT, evaluatedParam) then
      process_const_big_grow(params[1], getValue(evaluatedParam, bigInteger), c_expr);
    else
      statement.expr := "bigGrow(&(";
      process_expr(params[1], statement);
      statement.expr &:= "), ";
      getAnyParamToExpr(params[3], statement);
      statement.expr &:= ");\n";
      doLocalDeclsOfStatement(statement, c_expr);
    end if;
  end func;


const proc: process_big_gt (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[3], BIGINTOBJECT, evaluatedParam) then
      process_const_big_cmp(params[1], getValue(evaluatedParam, bigInteger), c_expr);
    elsif getConstant(params[1], BIGINTOBJECT, evaluatedParam) then
      process_const_big_cmp(getValue(evaluatedParam, bigInteger), params[3], c_expr);
    else
      c_expr.expr &:= "bigCmp(";
      getAnyParamToExpr(params[1], c_expr);
      c_expr.expr &:= ", ";
      getAnyParamToExpr(params[3], c_expr);
      c_expr.expr &:= ")";
    end if;
    c_expr.expr &:= " > 0";
  end func;


const proc: process_big_hashcode (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "bigHashCode(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_big_iconv (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bigint_result(c_expr);
    c_expr.result_expr := "bigIConv(";
    getStdParamToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_big_incr (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "bigIncr(&(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= "));\n";
  end func;


const proc: process_const_big_ipow (in reference: param1, in integer: exponent,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var bigInteger: bigNumber is 0_;
  begin
    if exponent < 0 then
      incr(countOptimizations);
      c_expr.expr &:= "(biginttype)(raise_error(NUMERIC_ERROR),NULL)";
    elsif getConstant(param1, BIGINTOBJECT, evaluatedParam) then
      incr(countOptimizations);
      bigNumber := getValue(evaluatedParam, bigInteger) ** exponent;
      c_expr.expr &:= bigIntegerLiteral(bigNumber);
    elsif exponent = 0 then
      incr(countOptimizations);
      c_expr.expr &:= bigIntegerLiteral(1_);
    elsif exponent = 1 then
      incr(countOptimizations);
      process_expr(param1, c_expr);
    elsif exponent = 2 then
      incr(countOptimizations);
      prepare_bigint_result(c_expr);
      c_expr.result_expr := "bigSquare(";
      getAnyParamToResultExpr(param1, c_expr);
      c_expr.result_expr &:= ")";
    else
      prepare_bigint_result(c_expr);
      c_expr.result_expr := "bigIPow(";
      getAnyParamToResultExpr(param1, c_expr);
      c_expr.result_expr &:= ", ";
      c_expr.result_expr &:= str(exponent);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_const_big_ipow (in bigInteger: base, in reference: param3,
    inout expr_type: c_expr) is func

  local
    var string: exponent_name is "";
  begin
    if base = -1_ then
      incr(countOptimizations);
      c_expr.expr &:= "(";
      exponent_name := getParameterAsVariable("inttype", "tmp_", param3, c_expr);
      c_expr.expr &:= exponent_name;
      c_expr.expr &:= "<0?(biginttype)(raise_error(NUMERIC_ERROR),NULL):(";
      c_expr.expr &:= exponent_name;
      c_expr.expr &:= "&1?";
      c_expr.expr &:= bigIntegerLiteral(-1_);
      c_expr.expr &:= ":";
      c_expr.expr &:= bigIntegerLiteral(1_);
      c_expr.expr &:= "))";
    elsif base = 0_ then
      incr(countOptimizations);
      c_expr.expr &:= "(";
      exponent_name := getParameterAsVariable("inttype", "tmp_", param3, c_expr);
      c_expr.expr &:= exponent_name;
      c_expr.expr &:= "<0?(biginttype)(raise_error(NUMERIC_ERROR),NULL):(";
      c_expr.expr &:= exponent_name;
      c_expr.expr &:= "==0?";
      c_expr.expr &:= bigIntegerLiteral(1_);
      c_expr.expr &:= ":";
      c_expr.expr &:= bigIntegerLiteral(0_);
      c_expr.expr &:= "))";
    elsif base = 1_ then
      incr(countOptimizations);
      c_expr.expr &:= "((";
      process_expr(param3, c_expr);
      c_expr.expr &:= ")<0?(biginttype)(raise_error(NUMERIC_ERROR),NULL):";
      c_expr.expr &:= bigIntegerLiteral(1_);
      c_expr.expr &:= ")";
    elsif base > 0_ and log2(base) <= INTTYPE_MAX and
        2_ ** ord(log2(base)) = base then
      incr(countOptimizations);
      prepare_bigint_result(c_expr);
      c_expr.result_expr := "bigLog2BaseIPow(";
      c_expr.result_expr &:= integerLiteral(ord(log2(base)));
      c_expr.result_expr &:= ", ";
      getStdParamToResultExpr(param3, c_expr);
      c_expr.result_expr &:= ")";
    else
      prepare_bigint_result(c_expr);
      c_expr.result_expr := "bigIPow(";
      c_expr.result_expr &:= bigIntegerLiteral(base);
      c_expr.result_expr &:= ", ";
      getStdParamToResultExpr(param3, c_expr);
      c_expr.result_expr &:= ")";
    end if
  end func;


const proc: process_big_ipow (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[3], INTOBJECT, evaluatedParam) then
      process_const_big_ipow(params[1], getValue(evaluatedParam, integer), c_expr);
    elsif getConstant(params[1], BIGINTOBJECT, evaluatedParam) then
      process_const_big_ipow(getValue(evaluatedParam, bigInteger), params[3], c_expr);
    else
      prepare_bigint_result(c_expr);
      c_expr.result_expr := "bigIPow(";
      getAnyParamToResultExpr(params[1], c_expr);
      c_expr.result_expr &:= ", ";
      getStdParamToResultExpr(params[3], c_expr);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_big_le (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[3], BIGINTOBJECT, evaluatedParam) then
      process_const_big_cmp(params[1], getValue(evaluatedParam, bigInteger), c_expr);
    elsif getConstant(params[1], BIGINTOBJECT, evaluatedParam) then
      process_const_big_cmp(getValue(evaluatedParam, bigInteger), params[3], c_expr);
    else
      c_expr.expr &:= "bigCmp(";
      getAnyParamToExpr(params[1], c_expr);
      c_expr.expr &:= ", ";
      getAnyParamToExpr(params[3], c_expr);
      c_expr.expr &:= ")";
    end if;
    c_expr.expr &:= " <= 0";
  end func;


const proc: process_big_log2 (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bigint_result(c_expr);
    c_expr.result_expr := "bigLog2(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_big_lowest_set_bit (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "bigLowestSetBit(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_const_big_lshift (in bigInteger: number, in reference: param3,
    inout expr_type: c_expr) is func

  local
    var bigInteger: bigNumber is 0_;
  begin
    (* if category(param3) = INTOBJECT and not isVar(param3) then
      incr(countOptimizations);
      bigNumber := number << getValue(param3, integer);
      c_expr.expr &:= bigIntegerLiteral(bigNumber);
    els *)
    if number = 0_ then
      incr(countOptimizations);
      c_expr.expr &:= bigIntegerLiteral(0_);
    elsif number = 1_ then
      incr(countOptimizations);
      prepare_bigint_result(c_expr);
      c_expr.result_expr := "bigLShiftOne(";
      getStdParamToResultExpr(param3, c_expr);
      c_expr.result_expr &:= ")";
    else
      prepare_bigint_result(c_expr);
      c_expr.result_expr := "bigLShift(";
      c_expr.result_expr &:= bigIntegerLiteral(number);
      c_expr.result_expr &:= ", ";
      getStdParamToResultExpr(param3, c_expr);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_const_big_lshift (in reference: param1, in integer: lshift,
    inout expr_type: c_expr) is func

  local
    var string: bigint_name is "";
    var expr_type: c_param1 is expr_type.value;
  begin
    prepare_bigint_result(c_expr);
    prepareAnyParamTemporarys(param1, c_param1, c_expr);
    if c_param1.result_expr <> "" then
      incr(c_expr.temp_num);
      bigint_name := "tmp_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "biginttype ";
      c_expr.temp_decls &:= bigint_name;
      c_expr.temp_decls &:= ";\n";
      c_expr.result_expr &:= "(bigLShiftAssign((";
      c_expr.result_expr &:= bigint_name;
      c_expr.result_expr &:= "=";
      c_expr.result_expr &:= c_param1.result_expr;
      c_expr.result_expr &:= ", &";
      c_expr.result_expr &:= bigint_name;
      c_expr.result_expr &:= "), ";
      c_expr.result_expr &:= integerLiteral(lshift);
      c_expr.result_expr &:= "), ";
      c_expr.result_expr &:= bigint_name;
    else
      c_expr.result_expr := "bigLShift(";
      c_expr.result_expr &:= c_param1.expr;
      c_expr.result_expr &:= ", ";
      c_expr.result_expr &:= integerLiteral(lshift);
    end if;
    c_expr.result_expr &:= ")";
  end func;


const proc: process_big_lshift (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: bigint_name is "";
    var expr_type: c_param1 is expr_type.value;
  begin
    if getConstant(params[1], BIGINTOBJECT, evaluatedParam) then
      process_const_big_lshift(getValue(evaluatedParam, bigInteger), params[3], c_expr);
    else
      prepare_bigint_result(c_expr);
      prepareAnyParamTemporarys(params[1], c_param1, c_expr);
      if c_param1.result_expr <> "" then
        incr(c_expr.temp_num);
        bigint_name := "tmp_" & str(c_expr.temp_num);
        c_expr.temp_decls &:= "biginttype ";
        c_expr.temp_decls &:= bigint_name;
        c_expr.temp_decls &:= ";\n";
        c_expr.result_expr := "(bigLShiftAssign((";
        c_expr.result_expr &:= bigint_name;
        c_expr.result_expr &:= "=";
        c_expr.result_expr &:= c_param1.result_expr;
        c_expr.result_expr &:= ", &";
        c_expr.result_expr &:= bigint_name;
        c_expr.result_expr &:= "), ";
        getStdParamToResultExpr(params[3], c_expr);
        c_expr.result_expr &:= "), ";
        c_expr.result_expr &:= bigint_name;
      else
        c_expr.result_expr := "bigLShift(";
        c_expr.result_expr &:= c_param1.expr;
        c_expr.result_expr &:= ", ";
        getStdParamToResultExpr(params[3], c_expr);
      end if;
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_big_lshift_assign (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    statement.expr := "bigLShiftAssign(&(";
    process_expr(params[1], statement);
    statement.expr &:= "), ";
    getAnyParamToExpr(params[3], statement);
    statement.expr &:= ");\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_big_lt (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[3], BIGINTOBJECT, evaluatedParam) then
      process_const_big_cmp(params[1], getValue(evaluatedParam, bigInteger), c_expr);
    elsif getConstant(params[1], BIGINTOBJECT, evaluatedParam) then
      process_const_big_cmp(getValue(evaluatedParam, bigInteger), params[3], c_expr);
    else
      c_expr.expr &:= "bigCmp(";
      getAnyParamToExpr(params[1], c_expr);
      c_expr.expr &:= ", ";
      getAnyParamToExpr(params[3], c_expr);
      c_expr.expr &:= ")";
    end if;
    c_expr.expr &:= " < 0";
  end func;


const proc: process_const_big_rshift (in reference: param1, in integer: rshift,
    inout expr_type: c_expr) is func

  local
    var string: bigint_name is "";
    var expr_type: c_param1 is expr_type.value;
  begin
    prepare_bigint_result(c_expr);
    prepareAnyParamTemporarys(param1, c_param1, c_expr);
    if c_param1.result_expr <> "" then
      incr(c_expr.temp_num);
      bigint_name := "tmp_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "biginttype ";
      c_expr.temp_decls &:= bigint_name;
      c_expr.temp_decls &:= ";\n";
      c_expr.result_expr := "(bigRShiftAssign((";
      c_expr.result_expr &:= bigint_name;
      c_expr.result_expr &:= "=";
      c_expr.result_expr &:= c_param1.result_expr;
      c_expr.result_expr &:= ", &";
      c_expr.result_expr &:= bigint_name;
      c_expr.result_expr &:= "), ";
      c_expr.result_expr &:= integerLiteral(rshift);
      c_expr.result_expr &:= "), ";
      c_expr.result_expr &:= bigint_name;
    else
      c_expr.result_expr := "bigRShift(";
      c_expr.result_expr &:= c_param1.expr;
      c_expr.result_expr &:= ", ";
      c_expr.result_expr &:= integerLiteral(rshift);
    end if;
    c_expr.result_expr &:= ")";
  end func;


const proc: process_const_big_mdiv (in reference: param1, in bigInteger: divisor,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var bigInteger: bigNumber is 0_;
    var string: bigint_name is "";
    var expr_type: c_param1 is expr_type.value;
  begin
    if divisor = 0_ then
      incr(countOptimizations);
      c_expr.expr &:= "(biginttype)(raise_error(NUMERIC_ERROR),NULL)";
    elsif getConstant(param1, BIGINTOBJECT, evaluatedParam) then
      incr(countOptimizations);
      bigNumber := getValue(evaluatedParam, bigInteger) mdiv divisor;
      c_expr.expr &:= bigIntegerLiteral(bigNumber);
    elsif divisor = 1_ then
      incr(countOptimizations);
      c_expr.expr &:= "(";
      process_expr(param1, c_expr);
      c_expr.expr &:= ")";
    elsif divisor = -1_ then
      incr(countOptimizations);
      prepare_bigint_result(c_expr);
      c_expr.result_expr := "bigNegate(";
      getAnyParamToResultExpr(param1, c_expr);
      c_expr.result_expr &:= ")";
    elsif divisor > 0_ and log2(divisor) <= INTTYPE_MAX and
        2_ ** ord(log2(divisor)) = divisor then
      incr(countOptimizations);
      process_const_big_rshift(param1, ord(log2(divisor)), c_expr);
    elsif divisor < 0_ and log2(-divisor) <= INTTYPE_MAX and
        2_ ** ord(log2(-divisor)) = -divisor then
      incr(countOptimizations);
      prepare_bigint_result(c_expr);
      incr(c_expr.temp_num);
      bigint_name := "tmp_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "biginttype ";
      c_expr.temp_decls &:= bigint_name;
      c_expr.temp_decls &:= ";\n";
      c_expr.result_expr := "(bigRShiftAssign((";
      c_expr.result_expr &:= bigint_name;
      c_expr.result_expr &:= "=";
      prepareAnyParamTemporarys(param1, c_param1, c_expr);
      if c_param1.result_expr <> "" then
        c_expr.result_expr &:= "bigNegateTemp(";
        c_expr.result_expr &:= c_param1.result_expr;
      else
        c_expr.result_expr := "bigNegate(";
        c_expr.result_expr &:= c_param1.expr;
      end if;
      c_expr.result_expr &:= "), &";
      c_expr.result_expr &:= bigint_name;
      c_expr.result_expr &:= "), ";
      c_expr.result_expr &:= integerLiteral(ord(log2(-divisor)));
      c_expr.result_expr &:= "), ";
      c_expr.result_expr &:= bigint_name;
      c_expr.result_expr &:= ")";
    else
      prepare_bigint_result(c_expr);
      c_expr.result_expr := "bigMDiv(";
      getAnyParamToResultExpr(param1, c_expr);
      c_expr.result_expr &:= ", ";
      c_expr.result_expr &:= bigIntegerLiteral(divisor);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_big_mdiv (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[3], BIGINTOBJECT, evaluatedParam) then
      process_const_big_mdiv(params[1], getValue(evaluatedParam, bigInteger), c_expr);
    else
      prepare_bigint_result(c_expr);
      c_expr.result_expr := "bigMDiv(";
      getAnyParamToResultExpr(params[1], c_expr);
      c_expr.result_expr &:= ", ";
      getAnyParamToResultExpr(params[3], c_expr);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_const_big_mod (in reference: param1, in bigInteger: divisor,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var bigInteger: modulus is 0_;
    var expr_type: c_param1 is expr_type.value;
  begin
    if divisor = 0_ then
      incr(countOptimizations);
      c_expr.expr &:= "(biginttype)(raise_error(NUMERIC_ERROR),NULL)";
    elsif getConstant(param1, BIGINTOBJECT, evaluatedParam) then
      incr(countOptimizations);
      modulus := getValue(evaluatedParam, bigInteger) mod divisor;
      c_expr.expr &:= bigIntegerLiteral(modulus);
    elsif divisor = 1_ or divisor = -1_ then
      incr(countOptimizations);
      c_expr.expr &:= bigIntegerLiteral(0_);
    elsif divisor > 0_ and log2(divisor) <= INTTYPE_MAX and
        2_ ** ord(log2(divisor)) = divisor then
      incr(countOptimizations);
      prepareAnyParamTemporarys(param1, c_param1, c_expr);
      if c_param1.result_expr <> "" then
        c_expr.result_expr &:= "bigLowerBitsTemp(";
        c_expr.result_expr &:= c_param1.result_expr;
      else
        c_expr.result_expr := "bigLowerBits(";
        c_expr.result_expr &:= c_param1.expr;
      end if;
      c_expr.result_expr &:= ", ";
      c_expr.result_expr &:= integerLiteral(ord(log2(divisor)));
      c_expr.result_expr &:= ")";
    elsif divisor < 0_ and log2(-divisor) <= INTTYPE_MAX and
        2_ ** ord(log2(-divisor)) = -divisor then
      incr(countOptimizations);
      c_expr.result_expr &:= "bigNegateTemp(bigLowerBitsTemp(";
      prepareAnyParamTemporarys(param1, c_param1, c_expr);
      if c_param1.result_expr <> "" then
        c_expr.result_expr &:= "bigNegateTemp(";
        c_expr.result_expr &:= c_param1.result_expr;
      else
        c_expr.result_expr := "bigNegate(";
        c_expr.result_expr &:= c_param1.expr;
      end if;
      c_expr.result_expr &:= "), ";
      c_expr.result_expr &:= integerLiteral(ord(log2(-divisor)));
      c_expr.result_expr &:= "))";
    else
      prepare_bigint_result(c_expr);
      c_expr.result_expr := "bigMod(";
      getAnyParamToResultExpr(param1, c_expr);
      c_expr.result_expr &:= ", ";
      c_expr.result_expr &:= bigIntegerLiteral(divisor);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_big_mod (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[3], BIGINTOBJECT, evaluatedParam) then
      process_const_big_mod(params[1], getValue(evaluatedParam, bigInteger), c_expr);
    else
      prepare_bigint_result(c_expr);
      c_expr.result_expr := "bigMod(";
      getAnyParamToResultExpr(params[1], c_expr);
      c_expr.result_expr &:= ", ";
      getAnyParamToResultExpr(params[3], c_expr);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_const_big_mult (in reference: param1, in bigInteger: factor,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var bigInteger: product is 0_;
  begin
    if getConstant(param1, BIGINTOBJECT, evaluatedParam) then
      incr(countOptimizations);
      product := getValue(evaluatedParam, bigInteger) * factor;
      c_expr.expr &:= bigIntegerLiteral(product);
    elsif factor = -1_ then
      incr(countOptimizations);
      prepare_bigint_result(c_expr);
      c_expr.result_expr := "bigNegate(";
      getAnyParamToResultExpr(param1, c_expr);
      c_expr.result_expr &:= ")";
    elsif factor = 0_ then
      incr(countOptimizations);
      c_expr.expr &:= bigIntegerLiteral(0_);
    elsif factor = 1_ then
      incr(countOptimizations);
      process_expr(param1, c_expr);
    elsif factor > 1_ and log2(factor) <= INTTYPE_MAX and
        2_ ** ord(log2(factor)) = factor then
      incr(countOptimizations);
      process_const_big_lshift(param1, ord(log2(factor)), c_expr);
    elsif factor < 1_ and log2(-factor) <= INTTYPE_MAX and
        2_ ** ord(log2(-factor)) = -factor then
      incr(countOptimizations);
      c_expr.result_expr := "bigNegateTemp(";
      process_const_big_lshift(param1, ord(log2(-factor)), c_expr);
      c_expr.result_expr &:= ")";
    elsif abs(factor) <= 127_ then
      incr(countOptimizations);
      prepare_bigint_result(c_expr);
      c_expr.result_expr := "bigMultSignedDigit(";
      getAnyParamToResultExpr(param1, c_expr);
      c_expr.result_expr &:= ", ";
      c_expr.result_expr &:= integerLiteral(ord(factor));
      c_expr.result_expr &:= ")";
    else
      prepare_bigint_result(c_expr);
      c_expr.result_expr := "bigMult(";
      getAnyParamToResultExpr(param1, c_expr);
      c_expr.result_expr &:= ", ";
      c_expr.result_expr &:= bigIntegerLiteral(factor);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_big_mult (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[3], BIGINTOBJECT, evaluatedParam) then
      process_const_big_mult(params[1], getValue(evaluatedParam, bigInteger), c_expr);
    elsif getConstant(params[1], BIGINTOBJECT, evaluatedParam) then
      process_const_big_mult(params[3], getValue(evaluatedParam, bigInteger), c_expr);
    elsif params[1] = params[3] then
      incr(countOptimizations);
      prepare_bigint_result(c_expr);
      c_expr.result_expr := "bigSquare(";
      getAnyParamToResultExpr(params[1], c_expr);
      c_expr.result_expr &:= ")";
    else
      prepare_bigint_result(c_expr);
      c_expr.result_expr := "bigMult(";
      getAnyParamToResultExpr(params[1], c_expr);
      c_expr.result_expr &:= ", ";
      getAnyParamToResultExpr(params[3], c_expr);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_const_big_mult_assign (in reference: param1, in bigInteger: factor,
    inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    if factor = 0_ then
      incr(countOptimizations);
      statement.expr := "bigCpy(&(";
      process_expr(param1, statement);
      statement.expr &:= "), ";
      statement.expr &:= bigIntegerLiteral(0_);
      statement.expr &:= ");\n";
      doLocalDeclsOfStatement(statement, c_expr);
    elsif factor = 1_ then
      incr(countOptimizations);
      c_expr.expr &:= "/* ignore bigInteger *:= 1_; */\n";
    elsif factor > 1_ and log2(factor) <= INTTYPE_MAX and
        2_ ** ord(log2(factor)) = factor then
      incr(countOptimizations);
      statement.expr := "bigLShiftAssign(&(";
      process_expr(param1, statement);
      statement.expr &:= "), ";
      statement.expr &:= integerLiteral(ord(log2(factor)));
      statement.expr &:= ");\n";
      doLocalDeclsOfStatement(statement, c_expr);
    else
      statement.expr := "bigMultAssign(&(";
      process_expr(param1, statement);
      statement.expr &:= "), ";
      statement.expr &:= bigIntegerLiteral(factor);
      statement.expr &:= ");\n";
      doLocalDeclsOfStatement(statement, c_expr);
    end if;
  end func;


const proc: process_big_mult_assign (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var expr_type: statement is expr_type.value;
  begin
    if getConstant(params[3], BIGINTOBJECT, evaluatedParam) then
      process_const_big_mult_assign(params[1], getValue(evaluatedParam, bigInteger), c_expr);
    else
      statement.expr := "bigMultAssign(&(";
      process_expr(params[1], statement);
      statement.expr &:= "), ";
      getAnyParamToExpr(params[3], statement);
      statement.expr &:= ");\n";
      doLocalDeclsOfStatement(statement, c_expr);
    end if;
  end func;


const proc: process_big_ne (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "!";
    process_big_eq(params, c_expr);
  end func;


const proc: process_big_negate (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var bigInteger: bigNumber is 0_;
    var expr_type: c_param1 is expr_type.value;
  begin
    if getConstant(params[2], BIGINTOBJECT, evaluatedParam) then
      incr(countOptimizations);
      bigNumber := -getValue(evaluatedParam, bigInteger);
      c_expr.expr &:= bigIntegerLiteral(bigNumber);
    else
      prepare_bigint_result(c_expr);
      prepareAnyParamTemporarys(params[2], c_param1, c_expr);
      if c_param1.result_expr <> "" then
        c_expr.result_expr := "bigNegateTemp(";
        c_expr.result_expr &:= c_param1.result_expr;
      else
        c_expr.result_expr := "bigNegate(";
        c_expr.result_expr &:= c_param1.expr;
      end if;
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_big_odd (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "bigOdd(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_big_ord (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "bigOrd(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_big_parse (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bigint_result(c_expr);
    c_expr.result_expr := "bigParse(";
    getAnyParamToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_big_parse_based (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bigint_result(c_expr);
    c_expr.result_expr := "bigParseBased(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_big_plus (in ref_list: params, inout expr_type: c_expr) is func

  begin
    process_expr(params[2], c_expr);
  end func;


const proc: process_big_pred (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: c_param1 is expr_type.value;
  begin
    prepare_bigint_result(c_expr);
    prepareAnyParamTemporarys(params[1], c_param1, c_expr);
    if c_param1.result_expr <> "" then
      c_expr.result_expr := "bigPredTemp(";
      c_expr.result_expr &:= c_param1.result_expr;
    else
      c_expr.result_expr := "bigPred(";
      c_expr.result_expr &:= c_param1.expr;
    end if;
    c_expr.result_expr &:= ")";
  end func;


const proc: process_big_rand (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bigint_result(c_expr);
    c_expr.result_expr := "bigRand(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getAnyParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_big_rem (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bigint_result(c_expr);
    c_expr.result_expr := "bigRem(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getAnyParamToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_big_rshift (in ref_list: params, inout expr_type: c_expr) is func

  local
    var string: bigint_name is "";
    var expr_type: c_param1 is expr_type.value;
  begin
    prepare_bigint_result(c_expr);
    prepareAnyParamTemporarys(params[1], c_param1, c_expr);
    if c_param1.result_expr <> "" then
      incr(c_expr.temp_num);
      bigint_name := "tmp_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "biginttype ";
      c_expr.temp_decls &:= bigint_name;
      c_expr.temp_decls &:= ";\n";
      c_expr.result_expr := "(bigRShiftAssign((";
      c_expr.result_expr &:= bigint_name;
      c_expr.result_expr &:= "=";
      c_expr.result_expr &:= c_param1.result_expr;
      c_expr.result_expr &:= ", &";
      c_expr.result_expr &:= bigint_name;
      c_expr.result_expr &:= "), ";
      getStdParamToResultExpr(params[3], c_expr);
      c_expr.result_expr &:= "), ";
      c_expr.result_expr &:= bigint_name;
    else
      c_expr.result_expr := "bigRShift(";
      c_expr.result_expr &:= c_param1.expr;
      c_expr.result_expr &:= ", ";
      getStdParamToResultExpr(params[3], c_expr);
    end if;
    c_expr.result_expr &:= ")";
  end func;


const proc: process_big_rshift_assign (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    statement.expr := "bigRShiftAssign(&(";
    process_expr(params[1], statement);
    statement.expr &:= "), ";
    getAnyParamToExpr(params[3], statement);
    statement.expr &:= ");\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


(**
 *  Produces code for the big integer subtraction.
 *  When the first parameter is a temporary value the subtraction
 *  is done with bigSbtrTemp. The bigSbtrTemp function returns
 *  the first parameter as result of the subtraction. That way the
 *  temporary of the first parameter must not be freed.
 *)
const proc: process_big_sbtr (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var expr_type: c_param1 is expr_type.value;
  begin
    if getConstant(params[3], BIGINTOBJECT, evaluatedParam) then
      process_const_big_add(params[1], -getValue(evaluatedParam, bigInteger), c_expr);
    else
      prepare_bigint_result(c_expr);
      prepareAnyParamTemporarys(params[1], c_param1, c_expr);
      if c_param1.result_expr <> "" then
        c_expr.result_expr := "bigSbtrTemp(";
        c_expr.result_expr &:= c_param1.result_expr;
      else
        c_expr.result_expr := "bigSbtr(";
        c_expr.result_expr &:= c_param1.expr;
      end if;
      c_expr.result_expr &:= ", ";
      getAnyParamToResultExpr(params[3], c_expr);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_const_big_shrink (in reference: param1, in bigInteger: number,
    inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    if number = -1_ then
      incr(countOptimizations);
      statement.expr := "bigIncr(&(";
      process_expr(param1, statement);
      statement.expr &:= "));\n";
      doLocalDeclsOfStatement(statement, c_expr);
    elsif number = 0_ then
      incr(countOptimizations);
      c_expr.expr &:= "/* ignore bigInteger -:= 0_; */\n";
    elsif number = 1_ then
      incr(countOptimizations);
      statement.expr := "bigDecr(&(";
      process_expr(param1, statement);
      statement.expr &:= "));\n";
      doLocalDeclsOfStatement(statement, c_expr);
    else
      statement.expr := "bigShrink(&(";
      process_expr(param1, statement);
      statement.expr &:= "), ";
      statement.expr &:= bigIntegerLiteral(number);
      statement.expr &:= ");\n";
      doLocalDeclsOfStatement(statement, c_expr);
    end if;
  end func;


const proc: process_big_shrink (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var expr_type: statement is expr_type.value;
  begin
    if getConstant(params[3], BIGINTOBJECT, evaluatedParam) then
      process_const_big_shrink(params[1], getValue(evaluatedParam, bigInteger), c_expr);
    else
      statement.expr := "bigShrink(&(";
      process_expr(params[1], statement);
      statement.expr &:= "), ";
      getAnyParamToExpr(params[3], statement);
      statement.expr &:= ");\n";
      doLocalDeclsOfStatement(statement, c_expr);
    end if;
  end func;


const proc: process_big_str (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "bigStr(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_big_succ (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: c_param1 is expr_type.value;
  begin
    prepare_bigint_result(c_expr);
    prepareAnyParamTemporarys(params[1], c_param1, c_expr);
    if c_param1.result_expr <> "" then
      c_expr.result_expr := "bigSuccTemp(";
      c_expr.result_expr &:= c_param1.result_expr;
    else
      c_expr.result_expr := "bigSucc(";
      c_expr.result_expr &:= c_param1.expr;
    end if;
    c_expr.result_expr &:= ")";
  end func;


const proc: process_big_to_bstri_be (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bstri_result(c_expr);
    c_expr.result_expr := "bigToBStriBe(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_big_to_bstri_le (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bstri_result(c_expr);
    c_expr.result_expr := "bigToBStriLe(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_big_value (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bigint_result(c_expr);
    c_expr.result_expr := "bigValue(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_bin_and (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "bigAnd(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_bin_or (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "bigOr(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_bin_xor (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "bigXor(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_bln_and (in ref_list: params, inout expr_type: c_expr) is func

  begin
    if isActionExpression(params[1], "BLN_AND") then
      process_expr(params[1], c_expr);
    else
      c_expr.expr &:= "(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ")";
    end if;
    c_expr.expr &:= " &&\n";
    if category(params[3]) = MATCHOBJECT then
      c_expr.expr &:= diagnosticLine(params[3]);
    else
      setDiagnosticLine(c_expr);
    end if;
    c_expr.expr &:= "(";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_bln_cpy (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    process_expr(params[1], statement);
    statement.expr &:= "=";
    process_expr(params[3], statement);
    statement.expr &:= ";\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_bln_eq (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") == (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_bln_ge (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") >= (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_bln_gt (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") > (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_bln_iconv (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ") & 1";
  end func;


const proc: process_bln_le (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") <= (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_bln_lt (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") < (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_bln_ne (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") != (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_bln_not (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "!(";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_bln_or (in ref_list: params, inout expr_type: c_expr) is func

  begin
    if isActionExpression(params[1], "BLN_OR") then
      process_expr(params[1], c_expr);
    else
      c_expr.expr &:= "(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ")";
    end if;
    c_expr.expr &:= " ||\n";
    if category(params[3]) = MATCHOBJECT then
      c_expr.expr &:= diagnosticLine(params[3]);
    else
      setDiagnosticLine(c_expr);
    end if;
    c_expr.expr &:= "(";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_bln_ord (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(inttype)(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_bln_value (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "blnValue(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_bst_append (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: c_param1 is expr_type.value;
    var expr_type: c_param3 is expr_type.value;
  begin
    process_expr(params[1], c_param1);
    c_param3.temp_num := c_param1.temp_num;
    getAnyParamToExpr(params[3], c_param3);
    if has_temp_values(c_param3) then
      c_expr.expr &:= "{\n";
      AppendWithDiagnostic(c_param1.temp_decls, c_expr);
      AppendWithDiagnostic(c_param3.temp_decls, c_expr);
      AppendWithDiagnostic(c_param1.temp_assigns, c_expr);
      AppendWithDiagnostic(c_param3.temp_assigns, c_expr);
    end if;
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "bstAppend(&(";
    c_expr.expr &:= c_param1.expr;
    c_expr.expr &:= "), ";
    c_expr.expr &:= c_param3.expr;
    c_expr.expr &:= ");\n";
    if has_temp_values(c_param3) then
      AppendWithDiagnostic(c_param1.temp_frees, c_expr);
      AppendWithDiagnostic(c_param3.temp_frees, c_expr);
      c_expr.expr &:= "}\n";
    end if;
  end func;


const proc: process_bst_cmp (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "bstCmp(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_bst_cpy (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: c_param1 is expr_type.value;
    var expr_type: c_param3 is expr_type.value;
  begin
    process_expr(params[1], c_param1);
    c_param3.temp_num := c_param1.temp_num;
    process_expr(params[3], c_param3);
    if has_temp_values(c_param3) then
      c_expr.expr &:= "{\n";
      AppendWithDiagnostic(c_param1.temp_decls, c_expr);
      AppendWithDiagnostic(c_param3.temp_decls, c_expr);
      AppendWithDiagnostic(c_param1.temp_assigns, c_expr);
      AppendWithDiagnostic(c_param3.temp_assigns, c_expr);
    end if;
    if c_param3.result_expr <> "" then
      c_expr.expr &:= "{\n";
      setDiagnosticLine(c_expr);
      if isNormalVariable(params[1]) then
        c_expr.expr &:= "bstritype old_bstri=";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ";\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= "=";
      else
        c_expr.expr &:= "bstritype *bstri_ptr=&(";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ");\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "bstritype old_bstri=*bstri_ptr;\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "*bstri_ptr=";
      end if;
      c_expr.expr &:= c_param3.result_expr;
      c_expr.expr &:= ";\n";
      setDiagnosticLine(c_expr);
      c_expr.expr &:= "bstDestr(old_bstri);\n";
      c_expr.expr &:= "}\n";
    else
      setDiagnosticLine(c_expr);
      c_expr.expr &:= "bstCpy(&(";
      c_expr.expr &:= c_param1.expr;
      c_expr.expr &:= "), ";
      c_expr.expr &:= c_param3.expr;
      c_expr.expr &:= ");\n";
    end if;
    if has_temp_values(c_param3) then
      AppendWithDiagnostic(c_param1.temp_frees, c_expr);
      AppendWithDiagnostic(c_param3.temp_frees, c_expr);
      c_expr.expr &:= "}\n";
    end if;
  end func;


const proc: process_bst_eq (in ref_list: params, inout expr_type: c_expr) is func

  local
    var string: bstri_a_name is "";
    var string: bstri_b_name is "";
  begin
    c_expr.expr &:= "(";
    bstri_a_name := getParameterAsVariable("const_bstritype", "tmp_a_", params[1], c_expr);
    bstri_b_name := getParameterAsVariable("const_bstritype", "tmp_b_", params[3], c_expr);
    (* Formula used: (a->size==b->size&&memcmp(a->mem,b->mem,
                     a->size*sizeof(unsigned char))==0) *)
    c_expr.expr &:= bstri_a_name;
    c_expr.expr &:= "->size==";
    c_expr.expr &:= bstri_b_name;
    c_expr.expr &:= "->size&&memcmp(";
    c_expr.expr &:= bstri_a_name;
    c_expr.expr &:= "->mem,";
    c_expr.expr &:= bstri_b_name;
    c_expr.expr &:= "->mem,";
    c_expr.expr &:= bstri_a_name;
    c_expr.expr &:= "->size*sizeof(unsigned char))==0)";
  end func;


const proc: process_bst_hashcode (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "bstHashCode(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_const_bst_idx (in reference: function, in bstring: bstri,
    in reference: param3, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var integer: index is 0;
    var string: index_name is "";
  begin
    incr(countOptimizations);
    if getConstant(param3, INTOBJECT, evaluatedParam) then
      index := getValue(evaluatedParam, integer);
      if index < 1 or index > length(bstri) then
        process_raise_error("RANGE_ERROR", function, c_expr);
      else
        c_expr.expr &:= charLiteral(bstri[index]);
      end if;
    else
      c_expr.expr &:= bstriLiteral(bstri);
      c_expr.expr &:= "->mem[";
      if array_range_check then
        incr(c_expr.temp_num);
        index_name := "idx_" & str(c_expr.temp_num);
        if ccConf.TWOS_COMPLEMENT_INTTYPE then
          c_expr.temp_decls &:= "uinttype ";
        else
          c_expr.temp_decls &:= "inttype ";
        end if;
        c_expr.temp_decls &:= index_name;
        c_expr.temp_decls &:= ";\n";
        c_expr.expr &:= "(";
        c_expr.expr &:= index_name;
        c_expr.expr &:= "=";
        if ccConf.TWOS_COMPLEMENT_INTTYPE then
          c_expr.expr &:= "(uinttype)((";
          process_expr(param3, c_expr);
          c_expr.expr &:= ")-1), ";
        else
          c_expr.expr &:= "(";
          process_expr(param3, c_expr);
          c_expr.expr &:= ")-1, ";
          c_expr.expr &:= index_name;
          c_expr.expr &:= "<0 || ";
        end if;
        c_expr.expr &:= index_name;
        c_expr.expr &:= ">=";
        c_expr.expr &:= str(length(bstri));
        c_expr.expr &:= " ? ";
        process_raise_error("RANGE_ERROR", function, c_expr);
        c_expr.expr &:= " : 0, ";
        c_expr.expr &:= index_name;
        c_expr.expr &:= ")";
      else
        c_expr.expr &:= "(";
        process_expr(param3, c_expr);
        c_expr.expr &:= ")-1";
      end if;
      c_expr.expr &:= "]";
    end if;
  end func;


const proc: process_const_bst_idx (in reference: function, in reference: param1,
    in integer: index, inout expr_type: c_expr) is func

  local
    var string: bstri_name is "";
  begin
    incr(countOptimizations);
    if index < 1 then
      process_raise_error("RANGE_ERROR", function, c_expr);
    elsif array_range_check then
      incr(c_expr.temp_num);
      bstri_name := "tmp_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "const_bstritype ";
      c_expr.temp_decls &:= bstri_name;
      c_expr.temp_decls &:= ";\n";
      c_expr.expr &:= "(*(";
      c_expr.expr &:= bstri_name;
      c_expr.expr &:= "=";
      getAnyParamToExpr(param1, c_expr);
      c_expr.expr &:= ", &";
      c_expr.expr &:= bstri_name;
      c_expr.expr &:= "->mem[(";
      c_expr.expr &:= bstri_name;
      c_expr.expr &:= "->size<";
      c_expr.expr &:= str(index);
      c_expr.expr &:= " ? ";
      process_raise_error("RANGE_ERROR", function, c_expr);
      c_expr.expr &:= " : 0, ";
      c_expr.expr &:= str(pred(index));
      c_expr.expr &:= ")]))";
    else
      c_expr.expr &:= "(";
      getAnyParamToExpr(param1, c_expr);
      c_expr.expr &:= ")->mem[";
      c_expr.expr &:= str(pred(index));
      c_expr.expr &:= "]";
    end if;
  end func;


const proc: process_bst_idx (in reference: function, in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: bstri_name is "";
    var string: index_name is "";
  begin
    if getConstant(params[1], BSTRIOBJECT, evaluatedParam) then
      process_const_bst_idx(function, getValue(evaluatedParam, bstring), params[3], c_expr);
    elsif getConstant(params[3], INTOBJECT, evaluatedParam) then
      process_const_bst_idx(function, params[1], getValue(evaluatedParam, integer), c_expr);
    elsif array_range_check then
      incr(c_expr.temp_num);
      bstri_name := "tmp_" & str(c_expr.temp_num);
      index_name := "idx_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "const_bstritype ";
      c_expr.temp_decls &:= bstri_name;
      c_expr.temp_decls &:= ";\n";
      if ccConf.TWOS_COMPLEMENT_INTTYPE then
        c_expr.temp_decls &:= "uinttype ";
      else
        c_expr.temp_decls &:= "inttype ";
      end if;
      c_expr.temp_decls &:= index_name;
      c_expr.temp_decls &:= ";\n";
      c_expr.expr &:= "(*(";
      c_expr.expr &:= bstri_name;
      c_expr.expr &:= "=";
      getAnyParamToExpr(params[1], c_expr);
      c_expr.expr &:= ", &";
      c_expr.expr &:= bstri_name;
      c_expr.expr &:= "->mem[(";
      c_expr.expr &:= index_name;
      c_expr.expr &:= "=";
      if ccConf.TWOS_COMPLEMENT_INTTYPE then
        c_expr.expr &:= "(uinttype)((";
        process_expr(params[3], c_expr);
        c_expr.expr &:= ")-1), ";
      else
        c_expr.expr &:= "(";
        process_expr(params[3], c_expr);
        c_expr.expr &:= ")-1, ";
        c_expr.expr &:= index_name;
        c_expr.expr &:= "<0 || ";
      end if;
      c_expr.expr &:= index_name;
      c_expr.expr &:= ">=";
      c_expr.expr &:= bstri_name;
      c_expr.expr &:= "->size ? ";
      process_raise_error("RANGE_ERROR", function, c_expr);
      c_expr.expr &:= " : 0, ";
      c_expr.expr &:= index_name;
      c_expr.expr &:= ")]))";
    else
      c_expr.expr &:= "(";
      getAnyParamToExpr(params[1], c_expr);
      c_expr.expr &:= ")->mem[(";
      process_expr(params[3], c_expr);
      c_expr.expr &:= ")-1]";
    end if;
  end func;


const proc: process_bst_lng (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(inttype)((";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")->size)";
  end func;


const proc: process_bst_ne (in ref_list: params, inout expr_type: c_expr) is func

  local
    var string: bstri_a_name is "";
    var string: bstri_b_name is "";
  begin
    c_expr.expr &:= "(";
    bstri_a_name := getParameterAsVariable("const_bstritype", "tmp_a_", params[1], c_expr);
    bstri_b_name := getParameterAsVariable("const_bstritype", "tmp_b_", params[3], c_expr);
    (* Formula used: (a->size!=b->size||memcmp(a->mem,b->mem,
                     a->size*sizeof(unsigned char))!=0) *)
    c_expr.expr &:= bstri_a_name;
    c_expr.expr &:= "->size!=";
    c_expr.expr &:= bstri_b_name;
    c_expr.expr &:= "->size||memcmp(";
    c_expr.expr &:= bstri_a_name;
    c_expr.expr &:= "->mem,";
    c_expr.expr &:= bstri_b_name;
    c_expr.expr &:= "->mem,";
    c_expr.expr &:= bstri_a_name;
    c_expr.expr &:= "->size*sizeof(unsigned char))!=0)";
  end func;


const proc: process_bst_parse (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bstri_result(c_expr);
    c_expr.result_expr := "bstParse(";
    getAnyParamToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_bst_str (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "bstStr(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_bst_value (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bstri_result(c_expr);
    c_expr.result_expr := "bstValue(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_const_chr_chr (in reference: function, in integer: number, inout expr_type: c_expr) is func

  begin
    incr(countOptimizations);
    if number < pred(-2147483647) or number > 2147483647 then
      process_raise_error("RANGE_ERROR", function, c_expr);
    else
      c_expr.expr &:= "(chartype) ";
      c_expr.expr &:= str(number);
    end if;
  end func;


const proc: process_chr_chr (in reference: function, in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: number_name is "";
  begin
    if getConstant(params[1], INTOBJECT, evaluatedParam) then
      process_const_chr_chr(function, getValue(evaluatedParam, integer), c_expr);
    elsif conversion_range_check and ccConf.INTTYPE_SIZE = 64 then
      c_expr.expr &:= "(";
      number_name := getParameterAsVariable("inttype", "tmp_", params[1], c_expr);
      c_expr.expr &:= number_name;
      c_expr.expr &:= "<INT32TYPE_MIN||";
      c_expr.expr &:= number_name;
      c_expr.expr &:= ">INT32TYPE_MAX?";
      process_raise_error("RANGE_ERROR", function, c_expr);
      c_expr.expr &:= ":(chartype)";
      c_expr.expr &:= number_name;
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= "(chartype)(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_chr_clit (in ref_list: params, inout expr_type: c_expr) is func

  local
    var string: buffer_name is "";
  begin
    if ccConf.ALLOW_STRITYPE_SLICES then
      incr(c_expr.temp_num);
      buffer_name := "buffer_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "char ";
      c_expr.temp_decls &:= buffer_name;
      c_expr.temp_decls &:= "[sizeof(struct stristruct) + ";
      if ccConf.INTTYPE_SIZE = 64 then
        c_expr.temp_decls &:= "19";
      elsif ccConf.INTTYPE_SIZE = 32 then
        c_expr.temp_decls &:= "10";
      end if;
      c_expr.temp_decls &:= " * sizeof(strelemtype)];\n";
      c_expr.expr &:= "chrCLitToBuffer(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ", (stritype) &";
      c_expr.expr &:= buffer_name;
      c_expr.expr &:= ")";
    else
      prepare_stri_result(c_expr);
      c_expr.result_expr := "chrCLit(";
      getStdParamToResultExpr(params[1], c_expr);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_chr_cmp (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "chrCmp(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_chr_conv (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_chr_cpy (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    process_expr(params[1], statement);
    statement.expr &:= "=";
    process_expr(params[3], statement);
    statement.expr &:= ";\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_chr_decr (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "--(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_chr_eq (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") == (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_chr_ge (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") >= (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_chr_grow (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    process_expr(params[1], statement);
    statement.expr &:= "+=";
    process_expr(params[3], statement);
    statement.expr &:= ";\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_chr_gt (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") > (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_chr_hashcode (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(inttype)((schartype)(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= "))";
  end func;


const proc: process_chr_iconv (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(chartype)(";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_chr_incr (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "++(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_chr_le (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") <= (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_chr_low (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "chrLow(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_chr_lt (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") < (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_chr_ne (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") != (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_chr_ord (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(inttype)((schartype)(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= "))";
  end func;


const proc: process_chr_pred (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")-1";
  end func;


const proc: process_chr_shrink (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    process_expr(params[1], statement);
    statement.expr &:= "-=";
    process_expr(params[3], statement);
    statement.expr &:= ";\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_chr_str (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: stristruct_name is "";
  begin
    if getConstant(params[1], CHAROBJECT, evaluatedParam) then
      incr(countOptimizations);
      c_expr.expr &:= "/*chrStr*/";
      c_expr.expr &:= stringLiteral(str(getValue(evaluatedParam, char)));
    else
      incr(c_expr.temp_num);
      stristruct_name := "stri_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "struct stristruct ";
      c_expr.temp_decls &:= stristruct_name;
      c_expr.temp_decls &:= ";\n";
      c_expr.expr &:= "chrStrMacro(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ",";
      c_expr.expr &:= stristruct_name;
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_chr_succ (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")+1";
  end func;


const proc: process_chr_up (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "chrUp(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_chr_value (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "chrValue(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_cmd_big_filesize (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bigint_result(c_expr);
    c_expr.result_expr := "cmdBigFileSize(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_cmd_chdir (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "cmdChdir(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_cmd_clone_file (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "cmdCloneFile(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_cmd_config_value (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "cmdConfigValue(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_cmd_copy_file (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "cmdCopyFile(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_cmd_environment (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  local
    var type: result_type is void;
  begin
    result_type := resultType(getType(function));
    prepare_typed_result(result_type, c_expr);
    c_expr.result_expr := "cmdEnvironment()";
  end func;


const proc: process_cmd_filemode (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  begin
    prepare_set_result(resultType(getType(function)), c_expr);
    c_expr.result_expr := "cmdFileMode(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_cmd_filesize (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "cmdFileSize(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_cmd_filetype (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "cmdFileType(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_cmd_filetype_sl (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "cmdFileTypeSL(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_cmd_getcwd (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "cmdGetcwd()";
  end func;


const proc: process_cmd_getenv (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "cmdGetenv(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_cmd_get_atime (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "cmdGetATime(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", &(";
    process_expr(params[2], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[3], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[4], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[5], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[6], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[7], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[8], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[9], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[10], c_expr);
    c_expr.expr &:= "));\n";
  end func;


const proc: process_cmd_get_ctime (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "cmdGetCTime(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", &(";
    process_expr(params[2], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[3], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[4], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[5], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[6], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[7], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[8], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[9], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[10], c_expr);
    c_expr.expr &:= "));\n";
  end func;


const proc: process_cmd_get_mtime (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "cmdGetMTime(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", &(";
    process_expr(params[2], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[3], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[4], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[5], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[6], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[7], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[8], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[9], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[10], c_expr);
    c_expr.expr &:= "));\n";
  end func;


const proc: process_cmd_get_search_path (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  local
    var type: result_type is void;
  begin
    result_type := resultType(getType(function));
    prepare_typed_result(result_type, c_expr);
    c_expr.result_expr := "cmdGetSearchPath()";
  end func;


const proc: process_cmd_homedir (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "cmdHomeDir()";
  end func;


const proc: process_cmd_ls (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_typed_result(array_type[getExprResultType(params[1])], c_expr);
    c_expr.result_expr := "cmdLs(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_cmd_mkdir (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "cmdMkdir(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_cmd_move (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "cmdMove(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_cmd_readlink (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "cmdReadlink(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_cmd_remove (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "cmdRemove(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_cmd_remove_any_file (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "cmdRemoveAnyFile(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_cmd_setenv (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "cmdSetenv(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_cmd_set_atime (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "cmdSetATime(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[6], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[7], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[8], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[9], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_cmd_set_filemode (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "cmdSetFileMode(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_cmd_set_mtime (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "cmdSetMTime(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[6], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[7], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[8], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[9], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_cmd_shell (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "cmdShell(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_cmd_shell_escape (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "cmdShellEscape(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_cmd_pipe2 (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "cmdPipe2(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ", &(";
    process_expr(params[3], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[4], c_expr);
    c_expr.expr &:= "));\n";
  end func;


const proc: process_cmd_pty (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "cmdPty(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ", &(";
    process_expr(params[3], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[4], c_expr);
    c_expr.expr &:= "));\n";
  end func;


const proc: process_cmd_start_process (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "cmdStartProcess(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_cmd_symlink (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "cmdSymlink(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_cmd_to_os_path (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "cmdToOsPath(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_con_clear (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "conClear(";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_con_cursor (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "conCursor(";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_con_flush (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "conFlush();\n";
  end func;


const proc: process_con_height (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "conHeight()";
  end func;


const proc: process_con_h_scl (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "conHScroll(";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[6], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_con_open (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "conOpen();\n";
  end func;


const proc: process_con_setpos (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "conSetpos(";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_con_v_scl (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "conVScroll(";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[6], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_con_width (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "conWidth()";
  end func;


const proc: process_con_write (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "conWrite(";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_arc (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwArc(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[6], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_arc2 (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwArc2(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[6], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_background (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwBackground(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_circle (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwCircle(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_clear (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwClear(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_cmp (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "ptrCmp(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_drw_color (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwColor(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_copyarea (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwCopyArea(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[6], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[7], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[8], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_cpy (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: c_param1 is expr_type.value;
    var expr_type: c_param3 is expr_type.value;
  begin
    process_expr(params[1], c_param1);
    c_param3.temp_num := c_param1.temp_num;
    process_expr(params[3], c_param3);
    if has_temp_values(c_param3) then
      c_expr.expr &:= "{\n";
      AppendWithDiagnostic(c_param1.temp_decls, c_expr);
      AppendWithDiagnostic(c_param3.temp_decls, c_expr);
      AppendWithDiagnostic(c_param1.temp_assigns, c_expr);
      AppendWithDiagnostic(c_param3.temp_assigns, c_expr);
    end if;
    if c_param3.result_expr <> "" then
      c_expr.expr &:= "{\n";
      setDiagnosticLine(c_expr);
      if isNormalVariable(params[1]) then
        c_expr.expr &:= "wintype old_win=";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ";\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= "=";
      else
        c_expr.expr &:= "wintype *win_ptr=&(";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ");\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "wintype old_win=*win_ptr;\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "*win_ptr=";
      end if;
      c_expr.expr &:= c_param3.result_expr;
      c_expr.expr &:= ";\n";
      setDiagnosticLine(c_expr);
      c_expr.expr &:= "drwDestr(old_win);\n";
      c_expr.expr &:= "}\n";
    else
      setDiagnosticLine(c_expr);
      c_expr.expr &:= "drwCpy(&(";
      c_expr.expr &:= c_param1.expr;
      c_expr.expr &:= "), ";
      c_expr.expr &:= c_param3.expr;
      c_expr.expr &:= ");\n";
    end if;
    if has_temp_values(c_param3) then
      AppendWithDiagnostic(c_param1.temp_frees, c_expr);
      AppendWithDiagnostic(c_param3.temp_frees, c_expr);
      c_expr.expr &:= "}\n";
    end if;
  end func;


const proc: process_drw_eq (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ") == (";
    getAnyParamToExpr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_drw_farcchord (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwFArcChord(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[6], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_farcpieslice(in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwFArcPieSlice(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[6], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_fcircle (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwFCircle(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_fellipse (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwFEllipse(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_flush (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwFlush();\n";
  end func;


const proc: process_drw_fpolyline (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwFPolyLine(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[4], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_genpointlist (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bstri_result(c_expr);
    c_expr.result_expr &:= "drwGenPointList(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_drw_get (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_win_result(c_expr);
    c_expr.result_expr := "drwGet(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[4], c_expr);
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[5], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_drw_getimage (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bstri_result(c_expr);
    c_expr.result_expr := "drwGetImage(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_drw_getimagepixel (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "drwGetImagePixel(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_drw_getpixel (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "drwGetPixel(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_drw_hashcode (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(inttype)(((memsizetype)(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")) >> 6)";
  end func;


const proc: process_drw_height (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "drwHeight(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_drw_image (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_win_result(c_expr);
    c_expr.result_expr := "drwRtlImage(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_drw_line (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwLine(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_ne (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ") != (";
    getAnyParamToExpr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_drw_new_pixmap (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_win_result(c_expr);
    c_expr.result_expr := "drwNewPixmap(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_drw_open (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_win_result(c_expr);
    c_expr.result_expr := "drwOpen(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[4], c_expr);
    c_expr.result_expr &:= ", ";
    getAnyParamToResultExpr(params[5], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_drw_open_sub_window (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_win_result(c_expr);
    c_expr.result_expr := "drwOpenSubWindow(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[4], c_expr);
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[5], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_drw_parc (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwPArc(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[6], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[7], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_pcircle (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwPCircle(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_pfarcchord (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwPFArcChord(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[6], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[7], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_pfarcpieslice (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwPFArcPieSlice(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[6], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[7], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_pfcircle (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwPFCircle(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_pfellipse (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwPFEllipse(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[6], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_pixeltorgb (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwPixelToRgb(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", &(";
    process_expr(params[2], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[3], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[4], c_expr);
    c_expr.expr &:= "));\n";
  end func;


const proc: process_drw_pline (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwPLine(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[6], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_point (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwPoint(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_pointer_xpos (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "drwPointerXpos(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_drw_pointer_ypos (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "drwPointerYpos(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_drw_polyline (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwPolyLine(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[4], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_ppoint (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwPPoint(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_prect (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwPRect(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[6], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_put (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwPut(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_rect (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwRect(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_rgbcol (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "drwRgbColor(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_drw_setcontent (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwSetContent(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_setpos (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwSetPos(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_setTransparentColor (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwSetTransparentColor(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_text (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwText(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[4], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[6], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_toBottom (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwToBottom(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_toTop (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "drwToTop(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_drw_value (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "drwValue(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_drw_width (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "drwWidth(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_drw_xpos (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "drwXPos(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_drw_ypos (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "drwYPos(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_enu_conv (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_enu_cpy (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    process_expr(params[1], statement);
    statement.expr &:= "=";
    process_expr(params[3], statement);
    statement.expr &:= ";\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_enu_eq (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") == (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_enu_iconv2 (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_enu_ne (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") != (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_enu_ord2 (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_enu_value (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "enuValue(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_fil_big_lng (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bigint_result(c_expr);
    c_expr.result_expr := "filBigLng(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_fil_big_seek (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "filBigSeek(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_fil_big_tell (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bigint_result(c_expr);
    c_expr.result_expr := "filBigTell(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_fil_close (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "filClose(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_fil_cpy (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    process_expr(params[1], statement);
    statement.expr &:= "=";
    process_expr(params[3], statement);
    statement.expr &:= ";\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_fil_eof (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "feof(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_fil_eq (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") == (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_fil_err (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "stderr";
  end func;


const proc: process_fil_flush (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "fflush(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_fil_getc (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "fgetc(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_fil_gets (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "filGets(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_fil_has_next (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "filHasNext(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_fil_in (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "stdin";
  end func;


const proc: process_fil_input_ready (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "filInputReady(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_fil_line_read (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "filLineRead(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", &(";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= "))";
  end func;


const proc: process_fil_lit (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "filLit(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_fil_lng (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "filLng(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_fil_ne (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") != (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_fil_nil (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "NULL";
  end func;


const proc: process_fil_open (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "filOpen(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_fil_out (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "stdout";
  end func;


const proc: process_fil_pclose (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "filPclose(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_fil_popen (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "filPopen(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_fil_print (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "filPrint(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_fil_seek (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "filSeek(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_fil_setbuf (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "filSetbuf(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_fil_tell (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "filTell(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_fil_value (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "filValue(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_fil_write (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "filWrite(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_fil_word_read (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "filWordRead(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", &(";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= "))";
  end func;


const proc: process_flt_a2tan (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "atan2(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_abs (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "fabs(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_acos (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "acos(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_add (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") + (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_asin (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "asin(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_atan (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "atan(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_cast (in ref_list: params, inout expr_type: c_expr) is func

  local
    var string: temp_name is "";
  begin
    incr(c_expr.temp_num);
    temp_name := "tmp_" & str(c_expr.temp_num);
    c_expr.temp_decls &:= "rtlValueunion ";
    c_expr.temp_decls &:= temp_name;
    c_expr.temp_decls &:= ";\n";
    c_expr.expr &:= "(";
    c_expr.expr &:= temp_name;
    c_expr.expr &:= ".floatvalue=";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ",";
    c_expr.expr &:= temp_name;
    c_expr.expr &:= ".intvalue)";
  end func;


const proc: process_flt_ceil (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "ceil(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_cmp (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "fltCmp(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_cos (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "cos(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_cosh (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "cosh(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_cpy (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    process_expr(params[1], statement);
    statement.expr &:= "=";
    process_expr(params[3], statement);
    statement.expr &:= ";\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_flt_dgts (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "fltDgts(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_const_flt_div (in reference: param1, in float: divisor,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var float: dividend is 0.0;
    var string: dividendTmp is "";
  begin
    incr(countOptimizations);
    if divisor = 0.0 and (ccConf.FLOAT_ZERO_DIV_ERROR or ccConf.CHECK_FLOAT_DIV_BY_ZERO) then
      if getConstant(param1, FLOATOBJECT, evaluatedParam) then
        dividend := getValue(evaluatedParam, float);
        if dividend = 0.0 or isNaN(dividend) then
          c_expr.expr &:= "NOT_A_NUMBER";
        elsif (dividend < 0.0) = isNegativeZero(divisor) then
          c_expr.expr &:= "POSITIVE_INFINITY";
        else
          c_expr.expr &:= "NEGATIVE_INFINITY";
        end if;
      else
        c_expr.expr &:= "(";
        dividendTmp := getParameterAsVariable("floattype", "tmp_", param1, c_expr);
        c_expr.expr &:= "isnan(";
        c_expr.expr &:= dividendTmp;
        c_expr.expr &:= ") || ";
        c_expr.expr &:= dividendTmp;
        c_expr.expr &:= "==0.0 ? NOT_A_NUMBER : (";
        c_expr.expr &:= dividendTmp;
        if isNegativeZero(divisor) then
          c_expr.expr &:= "<0.0 ? POSITIVE_INFINITY : NEGATIVE_INFINITY))";
        else
          c_expr.expr &:= "<0.0 ? NEGATIVE_INFINITY : POSITIVE_INFINITY))";
        end if;
      end if;
    else
      c_expr.expr &:= "(";
      process_expr(param1, c_expr);
      c_expr.expr &:= ") / ";
      c_expr.expr &:= floatLiteral(divisor);
    end if;
  end func;


const proc: process_flt_div (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: dividend is "";
    var string: divisor is "";
  begin
    if getConstant(params[3], FLOATOBJECT, evaluatedParam) then
      process_const_flt_div(params[1], getValue(evaluatedParam, float), c_expr);
    elsif ccConf.FLOAT_ZERO_DIV_ERROR and isActionExpression(params[3], "FLT_NEGATE") and
        category(getActionParameter(params[3], 2)) = FLOATOBJECT and
        not isVar(getActionParameter(params[3], 2)) then
      process_const_flt_div(params[1], getValue(evaluate(prog, params[3]), float), c_expr);
    elsif ccConf.CHECK_FLOAT_DIV_BY_ZERO then
      c_expr.expr &:= "(";
      dividend := getParameterAsVariable("floattype", "tmp_", params[1], c_expr);
      divisor := getParameterAsVariable("floattype", "tmp_", params[3], c_expr);
      c_expr.expr &:= divisor;
      c_expr.expr &:= "==0.0 ? (isnan(";
      c_expr.expr &:= dividend;
      c_expr.expr &:= ") || ";
      c_expr.expr &:= dividend;
      c_expr.expr &:= "==0.0 ? NOT_A_NUMBER : ((";
      c_expr.expr &:= dividend;
      c_expr.expr &:= "<0.0)==fltIsNegativeZero(";
      c_expr.expr &:= divisor;
      c_expr.expr &:= ") ? POSITIVE_INFINITY : NEGATIVE_INFINITY)) : ";
      c_expr.expr &:= dividend;
      c_expr.expr &:= " / ";
      c_expr.expr &:= divisor;
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= "(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ") / (";
      process_expr(params[3], c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_const_flt_div_assign (in reference: param1, in float: divisor,
    inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
    var integer: temp_num is 0;
    var string: dividend is "";
  begin
    incr(countOptimizations);
    if divisor = 0.0 and (ccConf.FLOAT_ZERO_DIV_ERROR or ccConf.CHECK_FLOAT_DIV_BY_ZERO) then
      if isNormalVariable(param1) then
        dividend := normalVariable(param1, statement);
      else
        incr(statement.temp_num);
        dividend := "tmp_" & str(statement.temp_num);
        statement.temp_decls &:= "floattype *";
        statement.temp_decls &:= dividend;
        statement.temp_decls &:= ";\n";
        statement.expr &:= dividend;
        statement.expr &:= "=&(";
        process_expr(param1, statement);
        statement.expr &:= ");\n";
        dividend := "*" & dividend;
      end if;
      statement.expr &:= dividend;
      statement.expr &:= "=(isnan(";
      statement.expr &:= dividend;
      statement.expr &:= ") || ";
      statement.expr &:= dividend;
      statement.expr &:= "==0.0 ? NOT_A_NUMBER : (";
      statement.expr &:= dividend;
      if isNegativeZero(divisor) then
        statement.expr &:= "<0.0 ? POSITIVE_INFINITY : NEGATIVE_INFINITY));\n";
      else
        statement.expr &:= "<0.0 ? NEGATIVE_INFINITY : POSITIVE_INFINITY));\n";
      end if;
      doLocalDeclsOfStatement(statement, c_expr);
    else
      process_expr(param1, statement);
      statement.expr &:= "/=";
      statement.expr &:= floatLiteral(divisor);
      statement.expr &:= ";\n";
      doLocalDeclsOfStatement(statement, c_expr);
    end if;
  end func;


const proc: process_flt_div_assign (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var expr_type: statement is expr_type.value;
    var string: dividend is "";
    var string: divisor is "";
  begin
    if getConstant(params[3], FLOATOBJECT, evaluatedParam) then
      process_const_flt_div_assign(params[1], getValue(evaluatedParam, float), c_expr);
    elsif ccConf.FLOAT_ZERO_DIV_ERROR and isActionExpression(params[3], "FLT_NEGATE") and
        category(getActionParameter(params[3], 2)) = FLOATOBJECT and
        not isVar(getActionParameter(params[3], 2)) then
      process_const_flt_div_assign(params[1], getValue(evaluate(prog, params[3]), float), c_expr);
    elsif ccConf.CHECK_FLOAT_DIV_BY_ZERO then
      if isNormalVariable(params[1]) then
        dividend := normalVariable(params[1], statement);
      else
        incr(statement.temp_num);
        dividend := "tmp_" & str(statement.temp_num);
        statement.temp_decls &:= "floattype *";
        statement.temp_decls &:= dividend;
        statement.temp_decls &:= ";\n";
        statement.expr &:= dividend;
        statement.expr &:= "=&(";
        process_expr(params[1], statement);
        statement.expr &:= ");\n";
        dividend := "*" & dividend;
      end if;
      if isNormalVariable(params[3]) then
        divisor := normalVariable(params[3], statement);
      else
        incr(statement.temp_num);
        divisor := "tmp_" & str(statement.temp_num);
        statement.temp_decls &:= "floattype ";
        statement.temp_decls &:= divisor;
        statement.temp_decls &:= ";\n";
        statement.expr &:= divisor;
        statement.expr &:= "=";
        process_expr(params[3], statement);
        statement.expr &:= ";\n";
      end if;
      statement.expr &:= dividend;
      statement.expr &:= "=(";
      statement.expr &:= divisor;
      statement.expr &:= "==0.0 ? (isnan(";
      statement.expr &:= dividend;
      statement.expr &:= ") || ";
      statement.expr &:= dividend;
      statement.expr &:= "==0.0 ? NOT_A_NUMBER : ((";
      statement.expr &:= dividend;
      statement.expr &:= "<0.0)==fltIsNegativeZero(";
      statement.expr &:= divisor;
      statement.expr &:= ") ? POSITIVE_INFINITY : NEGATIVE_INFINITY)) : ";
      statement.expr &:= dividend;
      statement.expr &:= " / ";
      statement.expr &:= divisor;
      statement.expr &:= ");\n";
      doLocalDeclsOfStatement(statement, c_expr);
    else
      process_expr(params[1], statement);
      statement.expr &:= "/=";
      process_expr(params[3], statement);
      statement.expr &:= ";\n";
      doLocalDeclsOfStatement(statement, c_expr);
    end if;
  end func;


const proc: process_const_flt_eq (in float: number, in reference: param3,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var float: number2 is 0.0;
  begin
    if isNaN(number) then
      incr(countOptimizations);
      c_expr.expr &:= "0/*NaN == anything*/";
    elsif getConstant(param3, FLOATOBJECT, evaluatedParam) then
      incr(countOptimizations);
      number2 := getValue(evaluatedParam, float);
      c_expr.expr &:= str(ord(number = number2));
      c_expr.expr &:= "/*";
      c_expr.expr &:= str(number);
      c_expr.expr &:= " == ";
      c_expr.expr &:= str(number2);
      c_expr.expr &:= "*/";
    elsif ccConf.NAN_COMPARISON_WRONG then
      c_expr.expr &:= "fltEq(";
      c_expr.expr &:= floatLiteral(number);
      c_expr.expr &:= ", ";
      process_expr(param3, c_expr);
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= floatLiteral(number);
      c_expr.expr &:= " == (";
      process_expr(param3, c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;

const proc: process_flt_eq (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[1], FLOATOBJECT, evaluatedParam) then
      process_const_flt_eq(getValue(evaluatedParam, float), params[3], c_expr);
    elsif getConstant(params[3], FLOATOBJECT, evaluatedParam) then
      process_const_flt_eq(getValue(evaluatedParam, float), params[1], c_expr);
    elsif ccConf.NAN_COMPARISON_WRONG then
      c_expr.expr &:= "fltEq(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ", ";
      process_expr(params[3], c_expr);
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= "(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ") == (";
      process_expr(params[3], c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_flt_exp (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "exp(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_floor (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "floor(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_const_flt_ge (in float: number, in reference: param3,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var float: number2 is 0.0;
  begin
    if isNaN(number) then
      incr(countOptimizations);
      c_expr.expr &:= "0/*NaN >= anything*/";
    elsif getConstant(param3, FLOATOBJECT, evaluatedParam) then
      incr(countOptimizations);
      number2 := getValue(evaluatedParam, float);
      c_expr.expr &:= str(ord(number >= number2));
      c_expr.expr &:= "/*";
      c_expr.expr &:= str(number);
      c_expr.expr &:= " >= ";
      c_expr.expr &:= str(number2);
      c_expr.expr &:= "*/";
    elsif ccConf.NAN_COMPARISON_WRONG then
      c_expr.expr &:= "fltGe(";
      c_expr.expr &:= floatLiteral(number);
      c_expr.expr &:= ", ";
      process_expr(param3, c_expr);
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= floatLiteral(number);
      c_expr.expr &:= " >= (";
      process_expr(param3, c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;

const proc: process_const_flt_ge (in reference: param1, in float: number,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var float: number1 is 0.0;
  begin
    if isNaN(number) then
      incr(countOptimizations);
      c_expr.expr &:= "0/*anything >= NaN*/";
    elsif getConstant(param1, FLOATOBJECT, evaluatedParam) then
      incr(countOptimizations);
      number1 := getValue(evaluatedParam, float);
      c_expr.expr &:= str(ord(number1 >= number));
      c_expr.expr &:= "/*";
      c_expr.expr &:= str(number1);
      c_expr.expr &:= " >= ";
      c_expr.expr &:= str(number);
      c_expr.expr &:= "*/";
    elsif ccConf.NAN_COMPARISON_WRONG then
      c_expr.expr &:= "fltGe(";
      process_expr(param1, c_expr);
      c_expr.expr &:= ", ";
      c_expr.expr &:= floatLiteral(number);
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= "(";
      process_expr(param1, c_expr);
      c_expr.expr &:= ") >= ";
      c_expr.expr &:= floatLiteral(number);
    end if;
  end func;

const proc: process_flt_ge (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[1], FLOATOBJECT, evaluatedParam) then
      process_const_flt_ge(getValue(evaluatedParam, float), params[3], c_expr);
    elsif getConstant(params[3], FLOATOBJECT, evaluatedParam) then
      process_const_flt_ge(params[1], getValue(evaluatedParam, float), c_expr);
    elsif ccConf.NAN_COMPARISON_WRONG then
      c_expr.expr &:= "fltGe(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ", ";
      process_expr(params[3], c_expr);
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= "(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ") >= (";
      process_expr(params[3], c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_flt_grow (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    process_expr(params[1], statement);
    statement.expr &:= "+=";
    process_expr(params[3], statement);
    statement.expr &:= ";\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_flt_gt (in ref_list: params, inout expr_type: c_expr) is func

  begin
    if ccConf.NAN_COMPARISON_WRONG then
      c_expr.expr &:= "fltGt(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ", ";
      process_expr(params[3], c_expr);
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= "(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ") > (";
      process_expr(params[3], c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_flt_hashcode (in ref_list: params, inout expr_type: c_expr) is func

  local
    var string: temp_name is "";
  begin
    incr(c_expr.temp_num);
    temp_name := "tmp_" & str(c_expr.temp_num);
    c_expr.temp_decls &:= "rtlValueunion ";
    c_expr.temp_decls &:= temp_name;
    c_expr.temp_decls &:= ";\n";
    c_expr.expr &:= "(";
    c_expr.expr &:= temp_name;
    c_expr.expr &:= ".floatvalue=";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ",";
    c_expr.expr &:= temp_name;
    c_expr.expr &:= ".intvalue)";
  end func;


const proc: process_flt_icast (in ref_list: params, inout expr_type: c_expr) is func

  local
    var string: temp_name is "";
  begin
    incr(c_expr.temp_num);
    temp_name := "tmp_" & str(c_expr.temp_num);
    c_expr.temp_decls &:= "rtlValueunion ";
    c_expr.temp_decls &:= temp_name;
    c_expr.temp_decls &:= ";\n";
    c_expr.expr &:= "(";
    c_expr.expr &:= temp_name;
    c_expr.expr &:= ".intvalue=";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ",";
    c_expr.expr &:= temp_name;
    c_expr.expr &:= ".floatvalue)";
  end func;


const proc: process_flt_iconv (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(floattype)(";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_iflt (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(floattype)(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_ipow (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "fltIPow(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_isnan (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "isnan(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_isnegativezero (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "fltIsNegativeZero(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_const_flt_le (in float: number, in reference: param3,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var float: number2 is 0.0;
  begin
    if isNaN(number) then
      incr(countOptimizations);
      c_expr.expr &:= "0/*NaN <= anything*/";
    elsif getConstant(param3, FLOATOBJECT, evaluatedParam) then
      incr(countOptimizations);
      number2 := getValue(evaluatedParam, float);
      c_expr.expr &:= str(ord(number <= number2));
      c_expr.expr &:= "/*";
      c_expr.expr &:= str(number);
      c_expr.expr &:= " <= ";
      c_expr.expr &:= str(number2);
      c_expr.expr &:= "*/";
    elsif ccConf.NAN_COMPARISON_WRONG then
      c_expr.expr &:= "fltLe(";
      c_expr.expr &:= floatLiteral(number);
      c_expr.expr &:= ", ";
      process_expr(param3, c_expr);
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= floatLiteral(number);
      c_expr.expr &:= " <= (";
      process_expr(param3, c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_const_flt_le (in reference: param1, in float: number,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var float: number1 is 0.0;
  begin
    if isNaN(number) then
      incr(countOptimizations);
      c_expr.expr &:= "0/*anything <= NaN*/";
    elsif getConstant(param1, FLOATOBJECT, evaluatedParam) then
      incr(countOptimizations);
      number1 := getValue(evaluatedParam, float);
      c_expr.expr &:= str(ord(number1 <= number));
      c_expr.expr &:= "/*";
      c_expr.expr &:= str(number1);
      c_expr.expr &:= " <= ";
      c_expr.expr &:= str(number);
      c_expr.expr &:= "*/";
    elsif ccConf.NAN_COMPARISON_WRONG then
      c_expr.expr &:= "fltLe(";
      process_expr(param1, c_expr);
      c_expr.expr &:= ", ";
      c_expr.expr &:= floatLiteral(number);
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= "(";
      process_expr(param1, c_expr);
      c_expr.expr &:= ") <= ";
      c_expr.expr &:= floatLiteral(number);
    end if;
  end func;


const proc: process_flt_le (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[1], FLOATOBJECT, evaluatedParam) then
      process_const_flt_le(getValue(evaluatedParam, float), params[3], c_expr);
    elsif getConstant(params[3], FLOATOBJECT, evaluatedParam) then
      process_const_flt_le(params[1], getValue(evaluatedParam, float), c_expr);
    elsif ccConf.NAN_COMPARISON_WRONG then
      c_expr.expr &:= "fltLe(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ", ";
      process_expr(params[3], c_expr);
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= "(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ") <= (";
      process_expr(params[3], c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_flt_log (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "log(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_log10 (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "log10(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_lt (in ref_list: params, inout expr_type: c_expr) is func

  begin
    if ccConf.NAN_COMPARISON_WRONG then
      c_expr.expr &:= "fltLt(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ", ";
      process_expr(params[3], c_expr);
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= "(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ") < (";
      process_expr(params[3], c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_flt_mult (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") * (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_mult_assign (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    process_expr(params[1], statement);
    statement.expr &:= "*=";
    process_expr(params[3], statement);
    statement.expr &:= ";\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_const_flt_ne (in float: number, in reference: param3,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var float: number2 is 0.0;
  begin
    if isNaN(number) then
      c_expr.expr &:= "1/*NaN != anything*/";
    elsif getConstant(param3, FLOATOBJECT, evaluatedParam) then
      incr(countOptimizations);
      number2 := getValue(evaluatedParam, float);
      c_expr.expr &:= str(ord(number <> number2));
      c_expr.expr &:= "/*";
      c_expr.expr &:= str(number);
      c_expr.expr &:= " != ";
      c_expr.expr &:= str(number2);
      c_expr.expr &:= "*/";
    elsif ccConf.NAN_COMPARISON_WRONG then
      c_expr.expr &:= "!fltEq(";
      c_expr.expr &:= floatLiteral(number);
      c_expr.expr &:= ", ";
      process_expr(param3, c_expr);
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= floatLiteral(number);
      c_expr.expr &:= " != (";
      process_expr(param3, c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;

const proc: process_flt_ne (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[1], FLOATOBJECT, evaluatedParam) then
      process_const_flt_ne(getValue(evaluatedParam, float), params[3], c_expr);
    elsif getConstant(params[3], FLOATOBJECT, evaluatedParam) then
      process_const_flt_ne(getValue(evaluatedParam, float), params[1], c_expr);
    elsif ccConf.NAN_COMPARISON_WRONG then
      c_expr.expr &:= "!fltEq(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ", ";
      process_expr(params[3], c_expr);
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= "(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ") != (";
      process_expr(params[3], c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_flt_negate (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[2], FLOATOBJECT, evaluatedParam) then
      incr(countOptimizations);
      c_expr.expr &:= floatLiteral(-getValue(evaluatedParam, float));
    else
      c_expr.expr &:= "-(";
      process_expr(params[2], c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_flt_parse (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "fltParse(";
    getAnyParamToExpr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_plus (in ref_list: params, inout expr_type: c_expr) is func

  begin
    process_expr(params[2], c_expr);
  end func;


const proc: process_flt_pow (in ref_list: params, inout expr_type: c_expr) is func

  begin
    if ccConf.POWER_OF_ZERO_WRONG then
      c_expr.expr &:= "fltPow(";
    else
      c_expr.expr &:= "pow(";
    end if;
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_rand (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "fltRand(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_round (in ref_list: params, inout expr_type: c_expr) is func

  local
    var string: temp_name is "";
  begin
    c_expr.expr &:= "(";
    temp_name := getParameterAsVariable("floattype", "tmp_a_", params[1], c_expr);
    (* Formula used: (a<0.0?-((inttype)(0.5-a)):(inttype)(0.5+a)) *)
    c_expr.expr &:= temp_name;
    c_expr.expr &:= "<0.0?-((inttype)(0.5-";
    c_expr.expr &:= temp_name;
    c_expr.expr &:= ")):(inttype)(0.5+";
    c_expr.expr &:= temp_name;
    c_expr.expr &:= "))";
  end func;


const proc: process_flt_sbtr (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") - (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_sci (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "fltSci(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_flt_shrink (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    process_expr(params[1], statement);
    statement.expr &:= "-=";
    process_expr(params[3], statement);
    statement.expr &:= ";\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_flt_sin (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "sin(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_sinh (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "sinh(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_sqrt (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "sqrt(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_str (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "fltStr(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_flt_tan (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "tan(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_tanh (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "tanh(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_trunc (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(inttype)(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_flt_value (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "fltValue(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_gkb_busy_getc (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(gkbKeyPressed() ? gkbGetc() : ";
    c_expr.expr &:= charLiteral(KEY_NONE);
    c_expr.expr &:= ")";
  end func;


const proc: process_gkb_getc (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "gkbGetc()";
  end func;


const proc: process_gkb_gets (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "gkbGets(";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_gkb_keypressed (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "gkbKeyPressed()";
  end func;


const proc: process_gkb_line_read (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "gkbLineRead(&(";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= "))";
  end func;


const proc: process_gkb_raw_getc (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "gkbRawGetc()";
  end func;


const proc: process_gkb_window (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_win_result(c_expr);
    c_expr.result_expr := "gkbWindow()";
  end func;


const proc: process_gkb_word_read (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "gkbWordRead(&(";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= "))";
  end func;


const proc: process_gkb_button_pressed (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "gkbButtonPressed(";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_gkb_button_xpos (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "gkbButtonXpos()";
  end func;


const proc: process_gkb_button_ypos (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "gkbButtonYpos()";
  end func;


const proc: process_hsh_contains (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "hshContains(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getGenericValue(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", (comparetype)(";
    process_expr(params[4], c_expr);
    c_expr.expr &:= "))";
  end func;


const proc: process_hsh_cpy (in ref_list: params, inout expr_type: c_expr) is func

  local
    var type: param_type is void;
    var expr_type: c_param1 is expr_type.value;
    var expr_type: c_param2 is expr_type.value;
    var expr_type: c_param3_6 is expr_type.value;
  begin
    declare_func_pointer_if_necessary(params[3], global_c_expr);
    declare_func_pointer_if_necessary(params[4], global_c_expr);
    declare_func_pointer_if_necessary(params[5], global_c_expr);
    declare_func_pointer_if_necessary(params[6], global_c_expr);
    param_type := getExprResultType(params[2]);
    process_expr(params[1], c_param1);
    c_param2.temp_num := c_param1.temp_num;
    process_expr(params[2], c_param2);
    if has_temp_values(c_param2) then
      c_expr.expr &:= "{\n";
      AppendWithDiagnostic(c_param1.temp_decls, c_expr);
      AppendWithDiagnostic(c_param2.temp_decls, c_expr);
      AppendWithDiagnostic(c_param1.temp_assigns, c_expr);
      AppendWithDiagnostic(c_param2.temp_assigns, c_expr);
    end if;
    if c_param2.result_expr <> "" then
      setDiagnosticLine(c_expr);
      c_expr.expr &:= c_param1.expr;
      c_expr.expr &:= "=";
      c_expr.expr &:= c_param2.result_expr;
      c_expr.expr &:= ";\n";
    else
      c_param3_6.expr &:= ", (createfunctype)(";
      process_expr(params[3], c_param3_6);
      c_param3_6.expr &:= "), (destrfunctype)(";
      process_expr(params[4], c_param3_6);
      c_param3_6.expr &:= "), (createfunctype)(";
      process_expr(params[5], c_param3_6);
      c_param3_6.expr &:= "), (destrfunctype)(";
      process_expr(params[6], c_param3_6);
      c_param3_6.expr &:= ")";
      if param_type not in parametersOfHshCpy then
        parametersOfHshCpy @:= [param_type] c_param3_6.expr;
      end if;
      setDiagnosticLine(c_expr);
      c_expr.expr &:= "hshCpy(&(";
      c_expr.expr &:= c_param1.expr;
      c_expr.expr &:= "), ";
      c_expr.expr &:= c_param2.expr;
      c_expr.expr &:= c_param3_6.expr;
      c_expr.expr &:= ");\n";
    end if;
    if has_temp_values(c_param2) then
      AppendWithDiagnostic(c_param1.temp_frees, c_expr);
      AppendWithDiagnostic(c_param2.temp_frees, c_expr);
      c_expr.expr &:= "}\n";
    end if;
  end func;


const proc: process_hsh_create (in ref_list: params, inout expr_type: c_expr) is func

  local
    var type: param_type is void;
    var expr_type: c_param1 is expr_type.value;
    var expr_type: c_param2 is expr_type.value;
    var expr_type: c_param3_6 is expr_type.value;
  begin
    param_type := getExprResultType(params[2]);
(*
    process_expr(params[1], c_param1);
    c_param2.temp_num := c_param1.temp_num;
    process_expr(params[2], c_param2);
    if c_param2.temp_num <> 0 then
      c_expr.expr &:= "{\n";
      AppendWithDiagnostic(c_param1.temp_decls, c_expr);
      AppendWithDiagnostic(c_param2.temp_decls, c_expr);
      AppendWithDiagnostic(c_param1.temp_assigns, c_expr);
      AppendWithDiagnostic(c_param2.temp_assigns, c_expr);
    end if;
*)
    c_param3_6.expr &:= ", (createfunctype)(";
    process_expr(params[3], c_param3_6);
    c_param3_6.expr &:= "), (destrfunctype)(";
    process_expr(params[4], c_param3_6);
    c_param3_6.expr &:= "), (createfunctype)(";
    process_expr(params[5], c_param3_6);
    c_param3_6.expr &:= "), (destrfunctype)(";
    process_expr(params[6], c_param3_6);
    c_param3_6.expr &:= ")";
    if param_type not in parametersOfHshCreate then
      parametersOfHshCreate @:= [param_type] c_param3_6.expr;
    end if;
(*
    setDiagnosticLine(c_expr);
    c_expr.expr &:= c_param1.expr;
    c_expr.expr &:= "=hshCreate(";
    c_expr.expr &:= c_param2.expr;
    c_expr.expr &:= c_param3_6.expr;
    c_expr.expr &:= ");\n";
    if c_param2.temp_num <> 0 then
      AppendWithDiagnostic(c_param1.temp_frees, c_expr);
      AppendWithDiagnostic(c_param2.temp_frees, c_expr);
      c_expr.expr &:= "}\n";
    end if;
*)
    c_expr.expr &:= "/* hshCreate implemented with create_";
    c_expr.expr &:= str(typeNumber(param_type));
    c_expr.expr &:= " */\n";
  end func;


const proc: process_hsh_destr (in ref_list: params, inout expr_type: c_expr) is func

  local
    var type: param_type is void;
    var expr_type: c_param2_3 is expr_type.value;
  begin
    param_type := getExprResultType(params[1]);
    c_param2_3.expr &:= ", (destrfunctype)(";
    process_expr(params[2], c_param2_3);
    c_param2_3.expr &:= "), (destrfunctype)(";
    process_expr(params[3], c_param2_3);
    c_param2_3.expr &:= ")";
    if param_type not in parametersOfHshDestr then
      parametersOfHshDestr @:= [param_type] c_param2_3.expr;
    end if;
(*
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "hshDestr(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= c_param2_3.expr;
    c_expr.expr &:= ");\n";
*)
    c_expr.expr &:= "/* hshDestr implemented with destr_";
    c_expr.expr &:= str(typeNumber(param_type));
    c_expr.expr &:= " */\n";
  end func;


const proc: process_hsh_excl (in ref_list: params, inout expr_type: c_expr) is func

  begin
    declare_func_pointer_if_necessary(params[4], global_c_expr);
    declare_func_pointer_if_necessary(params[5], global_c_expr);
    declare_func_pointer_if_necessary(params[6], global_c_expr);
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "hshExcl(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getGenericValue(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", (comparetype)(";
    process_expr(params[4], c_expr);
    c_expr.expr &:= "), (destrfunctype)(";
    process_expr(params[5], c_expr);
    c_expr.expr &:= "), (destrfunctype)(";
    process_expr(params[6], c_expr);
    c_expr.expr &:= "));\n";
  end func;


const proc: process_hsh_for_generic (in reference: forDataVariable,
    in reference: forKeyVariable, in reference: hashTable,
    in reference: statement, in reference: dataCopyFunc,
    in reference: keyCopyFunc, inout expr_type: c_expr) is func

  local
    var string: hash_temp_name is "";
    var string: counter_temp_name is "";
    var string: table_elem_temp_name is "";
    var string: helem_temp_name is "";
    var string: stack_temp_name is "";
  begin
    incr(c_expr.temp_num);
    hash_temp_name := "hash_" & str(c_expr.temp_num);
    incr(c_expr.temp_num);
    counter_temp_name := "counter_" & str(c_expr.temp_num);
    incr(c_expr.temp_num);
    table_elem_temp_name := "table_elem_" & str(c_expr.temp_num);
    incr(c_expr.temp_num);
    helem_temp_name := "helem_" & str(c_expr.temp_num);
    incr(c_expr.temp_num);
    stack_temp_name := "stack_" & str(c_expr.temp_num);
    c_expr.expr &:= "/* hsh_for */ {\n";
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "const_hashtype ";
    c_expr.expr &:= hash_temp_name;
    c_expr.expr &:= "=";
    process_expr(hashTable, c_expr);
    c_expr.expr &:= ";\n";
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "memsizetype ";
    c_expr.expr &:= counter_temp_name;
    c_expr.expr &:= "=";
    c_expr.expr &:= hash_temp_name;
    c_expr.expr &:= "->table_size;\n";
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "helemtype_const *";
    c_expr.expr &:= table_elem_temp_name;
    c_expr.expr &:= "=&";
    c_expr.expr &:= hash_temp_name;
    c_expr.expr &:= "->table[0];\n";
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "const_helemtype ";
    c_expr.expr &:= helem_temp_name;
    c_expr.expr &:= ";\n";
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "helemlisttype ";
    c_expr.expr &:= stack_temp_name;
    c_expr.expr &:= "=NULL;\n";

    setDiagnosticLine(c_expr);
    c_expr.expr &:= "while (";
    c_expr.expr &:= counter_temp_name;
    c_expr.expr &:= " > 0) {\n";

    setDiagnosticLine(c_expr);
    c_expr.expr &:= helem_temp_name;
    c_expr.expr &:= "=*";
    c_expr.expr &:= table_elem_temp_name;
    c_expr.expr &:= ";\n";

    setDiagnosticLine(c_expr);
    c_expr.expr &:= "while (";
    c_expr.expr &:= helem_temp_name;
    c_expr.expr &:= " != NULL) {\n";

    setDiagnosticLine(c_expr);
    c_expr.expr &:= "if (";
    c_expr.expr &:= helem_temp_name;
    c_expr.expr &:= "->next_greater != NULL) {\n";
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "push_stack(";
    c_expr.expr &:= stack_temp_name;
    c_expr.expr &:= ", ";
    c_expr.expr &:= helem_temp_name;
    c_expr.expr &:= "->next_greater);\n";
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "} /* if */\n";

    if forDataVariable <> NIL then
      process_cpy_declaration(getType(forDataVariable), global_c_expr);
      setDiagnosticLine(c_expr);
      process_cpy_call(getType(forDataVariable),
          normalVariable(forDataVariable, c_expr),
          helem_temp_name & "->data.value." & raw_type_value(getType(forDataVariable)),
          c_expr.expr);
      c_expr.expr &:= ";\n";
    end if;

    if forKeyVariable <> NIL then
      process_cpy_declaration(getType(forKeyVariable), global_c_expr);
      setDiagnosticLine(c_expr);
      process_cpy_call(getType(forKeyVariable),
          normalVariable(forKeyVariable, c_expr),
          helem_temp_name & "->key.value." & raw_type_value(getType(forKeyVariable)),
          c_expr.expr);
      c_expr.expr &:= ";\n";
    end if;

    process_expr(statement, c_expr);

    setDiagnosticLine(c_expr);
    c_expr.expr &:= "if (";
    c_expr.expr &:= helem_temp_name;
    c_expr.expr &:= "->next_less != NULL) {\n";
    setDiagnosticLine(c_expr);
    c_expr.expr &:= helem_temp_name;
    c_expr.expr &:= "=";
    c_expr.expr &:= helem_temp_name;
    c_expr.expr &:= "->next_less;\n";
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "} else {\n";
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "pop_stack(";
    c_expr.expr &:= stack_temp_name;
    c_expr.expr &:= ", ";
    c_expr.expr &:= helem_temp_name;
    c_expr.expr &:= ");\n";
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "} /* if */\n";

    setDiagnosticLine(c_expr);
    c_expr.expr &:= "} /* while */\n";

    setDiagnosticLine(c_expr);
    c_expr.expr &:= counter_temp_name;
    c_expr.expr &:= "--;\n";
    setDiagnosticLine(c_expr);
    c_expr.expr &:= table_elem_temp_name;
    c_expr.expr &:= "++;\n";
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "} /* while */\n";
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "} /* hsh_for */\n";
  end func;


const proc: process_hsh_for (in ref_list: params, inout expr_type: c_expr) is func

  begin
    declare_func_pointer_if_necessary(params[4], global_c_expr);
    process_hsh_for_generic(params[1], NIL, params[2], params[3], params[4], NIL, c_expr);
  end func;


const proc: process_hsh_for_data_key (in ref_list: params, inout expr_type: c_expr) is func

  begin
    declare_func_pointer_if_necessary(params[5], global_c_expr);
    declare_func_pointer_if_necessary(params[6], global_c_expr);
    process_hsh_for_generic(params[1], params[2], params[3], params[4], params[5], params[6], c_expr);
  end func;


const proc: process_hsh_for_key (in ref_list: params, inout expr_type: c_expr) is func

  begin
    declare_func_pointer_if_necessary(params[4], global_c_expr);
    process_hsh_for_generic(NIL, params[1], params[2], params[3], NIL, params[4], c_expr);
  end func;


const proc: process_hsh_idx (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  local
    var type: proc_type is void;
    var type: result_type is void;
    var string: temp_name is "";
  begin
    declare_func_pointer_if_necessary(params[4], global_c_expr);
    proc_type := getType(function);
    result_type := resultType(proc_type);
    if isVarfunc(proc_type) then
      c_expr.expr &:= "hshIdxAddr(";
    else
      temp_name := beginCastGeneric(result_type, c_expr);
      c_expr.expr &:= "hshIdx(";
    end if;
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getGenericValue(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", (comparetype)(";
    process_expr(params[4], c_expr);
    c_expr.expr &:= "))";
    if isVarfunc(proc_type) then
      c_expr.expr &:= select_value_from_rtlObjectptr(result_type);
    else
      endCastGeneric(result_type, temp_name, c_expr);
    end if;
  end func;


const proc: process_hsh_idx2 (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  local
    var type: proc_type is void;
    var type: result_type is void;
    var string: addr_temp_name is "";
  begin
    declare_func_pointer_if_necessary(params[5], global_c_expr);
    declare_func_pointer_if_necessary(params[6], global_c_expr);
    proc_type := getType(function);
    result_type := resultType(proc_type);
    incr(c_expr.temp_num);
    addr_temp_name := "addr_" & str(c_expr.temp_num);
    c_expr.temp_decls &:= "rtlObjecttype *";
    c_expr.temp_decls &:= addr_temp_name;
    c_expr.temp_decls &:= ";\n";
    c_expr.expr &:= "(";
    c_expr.expr &:= addr_temp_name;
    c_expr.expr &:= "=hshIdxAddr2(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getGenericValue(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", (comparetype)(";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ")),";
    c_expr.expr &:= addr_temp_name;
    c_expr.expr &:= "!=NULL?";
    c_expr.expr &:= addr_temp_name;
    c_expr.expr &:= select_value_from_rtlObjectptr(result_type);
    c_expr.expr &:= ":(";
    process_expr(params[4], c_expr);
    c_expr.expr &:= "))";
  end func;


const proc: process_hsh_incl (in ref_list: params, inout expr_type: c_expr) is func

  begin
    declare_func_pointer_if_necessary(params[5], global_c_expr);
    declare_func_pointer_if_necessary(params[6], global_c_expr);
    declare_func_pointer_if_necessary(params[7], global_c_expr);
    declare_func_pointer_if_necessary(params[8], global_c_expr);
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "hshIncl(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getGenericValue(params[2], c_expr);
    c_expr.expr &:= ", ";
    getGenericValue(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ", (comparetype)(";
    process_expr(params[5], c_expr);
    c_expr.expr &:= "), (createfunctype)(";
    process_expr(params[6], c_expr);
    c_expr.expr &:= "), (createfunctype)(";
    process_expr(params[7], c_expr);
    c_expr.expr &:= "), (copyfunctype)(";
    process_expr(params[8], c_expr);
    c_expr.expr &:= "));\n";
  end func;


const proc: process_hsh_keys (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  begin
    prepare_typed_result(resultType(getType(function)), c_expr);
    c_expr.result_expr := "hshKeys(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", (createfunctype)(";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= "), (destrfunctype)(";
    getStdParamToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= "))";
  end func;


const proc: process_hsh_lng (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(inttype)((";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")->size)";
  end func;


const proc: process_hsh_update (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  local
    var type: result_type is void;
    var string: temp_name is "";
  begin
    declare_func_pointer_if_necessary(params[5], global_c_expr);
    declare_func_pointer_if_necessary(params[6], global_c_expr);
    declare_func_pointer_if_necessary(params[7], global_c_expr);
    result_type := resultType(getType(function));
    if valueIsAtHeap(result_type) then
      prepare_typed_result(result_type, c_expr);
      temp_name := beginCastGenericToResultExpr(result_type, c_expr);
      c_expr.result_expr &:= "hshUpdate(";
      getAnyParamToResultExpr(params[1], c_expr);
      c_expr.result_expr &:= ", ";
      getGenericValueToResultExpr(params[2], c_expr);
      c_expr.result_expr &:= ", (generictype)(";
      getGenericTemporaryToResultExpr(params[3], c_expr);
      c_expr.result_expr &:= "), ";
      getAnyParamToResultExpr(params[4], c_expr);
      c_expr.result_expr &:= ", (comparetype)(";
      getAnyParamToResultExpr(params[5], c_expr);
      c_expr.result_expr &:= "), (createfunctype)(";
      getAnyParamToResultExpr(params[6], c_expr);
      c_expr.result_expr &:= "), (createfunctype)(";
      getAnyParamToResultExpr(params[7], c_expr);
      c_expr.result_expr &:= "))";
      endCastGenericToResultExpr(result_type, temp_name, c_expr);
    else
      temp_name := beginCastGeneric(result_type, c_expr);
      c_expr.expr &:= "hshUpdate(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ", ";
      getGenericValue(params[2], c_expr);
      c_expr.expr &:= ", ";
      getGenericValue(params[3], c_expr);
      c_expr.expr &:= ", ";
      process_expr(params[4], c_expr);
      c_expr.expr &:= ", (comparetype)(";
      process_expr(params[5], c_expr);
      c_expr.expr &:= "), (createfunctype)(";
      process_expr(params[6], c_expr);
      c_expr.expr &:= "), (createfunctype)(";
      process_expr(params[7], c_expr);
      c_expr.expr &:= "))";
      endCastGeneric(result_type, temp_name, c_expr);
    end if;
  end func;


const proc: process_hsh_values (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "hshValues(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", (createfunctype)(";
    process_expr(params[2], c_expr);
    c_expr.expr &:= "), (destrfunctype)(";
    process_expr(params[3], c_expr);
    c_expr.expr &:= "))";
  end func;


const proc: process_int_abs (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "labs(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_int_add (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") + (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_int_and (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") & (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_int_and_assign (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    process_expr(params[1], statement);
    statement.expr &:= "&=";
    process_expr(params[3], statement);
    statement.expr &:= ";\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_int_binom (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "intBinom(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_int_bit_length (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "intBitLength(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_int_cmp (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "intCmp(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_int_conv (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_int_cpy (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    process_expr(params[1], statement);
    statement.expr &:= "=";
    process_expr(params[3], statement);
    statement.expr &:= ";\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_int_decr (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "--(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_const_int_div (in reference: param1, in integer: divisor,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if divisor = 0 then
      incr(countOptimizations);
      c_expr.expr &:= raiseError("NUMERIC_ERROR");
    elsif getConstant(param1, INTOBJECT, evaluatedParam) then
      incr(countOptimizations);
      c_expr.expr &:= str(getValue(evaluatedParam, integer) div divisor);
    elsif divisor = 1 then
      incr(countOptimizations);
      c_expr.expr &:= "(";
      process_expr(param1, c_expr);
      c_expr.expr &:= ")";
    elsif divisor = -1 then
      incr(countOptimizations);
      c_expr.expr &:= "-(";
      process_expr(param1, c_expr);
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= "(";
      process_expr(param1, c_expr);
      c_expr.expr &:= ") / ";
      c_expr.expr &:= str(divisor);
    end if;
  end func;


const proc: process_const_int_div (in integer: dividend, in reference: param3,
    inout expr_type: c_expr) is func

  local
    var string: divisor_name is "";
  begin
    if dividend = 0 then
      incr(countOptimizations);
      c_expr.expr &:= "((";
      process_expr(param3, c_expr);
      c_expr.expr &:= ")==0?";
      c_expr.expr &:= raiseError("NUMERIC_ERROR");
      c_expr.expr &:= ":0)";
    elsif ccConf.CHECK_INT_DIV_BY_ZERO then
      c_expr.expr &:= "(";
      divisor_name := getParameterAsVariable("inttype", "tmp_b_", param3, c_expr);
      c_expr.expr &:= divisor_name;
      c_expr.expr &:= "==0?";
      c_expr.expr &:= raiseError("NUMERIC_ERROR");
      c_expr.expr &:= ":";
      c_expr.expr &:= str(dividend);
      c_expr.expr &:= " / ";
      c_expr.expr &:= divisor_name;
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= str(dividend);
      c_expr.expr &:= " / (";
      process_expr(param3, c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_int_div (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: divisor_name is "";
  begin
    if getConstant(params[3], INTOBJECT, evaluatedParam) then
      process_const_int_div(params[1], getValue(evaluatedParam, integer), c_expr);
    elsif getConstant(params[1], INTOBJECT, evaluatedParam) then
      process_const_int_div(getValue(evaluatedParam, integer), params[3], c_expr);
    elsif ccConf.CHECK_INT_DIV_BY_ZERO then
      c_expr.expr &:= "(";
      divisor_name := getParameterAsVariable("inttype", "tmp_b_", params[3], c_expr);
      c_expr.expr &:= divisor_name;
      c_expr.expr &:= "==0?";
      c_expr.expr &:= raiseError("NUMERIC_ERROR");
      c_expr.expr &:= ":(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ") / ";
      c_expr.expr &:= divisor_name;
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= "(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ") / (";
      process_expr(params[3], c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_int_eq (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") == (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_int_fact (in ref_list: params, inout expr_type: c_expr) is func

  local
    var string: number_name is "";
  begin
    c_expr.expr &:= "(";
    number_name := getParameterAsVariable("inttype", "tmp_", params[2], c_expr);
    c_expr.expr &:= number_name;
    c_expr.expr &:= "<0||";
    c_expr.expr &:= number_name;
    c_expr.expr &:= ">=sizeof(fact)/sizeof(inttype)?";
    c_expr.expr &:= raiseError("NUMERIC_ERROR");
    c_expr.expr &:= ":fact[";
    c_expr.expr &:= number_name;
    c_expr.expr &:= "])";
  end func;


const proc: process_int_ge (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") >= (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_int_grow (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    process_expr(params[1], statement);
    statement.expr &:= "+=";
    process_expr(params[3], statement);
    statement.expr &:= ";\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_int_gt (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") > (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_int_hashcode (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_int_incr (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "++(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_int_le (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") <= (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_int_log2 (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "intLog2(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_int_lowest_set_bit (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "intLowestSetBit(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_int_lpad0 (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "intLpad0(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ",";
    getStdParamToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_const_int_lshift (in reference: param1, in integer: shiftCount,
    inout expr_type: c_expr) is func

  begin
    if shiftCount < 0 then
      incr(countOptimizations);
      c_expr.expr &:= raiseError("NUMERIC_ERROR");
    elsif shiftCount >= ccConf.INTTYPE_SIZE then
      incr(countOptimizations);
      c_expr.expr &:= "(";
      process_expr(param1, c_expr);
      c_expr.expr &:= ")!=0?";
      c_expr.expr &:= raiseError("NUMERIC_ERROR");
      c_expr.expr &:= ":0";
    else
      c_expr.expr &:= "(";
      process_expr(param1, c_expr);
      c_expr.expr &:= ") << ";
      c_expr.expr &:= str(shiftCount);
    end if;
  end func;


const proc: process_int_lshift (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: lshift_name is "";
  begin
    if getConstant(params[3], INTOBJECT, evaluatedParam) then
      process_const_int_lshift(params[1], getValue(evaluatedParam, integer), c_expr);
    elsif integer_shift_check then
      c_expr.expr &:= "(";
      lshift_name := getParameterAsVariable("inttype", "lshift_", params[3], c_expr);
      c_expr.expr &:= lshift_name;
      c_expr.expr &:= "<0?";
      c_expr.expr &:= raiseError("NUMERIC_ERROR");
      c_expr.expr &:= ":";
      c_expr.expr &:= lshift_name;
      c_expr.expr &:= ">=";
      c_expr.expr &:= integerLiteral(ccConf.INTTYPE_SIZE);
      c_expr.expr &:= "?((";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ")!=0?";
      c_expr.expr &:= raiseError("NUMERIC_ERROR");
      c_expr.expr &:= ":0):(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ") << ";
      c_expr.expr &:= lshift_name;
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= "(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ") << (";
      process_expr(params[3], c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_int_lshift_assign (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    process_expr(params[1], statement);
    statement.expr &:= "<<=";
    process_expr(params[3], statement);
    statement.expr &:= ";\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_int_lt (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") < (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_const_int_mdiv (in reference: param1, in integer: divisor,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: dividend_name is "";
  begin
    incr(countOptimizations);
    if divisor = 0 then
      c_expr.expr &:= raiseError("NUMERIC_ERROR");
    elsif getConstant(param1, INTOBJECT, evaluatedParam) then
      c_expr.expr &:= str(getValue(evaluatedParam, integer) mdiv divisor);
    elsif divisor = 1 then
      c_expr.expr &:= "(";
      process_expr(param1, c_expr);
      c_expr.expr &:= ")";
    elsif divisor = -1 then
      c_expr.expr &:= "-(";
      process_expr(param1, c_expr);
      c_expr.expr &:= ")";
    elsif divisor > 0 and 2 ** log2(divisor) = divisor then
      if ccConf.RSHIFT_DOES_SIGN_EXTEND then
        c_expr.expr &:= "(";
        process_expr(param1, c_expr);
        c_expr.expr &:= ") >> ";
        c_expr.expr &:= str(log2(divisor));
      else
        c_expr.expr &:= "(";
        dividend_name := getParameterAsVariable("inttype", "tmp_a_", param1, c_expr);
        doRshift(dividend_name, str(log2(divisor)), c_expr);
        c_expr.expr &:= ")";
      end if;
    elsif divisor < 0 and bitLength(divisor) = lowestSetBit(divisor) then
      # The check above is (almost) equivalent to:
      #   divisor < 0 and 2 ** log2(-divisor) = -divisor
      # The check with bitLength is used to avoid negating the divisor.
      # Negating the divisor would fail for the most negative integer.
      if ccConf.RSHIFT_DOES_SIGN_EXTEND then
        c_expr.expr &:= "-(";
        process_expr(param1, c_expr);
        c_expr.expr &:= ") >> ";
        c_expr.expr &:= str(bitLength(divisor));
      else
        incr(c_expr.temp_num);
        dividend_name := "tmp_a_" & str(c_expr.temp_num);
        c_expr.temp_decls &:= "inttype ";
        c_expr.temp_decls &:= dividend_name;
        c_expr.temp_decls &:= ";\n";
        c_expr.expr &:= "(";
        c_expr.expr &:= dividend_name;
        c_expr.expr &:= "=-(";
        process_expr(param1, c_expr);
        c_expr.expr &:= "),";
        doRshift(dividend_name, str(bitLength(divisor)), c_expr);
        c_expr.expr &:= ")";
      end if;
    else
      c_expr.expr &:= "(";
      dividend_name := getParameterAsVariable("inttype", "tmp_a_", param1, c_expr);
      c_expr.expr &:= dividend_name;
      if divisor > 0 then
        (* Formula used: a<0?(a+1)/b-1:a/b *)
        c_expr.expr &:= "<0?(";
        c_expr.expr &:= dividend_name;
        c_expr.expr &:= "+1)/";
      else # divisor < 0
        (* Formula used: a>0?(a-1)/b-1:a/b *)
        c_expr.expr &:= ">0?(";
        c_expr.expr &:= dividend_name;
        c_expr.expr &:= "-1)/";
      end if;
      c_expr.expr &:= str(divisor);
      c_expr.expr &:= "-1:";
      c_expr.expr &:= dividend_name;
      c_expr.expr &:= "/";
      c_expr.expr &:= str(divisor);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_const_int_mdiv (in integer: dividend, in reference: param3,
    inout expr_type: c_expr) is func

  local
    var string: divisor_name is "";
  begin
    incr(countOptimizations);
    if dividend = 0 then
      c_expr.expr &:= "((";
      process_expr(param3, c_expr);
      c_expr.expr &:= ")==0?";
      c_expr.expr &:= raiseError("NUMERIC_ERROR");
      c_expr.expr &:= ":0)";
    else
      c_expr.expr &:= "(";
      divisor_name := getParameterAsVariable("inttype", "tmp_b_", param3, c_expr);
      c_expr.expr &:= divisor_name;
      if dividend > 0 then
        (* Formula used: b<0?(a-1)/b-1:a/b *)
        c_expr.expr &:= "<0?";
        c_expr.expr &:= str(pred(dividend));
      else # dividend < 0
        (* Formula used: b>0?(a+1)/b-1:a/b *)
        c_expr.expr &:= ">0?";
        c_expr.expr &:= str(succ(dividend));
      end if;
      c_expr.expr &:= "/";
      c_expr.expr &:= divisor_name;
      c_expr.expr &:= "-1:";
      if ccConf.CHECK_INT_DIV_BY_ZERO then
        c_expr.expr &:= divisor_name;
        c_expr.expr &:= "==0?";
        c_expr.expr &:= raiseError("NUMERIC_ERROR");
        c_expr.expr &:= ":";
      end if;
      c_expr.expr &:= str(dividend);
      c_expr.expr &:= "/";
      c_expr.expr &:= divisor_name;
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_int_mdiv (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: dividend_name is "";
    var string: divisor_name is "";
  begin
    if getConstant(params[3], INTOBJECT, evaluatedParam) then
      process_const_int_mdiv(params[1], getValue(evaluatedParam, integer), c_expr);
    elsif getConstant(params[1], INTOBJECT, evaluatedParam) then
      process_const_int_mdiv(getValue(evaluatedParam, integer), params[3], c_expr);
    else
      c_expr.expr &:= "(";
      dividend_name := getParameterAsVariable("inttype", "tmp_a_", params[1], c_expr);
      divisor_name := getParameterAsVariable("inttype", "tmp_b_", params[3], c_expr);
      (* Formula used: a>0&&b<0?(a-1)/b-1:a<0&&b>0?(a+1)/b-1:a/b *)
      c_expr.expr &:= dividend_name;
      c_expr.expr &:= ">0&&";
      c_expr.expr &:= divisor_name;
      c_expr.expr &:= "<0?(";
      c_expr.expr &:= dividend_name;
      c_expr.expr &:= "-1)/";
      c_expr.expr &:= divisor_name;
      c_expr.expr &:= "-1:";
      c_expr.expr &:= dividend_name;
      c_expr.expr &:= "<0&&";
      c_expr.expr &:= divisor_name;
      c_expr.expr &:= ">0?(";
      c_expr.expr &:= dividend_name;
      c_expr.expr &:= "+1)/";
      c_expr.expr &:= divisor_name;
      c_expr.expr &:= "-1:";
      if ccConf.CHECK_INT_DIV_BY_ZERO then
        c_expr.expr &:= divisor_name;
        c_expr.expr &:= "==0?";
        c_expr.expr &:= raiseError("NUMERIC_ERROR");
        c_expr.expr &:= ":";
      end if;
      c_expr.expr &:= dividend_name;
      c_expr.expr &:= "/";
      c_expr.expr &:= divisor_name;
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_const_int_mod (in reference: param1, in integer: divisor,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: dividend_name is "";
    var string: quotient_name is "";
  begin
    incr(countOptimizations);
    if divisor = 0 then
      c_expr.expr &:= raiseError("NUMERIC_ERROR");
    elsif getConstant(param1, INTOBJECT, evaluatedParam) then
      c_expr.expr &:= str(getValue(evaluatedParam, integer) mod divisor);
    elsif divisor = 1 or divisor = -1 then
      c_expr.expr &:= "0";
    elsif divisor > 0 and 2 ** log2(divisor) = divisor then
      c_expr.expr &:= "(";
      process_expr(param1, c_expr);
      c_expr.expr &:= ")&";
      c_expr.expr &:= str(pred(divisor));
    elsif divisor < 0 and bitLength(divisor) = lowestSetBit(divisor) then
      # The check above is (almost) equivalent to:
      #   divisor < 0 and 2 ** log2(-divisor) = -divisor
      # The check with bitLength is used to avoid negating the divisor.
      # Negating the divisor would fail for the most negative integer.
      c_expr.expr &:= "-(-(";
      process_expr(param1, c_expr);
      c_expr.expr &:= ")&";
      c_expr.expr &:= str(-succ(divisor));
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= "(";
      dividend_name := getParameterAsVariable("inttype", "tmp_a_", param1, c_expr);
      incr(c_expr.temp_num);
      quotient_name := "tmp_c_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "inttype ";
      c_expr.temp_decls &:= quotient_name;
      c_expr.temp_decls &:= ";\n";
      (* Formula used: c=a%b,a<0^b<0&&c!=0?c+b:c *)
      c_expr.expr &:= quotient_name;
      c_expr.expr &:= "=";
      c_expr.expr &:= dividend_name;
      c_expr.expr &:= "%";
      c_expr.expr &:= str(divisor);
      c_expr.expr &:= ",";
      c_expr.expr &:= dividend_name;
      if divisor > 0 then
        (* Formula used: c=a%b,a<0&&c!=0?c+b:c *)
        c_expr.expr &:= "<0";
      else # divisor < 0
        (* Formula used: c=a%b,a>0&&c!=0?c+b:c *)
        c_expr.expr &:= ">0";
      end if;
      c_expr.expr &:= "&&";
      c_expr.expr &:= quotient_name;
      c_expr.expr &:= "!=0?";
      c_expr.expr &:= quotient_name;
      c_expr.expr &:= "+";
      c_expr.expr &:= str(divisor);
      c_expr.expr &:= ":";
      c_expr.expr &:= quotient_name;
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_const_int_mod (in integer: dividend, in reference: param3,
    inout expr_type: c_expr) is func

  local
    var string: divisor_name is "";
    var string: quotient_name is "";
  begin
    incr(countOptimizations);
    if dividend = 0 then
      c_expr.expr &:= "((";
      process_expr(param3, c_expr);
      c_expr.expr &:= ")==0?";
      c_expr.expr &:= raiseError("NUMERIC_ERROR");
      c_expr.expr &:= ":0)";
    elsif dividend = 1 then
      c_expr.expr &:= "(";
      divisor_name := getParameterAsVariable("inttype", "tmp_b_", param3, c_expr);
      c_expr.expr &:= divisor_name;
      c_expr.expr &:= "<=0?(";
      c_expr.expr &:= divisor_name;
      c_expr.expr &:= "==0?";
      c_expr.expr &:= raiseError("NUMERIC_ERROR");
      c_expr.expr &:= ":";
      c_expr.expr &:= divisor_name;
      c_expr.expr &:= "+1):(";
      c_expr.expr &:= divisor_name;
      c_expr.expr &:= "==1?0:1))";
    else
      c_expr.expr &:= "(";
      divisor_name := getParameterAsVariable("inttype", "tmp_b_", param3, c_expr);
      incr(c_expr.temp_num);
      quotient_name := "tmp_c_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "inttype ";
      c_expr.temp_decls &:= quotient_name;
      c_expr.temp_decls &:= ";\n";
      if ccConf.CHECK_INT_DIV_BY_ZERO then
        c_expr.expr &:= divisor_name;
        c_expr.expr &:= "==0?";
        c_expr.expr &:= raiseError("NUMERIC_ERROR");
        c_expr.expr &:= ":(";
      end if;
      (* Formula used: c=a%b,a<0^b<0&&c!=0?c+b:c *)
      c_expr.expr &:= quotient_name;
      c_expr.expr &:= "=";
      c_expr.expr &:= str(dividend);
      c_expr.expr &:= "%";
      c_expr.expr &:= divisor_name;
      c_expr.expr &:= ",";
      c_expr.expr &:= divisor_name;
      if dividend > 0 then
        (* Formula used: c=a%b,b<0&&c!=0?c+b:c *)
        c_expr.expr &:= "<0";
      else # dividend < 0 then
        (* Formula used: c=a%b,b>0&&c!=0?c+b:c *)
        c_expr.expr &:= ">0";
      end if;
      c_expr.expr &:= "&&";
      c_expr.expr &:= quotient_name;
      c_expr.expr &:= "!=0?";
      c_expr.expr &:= quotient_name;
      c_expr.expr &:= "+";
      c_expr.expr &:= divisor_name;
      c_expr.expr &:= ":";
      c_expr.expr &:= quotient_name;
      if ccConf.CHECK_INT_DIV_BY_ZERO then
        c_expr.expr &:= ")";
      end if;
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_int_mod (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: dividend_name is "";
    var string: divisor_name is "";
    var string: quotient_name is "";
  begin
    if getConstant(params[3], INTOBJECT, evaluatedParam) then
      process_const_int_mod(params[1], getValue(evaluatedParam, integer), c_expr);
    elsif getConstant(params[1], INTOBJECT, evaluatedParam) then
      process_const_int_mod(getValue(evaluatedParam, integer), params[3], c_expr);
(*
    elsif isActionExpression(params[3], "INT_LSHIFT") and
        category(getValue(params[3], ref_list)[2]) = INTOBJECT and
        not isVar(getValue(params[3], ref_list)[2]) and
        getValue(getValue(params[3], ref_list)[2], integer) = 1 then
      incr(countOptimizations);
      c_expr.expr &:= "/* mask lower bits */ (";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ")&((1<<(";
      process_expr(getValue(params[3], ref_list)[4], c_expr);
      c_expr.expr &:= "))-1)";
*)
    else
      c_expr.expr &:= "(";
      dividend_name := getParameterAsVariable("inttype", "tmp_a_", params[1], c_expr);
      divisor_name := getParameterAsVariable("inttype", "tmp_b_", params[3], c_expr);
      incr(c_expr.temp_num);
      quotient_name := "tmp_c_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "inttype ";
      c_expr.temp_decls &:= quotient_name;
      c_expr.temp_decls &:= ";\n";
      (* Formula used: c=a%b,a<0^b<0&&c!=0?c+b:c *)
      if ccConf.CHECK_INT_DIV_BY_ZERO then
        c_expr.expr &:= divisor_name;
        c_expr.expr &:= "==0?";
        c_expr.expr &:= raiseError("NUMERIC_ERROR");
        c_expr.expr &:= ":(";
      end if;
      c_expr.expr &:= quotient_name;
      c_expr.expr &:= "=";
      c_expr.expr &:= dividend_name;
      c_expr.expr &:= "%";
      c_expr.expr &:= divisor_name;
      c_expr.expr &:= ",";
      c_expr.expr &:= dividend_name;
      c_expr.expr &:= "<0^";
      c_expr.expr &:= divisor_name;
      c_expr.expr &:= "<0&&";
      c_expr.expr &:= quotient_name;
      c_expr.expr &:= "!=0?";
      c_expr.expr &:= quotient_name;
      c_expr.expr &:= "+";
      c_expr.expr &:= divisor_name;
      c_expr.expr &:= ":";
      c_expr.expr &:= quotient_name;
      if ccConf.CHECK_INT_DIV_BY_ZERO then
        c_expr.expr &:= ")";
      end if;
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_int_mult (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") * (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_int_mult_assign (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    process_expr(params[1], statement);
    statement.expr &:= "*=";
    process_expr(params[3], statement);
    statement.expr &:= ";\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_int_ne (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") != (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_int_negate (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "-(";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_int_odd (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")&1";
  end func;


const proc: process_int_or (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") | (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_int_ord (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_int_or_assign (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    process_expr(params[1], statement);
    statement.expr &:= "|=";
    process_expr(params[3], statement);
    statement.expr &:= ";\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_int_parse (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "intParse(";
    getAnyParamToExpr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_int_plus (in ref_list: params, inout expr_type: c_expr) is func

  begin
    process_expr(params[2], c_expr);
  end func;


const proc: process_const_int_pow (in reference: param1, in integer: exponent,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: integer_name is "";
  begin
    if exponent < 0 then
      incr(countOptimizations);
      c_expr.expr &:= raiseError("NUMERIC_ERROR");
    elsif getConstant(param1, INTOBJECT, evaluatedParam) then
      incr(countOptimizations);
      c_expr.expr &:= str(getValue(evaluatedParam, integer) ** exponent);
    elsif exponent = 0 then
      incr(countOptimizations);
      c_expr.expr &:= integerLiteral(1);
    elsif exponent = 1 then
      incr(countOptimizations);
      process_expr(param1, c_expr);
    elsif exponent in {2, 3} then
      incr(countOptimizations);
      c_expr.expr &:= "(";
      integer_name := getParameterAsVariable("inttype", "tmp_", param1, c_expr);
      c_expr.expr &:= integer_name;
      c_expr.expr &:= "*";
      c_expr.expr &:= integer_name;
      if exponent = 3 then
        c_expr.expr &:= "*";
        c_expr.expr &:= integer_name;
      end if;
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= "intPow(";
      process_expr(param1, c_expr);
      c_expr.expr &:= ", ";
      c_expr.expr &:= str(exponent);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_const_int_pow (in integer: base, in reference: param3,
    inout expr_type: c_expr) is func

  local
    var string: exponent_name is "";
  begin
    if base = -1 then
      incr(countOptimizations);
      c_expr.expr &:= "(";
      exponent_name := getParameterAsVariable("inttype", "tmp_", param3, c_expr);
      c_expr.expr &:= exponent_name;
      c_expr.expr &:= "<0?";
      c_expr.expr &:= raiseError("NUMERIC_ERROR");
      c_expr.expr &:= ":1-((";
      c_expr.expr &:= exponent_name;
      c_expr.expr &:= "&1)<<1))";
    elsif base = 0 then
      incr(countOptimizations);
      c_expr.expr &:= "(";
      exponent_name := getParameterAsVariable("inttype", "tmp_", param3, c_expr);
      c_expr.expr &:= exponent_name;
      c_expr.expr &:= "<0?";
      c_expr.expr &:= raiseError("NUMERIC_ERROR");
      c_expr.expr &:= ":(";
      c_expr.expr &:= exponent_name;
      c_expr.expr &:= "==0?";
      c_expr.expr &:= integerLiteral(1);
      c_expr.expr &:= ":";
      c_expr.expr &:= integerLiteral(0);
      c_expr.expr &:= "))";
    elsif base = 1 then
      incr(countOptimizations);
      c_expr.expr &:= "((";
      process_expr(param3, c_expr);
      c_expr.expr &:= ")<0?";
      c_expr.expr &:= raiseError("NUMERIC_ERROR");
      c_expr.expr &:= ":";
      c_expr.expr &:= integerLiteral(1);
      c_expr.expr &:= ")";
    elsif base = 2 then
      incr(countOptimizations);
      c_expr.expr &:= "(";
      exponent_name := getParameterAsVariable("inttype", "tmp_", param3, c_expr);
      c_expr.expr &:= exponent_name;
      c_expr.expr &:= "<0?";
      c_expr.expr &:= raiseError("NUMERIC_ERROR");
      c_expr.expr &:= ":";
      c_expr.expr &:= integerLiteral(1);
      c_expr.expr &:= "<<";
      c_expr.expr &:= exponent_name;
      c_expr.expr &:= ")";
    elsif base > 0 and 2 ** log2(base) = base then
      incr(countOptimizations);
      c_expr.expr &:= "(";
      exponent_name := getParameterAsVariable("inttype", "tmp_", param3, c_expr);
      c_expr.expr &:= exponent_name;
      c_expr.expr &:= "<0?";
      c_expr.expr &:= raiseError("NUMERIC_ERROR");
      c_expr.expr &:= ":";
      c_expr.expr &:= integerLiteral(1);
      c_expr.expr &:= "<<";
      c_expr.expr &:= str(log2(base));
      c_expr.expr &:= "*";
      c_expr.expr &:= exponent_name;
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= "intPow(";
      c_expr.expr &:= str(base);
      c_expr.expr &:= ", ";
      process_expr(param3, c_expr);
      c_expr.expr &:= ")";
    end if
  end func;


const proc: process_int_pow (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[3], INTOBJECT, evaluatedParam) then
      process_const_int_pow(params[1], getValue(evaluatedParam, integer), c_expr);
    elsif getConstant(params[1], INTOBJECT, evaluatedParam) then
      process_const_int_pow(getValue(evaluatedParam, integer), params[3], c_expr);
    else
      c_expr.expr &:= "intPow(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ", ";
      process_expr(params[3], c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_int_pred (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")-1";
  end func;


const proc: process_const_int_radix (in reference: param1, in integer: base,
    in boolean: upperCase, inout expr_type: c_expr) is func

  begin
    if base < 2 or base > 36 then
      c_expr.expr &:= raiseError("NUMERIC_ERROR");
    elsif base = 10 then
      prepare_stri_result(c_expr);
      c_expr.result_expr := "intStr(";
      getStdParamToResultExpr(param1, c_expr);
      c_expr.result_expr &:= ")";
    elsif 2 ** log2(base) = base then
      prepare_stri_result(c_expr);
      c_expr.result_expr := "intRadixPow2(";
      getStdParamToResultExpr(param1, c_expr);
      c_expr.result_expr &:= ",";
      c_expr.result_expr &:= str(log2(base));
      c_expr.result_expr &:= ",";
      c_expr.result_expr &:= str(pred(base));
      c_expr.result_expr &:= ",";
      c_expr.result_expr &:= str(ord(upperCase));
      c_expr.result_expr &:= ")";
    else
      prepare_stri_result(c_expr);
      c_expr.result_expr := "intRadix(";
      getStdParamToResultExpr(param1, c_expr);
      c_expr.result_expr &:= ", ";
      c_expr.result_expr &:= str(base);
      c_expr.result_expr &:= ",";
      c_expr.result_expr &:= str(ord(upperCase));
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_int_radix (in ref_list: params, in boolean: upperCase,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[3], INTOBJECT, evaluatedParam) then
      process_const_int_radix(params[1], getValue(evaluatedParam, integer), upperCase, c_expr);
    else
      prepare_stri_result(c_expr);
      c_expr.result_expr := "intRadix(";
      getStdParamToResultExpr(params[1], c_expr);
      c_expr.result_expr &:= ", ";
      getStdParamToResultExpr(params[3], c_expr);
      c_expr.result_expr &:= ",";
      c_expr.result_expr &:= str(ord(upperCase));
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_int_rand (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "intRand(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_const_int_rem (in reference: param1, in integer: divisor,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if divisor = 0 then
      incr(countOptimizations);
      c_expr.expr &:= raiseError("NUMERIC_ERROR");
    elsif getConstant(param1, INTOBJECT, evaluatedParam) then
      incr(countOptimizations);
      c_expr.expr &:= str(getValue(evaluatedParam, integer) rem divisor);
    elsif divisor = 1 or divisor = -1 then
      incr(countOptimizations);
      c_expr.expr &:= "0";
    else
      c_expr.expr &:= "(";
      process_expr(param1, c_expr);
      c_expr.expr &:= ") % ";
      c_expr.expr &:= str(divisor);
    end if;
  end func;


const proc: process_const_int_rem (in integer: dividend, in reference: param3,
    inout expr_type: c_expr) is func

  local
    var string: divisor_name is "";
  begin
    if dividend = 0 then
      incr(countOptimizations);
      c_expr.expr &:= "((";
      process_expr(param3, c_expr);
      c_expr.expr &:= ")==0?";
      c_expr.expr &:= raiseError("NUMERIC_ERROR");
      c_expr.expr &:= ":0)";
    elsif ccConf.CHECK_INT_DIV_BY_ZERO then
      c_expr.expr &:= "(";
      divisor_name := getParameterAsVariable("inttype", "tmp_b_", param3, c_expr);
      c_expr.expr &:= divisor_name;
      c_expr.expr &:= "==0?";
      c_expr.expr &:= raiseError("NUMERIC_ERROR");
      c_expr.expr &:= ":";
      c_expr.expr &:= str(dividend);
      c_expr.expr &:= " % ";
      c_expr.expr &:= divisor_name;
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= str(dividend);
      c_expr.expr &:= " % (";
      process_expr(param3, c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_int_rem (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: divisor_name is "";
  begin
    if getConstant(params[3], INTOBJECT, evaluatedParam) then
      process_const_int_rem(params[1], getValue(evaluatedParam, integer), c_expr);
    elsif getConstant(params[1], INTOBJECT, evaluatedParam) then
      process_const_int_rem(getValue(evaluatedParam, integer), params[3], c_expr);
    elsif ccConf.CHECK_INT_DIV_BY_ZERO then
      c_expr.expr &:= "(";
      divisor_name := getParameterAsVariable("inttype", "tmp_b_", params[3], c_expr);
      c_expr.expr &:= divisor_name;
      c_expr.expr &:= "==0?";
      c_expr.expr &:= raiseError("NUMERIC_ERROR");
      c_expr.expr &:= ":(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ") % ";
      c_expr.expr &:= divisor_name;
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= "(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ") % (";
      process_expr(params[3], c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_const_int_rshift (in reference: param1, in integer: shiftCount,
    inout expr_type: c_expr) is func

  local
    var string: number_name is "";
  begin
    if shiftCount < 0 then
      incr(countOptimizations);
      c_expr.expr &:= raiseError("NUMERIC_ERROR");
    elsif shiftCount >= ccConf.INTTYPE_SIZE then
      incr(countOptimizations);
      c_expr.expr &:= "((";
      process_expr(param1, c_expr);
      c_expr.expr &:= ")<0?-1:0)";
    else
      if ccConf.RSHIFT_DOES_SIGN_EXTEND then
        c_expr.expr &:= "(";
        process_expr(param1, c_expr);
        c_expr.expr &:= ") >> ";
        c_expr.expr &:= str(shiftCount);
      else
        c_expr.expr &:= "(";
        number_name := getParameterAsVariable("inttype", "tmp_", param1, c_expr);
        doRshift(number_name, str(shiftCount), c_expr);
        c_expr.expr &:= ")";
      end if;
    end if;
  end func;


const proc: process_int_rshift (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: number_name is "";
    var string: rshift_name is "";
  begin
    if getConstant(params[3], INTOBJECT, evaluatedParam) then
      process_const_int_rshift(params[1], getValue(evaluatedParam, integer), c_expr);
    elsif integer_shift_check then
      if ccConf.RSHIFT_DOES_SIGN_EXTEND then
        c_expr.expr &:= "(";
        rshift_name := getParameterAsVariable("inttype", "rshift_", params[3], c_expr);
        c_expr.expr &:= rshift_name;
        c_expr.expr &:= "<0?";
        c_expr.expr &:= raiseError("NUMERIC_ERROR");
        c_expr.expr &:= ":";
        c_expr.expr &:= rshift_name;
        c_expr.expr &:= ">=";
        c_expr.expr &:= integerLiteral(ccConf.INTTYPE_SIZE);
        c_expr.expr &:= "?((";
        process_expr(params[1], c_expr);
        c_expr.expr &:= ")<0?-1:0):(";
        process_expr(params[1], c_expr);
        c_expr.expr &:= ") >> ";
        c_expr.expr &:= rshift_name;
        c_expr.expr &:= ")";
      else
        c_expr.expr &:= "(";
        number_name := getParameterAsVariable("inttype", "tmp_", params[1], c_expr);
        rshift_name := getParameterAsVariable("inttype", "rshift_", params[3], c_expr);
        c_expr.expr &:= rshift_name;
        c_expr.expr &:= "<0?";
        c_expr.expr &:= raiseError("NUMERIC_ERROR");
        c_expr.expr &:= ":";
        c_expr.expr &:= rshift_name;
        c_expr.expr &:= ">=";
        c_expr.expr &:= integerLiteral(ccConf.INTTYPE_SIZE);
        c_expr.expr &:= "?(";
        c_expr.expr &:= number_name;
        c_expr.expr &:= "<0?-1:0):";
        doRshift(number_name, rshift_name, c_expr);
        c_expr.expr &:= ")";
      end if;
    else
      if ccConf.RSHIFT_DOES_SIGN_EXTEND then
        c_expr.expr &:= "(";
        process_expr(params[1], c_expr);
        c_expr.expr &:= ") >> (";
        process_expr(params[3], c_expr);
        c_expr.expr &:= ")";
      else
        c_expr.expr &:= "(";
        number_name := getParameterAsVariable("inttype", "tmp_", params[1], c_expr);
        (* Formula used: a<0?~(~a>>b):a>>b *)
        c_expr.expr &:= number_name;
        c_expr.expr &:= "<0?~(~";
        c_expr.expr &:= number_name;
        c_expr.expr &:= " >> (";
        process_expr(params[3], c_expr);
        c_expr.expr &:= ")):";
        c_expr.expr &:= number_name;
        c_expr.expr &:= " >> (";
        process_expr(params[3], c_expr);
        c_expr.expr &:= "))";
      end if;
    end if;
  end func;


const proc: process_int_rshift_assign (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
    var string: number_name is "";
  begin
    if ccConf.RSHIFT_DOES_SIGN_EXTEND then
      process_expr(params[1], statement);
      statement.expr &:= ">>=";
      process_expr(params[3], statement);
      statement.expr &:= ";\n";
    else
      (* Formula used: if (a<0) a= ~(~a>>b); else a>>=b; *)
      if isNormalVariable(params[1]) then
        number_name := normalVariable(params[1], statement);
      else
        incr(statement.temp_num);
        number_name := "tmp_" & str(statement.temp_num);
        statement.temp_decls &:= "inttype *";
        statement.temp_decls &:= number_name;
        statement.temp_decls &:= ";\n";
        statement.expr &:= number_name;
        statement.expr &:= "=&(";
        process_expr(params[1], statement);
        statement.expr &:= ");\n";
        number_name := "*" & number_name;
      end if;
      statement.expr &:= "if (";
      statement.expr &:= number_name;
      statement.expr &:= "<0) ";
      statement.expr &:= number_name;
      statement.expr &:= "= ~(~";
      statement.expr &:= number_name;
      statement.expr &:= " >> (";
      process_expr(params[3], statement);
      statement.expr &:= ")); else ";
      statement.expr &:= number_name;
      statement.expr &:= " >>= (";
      process_expr(params[3], statement);
      statement.expr &:= ");\n";
    end if;
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_int_sbtr (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") - (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_int_shrink (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    process_expr(params[1], statement);
    statement.expr &:= "-=";
    process_expr(params[3], statement);
    statement.expr &:= ";\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_int_sqrt (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "intSqrt(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_int_str (in ref_list: params, inout expr_type: c_expr) is func

  local
    var string: buffer_name is "";
  begin
    if ccConf.ALLOW_STRITYPE_SLICES then
      incr(c_expr.temp_num);
      buffer_name := "buffer_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "char ";
      c_expr.temp_decls &:= buffer_name;
      c_expr.temp_decls &:= "[sizeof(struct stristruct) + ";
      if ccConf.INTTYPE_SIZE = 64 then
        c_expr.temp_decls &:= "19";
      elsif ccConf.INTTYPE_SIZE = 32 then
        c_expr.temp_decls &:= "10";
      end if;
      c_expr.temp_decls &:= " * sizeof(strelemtype)];\n";
      c_expr.expr &:= "intStrToBuffer(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ", (stritype) &";
      c_expr.expr &:= buffer_name;
      c_expr.expr &:= ")";
    else
      prepare_stri_result(c_expr);
      c_expr.result_expr := "intStr(";
      getStdParamToResultExpr(params[1], c_expr);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_int_succ (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")+1";
  end func;


const proc: process_int_to_bstri_be (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bstri_result(c_expr);
    c_expr.result_expr := "intToBStriBe(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_int_to_bstri_le (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bstri_result(c_expr);
    c_expr.result_expr := "intToBStriLe(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_const_int_urshift (in reference: param1, in integer: shiftCount,
    inout expr_type: c_expr) is func

  begin
    if shiftCount < 0 then
      incr(countOptimizations);
      c_expr.expr &:= raiseError("NUMERIC_ERROR");
    elsif shiftCount >= ccConf.INTTYPE_SIZE then
      incr(countOptimizations);
      c_expr.expr &:= "0";
    else
      c_expr.expr &:= "(inttype)((uinttype)(";
      process_expr(param1, c_expr);
      c_expr.expr &:= ") >> ";
      c_expr.expr &:= str(shiftCount);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_int_urshift (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: urshift_name is "";
  begin
    if getConstant(params[3], INTOBJECT, evaluatedParam) then
      process_const_int_urshift(params[1], getValue(evaluatedParam, integer), c_expr);
    elsif integer_shift_check then
      c_expr.expr &:= "(";
      urshift_name := getParameterAsVariable("inttype", "urshift_", params[3], c_expr);
      c_expr.expr &:= urshift_name;
      c_expr.expr &:= "<0?";
      c_expr.expr &:= raiseError("NUMERIC_ERROR");
      c_expr.expr &:= ":";
      c_expr.expr &:= urshift_name;
      c_expr.expr &:= ">=";
      c_expr.expr &:= integerLiteral(ccConf.INTTYPE_SIZE);
      c_expr.expr &:= "?0:(inttype)((uinttype)(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ") >> ";
      c_expr.expr &:= urshift_name;
      c_expr.expr &:= "))";
    else
      c_expr.expr &:= "(inttype)((uinttype)(";
      process_expr(params[1], c_expr);
      c_expr.expr &:= ") >> (";
      process_expr(params[3], c_expr);
      c_expr.expr &:= "))";
    end if;
  end func;


const proc: process_int_urshift_assign (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
    var string: number_name is "";
  begin
    if isNormalVariable(params[1]) then
      number_name := normalVariable(params[1], statement);
    else
      incr(statement.temp_num);
      number_name := "tmp_" & str(statement.temp_num);
      statement.temp_decls &:= "inttype *";
      statement.temp_decls &:= number_name;
      statement.temp_decls &:= ";\n";
      statement.expr &:= number_name;
      statement.expr &:= "=&(";
      process_expr(params[1], statement);
      statement.expr &:= ");\n";
    end if;
    statement.expr &:= number_name;
    statement.expr &:= "=(inttype)((uinttype)(";
    statement.expr &:= number_name;
    statement.expr &:= ") >> (";
    process_expr(params[3], statement);
    statement.expr &:= "));\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_int_value (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "intValue(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_int_xor (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") ^ (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_int_xor_assign (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    process_expr(params[1], statement);
    statement.expr &:= "^=";
    process_expr(params[3], statement);
    statement.expr &:= ";\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_itf_cmp (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "ptrCmp(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_itf_conv2 (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_itf_cpy (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: c_param1 is expr_type.value;
    var expr_type: c_param3 is expr_type.value;
  begin
    process_expr(params[1], c_param1);
    c_param3.temp_num := c_param1.temp_num;
    process_expr(params[3], c_param3);
    c_expr.expr &:= "{\n";
    if has_temp_values(c_param3) then
      AppendWithDiagnostic(c_param1.temp_decls, c_expr);
      AppendWithDiagnostic(c_param3.temp_decls, c_expr);
      AppendWithDiagnostic(c_param1.temp_assigns, c_expr);
      AppendWithDiagnostic(c_param3.temp_assigns, c_expr);
    end if;
    setDiagnosticLine(c_expr);
    if isNormalVariable(params[1]) then
      c_expr.expr &:= "structtype old_struct=";
      c_expr.expr &:= c_param1.expr;
      c_expr.expr &:= ";\n";
      setDiagnosticLine(c_expr);
      c_expr.expr &:= c_param1.expr;
      c_expr.expr &:= "=";
    else
      c_expr.expr &:= "interfacetype *interface_ptr=&(";
      c_expr.expr &:= c_param1.expr;
      c_expr.expr &:= ");\n";
      setDiagnosticLine(c_expr);
      c_expr.expr &:= "structtype old_struct=*interface_ptr;\n";
      setDiagnosticLine(c_expr);
      c_expr.expr &:= "*interface_ptr=";
    end if;
    if c_param3.result_expr <> "" then
      c_expr.expr &:= c_param3.result_expr;
      c_expr.expr &:= ";\n";
    else
      c_expr.expr &:= c_param3.expr;
      c_expr.expr &:= ";\n";
      setDiagnosticLine(c_expr);
      if isNormalVariable(params[1]) then
        c_expr.expr &:= "if ((";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ")->usage_count != 0) {(";
        c_expr.expr &:= c_param1.expr;
      else
        c_expr.expr &:= "if ((*interface_ptr)->usage_count != 0) {(*interface_ptr";
      end if;
      c_expr.expr &:= ")->usage_count++; }\n";
    end if;
    process_destr_declaration(getExprResultType(params[1]), global_c_expr);
    setDiagnosticLine(c_expr);
    process_destr_call(getExprResultType(params[1]),
        "old_struct", c_expr.expr);
    if has_temp_values(c_param3) then
      AppendWithDiagnostic(c_param1.temp_frees, c_expr);
      AppendWithDiagnostic(c_param3.temp_frees, c_expr);
    end if;
    c_expr.expr &:= "}\n";
  end func;


const proc: process_itf_eq (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ") == (";
    getAnyParamToExpr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_itf_hashcode (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(inttype)(((memsizetype)(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")) >> 6)";
  end func;


const proc: process_itf_ne (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ") != (";
    getAnyParamToExpr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_itf_to_interface (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  local
    var string: result_name is "";
  begin
    prepare_typed_result(resultType(getType(function)), c_expr);
    incr(c_expr.temp_num);
    result_name := "result_" & str(c_expr.temp_num);
    c_expr.temp_decls &:= "interfacetype ";
    c_expr.temp_decls &:= result_name;
    c_expr.temp_decls &:= ";\n";
    c_expr.result_expr &:= "/* ITF_TO_INTERFACE */(";
    c_expr.result_expr &:= result_name;
    c_expr.result_expr &:= "=";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ",";
    c_expr.result_expr &:= result_name;
    c_expr.result_expr &:= "->usage_count!=0 ? ";
    c_expr.result_expr &:= result_name;
    c_expr.result_expr &:= "->usage_count++ : 0,";
    c_expr.result_expr &:= result_name;
    c_expr.result_expr &:= ")";
  end func;


const proc: process_kbd_busy_getc (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(kbdKeyPressed() ? kbdGetc() : ";
    c_expr.expr &:= charLiteral(KEY_NONE);
    c_expr.expr &:= ")";
  end func;


const proc: process_kbd_getc (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "kbdGetc()";
  end func;


const proc: process_kbd_gets (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "kbdGets(";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_kbd_keypressed (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "kbdKeyPressed()";
  end func;


const proc: process_kbd_line_read (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "kbdLineRead(&(";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= "))";
  end func;


const proc: process_kbd_raw_getc (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "kbdRawGetc()";
  end func;


const proc: process_kbd_word_read (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "kbdWordRead(&(";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= "))";
  end func;


const proc: process_pol_addCheck (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "polAddCheck(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", (generictype)(";
    process_expr(params[4], c_expr);
    c_expr.expr &:= "));\n";
  end func;


const proc: process_pol_clear (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "polClear(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_pol_cpy (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: c_param1 is expr_type.value;
    var expr_type: c_param3 is expr_type.value;
  begin
    process_expr(params[1], c_param1);
    c_param3.temp_num := c_param1.temp_num;
    process_expr(params[3], c_param3);
    if has_temp_values(c_param3) then
      c_expr.expr &:= "{\n";
      AppendWithDiagnostic(c_param1.temp_decls, c_expr);
      AppendWithDiagnostic(c_param3.temp_decls, c_expr);
      AppendWithDiagnostic(c_param1.temp_assigns, c_expr);
      AppendWithDiagnostic(c_param3.temp_assigns, c_expr);
    end if;
    if c_param3.result_expr <> "" then
      c_expr.expr &:= "{\n";
      setDiagnosticLine(c_expr);
      if isNormalVariable(params[1]) then
        c_expr.expr &:= "polltype old_poll=";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ";\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= "=";
      else
        c_expr.expr &:= "polltype *poll_ptr=&(";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ");\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "polltype old_poll=*poll_ptr;\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "*poll_ptr=";
      end if;
      c_expr.expr &:= c_param3.result_expr;
      c_expr.expr &:= ";\n";
      setDiagnosticLine(c_expr);
      c_expr.expr &:= "polDestr(old_poll);\n";
      c_expr.expr &:= "}\n";
    else
      setDiagnosticLine(c_expr);
      c_expr.expr &:= "polCpy(";
      c_expr.expr &:= c_param1.expr;
      c_expr.expr &:= ", ";
      c_expr.expr &:= c_param3.expr;
      c_expr.expr &:= ");\n";
    end if;
    if has_temp_values(c_param3) then
      AppendWithDiagnostic(c_param1.temp_frees, c_expr);
      AppendWithDiagnostic(c_param3.temp_frees, c_expr);
      c_expr.expr &:= "}\n";
    end if;
  end func;


const proc: process_pol_hasNext (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "polHasNext(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_pol_iterChecks (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "polIterChecks(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_pol_iterFindings (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "polIterFindings(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_pol_nextFile (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "polNextFile(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", (generictype)(";
    process_expr(params[2], c_expr);
    c_expr.expr &:= "))";
  end func;


const proc: process_pol_nextWriteFile (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "polNextWriteFile(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", (generictype)(";
    process_expr(params[2], c_expr);
    c_expr.expr &:= "))";
  end func;


const proc: process_pol_poll (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "polPoll(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_pol_getCheck (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "polGetCheck(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_pol_getFinding (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "polGetFinding(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_pol_removeCheck (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "polRemoveCheck(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_pol_value (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "polValue(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_prg_cpy (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: c_param1 is expr_type.value;
    var expr_type: c_param3 is expr_type.value;
  begin
    compilerLibraryUsed := TRUE;
    process_expr(params[1], c_param1);
    c_param3.temp_num := c_param1.temp_num;
    process_expr(params[3], c_param3);
    if has_temp_values(c_param3) then
      c_expr.expr &:= "{\n";
      AppendWithDiagnostic(c_param1.temp_decls, c_expr);
      AppendWithDiagnostic(c_param3.temp_decls, c_expr);
      AppendWithDiagnostic(c_param1.temp_assigns, c_expr);
      AppendWithDiagnostic(c_param3.temp_assigns, c_expr);
    end if;
    if c_param3.result_expr <> "" then
      c_expr.expr &:= "{\n";
      setDiagnosticLine(c_expr);
      if isNormalVariable(params[1]) then
        c_expr.expr &:= "progtype old_prog=";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ";\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= "=";
      else
        c_expr.expr &:= "progtype *prg_ptr=&(";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ");\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "progtype old_prog=*prg_ptr;\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "*prg_ptr=";
      end if;
      c_expr.expr &:= c_param3.result_expr;
      c_expr.expr &:= ";\n";
      setDiagnosticLine(c_expr);
      c_expr.expr &:= "prgDestr(old_prog);\n";
      c_expr.expr &:= "}\n";
    else
      setDiagnosticLine(c_expr);
      c_expr.expr &:= "prgCpy(&(";
      c_expr.expr &:= c_param1.expr;
      c_expr.expr &:= "), ";
      c_expr.expr &:= c_param3.expr;
      c_expr.expr &:= ");\n";
    end if;
    if has_temp_values(c_param3) then
      AppendWithDiagnostic(c_param1.temp_frees, c_expr);
      AppendWithDiagnostic(c_param3.temp_frees, c_expr);
      c_expr.expr &:= "}\n";
    end if;
  end func;


const proc: process_prg_eq (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") == (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_prg_error_count (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compilerLibraryUsed := TRUE;
    c_expr.expr &:= "prgErrorCount(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_prg_eval (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compilerLibraryUsed := TRUE;
    c_expr.expr &:= "prgEval(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_prg_exec (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compilerLibraryUsed := TRUE;
    c_expr.expr &:= "prgExec(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[3], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[4], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_prg_fil_parse (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compilerLibraryUsed := TRUE;
    prepare_prog_result(c_expr);
    c_expr.result_expr := "prgFilParse(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getAnyParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= ", ";
    getAnyParamToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= ", ";
    getAnyParamToResultExpr(params[4], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_prg_global_objects (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  begin
    compilerLibraryUsed := TRUE;
    prepare_list_result(resultType(getType(function)), c_expr);
    c_expr.result_expr := "prgGlobalObjects(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_prg_match (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compilerLibraryUsed := TRUE;
    c_expr.expr &:= "prgMatch(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_prg_match_expr (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compilerLibraryUsed := TRUE;
    c_expr.expr &:= "prgMatchExpr(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_prg_name (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compilerLibraryUsed := TRUE;
    c_expr.expr &:= "prgName(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_prg_ne (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") != (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_prg_own_name (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "programName";
  end func;


const proc: process_prg_own_path (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "programPath";
  end func;


const proc: process_prg_path (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compilerLibraryUsed := TRUE;
    c_expr.expr &:= "prgPath(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_prg_str_parse (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compilerLibraryUsed := TRUE;
    prepare_prog_result(c_expr);
    c_expr.result_expr := "prgStrParse(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getAnyParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= ", ";
    getAnyParamToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= ", ";
    getAnyParamToResultExpr(params[4], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_prg_syobject (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compilerLibraryUsed := TRUE;
    c_expr.expr &:= "prgSyobject(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_prg_sysvar (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compilerLibraryUsed := TRUE;
    c_expr.expr &:= "prgSysvar(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_prg_value (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compilerLibraryUsed := TRUE;
    c_expr.expr &:= "prgValue(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_ref_addr (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "&(";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_ref_alloc (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "refAlloc(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_ref_arrmaxidx (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "refArrMaxIdx(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_ref_arrminidx (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "refArrMinIdx(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_ref_arrtolist (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    prepare_list_result(resultType(getType(function)), c_expr);
    c_expr.result_expr := "refArrToList(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_ref_body (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "refBody(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_ref_category (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "refCategory(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_ref_cat_parse (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "refCatParse(";
    getAnyParamToExpr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_ref_cat_str (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    prepare_stri_result(c_expr);
    c_expr.result_expr := "refCatStr(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_ref_cmp (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "ptrCmp(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_ref_conv (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_ref_cpy (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    process_expr(params[1], statement);
    statement.expr &:= "=";
    process_expr(params[3], statement);
    statement.expr &:= ";\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_ref_deref (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "/*ref_deref*/ *((";
    c_expr.expr &:= type_name(resultType(getType(function)));
    c_expr.expr &:= " *)(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= "))";
  end func;


const proc: process_ref_eq (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") == (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_ref_file (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "refFile(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_ref_getref (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "refGetRef(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_ref_hashcode (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(inttype)(((memsizetype)(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")) >> 6)";
  end func;


const proc: process_ref_hshdatatolist (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    prepare_list_result(resultType(getType(function)), c_expr);
    c_expr.result_expr := "refHshDataToList(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_ref_hshkeystolist (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    prepare_list_result(resultType(getType(function)), c_expr);
    c_expr.result_expr := "refHshKeysToList(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_ref_isvar (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "refIsVar(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_ref_itftosct (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "refItfToSct(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_ref_line (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "refLine(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_ref_local_consts (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    prepare_list_result(resultType(getType(function)), c_expr);
    c_expr.result_expr := "refLocalConsts(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_ref_local_vars (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    prepare_list_result(resultType(getType(function)), c_expr);
    c_expr.result_expr := "refLocalVars(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_ref_ne (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") != (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_ref_num (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "refNum(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_ref_params (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "refParams(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_ref_resini (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "refResini(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_ref_result (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "refResult(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_ref_scttolist (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    prepare_list_result(resultType(getType(function)), c_expr);
    c_expr.result_expr := "refSctToList(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_ref_select (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  local
    var type: object_type is void;
  begin
    object_type := getExprResultType(params[1]);
    if object_type in struct_elements and params[3] in struct_elements[object_type] then

      c_expr.expr &:= "((structtype)(";
      getAnyParamToExpr(params[1], c_expr);
      c_expr.expr &:= "))->stru[";
(*
      c_expr.expr &:= "(*((structtype *)(";
      getAnyParamToExpr(params[1], c_expr);
      c_expr.expr &:= ")))->stru[";
*)
      c_expr.expr &:= str(struct_elements[object_type][params[3]]);
      c_expr.expr &:= "]";
      c_expr.expr &:= select_value_from_rtlObjectstruct(resultType(getType(function)));
      c_expr.expr &:= "/*->o_";
      create_name2(params[3], c_expr.expr);
      c_expr.expr &:= "*/";
    end if;
  end func;


const proc: process_ref_setcategory (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "refSetCategory(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_ref_setparams (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "refSetParams(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_ref_settype (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "refSetType(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_ref_setvar (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "refSetVar(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_ref_str (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    prepare_stri_result(c_expr);
    c_expr.result_expr := "refStr(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_ref_trace (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: traceParam is NIL;
    var type: object_type is void;
    var expr_type: param1 is expr_type.value;
  begin
    traceParam := params[1];
    object_type := getExprResultType(traceParam);
    c_expr.expr &:= "printf(\"";
    if isVar(traceParam) or isVarfunc(getType(traceParam)) then
      c_expr.expr &:= "var ";
    else
      c_expr.expr &:= "const ";
    end if;
    process_expr(traceParam, param1);
    if param1.result_expr <> "" or param1.temp_decls <> "" then
      c_expr.expr &:= "[TEMP] \");\n";
      c_expr.expr &:= "{\n";
      c_expr.expr &:= param1.temp_decls;
      c_expr.expr &:= param1.result_decl;
      c_expr.expr &:= param1.temp_assigns;
      c_expr.expr &:= "printf(\"";
      param1.expr &:= param1.result_intro;
      param1.expr &:= param1.result_expr;
      param1.expr &:= param1.result_finish;
    end if;
    c_expr.expr &:= "%s: %s is \", ";
    c_expr.expr &:= c_literal(str(object_type));
    c_expr.expr &:= ", ";
    c_expr.expr &:= c_literal(str(traceParam));
    c_expr.expr &:= ");\n";
    if object_type in typeCategory then
      case typeCategory[object_type] of
        when {VOIDOBJECT}:
          c_expr.expr &:= "printf(\"<VOIDOBJECT>\")";
        when {BOOLOBJECT}:
          c_expr.expr &:= "printf(\"<BOOLOBJECT> %d\", ";
          c_expr.expr &:= param1.expr;
          c_expr.expr &:= ")";
        when {ENUMOBJECT}:
          c_expr.expr &:= "printf(\"<ENUMOBJECT> %d\", ";
          c_expr.expr &:= param1.expr;
          c_expr.expr &:= ")";
        when {INTOBJECT}:
          c_expr.expr &:= "printf(\"<INTOBJECT> %ld\", ";
          c_expr.expr &:= param1.expr;
          c_expr.expr &:= ")";
        when {BIGINTOBJECT}:
          c_expr.expr &:= "{\n";
          c_expr.expr &:= "char *cstri=bigHexCStri(";
          c_expr.expr &:= param1.expr;
          c_expr.expr &:= ");\n";
          c_expr.expr &:= "printf(\"<BIGINTOBJECT> %s\", cstri);\n";
          c_expr.expr &:= "free((void *) cstri);\n";
          c_expr.expr &:= "}\n";
        when {FLOATOBJECT}:
          c_expr.expr &:= "printf(\"<FLOATOBJECT> %f\", ";
          c_expr.expr &:= param1.expr;
          c_expr.expr &:= ")";
        when {CHAROBJECT}:
          c_expr.expr &:= "printf(\"<CHAROBJECT> %c\", ";
          c_expr.expr &:= param1.expr;
          c_expr.expr &:= ")";
        when {STRIOBJECT}:
          c_expr.expr &:= "printf(\"<STRIOBJECT>\"); ";
          c_expr.expr &:= "filPrint(";
          c_expr.expr &:= param1.expr;
          c_expr.expr &:= ")";
        when {BSTRIOBJECT}:
          c_expr.expr &:= "printf(\"<BSTRIOBJECT>\")";
        when {FILEOBJECT}:
          c_expr.expr &:= "printf(\"<FILEOBJECT>\")";
        when {SOCKETOBJECT}:
          c_expr.expr &:= "printf(\"<SOCKETOBJECT>\")";
        when {POLLOBJECT}:
          c_expr.expr &:= "printf(\"<POLLOBJECT>\")";
        when {TYPEOBJECT}:
          c_expr.expr &:= "printf(\"<TYPEOBJECT> %X\", ";
          c_expr.expr &:= param1.expr;
          c_expr.expr &:= ")";
        when {WINOBJECT}:
          c_expr.expr &:= "{\n";
          c_expr.expr &:= "wintype win=";
          c_expr.expr &:= param1.expr;
          c_expr.expr &:= ";\n";
          c_expr.expr &:= "printf(\"<WINOBJECT>\");\n";
          c_expr.expr &:= "if (win == NULL) {\n";
          c_expr.expr &:= "printf(\"  *NULL_WINDOW* \");\n";
          c_expr.expr &:= "} else {\n";
          c_expr.expr &:= "printf(\" window [%lu] %lu\", win->usage_count, win);\n";
          c_expr.expr &:= "}\n";
          c_expr.expr &:= "}\n";
        when {PROGOBJECT}:
          c_expr.expr &:= "{\n";
          c_expr.expr &:= "progtype prg=";
          c_expr.expr &:= param1.expr;
          c_expr.expr &:= ";\n";
          c_expr.expr &:= "printf(\"<PROGOBJECT>\");\n";
          c_expr.expr &:= "if (prg == NULL) {\n";
          c_expr.expr &:= "printf(\"  *NULL_PROG* \");\n";
          c_expr.expr &:= "} else {\n";
          c_expr.expr &:= "printf(\" program [%lu] %lu\", prg->usage_count, prg);\n";
          c_expr.expr &:= "}\n";
          c_expr.expr &:= "}\n";
        when {REFOBJECT}:
          compDataLibraryUsed := TRUE;
          c_expr.expr &:= "{\n";
          c_expr.expr &:= "objreftype ref=";
          c_expr.expr &:= param1.expr;
          c_expr.expr &:= ";\n";
          c_expr.expr &:= "stritype typeStri=typStr(refType(ref));\n";
          c_expr.expr &:= "stritype nameStri=refStr(ref);\n";
          c_expr.expr &:= "stritype categoryStri=refCatStr(refCategory(ref));\n";
          c_expr.expr &:= "printf(\"<REFOBJECT>\\n\");\n";
          c_expr.expr &:= "if (refIsVar(ref)) {\n";
          c_expr.expr &:= "printf(\"  var \");\n";
          c_expr.expr &:= "} else {\n";
          c_expr.expr &:= "printf(\"  const \");\n";
          c_expr.expr &:= "}\n";
          c_expr.expr &:= "filWrite(stdout, typeStri);\n";
          c_expr.expr &:= "printf(\": \");\n";
          c_expr.expr &:= "filWrite(stdout, nameStri);\n";
          c_expr.expr &:= "printf(\" is <\");\n";
          c_expr.expr &:= "filWrite(stdout, categoryStri);\n";
          c_expr.expr &:= "printf(\">\");\n";
          c_expr.expr &:= "strDestr(typeStri);\n";
          c_expr.expr &:= "strDestr(nameStri);\n";
          c_expr.expr &:= "strDestr(categoryStri);\n";
          c_expr.expr &:= "}\n";
        when {REFLISTOBJECT}:
          c_expr.expr &:= "printf(\"<REFLISTOBJECT>\")";
        when {SETOBJECT}:
          c_expr.expr &:= "{\n";
          c_expr.expr &:= "settype aSet=";
          c_expr.expr &:= param1.expr;
          c_expr.expr &:= ";\n";
          c_expr.expr &:= "printf(\"<SETOBJECT>\");\n";
          c_expr.expr &:= "if (aSet == NULL) {\n";
          c_expr.expr &:= "printf(\"  *NULL_SET* \");\n";
          c_expr.expr &:= "} else {\n";
          c_expr.expr &:= "printf(\" set[%ld/%ld]\", aSet->min_position, aSet->max_position);\n";
          c_expr.expr &:= "}\n";
          c_expr.expr &:= "}\n";
        when {ARRAYOBJECT}:
          c_expr.expr &:= "{\n";
          c_expr.expr &:= "arraytype arr=";
          c_expr.expr &:= param1.expr;
          c_expr.expr &:= ";\n";
          c_expr.expr &:= "printf(\"<ARRAYOBJECT>\");\n";
          c_expr.expr &:= "if (arr == NULL) {\n";
          c_expr.expr &:= "printf(\"  *NULL_ARRAY* \");\n";
          c_expr.expr &:= "} else {\n";
          c_expr.expr &:= "printf(\" array[%ld .. %ld]\", arr->min_position, arr->max_position);\n";
          c_expr.expr &:= "}\n";
          c_expr.expr &:= "}\n";
        when {HASHOBJECT}:
          c_expr.expr &:= "{\n";
          c_expr.expr &:= "hashtype hsh=";
          c_expr.expr &:= param1.expr;
          c_expr.expr &:= ";\n";
          c_expr.expr &:= "printf(\"<HASHOBJECT>\");\n";
          c_expr.expr &:= "if (hsh == NULL) {\n";
          c_expr.expr &:= "printf(\"  *NULL_HASH* \");\n";
          c_expr.expr &:= "} else {\n";
          c_expr.expr &:= "printf(\" hash[%ld]\", hsh->size);\n";
          c_expr.expr &:= "}\n";
          c_expr.expr &:= "}\n";
        when {STRUCTOBJECT}:
          c_expr.expr &:= "{\n";
          c_expr.expr &:= "structtype sct=";
          c_expr.expr &:= param1.expr;
          c_expr.expr &:= ";\n";
          c_expr.expr &:= "printf(\"<STRUCTOBJECT>\");\n";
          c_expr.expr &:= "if (sct == NULL) {\n";
          c_expr.expr &:= "printf(\"  *NULL_STRUCT* \");\n";
          c_expr.expr &:= "} else {\n";
          c_expr.expr &:= "printf(\" struct[";
          c_expr.expr &:= str(length(struct_elements[object_type]));
          c_expr.expr &:= "]\");\n";
          c_expr.expr &:= "if (sct->usage_count != 0) {\n";
          c_expr.expr &:= "printf(\"<%lu>\", sct->usage_count);\n";
          c_expr.expr &:= "}\n";
          c_expr.expr &:= "printf(\" type_num=%lu %lx\", sct->type_num, sct);\n";
          c_expr.expr &:= "}\n";
          c_expr.expr &:= "}\n";
        when {INTERFACEOBJECT}:
          c_expr.expr &:= "{\n";
          c_expr.expr &:= "interfacetype itf=";
          c_expr.expr &:= param1.expr;
          c_expr.expr &:= ";\n";
          c_expr.expr &:= "printf(\"<INTERFACEOBJECT>\");\n";
          c_expr.expr &:= "if (itf == NULL) {\n";
          c_expr.expr &:= "printf(\"  *NULL_INTERFACE* \");\n";
          c_expr.expr &:= "} else {\n";
          c_expr.expr &:= "printf(\" usage_count=%lu %lx\", itf->usage_count, itf);\n";
          c_expr.expr &:= "printf(\" type_num=%lu %lx\", itf->type_num, itf);\n";
          c_expr.expr &:= "}\n";
          c_expr.expr &:= "}\n";
        otherwise:
          c_expr.expr &:= "printf(\"< ?? >\")";
      end case;
    elsif object_type = proctype then
      c_expr.expr &:= "printf(\"<CALLOBJECT> %X\", ";
      c_expr.expr &:= param1.expr;
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= "printf(\"< ?? >\")";
    end if;
    c_expr.expr &:= ";\n";
    if param1.result_expr <> "" or param1.temp_decls <> "" then
      c_expr.expr &:= param1.temp_frees;
      c_expr.expr &:= param1.result_free;
      c_expr.expr &:= "}";
    end if;
  end func;


const proc: process_ref_type (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "refType(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_ref_value (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "refValue(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_rfl_append (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: c_param1 is expr_type.value;
    var expr_type: c_param3 is expr_type.value;
  begin
    compDataLibraryUsed := TRUE;
    process_expr(params[1], c_param1);
    c_param3.temp_num := c_param1.temp_num;
    getTemporaryToResultExpr(params[3], c_param3);
    incr(c_param3.temp_num);
    if has_temp_values(c_param3) then
      c_expr.expr &:= "{\n";
      AppendWithDiagnostic(c_param1.temp_decls, c_expr);
      AppendWithDiagnostic(c_param3.temp_decls, c_expr);
      AppendWithDiagnostic(c_param1.temp_assigns, c_expr);
      AppendWithDiagnostic(c_param3.temp_assigns, c_expr);
    end if;
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "rflAppend(&(";
    c_expr.expr &:= c_param1.expr;
    c_expr.expr &:= "), ";
    c_expr.expr &:= c_param3.result_expr;
    c_expr.expr &:= ");\n";
    if has_temp_values(c_param3) then
      AppendWithDiagnostic(c_param1.temp_frees, c_expr);
      AppendWithDiagnostic(c_param3.temp_frees, c_expr);
      c_expr.expr &:= "}\n";
    end if;
  end func;


const proc: process_rfl_cat (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    prepare_list_result(getExprResultType(params[1]), c_expr);
    c_expr.result_expr := "rflCat(";
    getTemporaryToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getTemporaryToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_rfl_cpy (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: c_param1 is expr_type.value;
    var expr_type: c_param3 is expr_type.value;
  begin
    compDataLibraryUsed := TRUE;
    process_expr(params[1], c_param1);
    c_param3.temp_num := c_param1.temp_num;
    process_expr(params[3], c_param3);
    if has_temp_values(c_param3) then
      c_expr.expr &:= "{\n";
      AppendWithDiagnostic(c_param1.temp_decls, c_expr);
      AppendWithDiagnostic(c_param3.temp_decls, c_expr);
      AppendWithDiagnostic(c_param1.temp_assigns, c_expr);
      AppendWithDiagnostic(c_param3.temp_assigns, c_expr);
    end if;
    if c_param3.result_expr <> "" then
      c_expr.expr &:= "{\n";
      setDiagnosticLine(c_expr);
      if isNormalVariable(params[1]) then
        c_expr.expr &:= "listtype old_rfl=";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ";\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= "=";
      else
        c_expr.expr &:= "listtype *rfl_ptr=&(";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ");\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "listtype old_rfl=*rfl_ptr;\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "*rfl_ptr=";
      end if;
      c_expr.expr &:= c_param3.result_expr;
      c_expr.expr &:= ";\n";
      setDiagnosticLine(c_expr);
      c_expr.expr &:= "rflDestr(old_rfl);\n";
      c_expr.expr &:= "}\n";
    else
      setDiagnosticLine(c_expr);
      c_expr.expr &:= "rflCpy(&(";
      c_expr.expr &:= c_param1.expr;
      c_expr.expr &:= "), ";
      c_expr.expr &:= c_param3.expr;
      c_expr.expr &:= ");\n";
    end if;
    if has_temp_values(c_param3) then
      AppendWithDiagnostic(c_param1.temp_frees, c_expr);
      AppendWithDiagnostic(c_param3.temp_frees, c_expr);
      c_expr.expr &:= "}\n";
    end if;
  end func;


const proc: process_rfl_elem (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "rflElem(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_rfl_elemcpy (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: c_param1 is expr_type.value;
    var expr_type: c_param4 is expr_type.value;
    var expr_type: c_param6 is expr_type.value;
  begin
    compDataLibraryUsed := TRUE;
    process_expr(params[1], c_param1);
    c_param4.temp_num := c_param1.temp_num;
    process_expr(params[4], c_param4);
    c_param6.temp_num := c_param4.temp_num;
    process_expr(params[6], c_param6);
    if c_param6.temp_num <> 0 then
      c_expr.expr &:= "{\n";
      AppendWithDiagnostic(c_param1.temp_decls, c_expr);
      AppendWithDiagnostic(c_param4.temp_decls, c_expr);
      AppendWithDiagnostic(c_param6.temp_decls, c_expr);
      AppendWithDiagnostic(c_param1.temp_assigns, c_expr);
      AppendWithDiagnostic(c_param4.temp_assigns, c_expr);
      AppendWithDiagnostic(c_param6.temp_assigns, c_expr);
    end if;
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "rflElemcpy(";
    c_expr.expr &:= c_param1.expr;
    c_expr.expr &:= ", ";
    c_expr.expr &:= c_param4.expr;
    c_expr.expr &:= ", ";
    c_expr.expr &:= c_param6.expr;
    c_expr.expr &:= ");\n";
    if c_param6.temp_num <> 0 then
      AppendWithDiagnostic(c_param1.temp_frees, c_expr);
      AppendWithDiagnostic(c_param4.temp_frees, c_expr);
      AppendWithDiagnostic(c_param6.temp_frees, c_expr);
      c_expr.expr &:= "}\n";
    end if;
  end func;


const proc: process_rfl_eq (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "rflEq(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_rfl_for (in ref_list: params, inout expr_type: c_expr) is func

  local
    var string: elem_name is "";
  begin
    incr(c_expr.temp_num);
    elem_name := "tmp_elem_" & str(c_expr.temp_num);
    c_expr.expr &:= "{\n";
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "listtype ";
    c_expr.expr &:= elem_name;
    c_expr.expr &:= ";\n";
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "for (";
    c_expr.expr &:= elem_name;
    c_expr.expr &:= " = ";
    getAnyParamToExpr(params[4], c_expr);
    c_expr.expr &:= "; ";
    c_expr.expr &:= elem_name;
    c_expr.expr &:= " != NULL; ";
    c_expr.expr &:= elem_name;
    c_expr.expr &:= " = ";
    c_expr.expr &:= elem_name;
    c_expr.expr &:= "->next) {\n";
    setDiagnosticLine(c_expr);
    process_expr(params[2], c_expr);
    c_expr.expr &:= " = ";
    c_expr.expr &:= elem_name;
    c_expr.expr &:= "->obj;\n";
    process_expr(params[6], c_expr);
    c_expr.expr &:= "}\n}\n";
  end func;


const proc: process_rfl_for_until (in ref_list: params, inout expr_type: c_expr) is func

  local
    var string: elem_name is "";
  begin
    incr(c_expr.temp_num);
    elem_name := "tmp_elem_" & str(c_expr.temp_num);
    c_expr.expr &:= "{\n";
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "listtype ";
    c_expr.expr &:= elem_name;
    c_expr.expr &:= ";\n";
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "for (";
    c_expr.expr &:= elem_name;
    c_expr.expr &:= " = ";
    getAnyParamToExpr(params[4], c_expr);
    c_expr.expr &:= "; ";
    c_expr.expr &:= elem_name;
    c_expr.expr &:= " != NULL && (";
    process_expr(params[2], c_expr);
    c_expr.expr &:= " = ";
    c_expr.expr &:= elem_name;
    c_expr.expr &:= "->obj, !(";
    process_expr(params[6], c_expr);
    c_expr.expr &:= ")); ";
    c_expr.expr &:= elem_name;
    c_expr.expr &:= " = ";
    c_expr.expr &:= elem_name;
    c_expr.expr &:= "->next) {\n";
    process_expr(params[8], c_expr);
    c_expr.expr &:= "}\n}\n";
  end func;


const proc: process_rfl_head (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    prepare_list_result(getExprResultType(params[1]), c_expr);
    c_expr.result_expr := "rflHead(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[4], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_rfl_idx (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "rflIdx(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_rfl_incl (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    compDataLibraryUsed := TRUE;
    statement.expr := "rflIncl(&(";
    process_expr(params[1], statement);
    statement.expr &:= "), ";
    process_expr(params[2], statement);
    statement.expr &:= ");\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_rfl_ipos (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "rflIpos(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_rfl_lng (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "rflLng(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_rfl_mklist (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    prepare_list_result(resultType(getType(function)), c_expr);
    c_expr.result_expr := "rflMklist(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_rfl_ne (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "!rflEq(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_rfl_not_elem (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "!rflElem(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[4], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_rfl_pos (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "rflPos(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_rfl_setvalue (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "rflSetvalue(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_rfl_tail (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    prepare_list_result(getExprResultType(params[1]), c_expr);
    c_expr.result_expr := "rflTail(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_rfl_value (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    prepare_list_result(resultType(getType(function)), c_expr);
    c_expr.result_expr := "rflValue(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_sct_alloc (in ref_list: params, inout expr_type: c_expr) is func

  local
    var type: param_type is void;
    var expr_type: c_param1 is expr_type.value;
  begin
    param_type := getExprResultType(params[1]);
    # prepare_typed_result(param_type, c_expr);
    prepareAnyParamTemporarys(params[1], c_param1, c_expr);
    c_expr.expr &:= "/* SCT_ALLOC */ (objreftype)(";
    if c_param1.result_expr <> "" then
      c_expr.expr &:= c_param1.result_expr;
    else
      typeCategory @:= [param_type] STRUCTOBJECT;
      process_create_declaration(param_type, global_c_expr);
      process_create_call(param_type,
          c_param1.expr, c_expr.expr);
    end if;
    c_expr.expr &:= ")";
  end func;


const proc: process_sct_cpy (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: c_param1 is expr_type.value;
    var expr_type: c_param3 is expr_type.value;
  begin
    process_expr(params[1], c_param1);
    c_param3.temp_num := c_param1.temp_num;
    process_expr(params[3], c_param3);
    if has_temp_values(c_param3) then
      c_expr.expr &:= "{\n";
      AppendWithDiagnostic(c_param1.temp_decls, c_expr);
      AppendWithDiagnostic(c_param3.temp_decls, c_expr);
      AppendWithDiagnostic(c_param1.temp_assigns, c_expr);
      AppendWithDiagnostic(c_param3.temp_assigns, c_expr);
    end if;
    if c_param3.result_expr <> "" then
      c_expr.expr &:= "{\n";
      setDiagnosticLine(c_expr);
      if isNormalVariable(params[1]) then
        c_expr.expr &:= "structtype old_struct=";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ";\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= "=";
        c_expr.expr &:= c_param3.result_expr;
        c_expr.expr &:= ";\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "(";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ")->type_num = old_struct->type_num;\n";
      else
        c_expr.expr &:= "structtype *struct_ptr=&(";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ");\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "structtype old_struct=*struct_ptr;\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "*struct_ptr=";
        c_expr.expr &:= c_param3.result_expr;
        c_expr.expr &:= ";\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "(*struct_ptr)->type_num = old_struct->type_num;\n";
      end if;
      process_destr_declaration(getExprResultType(params[1]), global_c_expr);
      setDiagnosticLine(c_expr);
      process_destr_call(getExprResultType(params[1]),
          "old_struct", c_expr.expr);
      c_expr.expr &:= "}\n";
    else
      process_cpy_declaration(getExprResultType(params[1]), global_c_expr);
      setDiagnosticLine(c_expr);
      process_cpy_call(getExprResultType(params[1]),
          c_param1.expr, c_param3.expr, c_expr.expr);
      c_expr.expr &:= ";\n";
    end if;
    if has_temp_values(c_param3) then
      AppendWithDiagnostic(c_param1.temp_frees, c_expr);
      AppendWithDiagnostic(c_param3.temp_frees, c_expr);
      c_expr.expr &:= "}\n";
    end if;
  end func;


const proc: process_sct_select (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  local
    var type: object_type is void;
  begin
    object_type := getExprResultType(params[1]);
    if object_type in struct_elements and params[3] in struct_elements[object_type] then
      c_expr.expr &:= "((structtype)(";
      getAnyParamToExpr(params[1], c_expr);
      c_expr.expr &:= "))->stru[";
      c_expr.expr &:= str(struct_elements[object_type][params[3]]);
      c_expr.expr &:= "]";
      c_expr.expr &:= select_value_from_rtlObjectstruct(resultType(getType(function)));
      c_expr.expr &:= "/*->o_";
      create_name2(params[3], c_expr.expr);
      c_expr.expr &:= "*/";
    end if;
  end func;


const proc: process_set_arrlit (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  begin
    prepare_set_result(resultType(getType(function)), c_expr);
    c_expr.result_expr := "setArrlit(";
    getAnyParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_set_baselit (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  begin
    prepare_set_result(resultType(getType(function)), c_expr);
    c_expr.result_expr := "setBaselit(";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_set_card (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "setCard(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_set_cmp (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "setCmp(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_set_conv (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_set_cpy (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: c_param1 is expr_type.value;
    var expr_type: c_param3 is expr_type.value;
  begin
    process_expr(params[1], c_param1);
    c_param3.temp_num := c_param1.temp_num;
    process_expr(params[3], c_param3);
    if has_temp_values(c_param3) then
      c_expr.expr &:= "{\n";
      AppendWithDiagnostic(c_param1.temp_decls, c_expr);
      AppendWithDiagnostic(c_param3.temp_decls, c_expr);
      AppendWithDiagnostic(c_param1.temp_assigns, c_expr);
      AppendWithDiagnostic(c_param3.temp_assigns, c_expr);
    end if;
    if c_param3.result_expr <> "" then
      c_expr.expr &:= "{\n";
      setDiagnosticLine(c_expr);
      if isNormalVariable(params[1]) then
        c_expr.expr &:= "settype old_set=";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ";\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= "=";
      else
        c_expr.expr &:= "settype *set_ptr=&(";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ");\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "settype old_set=*set_ptr;\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "*set_ptr=";
      end if;
      c_expr.expr &:= c_param3.result_expr;
      c_expr.expr &:= ";\n";
      setDiagnosticLine(c_expr);
      c_expr.expr &:= "setDestr(old_set);\n";
      c_expr.expr &:= "}\n";
    else
      setDiagnosticLine(c_expr);
      c_expr.expr &:= "setCpy(&(";
      c_expr.expr &:= c_param1.expr;
      c_expr.expr &:= "), ";
      c_expr.expr &:= c_param3.expr;
      c_expr.expr &:= ");\n";
    end if;
    if has_temp_values(c_param3) then
      AppendWithDiagnostic(c_param1.temp_frees, c_expr);
      AppendWithDiagnostic(c_param3.temp_frees, c_expr);
      c_expr.expr &:= "}\n";
    end if;
  end func;


const proc: process_set_diff (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[1], SETOBJECT, evaluatedParam) and
        getValue(evaluatedParam, bitset) = EMPTY_SET then
      c_expr.expr &:= bitsetLiteral(EMPTY_SET);
    elsif getConstant(params[3], SETOBJECT, evaluatedParam) and
        getValue(evaluatedParam, bitset) = EMPTY_SET then
      getAnyParamToExpr(params[1], c_expr);
    else
      prepare_set_result(getExprResultType(params[1]), c_expr);
      c_expr.result_expr := "setDiff(";
      getAnyParamToResultExpr(params[1], c_expr);
      c_expr.result_expr &:= ", ";
      getAnyParamToResultExpr(params[3], c_expr);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_const_set_elem (in reference: param1, in bitset: aBitset,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: integer_name is "";
    var integer: number is 0;
    var boolean: first_element is TRUE;
    var boolean: isElement is FALSE;
  begin
    if getConstant(param1, INTOBJECT, evaluatedParam) then
      incr(countOptimizations);
      isElement := getValue(evaluatedParam, integer) in aBitset;
      c_expr.expr &:= str(ord(isElement));
      c_expr.expr &:= "/*";
      c_expr.expr &:= str(isElement);
      c_expr.expr &:= "*/";
    elsif aBitset = EMPTY_SET then
      incr(countOptimizations);
      c_expr.expr &:= "0/*FALSE*/";
    elsif card(aBitset) = 1 then
      incr(countOptimizations);
      c_expr.expr &:= "(";
      process_expr(param1, c_expr);
      c_expr.expr &:= ") == ";
      c_expr.expr &:= integerLiteral(min(aBitset));
    elsif card(aBitset) >= 3 and max(aBitset) - min(aBitset) = pred(card(aBitset)) then
      incr(countOptimizations);
      c_expr.expr &:= "(";
      integer_name := getParameterAsVariable("inttype", "tmp_", param1, c_expr);
      if ccConf.TWOS_COMPLEMENT_INTTYPE and min(aBitset) = 0 then
        c_expr.expr &:= "(uinttype)(";
        c_expr.expr &:= integer_name;
        c_expr.expr &:= ")";
      else
        c_expr.expr &:= integer_name;
        c_expr.expr &:= ">=";
        c_expr.expr &:= integerLiteral(min(aBitset));
        c_expr.expr &:= " && ";
        c_expr.expr &:= integer_name;
      end if;
      c_expr.expr &:= "<=";
      c_expr.expr &:= integerLiteral(max(aBitset));
      c_expr.expr &:= ")";
    elsif card(aBitset) = 2 or
        card(aBitset) = 3 and (min(aBitset) < 0 or max(aBitset) > 31) then
      incr(countOptimizations);
      c_expr.expr &:= "(";
      integer_name := getParameterAsVariable("inttype", "tmp_", param1, c_expr);
      for number range aBitset do
        if first_element then
          first_element := FALSE;
        else
          c_expr.expr &:= "||";
        end if;
        c_expr.expr &:= integer_name;
        c_expr.expr &:= "==";
        c_expr.expr &:= integerLiteral(number);
      end for;
      c_expr.expr &:= ")";
    elsif min(aBitset) >= 0 and max(aBitset) <= 31 then
      incr(countOptimizations);
      c_expr.expr &:= "(";
      integer_name := getParameterAsVariable("inttype", "tmp_", param1, c_expr);
      if ccConf.TWOS_COMPLEMENT_INTTYPE then
        c_expr.expr &:= "(uinttype)(";
        c_expr.expr &:= integer_name;
        c_expr.expr &:= ")";
      else
        c_expr.expr &:= integer_name;
        c_expr.expr &:= ">=0&&";
        c_expr.expr &:= integer_name;
      end if;
      c_expr.expr &:= "<=31&&";
      c_expr.expr &:= bitsetElemAsHex(aBitset, 0);
      c_expr.expr &:= ">>";
      c_expr.expr &:= integer_name;
      c_expr.expr &:= "&1)";
    elsif max(aBitset) - min(aBitset) <= 31 then
      incr(countOptimizations);
      c_expr.expr &:= "(";
      integer_name := getParameterAsVariable("inttype", "tmp_", param1, c_expr);
      c_expr.expr &:= integer_name;
      c_expr.expr &:= ">=";
      c_expr.expr &:= integerLiteral(min(aBitset));
      c_expr.expr &:= "&&";
      c_expr.expr &:= integer_name;
      c_expr.expr &:= "<=";
      c_expr.expr &:= integerLiteral(max(aBitset));
      c_expr.expr &:= "&&";
      c_expr.expr &:= bitsetElemAsHex(aBitset, min(aBitset));
      c_expr.expr &:= ">>";
      c_expr.expr &:= integer_name;
      c_expr.expr &:= "-";
      c_expr.expr &:= integerLiteral(min(aBitset));
      c_expr.expr &:= "&1)";
    elsif inlineFunctions then
      c_expr.expr &:= "(";
      integer_name := getParameterAsVariable("inttype", "tmp_", param1, c_expr);
      if ccConf.TWOS_COMPLEMENT_INTTYPE and bitset_pos(min(aBitset)) = 0 then
        c_expr.expr &:= "(uinttype)(";
        c_expr.expr &:= integer_name;
        c_expr.expr &:= ")";
      else
        c_expr.expr &:= integer_name;
        c_expr.expr &:= ">=";
        c_expr.expr &:= integerLiteral(min(aBitset));
        c_expr.expr &:= "&&";
        c_expr.expr &:= integer_name;
      end if;
      c_expr.expr &:= "<=";
      c_expr.expr &:= integerLiteral(max(aBitset));
      c_expr.expr &:= "&&";
      c_expr.expr &:= bitsetLiteral(aBitset);
      c_expr.expr &:= "->bitset[(uinttype)(bitset_pos(";
      c_expr.expr &:= integer_name;
      c_expr.expr &:= ")";
      if bitset_pos(min(aBitset)) <> 0 then
        c_expr.expr &:= "-";
        c_expr.expr &:= integerLiteral(bitset_pos(min(aBitset)));
      end if;
      c_expr.expr &:= ")] >> (";
      c_expr.expr &:= integer_name;
      c_expr.expr &:= " & bitset_mask)&1)";
    else
      c_expr.expr &:= "setElem(";
      process_expr(param1, c_expr);
      c_expr.expr &:= ", ";
      c_expr.expr &:= bitsetLiteral(aBitset);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_set_elem (in reference: param1, in reference: param3,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: integer_name is "";
    var string: position_name is "";
    var string: set_name is "";
  begin
    if getConstant(param3, SETOBJECT, evaluatedParam) then
      process_const_set_elem(param1, getValue(evaluatedParam, bitset), c_expr);
    elsif inlineFunctions then
      c_expr.expr &:= "(";
      integer_name := getParameterAsVariable("inttype", "tmp_", param1, c_expr);
      set_name := getParameterAsVariable("const_settype", "tmp_", param3, c_expr);
      incr(c_expr.temp_num);
      position_name := "tmp_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "inttype ";
      c_expr.temp_decls &:= position_name;
      c_expr.temp_decls &:= ";\n";
      c_expr.expr &:= position_name;
      c_expr.expr &:= "=bitset_pos(";
      c_expr.expr &:= integer_name;
      c_expr.expr &:= "),";
      c_expr.expr &:= position_name;
      c_expr.expr &:= ">=";
      c_expr.expr &:= set_name;
      c_expr.expr &:= "->min_position&&";
      c_expr.expr &:= position_name;
      c_expr.expr &:= "<=";
      c_expr.expr &:= set_name;
      c_expr.expr &:= "->max_position&&";
      c_expr.expr &:= set_name;
      c_expr.expr &:= "->bitset[(uinttype)(";
      c_expr.expr &:= position_name;
      c_expr.expr &:= "-";
      c_expr.expr &:= set_name;
      c_expr.expr &:= "->min_position)] >> (";
      c_expr.expr &:= integer_name;
      c_expr.expr &:= " & bitset_mask)&1)";
    else
      c_expr.expr &:= "setElem(";
      process_expr(param1, c_expr);
      c_expr.expr &:= ", ";
      getAnyParamToExpr(param3, c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_set_elem (in ref_list: params, inout expr_type: c_expr) is func

  begin
    process_set_elem(params[1], params[3], c_expr);
  end func;


const proc: process_const_set_eq (in reference: param1, in bitset: aBitset,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var boolean: isEqual is FALSE;
  begin
    if getConstant(param1, SETOBJECT, evaluatedParam) then
      incr(countOptimizations);
      isEqual := getValue(evaluatedParam, bitset) = aBitset;
      c_expr.expr &:= str(ord(isEqual));
      c_expr.expr &:= "/*";
      c_expr.expr &:= str(isEqual);
      c_expr.expr &:= "*/";
    elsif aBitset = EMPTY_SET then
      incr(countOptimizations);
      c_expr.expr &:= "setIsEmpty(";
      getAnyParamToExpr(param1, c_expr);
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= "setEq(";
      getAnyParamToExpr(param1, c_expr);
      c_expr.expr &:= ", ";
      c_expr.expr &:= bitsetLiteral(aBitset);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_set_eq (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[1], SETOBJECT, evaluatedParam) then
      process_const_set_eq(params[3], getValue(evaluatedParam, bitset), c_expr);
    elsif getConstant(params[3], SETOBJECT, evaluatedParam) then
      process_const_set_eq(params[1], getValue(evaluatedParam, bitset), c_expr);
    else
      c_expr.expr &:= "setEq(";
      getAnyParamToExpr(params[1], c_expr);
      c_expr.expr &:= ", ";
      getAnyParamToExpr(params[3], c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_inline_set_excl (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
    var string: integer_name is "";
    var string: position_name is "";
    var string: set_name is "";
  begin
    if isNormalVariable(params[1]) then
      set_name := normalVariable(params[1], statement);
    else
      incr(statement.temp_num);
      set_name := "tmp_" & str(statement.temp_num);
      statement.temp_decls &:= "settype ";
      statement.temp_decls &:= set_name;
      statement.temp_decls &:= ";\n";
      statement.expr &:= set_name;
      statement.expr &:= "=";
      process_expr(params[1], statement);
      statement.expr &:= ";\n";
    end if;
    if isNormalVariable(params[2]) then
      integer_name := normalVariable(params[2], statement);
    else
      incr(statement.temp_num);
      integer_name := "tmp_" & str(statement.temp_num);
      statement.temp_decls &:= "inttype ";
      statement.temp_decls &:= integer_name;
      statement.temp_decls &:= ";\n";
      statement.expr &:= integer_name;
      statement.expr &:= "=";
      process_expr(params[2], statement);
      statement.expr &:= ";\n";
    end if;
    incr(statement.temp_num);
    position_name := "tmp_" & str(statement.temp_num);
    statement.temp_decls &:= "inttype ";
    statement.temp_decls &:= position_name;
    statement.temp_decls &:= ";\n";
    statement.expr &:= position_name;
    statement.expr &:= "=bitset_pos(";
    statement.expr &:= integer_name;
    statement.expr &:= ");\n";
    statement.expr &:= "if (";
    statement.expr &:= position_name;
    statement.expr &:= ">=";
    statement.expr &:= set_name;
    statement.expr &:= "->min_position&&";
    statement.expr &:= position_name;
    statement.expr &:= "<=";
    statement.expr &:= set_name;
    statement.expr &:= "->max_position) {\n";
    statement.expr &:= set_name;
    statement.expr &:= "->bitset[(uinttype)(";
    statement.expr &:= position_name;
    statement.expr &:= "-";
    statement.expr &:= set_name;
    statement.expr &:= "->min_position)] &= ~((bitsettype) 1 << (((unsigned int) ";
    statement.expr &:= integer_name;
    statement.expr &:= ") & bitset_mask));\n";
    statement.expr &:= "}\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_set_excl (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    if inlineFunctions then
      process_inline_set_excl(params, c_expr);
    else
      statement.expr := "setExcl(&(";
      process_expr(params[1], statement);
      statement.expr &:= "), ";
      process_expr(params[2], statement);
      statement.expr &:= ");\n";
      doLocalDeclsOfStatement(statement, c_expr);
    end if;
  end func;


const proc: process_set_ge (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "setIsSubset(";
    getAnyParamToExpr(params[3], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_set_gt (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "setIsProperSubset(";
    getAnyParamToExpr(params[3], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_set_hashcode (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "setHashCode(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_set_iconv (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "setIConv(";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_set_incl (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    statement.expr := "setIncl(&(";
    process_expr(params[1], statement);
    statement.expr &:= "), ";
    process_expr(params[2], statement);
    statement.expr &:= ");\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_set_intersect (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[1], SETOBJECT, evaluatedParam) and
        getValue(evaluatedParam, bitset) = EMPTY_SET or
        getConstant(params[3], SETOBJECT, evaluatedParam) and
        getValue(evaluatedParam, bitset) = EMPTY_SET then
      c_expr.expr &:= bitsetLiteral(EMPTY_SET);
    else
      prepare_set_result(getExprResultType(params[1]), c_expr);
      c_expr.result_expr := "setIntersect(";
      getAnyParamToResultExpr(params[1], c_expr);
      c_expr.result_expr &:= ", ";
      getAnyParamToResultExpr(params[3], c_expr);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_set_le (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "setIsSubset(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_set_lt (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "setIsProperSubset(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_set_max (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "setMax(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_set_min (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "setMin(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_set_ne (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "!";
    process_set_eq(params, c_expr);
  end func;


const proc: process_set_next (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "setNext(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_set_not_elem (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "!(";
    process_set_elem(params[1], params[4], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_set_rand (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "setRand(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_set_rangelit (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  begin
    prepare_set_result(resultType(getType(function)), c_expr);
    c_expr.result_expr := "setRangelit(";
    getAnyParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= ", ";
    getAnyParamToResultExpr(params[4], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_set_sconv (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "setSConv(";
    getAnyParamToExpr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_set_symdiff (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_set_result(getExprResultType(params[1]), c_expr);
    c_expr.result_expr := "setSymdiff(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getAnyParamToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_set_union (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[1], SETOBJECT, evaluatedParam) and
        getValue(evaluatedParam, bitset) = EMPTY_SET then
      getAnyParamToExpr(params[3], c_expr);
    elsif getConstant(params[3], SETOBJECT, evaluatedParam) and
        getValue(evaluatedParam, bitset) = EMPTY_SET then
      getAnyParamToExpr(params[1], c_expr);
    else
      prepare_set_result(getExprResultType(params[1]), c_expr);
      c_expr.result_expr := "setUnion(";
      getAnyParamToResultExpr(params[1], c_expr);
      c_expr.result_expr &:= ", ";
      getAnyParamToResultExpr(params[3], c_expr);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_set_value (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  begin
    prepare_set_result(resultType(getType(function)), c_expr);
    c_expr.result_expr := "setValue(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_soc_accept (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "socAccept(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", &(";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= "))";
  end func;


const proc: process_soc_addr_family (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "socAddrFamily(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_soc_addr_numeric (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "socAddrNumeric(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_soc_addr_service (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "socAddrService(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_soc_bind (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "socBind(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_soc_close (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "socClose(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_soc_connect (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "socConnect(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_soc_cpy (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    process_expr(params[1], statement);
    statement.expr &:= "=";
    process_expr(params[3], statement);
    statement.expr &:= ";\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_soc_eq (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") == (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_soc_getc (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "socGetc(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", &(";
    process_expr(params[2], c_expr);
    c_expr.expr &:= "))";
  end func;


const proc: process_soc_gets (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "socGets(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= ", &(";
    getStdParamToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= "))";
  end func;


const proc: process_soc_get_addr (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bstri_result(c_expr);
    c_expr.result_expr := "socGetAddr(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_soc_get_hostname (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "socGetHostname()";
  end func;


const proc: process_soc_has_next (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "socHasNext(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_soc_inet_addr (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bstri_result(c_expr);
    c_expr.result_expr := "socInetAddr(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_soc_inet_local_addr (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bstri_result(c_expr);
    c_expr.result_expr := "socInetLocalAddr(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_soc_inet_serv_addr (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_bstri_result(c_expr);
    c_expr.result_expr := "socInetServAddr(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_soc_input_ready (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "socInputReady(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_soc_line_read (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "socLineRead(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", &(";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= "))";
  end func;


const proc: process_soc_listen (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "socListen(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_soc_ne (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") != (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_soc_recv (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "socRecv(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", &(";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= "), ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_soc_send (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "socSend(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_soc_socket (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "socSocket(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_soc_word_read (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "socWordRead(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", &(";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= "))";
  end func;


const proc: process_soc_write (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "socWrite(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_const_inline_str_push (in reference: param1, in char: ch,
    inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
    var string: stri_name is "";
  begin
    if isNormalVariable(param1) then
      stri_name := normalVariable(param1, statement);
    else
      incr(statement.temp_num);
      stri_name := "tmp_" & str(statement.temp_num);
      statement.temp_decls &:= "stritype *";
      statement.temp_decls &:= stri_name;
      statement.temp_decls &:= ";\n";
      statement.expr &:= stri_name;
      statement.expr &:= "=&(";
      process_expr(param1, statement);
      statement.expr &:= ");\n";
      stri_name := "*" & stri_name;
    end if;
    statement.expr &:= "if ((";
    statement.expr &:= stri_name;
    statement.expr &:= ")->size == (";
    statement.expr &:= stri_name;
    statement.expr &:= ")->capacity) {\n";
    statement.expr &:= "strPush(&(";
    statement.expr &:= stri_name;
    statement.expr &:= "), ";
    statement.expr &:= charLiteral(ch);
    statement.expr &:= ");\n";
    statement.expr &:= "} else {\n";
    statement.expr &:= "(";
    statement.expr &:= stri_name;
    statement.expr &:= ")->mem[(";
    statement.expr &:= stri_name;
    statement.expr &:= ")->size]=";
    statement.expr &:= charLiteral(ch);
    statement.expr &:= ";\n";
    statement.expr &:= "(";
    statement.expr &:= stri_name;
    statement.expr &:= ")->size++;\n";
    statement.expr &:= "}\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_const_str_push (in reference: param1, in char: ch,
    inout expr_type: c_expr) is func

  begin
    if inlineFunctions and ccConf.WITH_STRI_CAPACITY then
      process_const_inline_str_push(param1, ch, c_expr);
    else
      c_expr.expr &:= "strPush(&(";
      process_expr(param1, c_expr);
      c_expr.expr &:= "), ";
      c_expr.expr &:= charLiteral(ch);
      c_expr.expr &:= ");\n";
    end if;
  end func;


const proc: process_const_str_append (in reference: param1, in string: stri,
    inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    if stri = "" then
      incr(countOptimizations);
      c_expr.expr &:= "/* append empty string */\n";
    elsif length(stri) = 1 then
      incr(countOptimizations);
      process_const_str_push(param1, stri[1], c_expr);
    else
      c_expr.expr &:= "strAppend(&(";
      process_expr(param1, c_expr);
      c_expr.expr &:= "), ";
      c_expr.expr &:= stringLiteral(stri);
      c_expr.expr &:= ");\n";
    end if;
  end func;


const proc: process_str_append (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var expr_type: c_param1 is expr_type.value;
    var expr_type: c_param3 is expr_type.value;
  begin
    if getConstant(params[3], STRIOBJECT, evaluatedParam) then
      process_const_str_append(params[1], getValue(evaluatedParam, string), c_expr);
    else
      process_expr(params[1], c_param1);
      c_param3.temp_num := c_param1.temp_num;
      if isActionExpression(params[3], "CHR_STR") then
        incr(countOptimizations);
        process_expr(getActionParameter(params[3], 1), c_param3);
      else
        process_expr(params[3], c_param3);
      end if;
      if has_temp_values(c_param3) then
        c_expr.expr &:= "{\n";
        AppendWithDiagnostic(c_param1.temp_decls, c_expr);
        AppendWithDiagnostic(c_param3.temp_decls, c_expr);
        AppendWithDiagnostic(c_param1.temp_assigns, c_expr);
        AppendWithDiagnostic(c_param3.temp_assigns, c_expr);
      end if;
      setDiagnosticLine(c_expr);
      if isActionExpression(params[3], "CHR_STR") then
        c_expr.expr &:= "strPush(&(";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= "), ";
        c_expr.expr &:= c_param3.expr;
      elsif c_param3.result_expr <> "" then
        c_expr.expr &:= "strAppendTemp(&(";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= "), ";
        c_expr.expr &:= c_param3.result_expr;
      else
        c_expr.expr &:= "strAppend(&(";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= "), ";
        c_expr.expr &:= c_param3.expr;
      end if;
      c_expr.expr &:= ");\n";
      if has_temp_values(c_param3) then
        AppendWithDiagnostic(c_param1.temp_frees, c_expr);
        AppendWithDiagnostic(c_param3.temp_frees, c_expr);
        c_expr.expr &:= "}\n";
      end if;
    end if;
  end func;


(**
 *  Produces code for the string concatenation.
 *  When more than two strings are concatenated the function
 *  strConcatN is used. This saves copying and allocation operations.
 *  When the first parameter is a temporary value the concatenation
 *  is done with strConcatTemp. The strConcatTemp function returns
 *  the first parameter as result of the concatenation. That way the
 *  temporary of the first parameter must not be freed.
 *)
const proc: process_str_cat (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: leftParam is NIL;
    var array reference: concatNParamList is 0 times NIL;
    var boolean: concatFound is FALSE;
    var ref_list: subExprParams is ref_list.EMPTY;
    var string: concatNParamName is "";
    var integer: index is 0;
    var expr_type: c_param1 is expr_type.value;
  begin
    prepare_stri_result(c_expr);
    leftParam := params[1];
    concatNParamList := [] (params[3]);
    repeat
      concatFound := FALSE;
      if category(leftParam) = CALLOBJECT then
        subExprParams := getValue(leftParam, ref_list);
        if category(subExprParams[1]) = ACTOBJECT then
          if str(getValue(subExprParams[1], ACTION)) = "STR_CAT" then
            leftParam := subExprParams[2];
            concatNParamList := [] (subExprParams[4]) & concatNParamList;
            concatFound := TRUE;
          end if;
        end if;
      end if;
    until not concatFound;
    concatNParamList := [] (leftParam) & concatNParamList;
    if length(concatNParamList) > 2 then
      incr(c_expr.temp_num);
      concatNParamName := "tmp_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "const_stritype ";
      c_expr.temp_decls &:= concatNParamName;
      c_expr.temp_decls &:= "[";
      c_expr.temp_decls &:= str(length(concatNParamList));
      c_expr.temp_decls &:= "];\n";
      c_expr.result_expr := "(";
      for key index range concatNParamList do
        c_expr.result_expr &:= concatNParamName;
        c_expr.result_expr &:= "[";
        c_expr.result_expr &:= str(pred(index));
        c_expr.result_expr &:= "] = ";
        getAnyParamToResultExpr(concatNParamList[index], c_expr);
        c_expr.result_expr &:= ", ";
      end for;
      c_expr.result_expr &:= "strConcatN(";
      c_expr.result_expr &:= concatNParamName;
      c_expr.result_expr &:= ", ";
      c_expr.result_expr &:= str(length(concatNParamList));
      c_expr.result_expr &:= "))";
    else
      prepareAnyParamTemporarys(params[1], c_param1, c_expr);
      if c_param1.result_expr <> "" then
        c_expr.result_expr := "strConcatTemp(";
        c_expr.result_expr &:= c_param1.result_expr;
      else
        c_expr.result_expr := "strConcat(";
        c_expr.result_expr &:= c_param1.expr;
      end if;
      c_expr.result_expr &:= ", ";
      getAnyParamToResultExpr(params[3], c_expr);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_str_chipos (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "strChIPos(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_str_chpos (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "strChPos(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_str_chsplit (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_typed_result(array_type[getExprResultType(params[1])], c_expr);
    c_expr.result_expr := "strChSplit(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_str_clit (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "strCLit(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_str_cmp (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "strCompare(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_str_cpy (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: c_param1 is expr_type.value;
    var expr_type: c_param3 is expr_type.value;
  begin
    process_expr(params[1], c_param1);
    c_param3.temp_num := c_param1.temp_num;
    process_expr(params[3], c_param3);
    if has_temp_values(c_param3) then
      c_expr.expr &:= "{\n";
      AppendWithDiagnostic(c_param1.temp_decls, c_expr);
      AppendWithDiagnostic(c_param3.temp_decls, c_expr);
      AppendWithDiagnostic(c_param1.temp_assigns, c_expr);
      AppendWithDiagnostic(c_param3.temp_assigns, c_expr);
    end if;
    if c_param3.result_expr <> "" then
      if not has_temp_values(c_param3) then
        c_expr.expr &:= "{\n";
      end if;
      setDiagnosticLine(c_expr);
      if isNormalVariable(params[1]) then
        c_expr.expr &:= "stritype old_stri=";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ";\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= "=";
      else
        c_expr.expr &:= "stritype *stri_ptr=&(";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ");\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "stritype old_stri=*stri_ptr;\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "*stri_ptr=";
      end if;
      c_expr.expr &:= c_param3.result_expr;
      c_expr.expr &:= ";\n";
      setDiagnosticLine(c_expr);
      c_expr.expr &:= "strDestr(old_stri);\n";
      if not has_temp_values(c_param3) then
        c_expr.expr &:= "}\n";
      end if;
    else
      setDiagnosticLine(c_expr);
      c_expr.expr &:= "strCopy(&(";
      c_expr.expr &:= c_param1.expr;
      c_expr.expr &:= "), ";
      c_expr.expr &:= c_param3.expr;
      c_expr.expr &:= ");\n";
    end if;
    if has_temp_values(c_param3) then
      AppendWithDiagnostic(c_param1.temp_frees, c_expr);
      AppendWithDiagnostic(c_param3.temp_frees, c_expr);
      c_expr.expr &:= "}\n";
    end if;
  end func;


const proc: process_const_str_elemcpy (in reference: function, in reference: param1,
    in integer: index, in char: ch, inout expr_type: c_expr) is func

  local
    var expr_type: c_param1 is expr_type.value;
  begin
    incr(countOptimizations);
    if index < 1 then
      c_expr.expr &:= "/* 'string @:= [n] char' with n < 1 */\n";
      process_raise_error("RANGE_ERROR", function, c_expr);
      c_expr.expr &:= ";\n";
    else
      process_expr(param1, c_param1);
      if c_param1.temp_num <> 0 or array_range_check then
        c_expr.expr &:= "{\n";
      end if;
      if c_param1.temp_num <> 0 then
        AppendWithDiagnostic(c_param1.temp_decls, c_expr);
        AppendWithDiagnostic(c_param1.temp_assigns, c_expr);
      end if;
      if array_range_check then
        c_expr.expr &:= "stritype str1=";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ";\n";
        c_expr.expr &:= "if (str1->size<=";
        c_expr.expr &:= str(pred(index));
        c_expr.expr &:= ") {\n";
        c_expr.expr &:= "  ";
        process_raise_error("RANGE_ERROR", function, c_expr);
        c_expr.expr &:= ";\n";
        c_expr.expr &:= "} else {\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "  str1->mem[";
        c_expr.expr &:= str(pred(index));
        c_expr.expr &:= "] = (strelemtype)(";
        c_expr.expr &:= c_literal(ch);
        c_expr.expr &:= ");\n";
        c_expr.expr &:= "}\n";
      else
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "(";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ")->mem[";
        c_expr.expr &:= str(pred(index));
        c_expr.expr &:= "] = (strelemtype)(";
        c_expr.expr &:= c_literal(ch);
        c_expr.expr &:= ");\n";
      end if;
      if c_param1.temp_num <> 0 then
        AppendWithDiagnostic(c_param1.temp_frees, c_expr);
      end if;
      if c_param1.temp_num <> 0 or array_range_check then
        c_expr.expr &:= "}\n";
      end if;
    end if;
  end func;


const proc: process_const_str_elemcpy (in reference: function, in reference: param1,
    in integer: index, in reference: param6, inout expr_type: c_expr) is func

  local
    var expr_type: c_param1 is expr_type.value;
    var expr_type: c_param6 is expr_type.value;
  begin
    incr(countOptimizations);
    if index < 1 then
      c_expr.expr &:= "/* 'string @:= [n] char' with n < 1 */\n";
      process_raise_error("RANGE_ERROR", function, c_expr);
      c_expr.expr &:= ";\n";
    else
      process_expr(param1, c_param1);
      c_param6.temp_num := c_param1.temp_num;
      process_expr(param6, c_param6);
      if c_param6.temp_num <> 0 or array_range_check then
        c_expr.expr &:= "{\n";
      end if;
      if c_param6.temp_num <> 0 then
        AppendWithDiagnostic(c_param1.temp_decls, c_expr);
        AppendWithDiagnostic(c_param6.temp_decls, c_expr);
        AppendWithDiagnostic(c_param1.temp_assigns, c_expr);
        AppendWithDiagnostic(c_param6.temp_assigns, c_expr);
      end if;
      if array_range_check then
        c_expr.expr &:= "stritype str1=";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ";\n";
        c_expr.expr &:= "if (str1->size<=";
        c_expr.expr &:= str(pred(index));
        c_expr.expr &:= ") {\n";
        c_expr.expr &:= "  ";
        process_raise_error("RANGE_ERROR", function, c_expr);
        c_expr.expr &:= ";\n";
        c_expr.expr &:= "} else {\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "  str1->mem[";
        c_expr.expr &:= str(pred(index));
        c_expr.expr &:= "] = (strelemtype)(";
        c_expr.expr &:= c_param6.expr;
        c_expr.expr &:= ");\n";
        c_expr.expr &:= "}\n";
      else
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "(";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ")->mem[";
        c_expr.expr &:= str(pred(index));
        c_expr.expr &:= "] = (strelemtype)(";
        c_expr.expr &:= c_param6.expr;
        c_expr.expr &:= ");\n";
      end if;
      if c_param6.temp_num <> 0 then
        AppendWithDiagnostic(c_param1.temp_frees, c_expr);
        AppendWithDiagnostic(c_param6.temp_frees, c_expr);
      end if;
      if c_param6.temp_num <> 0 or array_range_check then
        c_expr.expr &:= "}\n";
      end if;
    end if;
  end func;


const proc: process_const_str_elemcpy (in reference: function, in reference: param1,
    in reference: param4, in char: ch, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var expr_type: c_param1 is expr_type.value;
    var expr_type: c_param4 is expr_type.value;
  begin
    if getConstant(param4, INTOBJECT, evaluatedParam) then
      process_const_str_elemcpy(function, param1, getValue(evaluatedParam, integer), ch, c_expr);
    else
      process_expr(param1, c_param1);
      c_param4.temp_num := c_param1.temp_num;
      process_expr(param4, c_param4);
      if c_param4.temp_num <> 0 or array_range_check then
        c_expr.expr &:= "{\n";
      end if;
      if c_param4.temp_num <> 0 then
        AppendWithDiagnostic(c_param1.temp_decls, c_expr);
        AppendWithDiagnostic(c_param4.temp_decls, c_expr);
        AppendWithDiagnostic(c_param1.temp_assigns, c_expr);
        AppendWithDiagnostic(c_param4.temp_assigns, c_expr);
      end if;
      if array_range_check then
        c_expr.expr &:= "stritype str1=";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ";\n";
        if ccConf.TWOS_COMPLEMENT_INTTYPE then
          c_expr.expr &:= "uinttype pos=(uinttype)(";
        else
          c_expr.expr &:= "inttype pos=(";
        end if;
        c_expr.expr &:= c_param4.expr;
        c_expr.expr &:= ")-1;\n";
        c_expr.expr &:= "if (";
        if not ccConf.TWOS_COMPLEMENT_INTTYPE then
          c_expr.expr &:= "pos<0 || ";
        end if;
        c_expr.expr &:= "pos>=str1->size) {\n";
        c_expr.expr &:= "  ";
        process_raise_error("RANGE_ERROR", function, c_expr);
        c_expr.expr &:= ";\n";
        c_expr.expr &:= "} else {\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "  str1->mem[pos] = (strelemtype)(";
        c_expr.expr &:= c_literal(ch);
        c_expr.expr &:= ");\n";
        c_expr.expr &:= "}\n";
      else
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "(";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ")->mem[(";
        c_expr.expr &:= c_param4.expr;
        c_expr.expr &:= ")-1] = (strelemtype)(";
        c_expr.expr &:= c_literal(ch);
        c_expr.expr &:= ");\n";
      end if;
      if c_param4.temp_num <> 0 then
        AppendWithDiagnostic(c_param1.temp_frees, c_expr);
        AppendWithDiagnostic(c_param4.temp_frees, c_expr);
      end if;
      if c_param4.temp_num <> 0 or array_range_check then
        c_expr.expr &:= "}\n";
      end if;
    end if;
  end func;


const proc: process_str_elemcpy (in reference: function, in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var expr_type: c_param1 is expr_type.value;
    var expr_type: c_param4 is expr_type.value;
    var expr_type: c_param6 is expr_type.value;
  begin
    if getConstant(params[6], CHAROBJECT, evaluatedParam) then
      process_const_str_elemcpy(function, params[1], params[4], getValue(evaluatedParam, char), c_expr);
    elsif getConstant(params[4], INTOBJECT, evaluatedParam) then
      process_const_str_elemcpy(function, params[1], getValue(evaluatedParam, integer), params[6], c_expr);
    else
      process_expr(params[1], c_param1);
      c_param4.temp_num := c_param1.temp_num;
      process_expr(params[4], c_param4);
      c_param6.temp_num := c_param4.temp_num;
      process_expr(params[6], c_param6);
      if c_param6.temp_num <> 0 or array_range_check then
        c_expr.expr &:= "{\n";
      end if;
      if c_param6.temp_num <> 0 then
        AppendWithDiagnostic(c_param1.temp_decls, c_expr);
        AppendWithDiagnostic(c_param4.temp_decls, c_expr);
        AppendWithDiagnostic(c_param6.temp_decls, c_expr);
        AppendWithDiagnostic(c_param1.temp_assigns, c_expr);
        AppendWithDiagnostic(c_param4.temp_assigns, c_expr);
        AppendWithDiagnostic(c_param6.temp_assigns, c_expr);
      end if;
      if array_range_check then
        c_expr.expr &:= "stritype str1=";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ";\n";
        if ccConf.TWOS_COMPLEMENT_INTTYPE then
          c_expr.expr &:= "uinttype pos=(uinttype)(";
        else
          c_expr.expr &:= "inttype pos=(";
        end if;
        c_expr.expr &:= c_param4.expr;
        c_expr.expr &:= ")-1;\n";
        c_expr.expr &:= "if (";
        if not ccConf.TWOS_COMPLEMENT_INTTYPE then
          c_expr.expr &:= "pos<0 || ";
        end if;
        c_expr.expr &:= "pos>=str1->size) {\n";
        c_expr.expr &:= "  ";
        process_raise_error("RANGE_ERROR", function, c_expr);
        c_expr.expr &:= ";\n";
        c_expr.expr &:= "} else {\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "  str1->mem[pos] = (strelemtype)(";
        c_expr.expr &:= c_param6.expr;
        c_expr.expr &:= ");\n";
        c_expr.expr &:= "}\n";
      else
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "(";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ")->mem[(";
        c_expr.expr &:= c_param4.expr;
        c_expr.expr &:= ")-1] = (strelemtype)(";
        c_expr.expr &:= c_param6.expr;
        c_expr.expr &:= ");\n";
      end if;
      if c_param6.temp_num <> 0 then
        AppendWithDiagnostic(c_param1.temp_frees, c_expr);
        AppendWithDiagnostic(c_param4.temp_frees, c_expr);
        AppendWithDiagnostic(c_param6.temp_frees, c_expr);
      end if;
      if c_param6.temp_num <> 0 or array_range_check then
        c_expr.expr &:= "}\n";
      end if;
    end if;
  end func;


const proc: process_const_str_eq (in reference: param1, in string: stri_b,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: stri_a_name is "";
  begin
    incr(countOptimizations);
    if getConstant(param1, STRIOBJECT, evaluatedParam) then
      c_expr.expr &:= "/* ";
      c_expr.expr &:= replace(literal(getValue(evaluatedParam, string)), "*/", "*\\/");
      c_expr.expr &:= " == ";
      c_expr.expr &:= replace(literal(stri_b), "*/", "*\\/");
      c_expr.expr &:= " */ ";
      if getValue(evaluatedParam, string) = stri_b then
        c_expr.expr &:= "1";
      else
        c_expr.expr &:= "0";
      end if;
    elsif stri_b = "" then
      c_expr.expr &:= "((";
      getAnyParamToExpr(param1, c_expr);
      c_expr.expr &:= ")->size==0 /* \"\" */)";
    else
      c_expr.expr &:= "(";
      stri_a_name := getParameterAsVariable("const_stritype", "tmp_", param1, c_expr);
      if length(stri_b) = 1 then
        (* Formula used: (a->size==1&&a->mem[0]==b->mem[0]) *)
        c_expr.expr &:= stri_a_name;
        c_expr.expr &:= "->size==1&&";
        c_expr.expr &:= stri_a_name;
        c_expr.expr &:= "->mem[0]==(strelemtype)(";
        c_expr.expr &:= c_literal(stri_b[1]);
        c_expr.expr &:= ") /* ";
        c_expr.expr &:= literal(stri_b);
        c_expr.expr &:= " */)";
      else
        (* Formula used: (a->size==b->size&&memcmp(a->mem,b->mem,
                         b->size*sizeof(strelemtype))==0) *)
        c_expr.expr &:= stri_a_name;
        c_expr.expr &:= "->size==";
        c_expr.expr &:= str(length(stri_b));
        c_expr.expr &:= "&&memcmp(";
        c_expr.expr &:= stri_a_name;
        c_expr.expr &:= "->mem,(";
        c_expr.expr &:= stringLiteral(stri_b);
        c_expr.expr &:= ")->mem,";
        c_expr.expr &:= str(length(stri_b));
        c_expr.expr &:= "*sizeof(strelemtype))==0)";
      end if;
    end if;
  end func;


const proc: process_str_eq (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: stri_a_name is "";
    var string: stri_b_name is "";
  begin
    if getConstant(params[3], STRIOBJECT, evaluatedParam) then
      process_const_str_eq(params[1], getValue(evaluatedParam, string), c_expr);
    elsif getConstant(params[1], STRIOBJECT, evaluatedParam) then
      process_const_str_eq(params[3], getValue(evaluatedParam, string), c_expr);
    else
      c_expr.expr &:= "(";
      stri_a_name := getParameterAsVariable("const_stritype", "tmp_a_", params[1], c_expr);
      stri_b_name := getParameterAsVariable("const_stritype", "tmp_b_", params[3], c_expr);
      (* Formula used: (a->size==b->size&&memcmp(a->mem,b->mem,
                       a->size*sizeof(strelemtype))==0) *)
      c_expr.expr &:= stri_a_name;
      c_expr.expr &:= "->size==";
      c_expr.expr &:= stri_b_name;
      c_expr.expr &:= "->size&&memcmp(";
      c_expr.expr &:= stri_a_name;
      c_expr.expr &:= "->mem,";
      c_expr.expr &:= stri_b_name;
      c_expr.expr &:= "->mem,";
      c_expr.expr &:= stri_a_name;
      c_expr.expr &:= "->size*sizeof(strelemtype))==0)";
    end if;
  end func;


const proc: process_str_ge (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "strGe(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_str_gt (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "strGt(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_str_hashcode (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: stri_name is "";
  begin
    if getConstant(params[1], STRIOBJECT, evaluatedParam) then
      incr(countOptimizations);
      c_expr.expr &:= integerLiteral(hashCode(getValue(evaluatedParam, string)));
    elsif inlineFunctions then
      c_expr.expr &:= "(";
      stri_name := getParameterAsVariable("const_stritype", "tmp_", params[1], c_expr);
      c_expr.expr &:= stri_name;
      c_expr.expr &:= "->size==0 ? 0 : (";
      c_expr.expr &:= stri_name;
      c_expr.expr &:= "->mem[0]<<5 ^ ";
      c_expr.expr &:= stri_name;
      c_expr.expr &:= "->mem[";
      c_expr.expr &:= stri_name;
      c_expr.expr &:= "->size>>1]<<3 ^ ";
      c_expr.expr &:= stri_name;
      c_expr.expr &:= "->mem[";
      c_expr.expr &:= stri_name;
      c_expr.expr &:= "->size-1]<<1 ^ ";
      c_expr.expr &:= stri_name;
      c_expr.expr &:= "->size))";
    else
      c_expr.expr &:= "strHashCode(";
      getAnyParamToExpr(params[1], c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_const_str_head (in string: stri, in reference: param4,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var integer: stop is 0;
    var string: slice_name is "";
  begin
    if getConstant(param4, INTOBJECT, evaluatedParam) then
      incr(countOptimizations);
      c_expr.expr &:= stringLiteral(stri[ .. getValue(evaluatedParam, integer)]);
    elsif stri = "" then
      incr(countOptimizations);
      c_expr.expr &:= "/* \"\"[ .. n] */ (";
      # The index expression could have a side effect or raise an exception
      process_expr(param4, c_expr);
      c_expr.expr &:= ",";
      c_expr.expr &:= stringLiteral("");
      c_expr.expr &:= ")";
    elsif length(stri) = 1 then
      incr(countOptimizations);
      c_expr.expr &:= "((";
      process_expr(param4, c_expr);
      c_expr.expr &:= ")>=1?";
      c_expr.expr &:= stringLiteral(stri);
      c_expr.expr &:= ":";
      c_expr.expr &:= stringLiteral("");
      c_expr.expr &:= ")";
    elsif ccConf.ALLOW_STRITYPE_SLICES then
      incr(c_expr.temp_num);
      slice_name := "slice_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "struct stristruct ";
      c_expr.temp_decls &:= slice_name;
      c_expr.temp_decls &:= ";\n";
      c_expr.expr &:= "(strHeadSlice(";
      c_expr.expr &:= stringLiteral(stri);
      c_expr.expr &:= ", ";
      process_expr(param4, c_expr);
      c_expr.expr &:= ", &";
      c_expr.expr &:= slice_name;
      c_expr.expr &:= "), &";
      c_expr.expr &:= slice_name;
      c_expr.expr &:= ")";
    else
      prepare_stri_result(c_expr);
      c_expr.result_expr := "strHead(";
      c_expr.result_expr &:= stringLiteral(stri);
      c_expr.result_expr &:= ", ";
      getStdParamToResultExpr(param4, c_expr);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_const_str_head1 (in reference: param1,
    inout expr_type: c_expr) is func

  local
    var string: temp_name is "";
    var string: stri1_name is "";
  begin
    incr(countOptimizations);
    c_expr.expr &:= "(";
    temp_name := getParameterAsVariable("const_stritype", "tmp_", param1, c_expr);
    incr(c_expr.temp_num);
    stri1_name := "stri1_" & str(c_expr.temp_num);
    c_expr.temp_decls &:= "struct stristruct ";
    c_expr.temp_decls &:= stri1_name;
    c_expr.temp_decls &:= ";\n";
    c_expr.expr &:= temp_name;
    c_expr.expr &:= "->size>=1?chrStrMacro(";
    c_expr.expr &:= temp_name;
    c_expr.expr &:= "->mem[0],";
    c_expr.expr &:= stri1_name;
    c_expr.expr &:= "):";
    c_expr.expr &:= stringLiteral("");
    c_expr.expr &:= ")";
  end func;


const proc: process_str_head (in reference: param1, in reference: param4,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var expr_type: c_param1 is expr_type.value;
    var string: slice_name is "";
  begin
    if getConstant(param1, STRIOBJECT, evaluatedParam) then
      process_const_str_head(getValue(evaluatedParam, string), param4, c_expr);
    elsif getConstant(param4, INTOBJECT, evaluatedParam) and
        getValue(evaluatedParam, integer) = 1 then
      process_const_str_head1(param1, c_expr);
    else
      prepareAnyParamTemporarys(param1, c_param1, c_expr);
      if c_param1.result_expr <> "" then
        prepare_stri_result(c_expr);
        c_expr.result_expr := "strHeadTemp(";
        c_expr.result_expr &:= c_param1.result_expr;
        c_expr.result_expr &:= ", ";
        getStdParamToResultExpr(param4, c_expr);
        c_expr.result_expr &:= ")";
      elsif ccConf.ALLOW_STRITYPE_SLICES then
        incr(c_expr.temp_num);
        slice_name := "slice_" & str(c_expr.temp_num);
        c_expr.temp_decls &:= "struct stristruct ";
        c_expr.temp_decls &:= slice_name;
        c_expr.temp_decls &:= ";\n";
        c_expr.expr &:= "(strHeadSlice(";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ", ";
        process_expr(param4, c_expr);
        c_expr.expr &:= ", &";
        c_expr.expr &:= slice_name;
        c_expr.expr &:= "), &";
        c_expr.expr &:= slice_name;
        c_expr.expr &:= ")";
      else
        prepare_stri_result(c_expr);
        c_expr.result_expr := "strHead(";
        c_expr.result_expr &:= c_param1.expr;
        c_expr.result_expr &:= ", ";
        getStdParamToResultExpr(param4, c_expr);
        c_expr.result_expr &:= ")";
      end if;
    end if;
  end func;


const proc: process_str_head (in ref_list: params, inout expr_type: c_expr) is func

  begin
    process_str_head(params[1], params[4], c_expr);
  end func;


const proc: process_const_str_idx (in reference: function, in string: stri,
    in reference: param3, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var integer: index is 0;
    var string: index_name is "";
  begin
    incr(countOptimizations);
    if getConstant(param3, INTOBJECT, evaluatedParam) then
      index := getValue(evaluatedParam, integer);
      if index < 1 or index > length(stri) then
        process_raise_error("RANGE_ERROR", function, c_expr);
      else
        c_expr.expr &:= charLiteral(stri[index]);
      end if;
    else
      c_expr.expr &:= "(";
      c_expr.expr &:= stringLiteral(stri);
      c_expr.expr &:= ")->mem[";
      if array_range_check then
        incr(c_expr.temp_num);
        index_name := "idx_" & str(c_expr.temp_num);
        if ccConf.TWOS_COMPLEMENT_INTTYPE then
          c_expr.temp_decls &:= "uinttype ";
        else
          c_expr.temp_decls &:= "inttype ";
        end if;
        c_expr.temp_decls &:= index_name;
        c_expr.temp_decls &:= ";\n";
        c_expr.expr &:= "(";
        c_expr.expr &:= index_name;
        c_expr.expr &:= "=";
        if ccConf.TWOS_COMPLEMENT_INTTYPE then
          c_expr.expr &:= "(uinttype)((";
          process_expr(param3, c_expr);
          c_expr.expr &:= ")-1), ";
        else
          c_expr.expr &:= "(";
          process_expr(param3, c_expr);
          c_expr.expr &:= ")-1, ";
          c_expr.expr &:= index_name;
          c_expr.expr &:= "<0 || ";
        end if;
        c_expr.expr &:= index_name;
        c_expr.expr &:= ">=";
        c_expr.expr &:= str(length(stri));
        c_expr.expr &:= " ? ";
        process_raise_error("RANGE_ERROR", function, c_expr);
        c_expr.expr &:= " : 0, ";
        c_expr.expr &:= index_name;
        c_expr.expr &:= ")";
      else
        c_expr.expr &:= "(";
        process_expr(param3, c_expr);
        c_expr.expr &:= ")-1";
      end if;
      c_expr.expr &:= "]";
    end if;
  end func;


const proc: process_const_str_idx (in reference: function, in reference: param1,
    in integer: index, inout expr_type: c_expr) is func

  local
    var string: stri_name is "";
  begin
    incr(countOptimizations);
    if index < 1 then
      process_raise_error("RANGE_ERROR", function, c_expr);
    elsif array_range_check then
      if isNormalVariable(param1) then
        stri_name := normalVariable(param1, c_expr);
      else
        incr(c_expr.temp_num);
        stri_name := "tmp_" & str(c_expr.temp_num);
        c_expr.temp_decls &:= "const_stritype ";
        c_expr.temp_decls &:= stri_name;
        c_expr.temp_decls &:= ";\n";
        c_expr.expr &:= "(*(";
        c_expr.expr &:= stri_name;
        c_expr.expr &:= "=";
        getAnyParamToExpr(param1, c_expr);
        c_expr.expr &:= ", &";
      end if;
      c_expr.expr &:= stri_name;
      c_expr.expr &:= "->mem[(";
      c_expr.expr &:= stri_name;
      c_expr.expr &:= "->size<";
      c_expr.expr &:= str(index);
      c_expr.expr &:= " ? ";
      process_raise_error("RANGE_ERROR", function, c_expr);
      c_expr.expr &:= " : 0, ";
      c_expr.expr &:= str(pred(index));
      c_expr.expr &:= ")]";
      if not isNormalVariable(param1) then
        c_expr.expr &:= "))";
      end if;
    else
      c_expr.expr &:= "(";
      getAnyParamToExpr(param1, c_expr);
      c_expr.expr &:= ")->mem[";
      c_expr.expr &:= str(pred(index));
      c_expr.expr &:= "]";
    end if;
  end func;


const proc: process_str_idx (in reference: function, in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: stri_name is "";
    var string: index_name is "";
  begin
    if getConstant(params[1], STRIOBJECT, evaluatedParam) then
      process_const_str_idx(function, getValue(evaluatedParam, string), params[3], c_expr);
    elsif getConstant(params[3], INTOBJECT, evaluatedParam) then
      process_const_str_idx(function, params[1], getValue(evaluatedParam, integer), c_expr);
    elsif array_range_check then
      incr(c_expr.temp_num);
      index_name := "idx_" & str(c_expr.temp_num);
      if ccConf.TWOS_COMPLEMENT_INTTYPE then
        c_expr.temp_decls &:= "uinttype ";
      else
        c_expr.temp_decls &:= "inttype ";
      end if;
      c_expr.temp_decls &:= index_name;
      c_expr.temp_decls &:= ";\n";
      if isNormalVariable(params[1]) then
        stri_name := normalVariable(params[1], c_expr);
      else
        stri_name := "tmp_" & str(c_expr.temp_num);
        c_expr.temp_decls &:= "const_stritype ";
        c_expr.temp_decls &:= stri_name;
        c_expr.temp_decls &:= ";\n";
        c_expr.expr &:= "(*(";
        c_expr.expr &:= stri_name;
        c_expr.expr &:= "=";
        getAnyParamToExpr(params[1], c_expr);
        c_expr.expr &:= ", &";
      end if;
      c_expr.expr &:= stri_name;
      c_expr.expr &:= "->mem[(";
      c_expr.expr &:= index_name;
      c_expr.expr &:= "=";
      if ccConf.TWOS_COMPLEMENT_INTTYPE then
        c_expr.expr &:= "(uinttype)((";
        process_expr(params[3], c_expr);
        c_expr.expr &:= ")-1), ";
      else
        c_expr.expr &:= "(";
        process_expr(params[3], c_expr);
        c_expr.expr &:= ")-1, ";
        c_expr.expr &:= index_name;
        c_expr.expr &:= "<0 || ";
      end if;
      c_expr.expr &:= index_name;
      c_expr.expr &:= ">=";
      c_expr.expr &:= stri_name;
      c_expr.expr &:= "->size ? ";
      process_raise_error("RANGE_ERROR", function, c_expr);
      c_expr.expr &:= " : 0, ";
      c_expr.expr &:= index_name;
      c_expr.expr &:= ")]";
      if not isNormalVariable(params[1]) then
        c_expr.expr &:= "))";
      end if;
    else
      c_expr.expr &:= "(";
      getAnyParamToExpr(params[1], c_expr);
      c_expr.expr &:= ")->mem[(";
      process_expr(params[3], c_expr);
      c_expr.expr &:= ")-1]";
    end if;
  end func;


const proc: process_str_ipos (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[2], STRIOBJECT, evaluatedParam) and
        length(getValue(evaluatedParam, string)) = 1 then
      incr(countOptimizations);
      c_expr.expr &:= "strChIPos(";
      getAnyParamToExpr(params[1], c_expr);
      c_expr.expr &:= ", ";
      c_expr.expr &:= charLiteral(getValue(evaluatedParam, string)[1]);
      c_expr.expr &:= ", ";
      process_expr(params[3], c_expr);
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= "strIPos(";
      getAnyParamToExpr(params[1], c_expr);
      c_expr.expr &:= ", ";
      getAnyParamToExpr(params[2], c_expr);
      c_expr.expr &:= ", ";
      process_expr(params[3], c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_str_le (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "strLe(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_str_lit (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "strLit(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_str_lng (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: stri is "";
  begin
    if getConstant(params[1], STRIOBJECT, evaluatedParam) then
      incr(countOptimizations);
      stri := getValue(evaluatedParam, string);
      c_expr.expr &:= str(length(stri));
      c_expr.expr &:= " /* length(";
      c_expr.expr &:= replace(literal(stri), "*/", "*\\/");
      c_expr.expr &:= ") */";
    else
      c_expr.expr &:= "(inttype)((";
      getAnyParamToExpr(params[1], c_expr);
      c_expr.expr &:= ")->size)";
    end if;
  end func;


(**
 *  Produces code to return a string converted to lower case.
 *  When the parameter is a temporary value the conversion is done
 *  with strLowTemp. The strLowTemp function returns the parameter as
 *  result of the conversion. That way the temporary of the parameter
 *  must not be freed.
 *)
const proc: process_str_low (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: c_param1 is expr_type.value;
  begin
    prepare_stri_result(c_expr);
    prepareAnyParamTemporarys(params[1], c_param1, c_expr);
    if c_param1.result_expr <> "" then
      c_expr.result_expr := "strLowTemp(";
      c_expr.result_expr &:= c_param1.result_expr;
    else
      c_expr.result_expr := "strLow(";
      c_expr.result_expr &:= c_param1.expr;
    end if;
    c_expr.result_expr &:= ")";
  end func;


(**
 *  Produces code for the lpad operator.
 *  When the first parameter is a temporary value the operation
 *  is done with strLpadTemp. The strLpadTemp function returns
 *  the first parameter as result of the operation. That way the
 *  temporary of the first parameter must not be freed.
 *)
const proc: process_str_lpad (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: c_param1 is expr_type.value;
  begin
    prepare_stri_result(c_expr);
    prepareAnyParamTemporarys(params[1], c_param1, c_expr);
    if c_param1.result_expr <> "" then
      c_expr.result_expr := "strLpadTemp(";
      c_expr.result_expr &:= c_param1.result_expr;
    else
      c_expr.result_expr := "strLpad(";
      c_expr.result_expr &:= c_param1.expr;
    end if;
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= ")";
  end func;


(**
 *  Produces code for the lpad0 operator.
 *  When the first parameter is a temporary value the operation
 *  is done with strLpad0Temp. The strLpad0Temp function returns
 *  the first parameter as result of the operation. That way the
 *  temporary of the first parameter must not be freed.
 *)
const proc: process_str_lpad0 (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: c_param1 is expr_type.value;
  begin
    prepare_stri_result(c_expr);
    prepareAnyParamTemporarys(params[1], c_param1, c_expr);
    if c_param1.result_expr <> "" then
      c_expr.result_expr := "strLpad0Temp(";
      c_expr.result_expr &:= c_param1.result_expr;
    else
      c_expr.result_expr := "strLpad0(";
      c_expr.result_expr &:= c_param1.expr;
    end if;
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_str_lt (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "strLt(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_str_ltrim (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "strLtrim(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_str_mult (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    prepare_stri_result(c_expr);
    if getConstant(params[1], STRIOBJECT, evaluatedParam) and
        length(getValue(evaluatedParam, string)) = 1 then
      c_expr.result_expr := "strChMult(";
      c_expr.result_expr &:= charLiteral(getValue(evaluatedParam, string)[1]);
    else
      c_expr.result_expr := "strMult(";
      getAnyParamToResultExpr(params[1], c_expr);
    end if;
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_const_str_ne (in reference: param1, in string: stri_b,
    inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: stri_a_name is "";
  begin
    incr(countOptimizations);
    if getConstant(param1, STRIOBJECT, evaluatedParam) then
      c_expr.expr &:= "/* ";
      c_expr.expr &:= replace(literal(getValue(evaluatedParam, string)), "*/", "*\\/");
      c_expr.expr &:= " != ";
      c_expr.expr &:= replace(literal(stri_b), "*/", "*\\/");
      c_expr.expr &:= " */ ";
      if getValue(evaluatedParam, string) <> stri_b then
        c_expr.expr &:= "1";
      else
        c_expr.expr &:= "0";
      end if;
    elsif stri_b = "" then
      c_expr.expr &:= "((";
      getAnyParamToExpr(param1, c_expr);
      c_expr.expr &:= ")->size!=0 /* \"\" */)";
    else
      c_expr.expr &:= "(";
      stri_a_name := getParameterAsVariable("const_stritype", "tmp_", param1, c_expr);
      if length(stri_b) = 1 then
        (* Formula used: (a->size!=1||a->mem[0]!=b->mem[0]) *)
        c_expr.expr &:= stri_a_name;
        c_expr.expr &:= "->size!=1||";
        c_expr.expr &:= stri_a_name;
        c_expr.expr &:= "->mem[0]!=(strelemtype)(";
        c_expr.expr &:= c_literal(stri_b[1]);
        c_expr.expr &:= ") /* ";
        c_expr.expr &:= literal(stri_b);
        c_expr.expr &:= " */)";
      else
        (* Formula used: (a->size!=b->size||memcmp(a->mem,b->mem,
                         b->size*sizeof(strelemtype))!=0) *)
        c_expr.expr &:= stri_a_name;
        c_expr.expr &:= "->size!=";
        c_expr.expr &:= str(length(stri_b));
        c_expr.expr &:= "||memcmp(";
        c_expr.expr &:= stri_a_name;
        c_expr.expr &:= "->mem,(";
        c_expr.expr &:= stringLiteral(stri_b);
        c_expr.expr &:= ")->mem,";
        c_expr.expr &:= str(length(stri_b));
        c_expr.expr &:= "*sizeof(strelemtype))!=0)";
      end if;
    end if;
  end func;


const proc: process_str_ne (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: stri_a_name is "";
    var string: stri_b_name is "";
  begin
    if getConstant(params[3], STRIOBJECT, evaluatedParam) then
      process_const_str_ne(params[1], getValue(evaluatedParam, string), c_expr);
    elsif getConstant(params[1], STRIOBJECT, evaluatedParam) then
      process_const_str_ne(params[3], getValue(evaluatedParam, string), c_expr);
    else
      c_expr.expr &:= "(";
      stri_a_name := getParameterAsVariable("const_stritype", "tmp_a_", params[1], c_expr);
      stri_b_name := getParameterAsVariable("const_stritype", "tmp_b_", params[3], c_expr);
      (* Formula used: (a->size!=b->size||memcmp(a->mem,b->mem,
                       a->size*sizeof(strelemtype))!=0) *)
      c_expr.expr &:= stri_a_name;
      c_expr.expr &:= "->size!=";
      c_expr.expr &:= stri_b_name;
      c_expr.expr &:= "->size||memcmp(";
      c_expr.expr &:= stri_a_name;
      c_expr.expr &:= "->mem,";
      c_expr.expr &:= stri_b_name;
      c_expr.expr &:= "->mem,";
      c_expr.expr &:= stri_a_name;
      c_expr.expr &:= "->size*sizeof(strelemtype))!=0)";
    end if;
  end func;


const proc: process_str_pos (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[2], STRIOBJECT, evaluatedParam) and
        length(getValue(evaluatedParam, string)) = 1 then
      incr(countOptimizations);
      c_expr.expr &:= "strChPos(";
      getAnyParamToExpr(params[1], c_expr);
      c_expr.expr &:= ", ";
      c_expr.expr &:= charLiteral(getValue(evaluatedParam, string)[1]);
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= "strPos(";
      getAnyParamToExpr(params[1], c_expr);
      c_expr.expr &:= ", ";
      getAnyParamToExpr(params[2], c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_const_str_poscpy (in reference: function, in reference: param1,
    in integer: index, in reference: param6, inout expr_type: c_expr) is func

  local
    var expr_type: c_param1 is expr_type.value;
    var expr_type: c_param6 is expr_type.value;
  begin
    incr(countOptimizations);
    if index < 1 then
      c_expr.expr &:= "/* 'string @:= [n] string' with n < 1 */\n";
      process_raise_error("RANGE_ERROR", function, c_expr);
      c_expr.expr &:= ";\n";
    else
      process_expr(param1, c_param1);
      c_param6.temp_num := c_param1.temp_num;
      getAnyParamToExpr(param6, c_param6);
      c_expr.expr &:= "{\n";
      if c_param6.temp_num <> 0 then
        AppendWithDiagnostic(c_param1.temp_decls, c_expr);
        AppendWithDiagnostic(c_param6.temp_decls, c_expr);
        AppendWithDiagnostic(c_param1.temp_assigns, c_expr);
        AppendWithDiagnostic(c_param6.temp_assigns, c_expr);
      end if;
      if array_range_check then
        c_expr.expr &:= "stritype str1=";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ";\n";
        c_expr.expr &:= "stritype str2=";
        c_expr.expr &:= c_param6.expr;
        c_expr.expr &:= ";\n";
        c_expr.expr &:= "if (str1->size<str2->size || ";
        c_expr.expr &:= str(pred(index));
        c_expr.expr &:= "+str2->size>str1->size) {\n";
        c_expr.expr &:= "  ";
        process_raise_error("RANGE_ERROR", function, c_expr);
        c_expr.expr &:= ";\n";
        c_expr.expr &:= "} else {\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "  memmove(&str1->mem[";
        c_expr.expr &:= str(pred(index));
        c_expr.expr &:= "], str2->mem, str2->size*sizeof(strelemtype));\n";
        c_expr.expr &:= "}\n";
      else
        c_expr.expr &:= "stritype str2=";
        c_expr.expr &:= c_param6.expr;
        c_expr.expr &:= ";\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "memmove(&(";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ")->mem[";
        c_expr.expr &:= str(pred(index));
        c_expr.expr &:= "], str2->mem, str2->size*sizeof(strelemtype));\n";
      end if;
      if c_param6.temp_num <> 0 then
        AppendWithDiagnostic(c_param1.temp_frees, c_expr);
        AppendWithDiagnostic(c_param6.temp_frees, c_expr);
      end if;
      c_expr.expr &:= "}\n";
    end if;
  end func;


const proc: process_str_poscpy (in reference: function, in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var expr_type: c_param1 is expr_type.value;
    var expr_type: c_param4 is expr_type.value;
    var expr_type: c_param6 is expr_type.value;
  begin
    if getConstant(params[6], STRIOBJECT, evaluatedParam) and
        length(getValue(evaluatedParam, string)) = 1 then
      process_const_str_elemcpy(function, params[1], params[4], getValue(evaluatedParam, string)[1], c_expr);
    elsif getConstant(params[4], INTOBJECT, evaluatedParam) then
      process_const_str_poscpy(function, params[1], getValue(evaluatedParam, integer), params[6], c_expr);
    else
      process_expr(params[1], c_param1);
      c_param4.temp_num := c_param1.temp_num;
      process_expr(params[4], c_param4);
      c_param6.temp_num := c_param4.temp_num;
      getAnyParamToExpr(params[6], c_param6);
      c_expr.expr &:= "{\n";
      if c_param6.temp_num <> 0 then
        AppendWithDiagnostic(c_param1.temp_decls, c_expr);
        AppendWithDiagnostic(c_param4.temp_decls, c_expr);
        AppendWithDiagnostic(c_param6.temp_decls, c_expr);
        AppendWithDiagnostic(c_param1.temp_assigns, c_expr);
        AppendWithDiagnostic(c_param4.temp_assigns, c_expr);
        AppendWithDiagnostic(c_param6.temp_assigns, c_expr);
      end if;
      if array_range_check then
        c_expr.expr &:= "stritype str1=";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ";\n";
        c_expr.expr &:= "stritype str2=";
        c_expr.expr &:= c_param6.expr;
        c_expr.expr &:= ";\n";
        if ccConf.TWOS_COMPLEMENT_INTTYPE then
          c_expr.expr &:= "uinttype pos=(uinttype)(";
        else
          c_expr.expr &:= "inttype pos=(";
        end if;
        c_expr.expr &:= c_param4.expr;
        c_expr.expr &:= ")-1;\n";
        c_expr.expr &:= "if (";
        if not ccConf.TWOS_COMPLEMENT_INTTYPE then
          c_expr.expr &:= "pos<0 || ";
        end if;
        c_expr.expr &:= "str1->size<str2->size || pos+str2->size>str1->size) {\n";
        c_expr.expr &:= "  ";
        process_raise_error("RANGE_ERROR", function, c_expr);
        c_expr.expr &:= ";\n";
        c_expr.expr &:= "} else {\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "  memmove(&str1->mem[pos], str2->mem, str2->size*sizeof(strelemtype));\n";
        c_expr.expr &:= "}\n";
      else
        c_expr.expr &:= "stritype str2=";
        c_expr.expr &:= c_param6.expr;
        c_expr.expr &:= ";\n";
        setDiagnosticLine(c_expr);
        c_expr.expr &:= "memmove(&(";
        c_expr.expr &:= c_param1.expr;
        c_expr.expr &:= ")->mem[(";
        c_expr.expr &:= c_param4.expr;
        c_expr.expr &:= ")-1], str2->mem, str2->size*sizeof(strelemtype));\n";
      end if;
      if c_param6.temp_num <> 0 then
        AppendWithDiagnostic(c_param1.temp_frees, c_expr);
        AppendWithDiagnostic(c_param4.temp_frees, c_expr);
        AppendWithDiagnostic(c_param6.temp_frees, c_expr);
      end if;
      c_expr.expr &:= "}\n";
    end if;
  end func;


const proc: process_inline_str_push (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
    var string: stri_name is "";
    var string: char_name is "";
  begin
    if isNormalVariable(params[1]) then
      stri_name := normalVariable(params[1], statement);
    else
      incr(statement.temp_num);
      stri_name := "tmp_" & str(statement.temp_num);
      statement.temp_decls &:= "stritype *";
      statement.temp_decls &:= stri_name;
      statement.temp_decls &:= ";\n";
      statement.expr &:= stri_name;
      statement.expr &:= "=&(";
      process_expr(params[1], statement);
      statement.expr &:= ");\n";
      stri_name := "*" & stri_name;
    end if;
    if isNormalVariable(params[3]) then
      char_name := normalVariable(params[3], statement);
    else
      incr(statement.temp_num);
      char_name := "tmp_" & str(statement.temp_num);
      statement.temp_decls &:= "chartype ";
      statement.temp_decls &:= char_name;
      statement.temp_decls &:= ";\n";
      statement.expr &:= char_name;
      statement.expr &:= "=";
      process_expr(params[3], statement);
      statement.expr &:= ";\n";
    end if;
    statement.expr &:= "if ((";
    statement.expr &:= stri_name;
    statement.expr &:= ")->size == (";
    statement.expr &:= stri_name;
    statement.expr &:= ")->capacity) {\n";
    statement.expr &:= "strPush(&(";
    statement.expr &:= stri_name;
    statement.expr &:= "), ";
    statement.expr &:= char_name;
    statement.expr &:= ");\n";
    statement.expr &:= "} else {\n";
    statement.expr &:= "(";
    statement.expr &:= stri_name;
    statement.expr &:= ")->mem[(";
    statement.expr &:= stri_name;
    statement.expr &:= ")->size]=";
    statement.expr &:= char_name;
    statement.expr &:= ";\n";
    statement.expr &:= "(";
    statement.expr &:= stri_name;
    statement.expr &:= ")->size++;\n";
    statement.expr &:= "}\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_str_push (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    if inlineFunctions and ccConf.WITH_STRI_CAPACITY then
      process_inline_str_push(params, c_expr);
    else
      statement.expr := "strPush(&(";
      process_expr(params[1], statement);
      statement.expr &:= "), ";
      process_expr(params[3], statement);
      statement.expr &:= ");\n";
      doLocalDeclsOfStatement(statement, c_expr);
    end if;
  end func;


const proc: process_str_range (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: stri_name is "";
    var string: start_name is "";
    var string: stop_name is "";
    var string: slice_name is "";
  begin
    if getConstant(params[1], STRIOBJECT, evaluatedParam) and
        getValue(evaluatedParam, string) = "" then
      incr(countOptimizations);
      c_expr.expr &:= "/* \"\"[m .. n] */ (";
      # The index expressions could have a side effect or raise an exception
      process_expr(params[3], c_expr);
      c_expr.expr &:= ",";
      process_expr(params[5], c_expr);
      c_expr.expr &:= ",";
      c_expr.expr &:= stringLiteral("");
      c_expr.expr &:= ")";
    elsif getConstant(params[3], INTOBJECT, evaluatedParam) and
        getValue(evaluatedParam, integer) = 1 then
      incr(countOptimizations);
      process_str_head(params[1], params[5], c_expr);
    elsif ccConf.ALLOW_STRITYPE_SLICES then
      c_expr.expr &:= "(";
      incr(c_expr.temp_num);
      slice_name := "slice_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "struct stristruct ";
      c_expr.temp_decls &:= slice_name;
      c_expr.temp_decls &:= ";\n";
      if inlineFunctions then
        stri_name := getParameterAsVariable("const_stritype", "stri_", params[1], c_expr);
        start_name := getTempVariable("inttype", "start_", params[3], c_expr);
        stop_name := getParameterAsVariable("inttype", "stop_", params[5], c_expr);
        (* Formula used: start<1 ? start=1 : 0 *)
        c_expr.expr &:= start_name;
        c_expr.expr &:= "<1 ? ";
        c_expr.expr &:= start_name;
        c_expr.expr &:= "=1 : 0, ";
        (* Formula used: slice.capacity=0,
                         stop>=start && (uinttype)start <= stri->size ?
                         (slice.mem = &stri->mem[start-1],
                         (uinttype)stop > stri->size ?
                         slice.size = stri->size-(memsizetype)start+1 :
                         (slice.size = (memsizetype)stop-(memsizetype)start+1)) :
                         (slice.mem = NULL,slice.size = 0) *)
        if ccConf.WITH_STRI_CAPACITY then
          c_expr.expr &:= slice_name;
          c_expr.expr &:= ".capacity=0, ";
        end if;
        c_expr.expr &:= stop_name;
        c_expr.expr &:= ">=";
        c_expr.expr &:= start_name;
        c_expr.expr &:= " && (uinttype)";
        c_expr.expr &:= start_name;
        c_expr.expr &:= "<=";
        c_expr.expr &:= stri_name;
        c_expr.expr &:= "->size ? (";
        c_expr.expr &:= slice_name;
        c_expr.expr &:= ".mem = &";
        c_expr.expr &:= stri_name;
        c_expr.expr &:= "->mem[";
        c_expr.expr &:= start_name;
        c_expr.expr &:= "-1], (uinttype)";
        c_expr.expr &:= stop_name;
        c_expr.expr &:= " > ";
        c_expr.expr &:= stri_name;
        c_expr.expr &:= "->size ? ";
        c_expr.expr &:= slice_name;
        c_expr.expr &:= ".size = ";
        c_expr.expr &:= stri_name;
        c_expr.expr &:= "->size-(memsizetype)";
        c_expr.expr &:= start_name;
        c_expr.expr &:= "+1 : (";
        c_expr.expr &:= slice_name;
        c_expr.expr &:= ".size = (memsizetype)";
        c_expr.expr &:= stop_name;
        c_expr.expr &:= "-(memsizetype)";
        c_expr.expr &:= start_name;
        c_expr.expr &:= "+1)) : (";
        c_expr.expr &:= slice_name;
        c_expr.expr &:= ".mem = NULL,";
        c_expr.expr &:= slice_name;
        c_expr.expr &:= ".size = 0)";
      else
        c_expr.expr &:= "strRangeSlice(";
        getAnyParamToExpr(params[1], c_expr);
        c_expr.expr &:= ", ";
        process_expr(params[3], c_expr);
        c_expr.expr &:= ", ";
        process_expr(params[5], c_expr);
        c_expr.expr &:= ", &";
        c_expr.expr &:= slice_name;
        c_expr.expr &:= ")";
      end if;
      c_expr.expr &:= ", &";
      c_expr.expr &:= slice_name;
      c_expr.expr &:= ")";
    else
      prepare_stri_result(c_expr);
      c_expr.result_expr := "strRange(";
      getAnyParamToResultExpr(params[1], c_expr);
      c_expr.result_expr &:= ", ";
      getStdParamToResultExpr(params[3], c_expr);
      c_expr.result_expr &:= ", ";
      getStdParamToResultExpr(params[5], c_expr);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_str_rchipos (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "strRChIPos(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_str_rchpos (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "strRChPos(";
    getAnyParamToExpr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_str_repl (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "strRepl(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getAnyParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= ", ";
    getAnyParamToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_str_ripos (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[2], STRIOBJECT, evaluatedParam) and
        length(getValue(evaluatedParam, string)) = 1 then
      incr(countOptimizations);
      c_expr.expr &:= "strRChIPos(";
      getAnyParamToExpr(params[1], c_expr);
      c_expr.expr &:= ", ";
      c_expr.expr &:= charLiteral(getValue(evaluatedParam, string)[1]);
      c_expr.expr &:= ", ";
      process_expr(params[3], c_expr);
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= "strRIPos(";
      getAnyParamToExpr(params[1], c_expr);
      c_expr.expr &:= ", ";
      getAnyParamToExpr(params[2], c_expr);
      c_expr.expr &:= ", ";
      process_expr(params[3], c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_str_rpad (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "strRpad(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[3], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_str_rpos (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    if getConstant(params[2], STRIOBJECT, evaluatedParam) and
        length(getValue(evaluatedParam, string)) = 1 then
      incr(countOptimizations);
      c_expr.expr &:= "strRChPos(";
      getAnyParamToExpr(params[1], c_expr);
      c_expr.expr &:= ", ";
      c_expr.expr &:= charLiteral(getValue(evaluatedParam, string)[1]);
      c_expr.expr &:= ")";
    else
      c_expr.expr &:= "strRPos(";
      getAnyParamToExpr(params[1], c_expr);
      c_expr.expr &:= ", ";
      getAnyParamToExpr(params[2], c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_str_rtrim (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "strRtrim(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_str_split (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
  begin
    prepare_typed_result(array_type[getExprResultType(params[1])], c_expr);
    if getConstant(params[2], STRIOBJECT, evaluatedParam) and
        length(getValue(evaluatedParam, string)) = 1 then
      incr(countOptimizations);
      c_expr.result_expr := "strChSplit(";
      getAnyParamToResultExpr(params[1], c_expr);
      c_expr.result_expr &:= ", ";
      c_expr.result_expr &:= charLiteral(getValue(evaluatedParam, string)[1]);
      c_expr.result_expr &:= ")";
    else
      c_expr.result_expr := "strSplit(";
      getAnyParamToResultExpr(params[1], c_expr);
      c_expr.result_expr &:= ", ";
      getAnyParamToResultExpr(params[2], c_expr);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_str_str (in ref_list: params, inout expr_type: c_expr) is func

  begin
    process_expr(params[1], c_expr);
  end func;


const proc: process_str_substr1 (in reference: param1, in reference: param3,
    inout expr_type: c_expr) is func

  local
    var string: stri_name is "";
    var string: index_name is "";
    var string: stristruct_name is "";
  begin
    incr(countOptimizations);
    c_expr.expr &:= "(";
    stri_name := getParameterAsVariable("const_stritype", "tmp_", param1, c_expr);
    incr(c_expr.temp_num);
    index_name := "idx_" & str(c_expr.temp_num);
    if ccConf.TWOS_COMPLEMENT_INTTYPE then
      c_expr.temp_decls &:= "uinttype ";
    else
      c_expr.temp_decls &:= "inttype ";
    end if;
    c_expr.temp_decls &:= index_name;
    c_expr.temp_decls &:= ";\n";
    incr(c_expr.temp_num);
    stristruct_name := "stri_" & str(c_expr.temp_num);
    c_expr.temp_decls &:= "struct stristruct ";
    c_expr.temp_decls &:= stristruct_name;
    c_expr.temp_decls &:= ";\n";
    c_expr.expr &:= index_name;
    c_expr.expr &:= "=";
    if ccConf.TWOS_COMPLEMENT_INTTYPE then
      c_expr.expr &:= "(uinttype)((";
      process_expr(param3, c_expr);
      c_expr.expr &:= ")-1), ";
    else
      c_expr.expr &:= "(";
      process_expr(param3, c_expr);
      c_expr.expr &:= ")-1, ";
      c_expr.expr &:= index_name;
      c_expr.expr &:= "<0 || ";
    end if;
    c_expr.expr &:= index_name;
    c_expr.expr &:= ">=";
    c_expr.expr &:= stri_name;
    c_expr.expr &:= "->size ? ";
    c_expr.expr &:= stringLiteral("");
    c_expr.expr &:= " : chrStrMacro(";
    c_expr.expr &:= stri_name;
    c_expr.expr &:= "->mem[";
    c_expr.expr &:= index_name;
    c_expr.expr &:= "],";
    c_expr.expr &:= stristruct_name;
    c_expr.expr &:= "))";
  end func;


const proc: process_str_substr (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: stri_name is "";
    var string: start_name is "";
    var string: length_name is "";
    var string: slice_name is "";
  begin
    if getConstant(params[1], STRIOBJECT, evaluatedParam) and
        getValue(evaluatedParam, string) = "" then
      incr(countOptimizations);
      c_expr.expr &:= "/* \"\"[m len n] */ (";
      # The index and length expressions could have a side effect or raise an exception
      process_expr(params[3], c_expr);
      c_expr.expr &:= ",";
      process_expr(params[5], c_expr);
      c_expr.expr &:= ",";
      c_expr.expr &:= stringLiteral("");
      c_expr.expr &:= ")";
    elsif getConstant(params[3], INTOBJECT, evaluatedParam) and
        getValue(evaluatedParam, integer) = 1 then
      incr(countOptimizations);
      process_str_head(params[1], params[5], c_expr);
    elsif getConstant(params[5], INTOBJECT, evaluatedParam) and
        getValue(evaluatedParam, integer) = 1 then
      process_str_substr1(params[1], params[3], c_expr);
    elsif ccConf.ALLOW_STRITYPE_SLICES then
      c_expr.expr &:= "(";
      incr(c_expr.temp_num);
      slice_name := "slice_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "struct stristruct ";
      c_expr.temp_decls &:= slice_name;
      c_expr.temp_decls &:= ";\n";
      if inlineFunctions then
        stri_name := getParameterAsVariable("const_stritype", "stri_", params[1], c_expr);
        start_name := getTempVariable("inttype", "start_", params[3], c_expr);
        length_name := getTempVariable("inttype", "length_", params[5], c_expr);
        (* Formula used: start<1 ? (length>=1 && start>1-length ? (length+=start-1, start=1) : (length=0)) : 0 *)
        c_expr.expr &:= start_name;
        c_expr.expr &:= "<1 ? (";
        c_expr.expr &:= length_name;
        c_expr.expr &:= ">=1 && ";
        c_expr.expr &:= start_name;
        c_expr.expr &:= ">1-";
        c_expr.expr &:= length_name;
        c_expr.expr &:= " ? (";
        c_expr.expr &:= length_name;
        c_expr.expr &:= "+=";
        c_expr.expr &:= start_name;
        c_expr.expr &:= "-1, ";
        c_expr.expr &:= start_name;
        c_expr.expr &:= "=1) : (";
        c_expr.expr &:= length_name;
        c_expr.expr &:= "=0)) : 0, ";
        (* Formula used: slice.capacity=0,
                         length>=1 && (uinttype)start<=stri->size ?
                         (slice.mem = &stri->mem[start-1],
                         (uinttype)length > stri->size-(memsizetype)start+1 ?
                         slice.size = stri->size-(memsizetype)start+1 :
                         (slice.size = (memsizetype)length)) :
                         (slice.mem = NULL, slice.size = 0) *)
        if ccConf.WITH_STRI_CAPACITY then
          c_expr.expr &:= slice_name;
          c_expr.expr &:= ".capacity=0, ";
        end if;
        c_expr.expr &:= length_name;
        c_expr.expr &:= ">=1 && (uinttype)";
        c_expr.expr &:= start_name;
        c_expr.expr &:= "<=";
        c_expr.expr &:= stri_name;
        c_expr.expr &:= "->size ? (";
        c_expr.expr &:= slice_name;
        c_expr.expr &:= ".mem = &";
        c_expr.expr &:= stri_name;
        c_expr.expr &:= "->mem[";
        c_expr.expr &:= start_name;
        c_expr.expr &:= "-1], (uinttype)";
        c_expr.expr &:= length_name;
        c_expr.expr &:= " > ";
        c_expr.expr &:= stri_name;
        c_expr.expr &:= "->size-(memsizetype)";
        c_expr.expr &:= start_name;
        c_expr.expr &:= "+1 ? ";
        c_expr.expr &:= slice_name;
        c_expr.expr &:= ".size = ";
        c_expr.expr &:= stri_name;
        c_expr.expr &:= "->size-(memsizetype)";
        c_expr.expr &:= start_name;
        c_expr.expr &:= "+1 : (";
        c_expr.expr &:= slice_name;
        c_expr.expr &:= ".size = (memsizetype)";
        c_expr.expr &:= length_name;
        c_expr.expr &:= ")) : (";
        c_expr.expr &:= slice_name;
        c_expr.expr &:= ".mem = NULL, ";
        c_expr.expr &:= slice_name;
        c_expr.expr &:= ".size = 0)";
      else
        c_expr.expr &:= "strSubstrSlice(";
        getAnyParamToExpr(params[1], c_expr);
        c_expr.expr &:= ", ";
        process_expr(params[3], c_expr);
        c_expr.expr &:= ", ";
        process_expr(params[5], c_expr);
        c_expr.expr &:= ", &";
        c_expr.expr &:= slice_name;
        c_expr.expr &:= ")";
      end if;
      c_expr.expr &:= ", &";
      c_expr.expr &:= slice_name;
      c_expr.expr &:= ")";
    else
      prepare_stri_result(c_expr);
      c_expr.result_expr := "strSubstr(";
      getAnyParamToResultExpr(params[1], c_expr);
      c_expr.result_expr &:= ", ";
      getStdParamToResultExpr(params[3], c_expr);
      c_expr.result_expr &:= ", ";
      getStdParamToResultExpr(params[5], c_expr);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_str_tail (in ref_list: params, inout expr_type: c_expr) is func

  local
    var reference: evaluatedParam is NIL;
    var string: slice_name is "";
  begin
    if getConstant(params[1], STRIOBJECT, evaluatedParam) and
        getValue(evaluatedParam, string) = "" then
      incr(countOptimizations);
      c_expr.expr &:= "/* \"\"[n .. ] */ (";
      # The index expression could have a side effect or raise an exception
      process_expr(params[3], c_expr);
      c_expr.expr &:= ",";
      c_expr.expr &:= stringLiteral("");
      c_expr.expr &:= ")";
    elsif ccConf.ALLOW_STRITYPE_SLICES then
      incr(c_expr.temp_num);
      slice_name := "slice_" & str(c_expr.temp_num);
      c_expr.temp_decls &:= "struct stristruct ";
      c_expr.temp_decls &:= slice_name;
      c_expr.temp_decls &:= ";\n";
      c_expr.expr &:= "(strTailSlice(";
      getAnyParamToExpr(params[1], c_expr);
      c_expr.expr &:= ", ";
      process_expr(params[3], c_expr);
      c_expr.expr &:= ", &";
      c_expr.expr &:= slice_name;
      c_expr.expr &:= "), &";
      c_expr.expr &:= slice_name;
      c_expr.expr &:= ")";
    else
      prepare_stri_result(c_expr);
      c_expr.result_expr := "strTail(";
      getAnyParamToResultExpr(params[1], c_expr);
      c_expr.result_expr &:= ", ";
      getStdParamToResultExpr(params[3], c_expr);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_str_toutf8 (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "strToUtf8(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_str_trim (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "strTrim(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


(**
 *  Produces code to return a string converted to upper case.
 *  When the parameter is a temporary value the conversion is done
 *  with strUpTemp. The strUpTemp function returns the parameter as
 *  result of the conversion. That way the temporary of the parameter
 *  must not be freed.
 *)
const proc: process_str_up (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: c_param1 is expr_type.value;
  begin
    prepare_stri_result(c_expr);
    prepareAnyParamTemporarys(params[1], c_param1, c_expr);
    if c_param1.result_expr <> "" then
      c_expr.result_expr := "strUpTemp(";
      c_expr.result_expr &:= c_param1.result_expr;
    else
      c_expr.result_expr := "strUp(";
      c_expr.result_expr &:= c_param1.expr;
    end if;
    c_expr.result_expr &:= ")";
  end func;


const proc: process_str_utf8tostri (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "strUtf8ToStri(";
    getAnyParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_str_value (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "strValue(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_tim_await (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "timAwait(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[6], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[7], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[8], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_tim_from_timestamp (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "timFromIntTimestamp(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", &(";
    process_expr(params[2], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[3], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[4], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[5], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[6], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[7], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[8], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[9], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[10], c_expr);
    c_expr.expr &:= "));\n";
  end func;


const proc: process_tim_now (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "timNow(&(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[2], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[3], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[4], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[5], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[6], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[7], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[8], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[9], c_expr);
    c_expr.expr &:= "));\n";
  end func;


const proc: process_tim_set_local_tz (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "timSetLocalTZ(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[4], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[5], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[6], c_expr);
    c_expr.expr &:= ", &(";
    process_expr(params[7], c_expr);
    c_expr.expr &:= "), &(";
    process_expr(params[8], c_expr);
    c_expr.expr &:= "));\n";
  end func;


const proc: process_typ_cmp (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "typCmp(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_typ_cpy (in ref_list: params, inout expr_type: c_expr) is func

  local
    var expr_type: statement is expr_type.value;
  begin
    process_expr(params[1], statement);
    statement.expr &:= "=";
    process_expr(params[3], statement);
    statement.expr &:= ";\n";
    doLocalDeclsOfStatement(statement, c_expr);
  end func;


const proc: process_typ_eq (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") == (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_typ_func (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "typFunc(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_typ_hashcode (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(inttype)(((memsizetype)(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")) >> 6)";
  end func;


const proc: process_typ_isderived (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "typIsDerived(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_typ_isfunc (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "typIsFunc(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_typ_isvarfunc (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "typIsVarfunc(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_typ_matchobj (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "typMatchobj(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_typ_meta (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "typMeta(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_typ_ne (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ") != (";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_typ_num (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "typNum(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_typ_result (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "typResult(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_typ_str (in ref_list: params, inout expr_type: c_expr) is func

  begin
    if category(params[1]) = TYPEOBJECT and not isVar(params[1]) then
      incr(countOptimizations);
      c_expr.expr &:= stringLiteral(str(getValue(params[1], type)));
    else
      compDataLibraryUsed := TRUE;
      prepare_stri_result(c_expr);
      c_expr.result_expr := "typStr(";
      getStdParamToResultExpr(params[1], c_expr);
      c_expr.result_expr &:= ")";
    end if;
  end func;


const proc: process_typ_value (in ref_list: params, inout expr_type: c_expr) is func

  begin
    compDataLibraryUsed := TRUE;
    c_expr.expr &:= "typValue(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_typ_varconv (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "(";
    process_expr(params[3], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_ut8_getc (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "ut8Getc(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ")";
  end func;


const proc: process_ut8_gets (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "ut8Gets(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", ";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= ")";
  end func;


const proc: process_ut8_line_read (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "ut8LineRead(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", &(";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= "))";
  end func;


const proc: process_ut8_seek (in ref_list: params, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "ut8Seek(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    process_expr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_ut8_word_read (in ref_list: params, inout expr_type: c_expr) is func

  begin
    prepare_stri_result(c_expr);
    c_expr.result_expr := "ut8WordRead(";
    getStdParamToResultExpr(params[1], c_expr);
    c_expr.result_expr &:= ", &(";
    getStdParamToResultExpr(params[2], c_expr);
    c_expr.result_expr &:= "))";
  end func;


const proc: process_ut8_write (in ref_list: params, inout expr_type: c_expr) is func

  begin
    setDiagnosticLine(c_expr);
    c_expr.expr &:= "ut8Write(";
    process_expr(params[1], c_expr);
    c_expr.expr &:= ", ";
    getAnyParamToExpr(params[2], c_expr);
    c_expr.expr &:= ");\n";
  end func;


const proc: process_unknown_action (in string: action_name, inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "/* ACTOBJECT { ";
    c_expr.expr &:= action_name;
    c_expr.expr &:= " }*/";
  end func;


const proc: process_action (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  local
    var ACTION: current_action is action "PRC_NOOP";
    var string: action_name is "";
    var string: action_prefix is "";
  begin
    current_action := getValue(function, ACTION);
    action_name := str(current_action);
    # c_expr.expr &:= "/* " <& action_name <& " */\n";
    action_prefix := action_name[ .. 3];
    if action_prefix = "ACT" then
      if action_name = "ACT_CPY" then
        process_act_cpy(params, c_expr);
      elsif action_name = "ACT_EQ" then
        process_act_eq(params, c_expr);
      elsif action_name = "ACT_ICONV" then
        process_act_iconv(params, c_expr);
      elsif action_name = "ACT_NE" then
        process_act_ne(params, c_expr);
      elsif action_name = "ACT_ORD" then
        process_act_ord(params, c_expr);
      elsif action_name = "ACT_STR" then
        process_act_str(params, c_expr);
      elsif action_name = "ACT_VALUE" then
        process_act_value(params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "ARR" then
      if action_name = "ARR_APPEND" then
        process_arr_append(params, c_expr);
      elsif action_name = "ARR_ARRLIT" then
        process_arr_arrlit(params, c_expr);
      elsif action_name = "ARR_ARRLIT2" then
        process_arr_arrlit2(params, c_expr);
      elsif action_name = "ARR_BASELIT" then
        process_arr_baselit(function, params, c_expr);
      elsif action_name = "ARR_BASELIT2" then
        process_arr_baselit2(function, params, c_expr);
      elsif action_name = "ARR_CAT" then
        process_arr_cat(params, c_expr);
      elsif action_name = "ARR_CONV" then
        process_arr_conv(params, c_expr);
      elsif action_name = "ARR_CPY" then
        process_arr_cpy(params, c_expr);
      elsif action_name = "ARR_CREATE" then
        process_arr_create(params, c_expr);
      elsif action_name = "ARR_DESTR" then
        process_arr_destr(params, c_expr);
      elsif action_name = "ARR_EXTEND" then
        process_arr_extend(params, c_expr);
      elsif action_name = "ARR_GEN" then
        process_arr_gen(function, params, c_expr);
      elsif action_name = "ARR_HEAD" then
        process_arr_head(params, c_expr);
      elsif action_name = "ARR_IDX" then
        process_arr_idx(function, params, c_expr);
      elsif action_name = "ARR_LNG" then
        process_arr_lng(params, c_expr);
      elsif action_name = "ARR_MAXIDX" then
        process_arr_maxidx(params, c_expr);
      elsif action_name = "ARR_MINIDX" then
        process_arr_minidx(params, c_expr);
      elsif action_name = "ARR_PUSH" then
        process_arr_push(params, c_expr);
      elsif action_name = "ARR_RANGE" then
        process_arr_range(params, c_expr);
      elsif action_name = "ARR_REMOVE" then
        process_arr_remove(function, params, c_expr);
      elsif action_name = "ARR_SORT" then
        process_arr_sort(params, c_expr);
      elsif action_name = "ARR_SUBARR" then
        process_arr_subarr(params, c_expr);
      elsif action_name = "ARR_TIMES" then
        process_arr_times(function, params, c_expr);
      elsif action_name = "ARR_TAIL" then
        process_arr_tail(params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "BIG" then
      if action_name = "BIG_ABS" then
        process_big_abs(params, c_expr);
      elsif action_name = "BIG_ADD" then
        process_big_add(params, c_expr);
      elsif action_name = "BIG_BIT_LENGTH" then
        process_big_bit_length(params, c_expr);
      elsif action_name = "BIG_CLIT" then
        process_big_clit(params, c_expr);
      elsif action_name = "BIG_CMP" then
        process_big_cmp(params, c_expr);
      elsif action_name = "BIG_CONV" then
        process_big_conv(params, c_expr);
      elsif action_name = "BIG_CPY" then
        process_big_cpy(params, c_expr);
      elsif action_name = "BIG_DECR" then
        process_big_decr(params, c_expr);
      elsif action_name = "BIG_DIV" then
        process_big_div(params, c_expr);
      elsif action_name = "BIG_EQ" then
        process_big_eq(params, c_expr);
      elsif action_name = "BIG_FROM_BSTRI_BE" then
        process_big_from_bstri_be(params, c_expr);
      elsif action_name = "BIG_FROM_BSTRI_LE" then
        process_big_from_bstri_le(params, c_expr);
      elsif action_name = "BIG_GCD" then
        process_big_gcd(params, c_expr);
      elsif action_name = "BIG_GE" then
        process_big_ge(params, c_expr);
      elsif action_name = "BIG_GROW" then
        process_big_grow(params, c_expr);
      elsif action_name = "BIG_GT" then
        process_big_gt(params, c_expr);
      elsif action_name = "BIG_HASHCODE" then
        process_big_hashcode(params, c_expr);
      elsif action_name = "BIG_ICONV" then
        process_big_iconv(params, c_expr);
      elsif action_name = "BIG_INCR" then
        process_big_incr(params, c_expr);
      elsif action_name = "BIG_IPOW" then
        process_big_ipow(params, c_expr);
      elsif action_name = "BIG_LE" then
        process_big_le(params, c_expr);
      elsif action_name = "BIG_LOG2" then
        process_big_log2(params, c_expr);
      elsif action_name = "BIG_LOWEST_SET_BIT" then
        process_big_lowest_set_bit(params, c_expr);
      elsif action_name = "BIG_LSHIFT" then
        process_big_lshift(params, c_expr);
      elsif action_name = "BIG_LSHIFT_ASSIGN" then
        process_big_lshift_assign(params, c_expr);
      elsif action_name = "BIG_LT" then
        process_big_lt(params, c_expr);
      elsif action_name = "BIG_MDIV" then
        process_big_mdiv(params, c_expr);
      elsif action_name = "BIG_MOD" then
        process_big_mod(params, c_expr);
      elsif action_name = "BIG_MULT" then
        process_big_mult(params, c_expr);
      elsif action_name = "BIG_MULT_ASSIGN" then
        process_big_mult_assign(params, c_expr);
      elsif action_name = "BIG_NE" then
        process_big_ne(params, c_expr);
      elsif action_name = "BIG_NEGATE" then
        process_big_negate(params, c_expr);
      elsif action_name = "BIG_ODD" then
        process_big_odd(params, c_expr);
      elsif action_name = "BIG_ORD" then
        process_big_ord(params, c_expr);
      elsif action_name = "BIG_PARSE" then
        process_big_parse(params, c_expr);
      elsif action_name = "BIG_PARSE_BASED" then
        process_big_parse_based(params, c_expr);
      elsif action_name = "BIG_PLUS" then
        process_big_plus(params, c_expr);
      elsif action_name = "BIG_PRED" then
        process_big_pred(params, c_expr);
      elsif action_name = "BIG_RAND" then
        process_big_rand(params, c_expr);
      elsif action_name = "BIG_REM" then
        process_big_rem(params, c_expr);
      elsif action_name = "BIG_RSHIFT" then
        process_big_rshift(params, c_expr);
      elsif action_name = "BIG_RSHIFT_ASSIGN" then
        process_big_rshift_assign(params, c_expr);
      elsif action_name = "BIG_SBTR" then
        process_big_sbtr(params, c_expr);
      elsif action_name = "BIG_SHRINK" then
        process_big_shrink(params, c_expr);
      elsif action_name = "BIG_STR" then
        process_big_str(params, c_expr);
      elsif action_name = "BIG_SUCC" then
        process_big_succ(params, c_expr);
      elsif action_name = "BIG_TO_BSTRI_BE" then
        process_big_to_bstri_be(params, c_expr);
      elsif action_name = "BIG_TO_BSTRI_LE" then
        process_big_to_bstri_le(params, c_expr);
      elsif action_name = "BIG_VALUE" then
        process_big_value(params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "BIN" then
      if action_name = "BIN_AND" then
        process_bin_and(params, c_expr);
      elsif action_name = "BIN_OR" then
        process_bin_or(params, c_expr);
      elsif action_name = "BIN_XOR" then
        process_bin_xor(params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "BLN" then
      if action_name = "BLN_AND" then
        process_bln_and(params, c_expr);
      elsif action_name = "BLN_CPY" then
        process_bln_cpy(params, c_expr);
      elsif action_name = "BLN_EQ" then
        process_bln_eq(params, c_expr);
      elsif action_name = "BLN_GE" then
        process_bln_ge(params, c_expr);
      elsif action_name = "BLN_GT" then
        process_bln_gt(params, c_expr);
      elsif action_name = "BLN_ICONV" then
        process_bln_iconv(params, c_expr);
      elsif action_name = "BLN_LE" then
        process_bln_le(params, c_expr);
      elsif action_name = "BLN_LT" then
        process_bln_lt(params, c_expr);
      elsif action_name = "BLN_NE" then
        process_bln_ne(params, c_expr);
      elsif action_name = "BLN_NOT" then
        process_bln_not(params, c_expr);
      elsif action_name = "BLN_OR" then
        process_bln_or(params, c_expr);
      elsif action_name = "BLN_ORD" then
        process_bln_ord(params, c_expr);
      elsif action_name = "BLN_VALUE" then
        process_bln_value(params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "BST" then
      if action_name = "BST_APPEND" then
        process_bst_append(params, c_expr);
      elsif action_name = "BST_CMP" then
        process_bst_cmp(params, c_expr);
      elsif action_name = "BST_CPY" then
        process_bst_cpy(params, c_expr);
      elsif action_name = "BST_EQ" then
        process_bst_eq(params, c_expr);
      elsif action_name = "BST_HASHCODE" then
        process_bst_hashcode(params, c_expr);
      elsif action_name = "BST_IDX" then
        process_bst_idx(function, params, c_expr);
      elsif action_name = "BST_LNG" then
        process_bst_lng(params, c_expr);
      elsif action_name = "BST_NE" then
        process_bst_ne(params, c_expr);
      elsif action_name = "BST_PARSE" then
        process_bst_parse(params, c_expr);
      elsif action_name = "BST_STR" then
        process_bst_str(params, c_expr);
      elsif action_name = "BST_VALUE" then
        process_bst_value(params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "CHR" then
      if action_name = "CHR_CHR" then
        process_chr_chr(function, params, c_expr);
      elsif action_name = "CHR_CLIT" then
        process_chr_clit(params, c_expr);
      elsif action_name = "CHR_CMP" then
        process_chr_cmp(params, c_expr);
      elsif action_name = "CHR_CONV" then
        process_chr_conv(params, c_expr);
      elsif action_name = "CHR_CPY" then
        process_chr_cpy(params, c_expr);
      elsif action_name = "CHR_EQ" then
        process_chr_eq(params, c_expr);
      elsif action_name = "CHR_DECR" then
        process_chr_decr(params, c_expr);
      elsif action_name = "CHR_GE" then
        process_chr_ge(params, c_expr);
      elsif action_name = "CHR_GROW" then
        process_chr_grow(params, c_expr);
      elsif action_name = "CHR_GT" then
        process_chr_gt(params, c_expr);
      elsif action_name = "CHR_HASHCODE" then
        process_chr_hashcode(params, c_expr);
      elsif action_name = "CHR_ICONV" then
        process_chr_iconv(params, c_expr);
      elsif action_name = "CHR_INCR" then
        process_chr_incr(params, c_expr);
      elsif action_name = "CHR_LE" then
        process_chr_le(params, c_expr);
      elsif action_name = "CHR_LOW" then
        process_chr_low(params, c_expr);
      elsif action_name = "CHR_LT" then
        process_chr_lt(params, c_expr);
      elsif action_name = "CHR_NE" then
        process_chr_ne(params, c_expr);
      elsif action_name = "CHR_ORD" then
        process_chr_ord(params, c_expr);
      elsif action_name = "CHR_PRED" then
        process_chr_pred(params, c_expr);
      elsif action_name = "CHR_SHRINK" then
        process_chr_shrink(params, c_expr);
      elsif action_name = "CHR_STR" then
        process_chr_str(params, c_expr);
      elsif action_name = "CHR_SUCC" then
        process_chr_succ(params, c_expr);
      elsif action_name = "CHR_UP" then
        process_chr_up(params, c_expr);
      elsif action_name = "CHR_VALUE" then
        process_chr_value(params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "CMD" then
      if action_name = "CMD_BIG_FILESIZE" then
        process_cmd_big_filesize(params, c_expr);
      elsif action_name = "CMD_CHDIR" then
        process_cmd_chdir(params, c_expr);
      elsif action_name = "CMD_CLONE_FILE" then
        process_cmd_clone_file(params, c_expr);
      elsif action_name = "CMD_CONFIG_VALUE" then
        process_cmd_config_value(params, c_expr);
      elsif action_name = "CMD_COPY_FILE" then
        process_cmd_copy_file(params, c_expr);
      elsif action_name = "CMD_ENVIRONMENT" then
        process_cmd_environment(function, params, c_expr);
      elsif action_name = "CMD_FILEMODE" then
        process_cmd_filemode(function, params, c_expr);
      elsif action_name = "CMD_FILESIZE" then
        process_cmd_filesize(params, c_expr);
      elsif action_name = "CMD_FILETYPE" then
        process_cmd_filetype(params, c_expr);
      elsif action_name = "CMD_FILETYPE_SL" then
        process_cmd_filetype_sl(params, c_expr);
      elsif action_name = "CMD_GETCWD" then
        process_cmd_getcwd(params, c_expr);
      elsif action_name = "CMD_GETENV" then
        process_cmd_getenv(params, c_expr);
      elsif action_name = "CMD_GET_ATIME" then
        process_cmd_get_atime(params, c_expr);
      elsif action_name = "CMD_GET_CTIME" then
        process_cmd_get_ctime(params, c_expr);
      elsif action_name = "CMD_GET_MTIME" then
        process_cmd_get_mtime(params, c_expr);
      elsif action_name = "CMD_GET_SEARCH_PATH" then
        process_cmd_get_search_path(function, params, c_expr);
      elsif action_name = "CMD_HOME_DIR" then
        process_cmd_homedir(params, c_expr);
      elsif action_name = "CMD_LS" then
        process_cmd_ls(params, c_expr);
      elsif action_name = "CMD_MKDIR" then
        process_cmd_mkdir(params, c_expr);
      elsif action_name = "CMD_MOVE" then
        process_cmd_move(params, c_expr);
      elsif action_name = "CMD_READLINK" then
        process_cmd_readlink(params, c_expr);
      elsif action_name = "CMD_REMOVE" then
        process_cmd_remove(params, c_expr);
      elsif action_name = "CMD_REMOVE_ANY_FILE" then
        process_cmd_remove_any_file(params, c_expr);
      elsif action_name = "CMD_SETENV" then
        process_cmd_setenv(params, c_expr);
      elsif action_name = "CMD_SET_ATIME" then
        process_cmd_set_atime(params, c_expr);
      elsif action_name = "CMD_SET_FILEMODE" then
        process_cmd_set_filemode(params, c_expr);
      elsif action_name = "CMD_SET_MTIME" then
        process_cmd_set_mtime(params, c_expr);
      elsif action_name = "CMD_SHELL" then
        process_cmd_shell(params, c_expr);
      elsif action_name = "CMD_SHELL_ESCAPE" then
        process_cmd_shell_escape(params, c_expr);
      elsif action_name = "CMD_PIPE2" then
        process_cmd_pipe2(params, c_expr);
      elsif action_name = "CMD_PTY" then
        process_cmd_pty(params, c_expr);
      elsif action_name = "CMD_START_PROCESS" then
        process_cmd_start_process(params, c_expr);
      elsif action_name = "CMD_SYMLINK" then
        process_cmd_symlink(params, c_expr);
      elsif action_name = "CMD_TO_OS_PATH" then
        process_cmd_to_os_path(params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "CON" then
      consoleLibraryUsed := TRUE;
      if action_name = "CON_CLEAR" then
        process_con_clear(params, c_expr);
      elsif action_name = "CON_CURSOR" then
        process_con_cursor(params, c_expr);
      elsif action_name = "CON_FLUSH" then
        process_con_flush(params, c_expr);
      elsif action_name = "CON_HEIGHT" then
        process_con_height(params, c_expr);
      elsif action_name = "CON_H_SCL" then
        process_con_h_scl(params, c_expr);
      elsif action_name = "CON_OPEN" then
        process_con_open(params, c_expr);
      elsif action_name = "CON_SETPOS" then
        process_con_setpos(params, c_expr);
      elsif action_name = "CON_V_SCL" then
        process_con_v_scl(params, c_expr);
      elsif action_name = "CON_WIDTH" then
        process_con_width(params, c_expr);
      elsif action_name = "CON_WRITE" then
        process_con_write(params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "DCL" then
      if action_name = "DCL_CONST" then
        write_object_declaration := FALSE;
      elsif action_name = "DCL_FWD" then
        write_object_declaration := FALSE;
      elsif action_name = "DCL_GLOBAL" then
        write_object_declaration := FALSE;
      elsif action_name = "DCL_VAR" then
        write_object_declaration := FALSE;
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "DRW" then
      drawLibraryUsed := TRUE;
      if action_name = "DRW_ARC" then
        process_drw_arc(params, c_expr);
      elsif action_name = "DRW_ARC2" then
        process_drw_arc2(params, c_expr);
      elsif action_name = "DRW_BACKGROUND" then
        process_drw_background(params, c_expr);
      elsif action_name = "DRW_CIRCLE" then
        process_drw_circle(params, c_expr);
      elsif action_name = "DRW_CLEAR" then
        process_drw_clear(params, c_expr);
      elsif action_name = "DRW_CMP" then
        process_drw_cmp(params, c_expr);
      elsif action_name = "DRW_COLOR" then
        process_drw_color(params, c_expr);
      elsif action_name = "DRW_COPYAREA" then
        process_drw_copyarea(params, c_expr);
      elsif action_name = "DRW_CPY" then
        process_drw_cpy(params, c_expr);
      elsif action_name = "DRW_EQ" then
        process_drw_eq(params, c_expr);
      elsif action_name = "DRW_FARCCHORD" then
        process_drw_farcchord(params, c_expr);
      elsif action_name = "DRW_FARCPIESLICE" then
        process_drw_farcpieslice(params, c_expr);
      elsif action_name = "DRW_FCIRCLE" then
        process_drw_fcircle(params, c_expr);
      elsif action_name = "DRW_FELLIPSE" then
        process_drw_fellipse(params, c_expr);
      elsif action_name = "DRW_FLUSH" then
        process_drw_flush(params, c_expr);
      elsif action_name = "DRW_FPOLYLINE" then
        process_drw_fpolyline(params, c_expr);
      elsif action_name = "DRW_GENPOINTLIST" then
        process_drw_genpointlist(params, c_expr);
      elsif action_name = "DRW_GET" then
        process_drw_get(params, c_expr);
      elsif action_name = "DRW_GETIMAGE" then
        process_drw_getimage(params, c_expr);
      elsif action_name = "DRW_GETIMAGEPIXEL" then
        process_drw_getimagepixel(params, c_expr);
      elsif action_name = "DRW_GETPIXEL" then
        process_drw_getpixel(params, c_expr);
      elsif action_name = "DRW_HASHCODE" then
        process_drw_hashcode(params, c_expr);
      elsif action_name = "DRW_HEIGHT" then
        process_drw_height(params, c_expr);
      elsif action_name = "DRW_IMAGE" then
        process_drw_image(params, c_expr);
      elsif action_name = "DRW_LINE" then
        process_drw_line(params, c_expr);
      elsif action_name = "DRW_NE" then
        process_drw_ne(params, c_expr);
      elsif action_name = "DRW_NEW_PIXMAP" then
        process_drw_new_pixmap(params, c_expr);
      elsif action_name = "DRW_OPEN" then
        process_drw_open(params, c_expr);
      elsif action_name = "DRW_OPEN_SUB_WINDOW" then
        process_drw_open_sub_window(params, c_expr);
      elsif action_name = "DRW_PARC" then
        process_drw_parc(params, c_expr);
      elsif action_name = "DRW_PCIRCLE" then
        process_drw_pcircle(params, c_expr);
      elsif action_name = "DRW_PFARCCHORD" then
        process_drw_pfarcchord(params, c_expr);
      elsif action_name = "DRW_PFARCPIESLICE" then
        process_drw_pfarcpieslice(params, c_expr);
      elsif action_name = "DRW_PFCIRCLE" then
        process_drw_pfcircle(params, c_expr);
      elsif action_name = "DRW_PFELLIPSE" then
        process_drw_pfellipse(params, c_expr);
      elsif action_name = "DRW_PIXELTORGB" then
        process_drw_pixeltorgb(params, c_expr);
      elsif action_name = "DRW_PLINE" then
        process_drw_pline(params, c_expr);
      elsif action_name = "DRW_POINT" then
        process_drw_point(params, c_expr);
      elsif action_name = "DRW_POINTER_XPOS" then
        process_drw_pointer_xpos(params, c_expr);
      elsif action_name = "DRW_POINTER_YPOS" then
        process_drw_pointer_ypos(params, c_expr);
      elsif action_name = "DRW_POLYLINE" then
        process_drw_polyline(params, c_expr);
      elsif action_name = "DRW_PPOINT" then
        process_drw_ppoint(params, c_expr);
      elsif action_name = "DRW_PRECT" then
        process_drw_prect(params, c_expr);
      elsif action_name = "DRW_PUT" then
        process_drw_put(params, c_expr);
      elsif action_name = "DRW_RECT" then
        process_drw_rect(params, c_expr);
      elsif action_name = "DRW_RGBCOL" then
        process_drw_rgbcol(params, c_expr);
      elsif action_name = "DRW_SETCONTENT" then
        process_drw_setcontent(params, c_expr);
      elsif action_name = "DRW_SETPOS" then
        process_drw_setpos(params, c_expr);
      elsif action_name = "DRW_SETTRANSPARENTCOLOR" then
        process_drw_setTransparentColor(params, c_expr);
      elsif action_name = "DRW_TEXT" then
        process_drw_text(params, c_expr);
      elsif action_name = "DRW_TOBOTTOM" then
        process_drw_toBottom(params, c_expr);
      elsif action_name = "DRW_TOTOP" then
        process_drw_toTop(params, c_expr);
      elsif action_name = "DRW_VALUE" then
        process_drw_value(params, c_expr);
      elsif action_name = "DRW_WIDTH" then
        process_drw_width(params, c_expr);
      elsif action_name = "DRW_XPOS" then
        process_drw_xpos(params, c_expr);
      elsif action_name = "DRW_YPOS" then
        process_drw_ypos(params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "ENU" then
      if action_name = "ENU_CONV" then
        process_enu_conv(params, c_expr);
      elsif action_name = "ENU_CPY" then
        process_enu_cpy(params, c_expr);
      elsif action_name = "ENU_EQ" then
        process_enu_eq(params, c_expr);
      elsif action_name = "ENU_ICONV2" then
        process_enu_iconv2(params, c_expr);
      elsif action_name = "ENU_NE" then
        process_enu_ne(params, c_expr);
      elsif action_name = "ENU_ORD2" then
        process_enu_ord2(params, c_expr);
      elsif action_name = "ENU_VALUE" then
        process_enu_value(params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "FIL" then
      if action_name = "FIL_BIG_LNG" then
        process_fil_big_lng(params, c_expr);
      elsif action_name = "FIL_BIG_SEEK" then
        process_fil_big_seek(params, c_expr);
      elsif action_name = "FIL_BIG_TELL" then
        process_fil_big_tell(params, c_expr);
      elsif action_name = "FIL_CLOSE" then
        process_fil_close(params, c_expr);
      elsif action_name = "FIL_CPY" then
        process_fil_cpy(params, c_expr);
      elsif action_name = "FIL_EOF" then
        process_fil_eof(params, c_expr);
      elsif action_name = "FIL_EQ" then
        process_fil_eq(params, c_expr);
      elsif action_name = "FIL_ERR" then
        process_fil_err(params, c_expr);
      elsif action_name = "FIL_FLUSH" then
        process_fil_flush(params, c_expr);
      elsif action_name = "FIL_GETC" then
        process_fil_getc(params, c_expr);
      elsif action_name = "FIL_GETS" then
        process_fil_gets(params, c_expr);
      elsif action_name = "FIL_HAS_NEXT" then
        process_fil_has_next(params, c_expr);
      elsif action_name = "FIL_IN" then
        process_fil_in(params, c_expr);
      elsif action_name = "FIL_INPUT_READY" then
        process_fil_input_ready(params, c_expr);
      elsif action_name = "FIL_LINE_READ" then
        process_fil_line_read(params, c_expr);
      elsif action_name = "FIL_LIT" then
        process_fil_lit(params, c_expr);
      elsif action_name = "FIL_LNG" then
        process_fil_lng(params, c_expr);
      elsif action_name = "FIL_NE" then
        process_fil_ne(params, c_expr);
      elsif action_name = "FIL_NIL" then
        process_fil_nil(params, c_expr);
      elsif action_name = "FIL_OPEN" then
        process_fil_open(params, c_expr);
      elsif action_name = "FIL_OUT" then
        process_fil_out(params, c_expr);
      elsif action_name = "FIL_PCLOSE" then
        process_fil_pclose(params, c_expr);
      elsif action_name = "FIL_POPEN" then
        process_fil_popen(params, c_expr);
      elsif action_name = "FIL_PRINT" then
        process_fil_print(params, c_expr);
      elsif action_name = "FIL_SEEK" then
        process_fil_seek(params, c_expr);
      elsif action_name = "FIL_SETBUF" then
        process_fil_setbuf(params, c_expr);
      elsif action_name = "FIL_TELL" then
        process_fil_tell(params, c_expr);
      elsif action_name = "FIL_VALUE" then
        process_fil_value(params, c_expr);
      elsif action_name = "FIL_WRITE" then
        process_fil_write(params, c_expr);
      elsif action_name = "FIL_WORD_READ" then
        process_fil_word_read(params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "FLT" then
      if action_name = "FLT_A2TAN" then
        process_flt_a2tan(params, c_expr);
      elsif action_name = "FLT_ABS" then
        process_flt_abs(params, c_expr);
      elsif action_name = "FLT_ACOS" then
        process_flt_acos(params, c_expr);
      elsif action_name = "FLT_ADD" then
        process_flt_add(params, c_expr);
      elsif action_name = "FLT_ASIN" then
        process_flt_asin(params, c_expr);
      elsif action_name = "FLT_ATAN" then
        process_flt_atan(params, c_expr);
      elsif action_name = "FLT_CAST" then
        process_flt_cast(params, c_expr);
      elsif action_name = "FLT_CEIL" then
        process_flt_ceil(params, c_expr);
      elsif action_name = "FLT_CMP" then
        process_flt_cmp(params, c_expr);
      elsif action_name = "FLT_COS" then
        process_flt_cos(params, c_expr);
      elsif action_name = "FLT_COSH" then
        process_flt_cosh(params, c_expr);
      elsif action_name = "FLT_CPY" then
        process_flt_cpy(params, c_expr);
      elsif action_name = "FLT_DGTS" then
        process_flt_dgts(params, c_expr);
      elsif action_name = "FLT_DIV" then
        process_flt_div(params, c_expr);
      elsif action_name = "FLT_DIV_ASSIGN" then
        process_flt_div_assign(params, c_expr);
      elsif action_name = "FLT_EQ" then
        process_flt_eq(params, c_expr);
      elsif action_name = "FLT_EXP" then
        process_flt_exp(params, c_expr);
      elsif action_name = "FLT_FLOOR" then
        process_flt_floor(params, c_expr);
      elsif action_name = "FLT_GE" then
        process_flt_ge(params, c_expr);
      elsif action_name = "FLT_GROW" then
        process_flt_grow(params, c_expr);
      elsif action_name = "FLT_GT" then
        process_flt_gt(params, c_expr);
      elsif action_name = "FLT_HASHCODE" then
        process_flt_hashcode(params, c_expr);
      elsif action_name = "FLT_ICAST" then
        process_flt_icast(params, c_expr);
      elsif action_name = "FLT_ICONV" then
        process_flt_iconv(params, c_expr);
      elsif action_name = "FLT_IFLT" then
        process_flt_iflt(params, c_expr);
      elsif action_name = "FLT_IPOW" then
        process_flt_ipow(params, c_expr);
      elsif action_name = "FLT_ISNAN" then
        process_flt_isnan(params, c_expr);
      elsif action_name = "FLT_ISNEGATIVEZERO" then
        process_flt_isnegativezero(params, c_expr);
      elsif action_name = "FLT_LE" then
        process_flt_le(params, c_expr);
      elsif action_name = "FLT_LOG" then
        process_flt_log(params, c_expr);
      elsif action_name = "FLT_LOG10" then
        process_flt_log10(params, c_expr);
      elsif action_name = "FLT_LT" then
        process_flt_lt(params, c_expr);
      elsif action_name = "FLT_MULT" then
        process_flt_mult(params, c_expr);
      elsif action_name = "FLT_MULT_ASSIGN" then
        process_flt_mult_assign(params, c_expr);
      elsif action_name = "FLT_NE" then
        process_flt_ne(params, c_expr);
      elsif action_name = "FLT_NEGATE" then
        process_flt_negate(params, c_expr);
      elsif action_name = "FLT_PARSE" then
        process_flt_parse(params, c_expr);
      elsif action_name = "FLT_PLUS" then
        process_flt_plus(params, c_expr);
      elsif action_name = "FLT_POW" then
        process_flt_pow(params, c_expr);
      elsif action_name = "FLT_RAND" then
        process_flt_rand(params, c_expr);
      elsif action_name = "FLT_ROUND" then
        process_flt_round(params, c_expr);
      elsif action_name = "FLT_SBTR" then
        process_flt_sbtr(params, c_expr);
      elsif action_name = "FLT_SCI" then
        process_flt_sci(params, c_expr);
      elsif action_name = "FLT_SHRINK" then
        process_flt_shrink(params, c_expr);
      elsif action_name = "FLT_SIN" then
        process_flt_sin(params, c_expr);
      elsif action_name = "FLT_SINH" then
        process_flt_sinh(params, c_expr);
      elsif action_name = "FLT_SQRT" then
        process_flt_sqrt(params, c_expr);
      elsif action_name = "FLT_STR" then
        process_flt_str(params, c_expr);
      elsif action_name = "FLT_TAN" then
        process_flt_tan(params, c_expr);
      elsif action_name = "FLT_TANH" then
        process_flt_tanh(params, c_expr);
      elsif action_name = "FLT_TRUNC" then
        process_flt_trunc(params, c_expr);
      elsif action_name = "FLT_VALUE" then
        process_flt_value(params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "GKB" then
      drawLibraryUsed := TRUE;
      if action_name = "GKB_BUSY_GETC" then
        process_gkb_busy_getc(params, c_expr);
      elsif action_name = "GKB_GETC" then
        process_gkb_getc(params, c_expr);
      elsif action_name = "GKB_GETS" then
        process_gkb_gets(params, c_expr);
      elsif action_name = "GKB_KEYPRESSED" then
        process_gkb_keypressed(params, c_expr);
      elsif action_name = "GKB_LINE_READ" then
        process_gkb_line_read(params, c_expr);
      elsif action_name = "GKB_RAW_GETC" then
        process_gkb_raw_getc(params, c_expr);
      elsif action_name = "GKB_WINDOW" then
        process_gkb_window(params, c_expr);
      elsif action_name = "GKB_WORD_READ" then
        process_gkb_word_read(params, c_expr);
      elsif action_name = "GKB_BUTTON_PRESSED" then
        process_gkb_button_pressed(params, c_expr);
      elsif action_name = "GKB_BUTTON_XPOS" then
        process_gkb_button_xpos(params, c_expr);
      elsif action_name = "GKB_BUTTON_YPOS" then
        process_gkb_button_ypos(params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "HSH" then
      if action_name = "HSH_CONTAINS" then
        process_hsh_contains(params, c_expr);
      elsif action_name = "HSH_CPY" then
        process_hsh_cpy(params, c_expr);
      elsif action_name = "HSH_CREATE" then
        process_hsh_create(params, c_expr);
      elsif action_name = "HSH_DESTR" then
        process_hsh_destr(params, c_expr);
      elsif action_name = "HSH_EXCL" then
        process_hsh_excl(params, c_expr);
      elsif action_name = "HSH_FOR" then
        process_hsh_for(params, c_expr);
      elsif action_name = "HSH_FOR_DATA_KEY" then
        process_hsh_for_data_key(params, c_expr);
      elsif action_name = "HSH_FOR_KEY" then
        process_hsh_for_key(params, c_expr);
      elsif action_name = "HSH_IDX" then
        process_hsh_idx(function, params, c_expr);
      elsif action_name = "HSH_IDX2" then
        process_hsh_idx2(function, params, c_expr);
      elsif action_name = "HSH_INCL" then
        process_hsh_incl(params, c_expr);
      elsif action_name = "HSH_KEYS" then
        process_hsh_keys(function, params, c_expr);
      elsif action_name = "HSH_LNG" then
        process_hsh_lng(params, c_expr);
      elsif action_name = "HSH_UPDATE" then
        process_hsh_update(function, params, c_expr);
      elsif action_name = "HSH_VALUES" then
        process_hsh_values(params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "INT" then
      if action_name = "INT_ABS" then
        process_int_abs(params, c_expr);
      elsif action_name = "INT_ADD" then
        process_int_add(params, c_expr);
      elsif action_name = "INT_AND" then
        process_int_and(params, c_expr);
      elsif action_name = "INT_AND_ASSIGN" then
        process_int_and_assign(params, c_expr);
      elsif action_name = "INT_BINOM" then
        process_int_binom(params, c_expr);
      elsif action_name = "INT_BIT_LENGTH" then
        process_int_bit_length(params, c_expr);
      elsif action_name = "INT_CMP" then
        process_int_cmp(params, c_expr);
      elsif action_name = "INT_CONV" then
        process_int_conv(params, c_expr);
      elsif action_name = "INT_CPY" then
        process_int_cpy(params, c_expr);
      elsif action_name = "INT_DECR" then
        process_int_decr(params, c_expr);
      elsif action_name = "INT_DIV" then
        process_int_div(params, c_expr);
      elsif action_name = "INT_EQ" then
        process_int_eq(params, c_expr);
      elsif action_name = "INT_FACT" then
        process_int_fact(params, c_expr);
      elsif action_name = "INT_GE" then
        process_int_ge(params, c_expr);
      elsif action_name = "INT_GROW" then
        process_int_grow(params, c_expr);
      elsif action_name = "INT_GT" then
        process_int_gt(params, c_expr);
      elsif action_name = "INT_HASHCODE" then
        process_int_hashcode(params, c_expr);
      elsif action_name = "INT_INCR" then
        process_int_incr(params, c_expr);
      elsif action_name = "INT_LE" then
        process_int_le(params, c_expr);
      elsif action_name = "INT_LOG2" then
        process_int_log2(params, c_expr);
      elsif action_name = "INT_LOWEST_SET_BIT" then
        process_int_lowest_set_bit(params, c_expr);
      elsif action_name = "INT_LPAD0" then
        process_int_lpad0(params, c_expr);
      elsif action_name = "INT_LSHIFT" then
        process_int_lshift(params, c_expr);
      elsif action_name = "INT_LSHIFT_ASSIGN" then
        process_int_lshift_assign(params, c_expr);
      elsif action_name = "INT_LT" then
        process_int_lt(params, c_expr);
      elsif action_name = "INT_MDIV" then
        process_int_mdiv(params, c_expr);
      elsif action_name = "INT_MOD" then
        process_int_mod(params, c_expr);
      elsif action_name = "INT_MULT" then
        process_int_mult(params, c_expr);
      elsif action_name = "INT_MULT_ASSIGN" then
        process_int_mult_assign(params, c_expr);
      elsif action_name = "INT_NE" then
        process_int_ne(params, c_expr);
      elsif action_name = "INT_NEGATE" then
        process_int_negate(params, c_expr);
      elsif action_name = "INT_ODD" then
        process_int_odd(params, c_expr);
      elsif action_name = "INT_OR" then
        process_int_or(params, c_expr);
      elsif action_name = "INT_ORD" then
        process_int_ord(params, c_expr);
      elsif action_name = "INT_OR_ASSIGN" then
        process_int_or_assign(params, c_expr);
      elsif action_name = "INT_PARSE" then
        process_int_parse(params, c_expr);
      elsif action_name = "INT_PLUS" then
        process_int_plus(params, c_expr);
      elsif action_name = "INT_POW" then
        process_int_pow(params, c_expr);
      elsif action_name = "INT_PRED" then
        process_int_pred(params, c_expr);
      elsif action_name = "INT_radix" then
        process_int_radix(params, FALSE, c_expr);
      elsif action_name = "INT_RADIX" then
        process_int_radix(params, TRUE, c_expr);
      elsif action_name = "INT_RAND" then
        process_int_rand(params, c_expr);
      elsif action_name = "INT_REM" then
        process_int_rem(params, c_expr);
      elsif action_name = "INT_RSHIFT" then
        process_int_rshift(params, c_expr);
      elsif action_name = "INT_RSHIFT_ASSIGN" then
        process_int_rshift_assign(params, c_expr);
      elsif action_name = "INT_SBTR" then
        process_int_sbtr(params, c_expr);
      elsif action_name = "INT_SHRINK" then
        process_int_shrink(params, c_expr);
      elsif action_name = "INT_SQRT" then
        process_int_sqrt(params, c_expr);
      elsif action_name = "INT_STR" then
        process_int_str(params, c_expr);
      elsif action_name = "INT_SUCC" then
        process_int_succ(params, c_expr);
      elsif action_name = "INT_TO_BSTRI_BE" then
        process_int_to_bstri_be(params, c_expr);
      elsif action_name = "INT_TO_BSTRI_LE" then
        process_int_to_bstri_le(params, c_expr);
      elsif action_name = "INT_URSHIFT" then
        process_int_urshift(params, c_expr);
      elsif action_name = "INT_URSHIFT_ASSIGN" then
        process_int_urshift_assign(params, c_expr);
      elsif action_name = "INT_VALUE" then
        process_int_value(params, c_expr);
      elsif action_name = "INT_XOR" then
        process_int_xor(params, c_expr);
      elsif action_name = "INT_XOR_ASSIGN" then
        process_int_xor_assign(params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "ITF" then
      if action_name = "ITF_CMP" then
        process_itf_cmp(params, c_expr);
      elsif action_name = "ITF_CONV2" then
        process_itf_conv2(params, c_expr);
      elsif action_name = "ITF_CPY" then
        process_itf_cpy(params, c_expr);
      elsif action_name = "ITF_CPY2" then
        process_itf_cpy(params, c_expr);
      elsif action_name = "ITF_EQ" then
        process_itf_eq(params, c_expr);
      elsif action_name = "ITF_HASHCODE" then
        process_itf_hashcode(params, c_expr);
      elsif action_name = "ITF_NE" then
        process_itf_ne(params, c_expr);
      elsif action_name = "ITF_TO_INTERFACE" then
        process_itf_to_interface(function, params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "KBD" then
      consoleLibraryUsed := TRUE;
      if action_name = "KBD_BUSY_GETC" then
        process_kbd_busy_getc(params, c_expr);
      elsif action_name = "KBD_GETC" then
        process_kbd_getc(params, c_expr);
      elsif action_name = "KBD_GETS" then
        process_kbd_gets(params, c_expr);
      elsif action_name = "KBD_KEYPRESSED" then
        process_kbd_keypressed(params, c_expr);
      elsif action_name = "KBD_LINE_READ" then
        process_kbd_line_read(params, c_expr);
      elsif action_name = "KBD_RAW_GETC" then
        process_kbd_raw_getc(params, c_expr);
      elsif action_name = "KBD_WORD_READ" then
        process_kbd_word_read(params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "PRC" then
      if action_name = "PRC_ARGS" then
        process_prc_args(function, params, c_expr);
      elsif action_name = "PRC_BLOCK" then
        process_prc_block(params, c_expr);
      elsif action_name = "PRC_CASE" then
        process_prc_case(params, c_expr);
      elsif action_name = "PRC_CASE_DEF" then
        process_prc_case_def(params, c_expr);
      elsif action_name = "PRC_CPY" then
        process_prc_cpy(params, c_expr);
      elsif action_name = "PRC_DYNAMIC" then
        process_prc_dynamic(function, params, c_expr);
      elsif action_name = "PRC_EXIT" then
        process_prc_exit(params, c_expr);
      elsif action_name = "PRC_FOR_DOWNTO" then
        process_prc_for_downto(params, c_expr);
      elsif action_name = "PRC_FOR_TO" then
        process_prc_for_to(params, c_expr);
      elsif action_name = "PRC_HSIZE" then
        process_prc_hsize(params, c_expr);
      elsif action_name = "PRC_IF" then
        process_prc_if(params, c_expr);
      elsif action_name = "PRC_IF_ELSIF" then
        process_prc_if_elsif(params, c_expr);
      elsif action_name = "PRC_NOOP" then
        process_prc_noop(function, params, c_expr);
      elsif action_name = "PRC_RAISE" then
        process_prc_raise(function, params, c_expr);
      elsif action_name = "PRC_REPEAT" then
        process_prc_repeat(params, c_expr);
      elsif action_name = "PRC_WHILE" then
        process_prc_while(params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "POL" then
      if action_name = "POL_ADD_CHECK" then
        process_pol_addCheck(params, c_expr);
      elsif action_name = "POL_CLEAR" then
        process_pol_clear(params, c_expr);
      elsif action_name = "POL_CPY" then
        process_pol_cpy(params, c_expr);
      elsif action_name = "POL_GET_CHECK" then
        process_pol_getCheck(params, c_expr);
      elsif action_name = "POL_GET_FINDING" then
        process_pol_getFinding(params, c_expr);
      elsif action_name = "POL_HAS_NEXT" then
        process_pol_hasNext(params, c_expr);
      elsif action_name = "POL_ITER_CHECKS" then
        process_pol_iterChecks(params, c_expr);
      elsif action_name = "POL_ITER_FINDINGS" then
        process_pol_iterFindings(params, c_expr);
      elsif action_name = "POL_NEXT_FILE" then
        process_pol_nextFile(params, c_expr);
      elsif action_name = "POL_POLL" then
        process_pol_poll(params, c_expr);
      elsif action_name = "POL_REMOVE_CHECK" then
        process_pol_removeCheck(params, c_expr);
      elsif action_name = "POL_VALUE" then
        process_pol_value(params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "PRG" then
      if action_name = "PRG_CPY" then
        process_prg_cpy(params, c_expr);
      elsif action_name = "PRG_EQ" then
        process_prg_eq(params, c_expr);
      elsif action_name = "PRG_ERROR_COUNT" then
        process_prg_error_count(params, c_expr);
      elsif action_name = "PRG_EVAL" then
        process_prg_eval(params, c_expr);
      elsif action_name = "PRG_EXEC" then
        process_prg_exec(params, c_expr);
      elsif action_name = "PRG_FIL_PARSE" then
        process_prg_fil_parse(params, c_expr);
      elsif action_name = "PRG_GLOBAL_OBJECTS" then
        process_prg_global_objects(function, params, c_expr);
      elsif action_name = "PRG_MATCH" then
        process_prg_match(params, c_expr);
      elsif action_name = "PRG_MATCH_EXPR" then
        process_prg_match_expr(params, c_expr);
      elsif action_name = "PRG_NAME" then
        process_prg_name(params, c_expr);
      elsif action_name = "PRG_NE" then
        process_prg_ne(params, c_expr);
      elsif action_name = "PRG_OWN_NAME" then
        process_prg_own_name(params, c_expr);
      elsif action_name = "PRG_OWN_PATH" then
        process_prg_own_path(params, c_expr);
      elsif action_name = "PRG_PATH" then
        process_prg_path(params, c_expr);
      elsif action_name = "PRG_STR_PARSE" then
        process_prg_str_parse(params, c_expr);
      elsif action_name = "PRG_SYOBJECT" then
        process_prg_syobject(params, c_expr);
      elsif action_name = "PRG_SYSVAR" then
        process_prg_sysvar(params, c_expr);
      elsif action_name = "PRG_VALUE" then
        process_prg_value(params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "REF" then
      if action_name = "REF_ADDR" then
        process_ref_addr(params, c_expr);
      elsif action_name = "REF_ALLOC" then
        process_ref_alloc(params, c_expr);
      elsif action_name = "REF_ARRMAXIDX" then
        process_ref_arrmaxidx(params, c_expr);
      elsif action_name = "REF_ARRMINIDX" then
        process_ref_arrminidx(params, c_expr);
      elsif action_name = "REF_ARRTOLIST" then
        process_ref_arrtolist(function, params, c_expr);
      elsif action_name = "REF_BODY" then
        process_ref_body(params, c_expr);
      elsif action_name = "REF_CATEGORY" then
        process_ref_category(params, c_expr);
      elsif action_name = "REF_CAT_PARSE" then
        process_ref_cat_parse(params, c_expr);
      elsif action_name = "REF_CAT_STR" then
        process_ref_cat_str(params, c_expr);
      elsif action_name = "REF_CMP" then
        process_ref_cmp(params, c_expr);
      elsif action_name = "REF_CONV" then
        process_ref_conv(params, c_expr);
      elsif action_name = "REF_CPY" then
        process_ref_cpy(params, c_expr);
      elsif action_name = "REF_DEREF" then
        process_ref_deref(function, params, c_expr);
      elsif action_name = "REF_EQ" then
        process_ref_eq(params, c_expr);
      elsif action_name = "REF_FILE" then
        process_ref_file(params, c_expr);
      elsif action_name = "REF_GETREF" then
        process_ref_getref(params, c_expr);
      elsif action_name = "REF_HASHCODE" then
        process_ref_hashcode(params, c_expr);
      elsif action_name = "REF_HSHDATATOLIST" then
        process_ref_hshdatatolist(function, params, c_expr);
      elsif action_name = "REF_HSHKEYSTOLIST" then
        process_ref_hshkeystolist(function, params, c_expr);
      elsif action_name = "REF_ISVAR" then
        process_ref_isvar(params, c_expr);
      elsif action_name = "REF_ITFTOSCT" then
        process_ref_itftosct(params, c_expr);
      elsif action_name = "REF_LINE" then
        process_ref_line(params, c_expr);
      elsif action_name = "REF_LOCAL_CONSTS" then
        process_ref_local_consts(function, params, c_expr);
      elsif action_name = "REF_LOCAL_VARS" then
        process_ref_local_vars(function, params, c_expr);
      elsif action_name = "REF_NE" then
        process_ref_ne(params, c_expr);
      elsif action_name = "REF_NUM" then
        process_ref_num(params, c_expr);
      elsif action_name = "REF_PARAMS" then
        process_ref_params(params, c_expr);
      elsif action_name = "REF_RESINI" then
        process_ref_resini(params, c_expr);
      elsif action_name = "REF_RESULT" then
        process_ref_result(params, c_expr);
      elsif action_name = "REF_SCTTOLIST" then
        process_ref_scttolist(function, params, c_expr);
      elsif action_name = "REF_SELECT" then
        process_ref_select(function, params, c_expr);
      elsif action_name = "REF_SETCATEGORY" then
        process_ref_setcategory(params, c_expr);
      elsif action_name = "REF_SETPARAMS" then
        process_ref_setparams(params, c_expr);
      elsif action_name = "REF_SETTYPE" then
        process_ref_settype(params, c_expr);
      elsif action_name = "REF_SETVAR" then
        process_ref_setvar(params, c_expr);
      elsif action_name = "REF_STR" then
        process_ref_str(params, c_expr);
      elsif action_name = "REF_TRACE" then
        process_ref_trace(params, c_expr);
      elsif action_name = "REF_TYPE" then
        process_ref_type(params, c_expr);
      elsif action_name = "REF_VALUE" then
        process_ref_value(params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "RFL" then
      if action_name = "RFL_APPEND" then
        process_rfl_append(params, c_expr);
      elsif action_name = "RFL_CAT" then
        process_rfl_cat(params, c_expr);
      elsif action_name = "RFL_CPY" then
        process_rfl_cpy(params, c_expr);
      elsif action_name = "RFL_ELEM" then
        process_rfl_elem(params, c_expr);
      elsif action_name = "RFL_ELEMCPY" then
        process_rfl_elemcpy(params, c_expr);
      elsif action_name = "RFL_EQ" then
        process_rfl_eq(params, c_expr);
      elsif action_name = "RFL_FOR" then
        process_rfl_for(params, c_expr);
      elsif action_name = "RFL_FOR_UNTIL" then
        process_rfl_for_until(params, c_expr);
      elsif action_name = "RFL_HEAD" then
        process_rfl_head(params, c_expr);
      elsif action_name = "RFL_IDX" then
        process_rfl_idx(params, c_expr);
      elsif action_name = "RFL_INCL" then
        process_rfl_incl(params, c_expr);
      elsif action_name = "RFL_IPOS" then
        process_rfl_ipos(params, c_expr);
      elsif action_name = "RFL_LNG" then
        process_rfl_lng(params, c_expr);
      elsif action_name = "RFL_MKLIST" then
        process_rfl_mklist(function, params, c_expr);
      elsif action_name = "RFL_NE" then
        process_rfl_ne(params, c_expr);
      elsif action_name = "RFL_NOT_ELEM" then
        process_rfl_not_elem(params, c_expr);
      elsif action_name = "RFL_POS" then
        process_rfl_pos(params, c_expr);
      elsif action_name = "RFL_SETVALUE" then
        process_rfl_setvalue(params, c_expr);
      elsif action_name = "RFL_TAIL" then
        process_rfl_tail(params, c_expr);
      elsif action_name = "RFL_VALUE" then
        process_rfl_value(function, params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "SCT" then
      if action_name = "SCT_ALLOC" then
        process_sct_alloc(params, c_expr);
      elsif action_name = "SCT_CPY" then
        process_sct_cpy(params, c_expr);
      elsif action_name = "SCT_SELECT" then
        process_sct_select(function, params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "SET" then
      if action_name = "SET_ARRLIT" then
        process_set_arrlit(function, params, c_expr);
      elsif action_name = "SET_BASELIT" then
        process_set_baselit(function, params, c_expr);
      elsif action_name = "SET_CARD" then
        process_set_card(params, c_expr);
      elsif action_name = "SET_CMP" then
        process_set_cmp(params, c_expr);
      elsif action_name = "SET_CONV" then
        process_set_conv(params, c_expr);
      elsif action_name = "SET_CPY" then
        process_set_cpy(params, c_expr);
      elsif action_name = "SET_DIFF" then
        process_set_diff(params, c_expr);
      elsif action_name = "SET_ELEM" then
        process_set_elem(params, c_expr);
      elsif action_name = "SET_EQ" then
        process_set_eq(params, c_expr);
      elsif action_name = "SET_EXCL" then
        process_set_excl(params, c_expr);
      elsif action_name = "SET_GE" then
        process_set_ge(params, c_expr);
      elsif action_name = "SET_GT" then
        process_set_gt(params, c_expr);
      elsif action_name = "SET_HASHCODE" then
        process_set_hashcode(params, c_expr);
      elsif action_name = "SET_ICONV" then
        process_set_iconv(params, c_expr);
      elsif action_name = "SET_INCL" then
        process_set_incl(params, c_expr);
      elsif action_name = "SET_INTERSECT" then
        process_set_intersect(params, c_expr);
      elsif action_name = "SET_LE" then
        process_set_le(params, c_expr);
      elsif action_name = "SET_LT" then
        process_set_lt(params, c_expr);
      elsif action_name = "SET_MAX" then
        process_set_max(params, c_expr);
      elsif action_name = "SET_MIN" then
        process_set_min(params, c_expr);
      elsif action_name = "SET_NE" then
        process_set_ne(params, c_expr);
      elsif action_name = "SET_NEXT" then
        process_set_next(params, c_expr);
      elsif action_name = "SET_NOT_ELEM" then
        process_set_not_elem(params, c_expr);
      elsif action_name = "SET_RAND" then
        process_set_rand(params, c_expr);
      elsif action_name = "SET_RANGELIT" then
        process_set_rangelit(function, params, c_expr);
      elsif action_name = "SET_SCONV" then
        process_set_sconv(params, c_expr);
      elsif action_name = "SET_SYMDIFF" then
        process_set_symdiff(params, c_expr);
      elsif action_name = "SET_UNION" then
        process_set_union(params, c_expr);
      elsif action_name = "SET_VALUE" then
        process_set_value(function, params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "SOC" then
      if action_name = "SOC_ACCEPT" then
        process_soc_accept(params, c_expr);
      elsif action_name = "SOC_ADDR_FAMILY" then
        process_soc_addr_family(params, c_expr);
      elsif action_name = "SOC_ADDR_NUMERIC" then
        process_soc_addr_numeric(params, c_expr);
      elsif action_name = "SOC_ADDR_SERVICE" then
        process_soc_addr_service(params, c_expr);
      elsif action_name = "SOC_BIND" then
        process_soc_bind(params, c_expr);
      elsif action_name = "SOC_CLOSE" then
        process_soc_close(params, c_expr);
      elsif action_name = "SOC_CONNECT" then
        process_soc_connect(params, c_expr);
      elsif action_name = "SOC_CPY" then
        process_soc_cpy(params, c_expr);
      elsif action_name = "SOC_EQ" then
        process_soc_eq(params, c_expr);
      elsif action_name = "SOC_GETC" then
        process_soc_getc(params, c_expr);
      elsif action_name = "SOC_GETS" then
        process_soc_gets(params, c_expr);
      elsif action_name = "SOC_GET_ADDR" then
        process_soc_get_addr(params, c_expr);
      elsif action_name = "SOC_GET_HOSTNAME" then
        process_soc_get_hostname(params, c_expr);
      elsif action_name = "SOC_HAS_NEXT" then
        process_soc_has_next(params, c_expr);
      elsif action_name = "SOC_INET_ADDR" then
        process_soc_inet_addr(params, c_expr);
      elsif action_name = "SOC_INET_LOCAL_ADDR" then
        process_soc_inet_local_addr(params, c_expr);
      elsif action_name = "SOC_INET_SERV_ADDR" then
        process_soc_inet_serv_addr(params, c_expr);
      elsif action_name = "SOC_INPUT_READY" then
        process_soc_input_ready(params, c_expr);
      elsif action_name = "SOC_LINE_READ" then
        process_soc_line_read(params, c_expr);
      elsif action_name = "SOC_LISTEN" then
        process_soc_listen(params, c_expr);
      elsif action_name = "SOC_NE" then
        process_soc_ne(params, c_expr);
      elsif action_name = "SOC_RECV" then
        process_soc_recv(params, c_expr);
      elsif action_name = "SOC_SEND" then
        process_soc_send(params, c_expr);
      elsif action_name = "SOC_SOCKET" then
        process_soc_socket(params, c_expr);
      elsif action_name = "SOC_WORD_READ" then
        process_soc_word_read(params, c_expr);
      elsif action_name = "SOC_WRITE" then
        process_soc_write(params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "STR" then
      if action_name = "STR_APPEND" then
        process_str_append(params, c_expr);
      elsif action_name = "STR_CAT" then
        process_str_cat(params, c_expr);
      elsif action_name = "STR_CHIPOS" then
        process_str_chipos(params, c_expr);
      elsif action_name = "STR_CHPOS" then
        process_str_chpos(params, c_expr);
      elsif action_name = "STR_CHSPLIT" then
        process_str_chsplit(params, c_expr);
      elsif action_name = "STR_CLIT" then
        process_str_clit(params, c_expr);
      elsif action_name = "STR_CMP" then
        process_str_cmp(params, c_expr);
      elsif action_name = "STR_CPY" then
        process_str_cpy(params, c_expr);
      elsif action_name = "STR_ELEMCPY" then
        process_str_elemcpy(function, params, c_expr);
      elsif action_name = "STR_EQ" then
        process_str_eq(params, c_expr);
      elsif action_name = "STR_GE" then
        process_str_ge(params, c_expr);
      elsif action_name = "STR_GT" then
        process_str_gt(params, c_expr);
      elsif action_name = "STR_HASHCODE" then
        process_str_hashcode(params, c_expr);
      elsif action_name = "STR_HEAD" then
        process_str_head(params, c_expr);
      elsif action_name = "STR_IDX" then
        process_str_idx(function, params, c_expr);
      elsif action_name = "STR_IPOS" then
        process_str_ipos(params, c_expr);
      elsif action_name = "STR_LE" then
        process_str_le(params, c_expr);
      elsif action_name = "STR_LIT" then
        process_str_lit(params, c_expr);
      elsif action_name = "STR_LNG" then
        process_str_lng(params, c_expr);
      elsif action_name = "STR_LOW" then
        process_str_low(params, c_expr);
      elsif action_name = "STR_LPAD" then
        process_str_lpad(params, c_expr);
      elsif action_name = "STR_LPAD0" then
        process_str_lpad0(params, c_expr);
      elsif action_name = "STR_LT" then
        process_str_lt(params, c_expr);
      elsif action_name = "STR_LTRIM" then
        process_str_ltrim(params, c_expr);
      elsif action_name = "STR_MULT" then
        process_str_mult(params, c_expr);
      elsif action_name = "STR_NE" then
        process_str_ne(params, c_expr);
      elsif action_name = "STR_POS" then
        process_str_pos(params, c_expr);
      elsif action_name = "STR_POSCPY" then
        process_str_poscpy(function, params, c_expr);
      elsif action_name = "STR_PUSH" then
        process_str_push(params, c_expr);
      elsif action_name = "STR_RANGE" then
        process_str_range(params, c_expr);
      elsif action_name = "STR_RCHIPOS" then
        process_str_rchipos(params, c_expr);
      elsif action_name = "STR_RCHPOS" then
        process_str_rchpos(params, c_expr);
      elsif action_name = "STR_REPL" then
        process_str_repl(params, c_expr);
      elsif action_name = "STR_RIPOS" then
        process_str_ripos(params, c_expr);
      elsif action_name = "STR_RPAD" then
        process_str_rpad(params, c_expr);
      elsif action_name = "STR_RPOS" then
        process_str_rpos(params, c_expr);
      elsif action_name = "STR_RTRIM" then
        process_str_rtrim(params, c_expr);
      elsif action_name = "STR_SPLIT" then
        process_str_split(params, c_expr);
      elsif action_name = "STR_STR" then
        process_str_str(params, c_expr);
      elsif action_name = "STR_SUBSTR" then
        process_str_substr(params, c_expr);
      elsif action_name = "STR_TAIL" then
        process_str_tail(params, c_expr);
      elsif action_name = "STR_TOUTF8" then
        process_str_toutf8(params, c_expr);
      elsif action_name = "STR_TRIM" then
        process_str_trim(params, c_expr);
      elsif action_name = "STR_UP" then
        process_str_up(params, c_expr);
      elsif action_name = "STR_UTF8TOSTRI" then
        process_str_utf8tostri(params, c_expr);
      elsif action_name = "STR_VALUE" then
        process_str_value(params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "TIM" then
      if action_name = "TIM_AWAIT" then
        process_tim_await(params, c_expr);
      elsif action_name = "TIM_FROM_TIMESTAMP" then
        process_tim_from_timestamp(params, c_expr);
      elsif action_name = "TIM_NOW" then
        process_tim_now(params, c_expr);
      elsif action_name = "TIM_SET_LOCAL_TZ" then
        process_tim_set_local_tz(params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "TYP" then
      if action_name = "TYP_CMP" then
        process_typ_cmp(params, c_expr);
      elsif action_name = "TYP_CPY" then
        process_typ_cpy(params, c_expr);
      elsif action_name = "TYP_EQ" then
        process_typ_eq(params, c_expr);
      elsif action_name = "TYP_FUNC" then
        process_typ_func(params, c_expr);
      elsif action_name = "TYP_HASHCODE" then
        process_typ_hashcode(params, c_expr);
      elsif action_name = "TYP_ISDERIVED" then
        process_typ_isderived(params, c_expr);
      elsif action_name = "TYP_ISFUNC" then
        process_typ_isfunc(params, c_expr);
      elsif action_name = "TYP_ISVARFUNC" then
        process_typ_isvarfunc(params, c_expr);
      elsif action_name = "TYP_MATCHOBJ" then
        process_typ_matchobj(params, c_expr);
      elsif action_name = "TYP_META" then
        process_typ_meta(params, c_expr);
      elsif action_name = "TYP_NE" then
        process_typ_ne(params, c_expr);
      elsif action_name = "TYP_NUM" then
        process_typ_num(params, c_expr);
      elsif action_name = "TYP_RESULT" then
        process_typ_result(params, c_expr);
      elsif action_name = "TYP_STR" then
        process_typ_str(params, c_expr);
      elsif action_name = "TYP_VALUE" then
        process_typ_value(params, c_expr);
      elsif action_name = "TYP_VARCONV" then
        process_typ_varconv(params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    elsif action_prefix = "UT8" then
      if action_name = "UT8_GETC" then
        process_ut8_getc(params, c_expr);
      elsif action_name = "UT8_GETS" then
        process_ut8_gets(params, c_expr);
      elsif action_name = "UT8_LINE_READ" then
        process_ut8_line_read(params, c_expr);
      elsif action_name = "UT8_SEEK" then
        process_ut8_seek(params, c_expr);
      elsif action_name = "UT8_WORD_READ" then
        process_ut8_word_read(params, c_expr);
      elsif action_name = "UT8_WRITE" then
        process_ut8_write(params, c_expr);
      else
        process_unknown_action(action_name, c_expr);
      end if;
    else
      process_unknown_action(action_name, c_expr);
    end if;
  end func;


const func boolean: isPointerParam (in reference: a_param) is
  return category(a_param) = REFPARAMOBJECT and
        (not valueIsAtHeap(a_param) or isVar(a_param));


const func boolean: isCopyParam (in reference: a_param) is
  return category(a_param) = VALUEPARAMOBJECT and
        valueIsAtHeap(a_param);


const func boolean: isInOutParam (in reference: a_param) is
  return category(a_param) = REFPARAMOBJECT and isVar(a_param);


const func boolean: canTakeAddress (in reference: an_expression) is func

  result
    var boolean: canTakeAddress is TRUE;
  local
    var category: exprCategory is category.value;
    var string: action_name is "";
  begin
    exprCategory := category(an_expression);
    if (exprCategory = INTOBJECT or
        exprCategory = CHAROBJECT or
        exprCategory = FLOATOBJECT) and
        not isVar(an_expression) then
      canTakeAddress := FALSE;
    end if;
    if isFunc(getType(an_expression)) then
      canTakeAddress := FALSE;
    end if;
    if exprCategory = CALLOBJECT then
      if category(getValue(an_expression, ref_list)[1]) = ACTOBJECT then
        action_name := str(getValue(getValue(an_expression, ref_list)[1], ACTION));
        if  action_name = "ARR_IDX" or
            action_name = "SCT_SELECT" then
          canTakeAddress := TRUE;
        end if;
      end if;
    end if;
  end func;


const proc: process_constenumobject (in reference: function, in ref_list: params,
    inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "/*constenumobject*/";
    noop_params(formalParams(function), params, c_expr);
  end func;


const func boolean: param_list_okay (in ref_list: formal_params) is func

  result
    var boolean: okay is TRUE;
  local
    var reference: obj is NIL;
    var category: paramCategory is category.value;
  begin
    for obj range formal_params do
      paramCategory := category(obj);
      if paramCategory <> SYMBOLOBJECT and paramCategory <> TYPEOBJECT then
        if isFunc(getType(obj)) then
          okay := FALSE;
        end if;
      end if;
    end for;
  end func;


const func boolean: containsFunctionCall (in reference: function,
    in reference: current_expression) is func

  result
    var boolean: containsCall is FALSE;
  local
    var category: exprCategory is category.value;
    var ref_list: params is ref_list.EMPTY;
    var reference: currentFunction is NIL;
    var integer: paramNum is 0;
  begin
    exprCategory := category(current_expression);
    if exprCategory = MATCHOBJECT or exprCategory = CALLOBJECT then
      params := getValue(current_expression, ref_list);
      currentFunction := params[1];
      if currentFunction = function then
        containsCall := TRUE;
      else
        paramNum := 2;
        while paramNum <= length(params) and not containsCall do
          containsCall := containsFunctionCall(function, params[paramNum]);
          incr(paramNum);
        end while;
      end if;
    elsif exprCategory = BLOCKOBJECT then
      containsCall := current_expression = function;
    end if;
  end func;


const func boolean: recursiveFunctionCall (in reference: function,
    in reference: current_expression) is func

  result
    var boolean: recursiveCall is FALSE;
  local
    var reference: obj is NIL;
  begin
    recursiveCall := containsFunctionCall(function, current_expression);
    if not recursiveCall then
      for obj range localConsts(function) do
        if not recursiveCall and category(obj) = BLOCKOBJECT then
          recursiveCall := containsFunctionCall(function, body(obj));
        end if;
      end for;
    end if;
  end func;


const proc: process_local_declaration (in reference: current_object, in var reference: object_value,
    inout expr_type: c_expr) is func

  local
    var type: objectType is void;
    var category: valueCategory is category.value;
    var expr_type: c_declaration is expr_type.value;
    var expr_type: c_value is expr_type.value;
    var string: param_name is "";
    var string: param_value is "";
  begin
    c_declaration.temp_num := c_expr.temp_num;
    valueCategory := category(object_value);
    objectType := getType(current_object);
    if objectType = getType(object_value) and objectType not in typeCategory then
      typeCategory @:= [objectType] valueCategory;
    end if;
    declare_type_if_necessary(objectType, global_c_expr);
    c_declaration.temp_decls &:= diagnosticLine(current_object);
    c_declaration.temp_decls &:= type_name(objectType);
    c_declaration.temp_decls &:= " o_";
    create_name(current_object, c_declaration.temp_decls);
    if objectType in typeCategory and typeCategory[objectType] = INTERFACEOBJECT then
      if valueCategory = INTERFACEOBJECT then
        object_value := interfaceToStruct(object_value);
        valueCategory := category(object_value);
      end if;
      if isVar(object_value) then
        c_declaration.temp_assigns &:= diagnosticLine(current_object);
        c_declaration.temp_assigns &:= "o_";
        create_name(current_object, c_declaration.temp_assigns);
        c_declaration.temp_assigns &:= "=itfCreate(o_";
        create_name(object_value, c_declaration.temp_assigns);
        c_declaration.temp_assigns &:= "/* ";
        c_declaration.temp_assigns &:= str(valueCategory);
        c_declaration.temp_assigns &:= " */);\n";
      else
        if object_value not in const_table then
          const_table @:= [object_value] length(const_table);
        end if;
        c_declaration.temp_assigns &:= diagnosticLine(current_object);
        c_declaration.temp_assigns &:= "o_";
        create_name(current_object, c_declaration.temp_assigns);
        c_declaration.temp_assigns &:= "=(";
        c_declaration.temp_assigns &:= type_name(objectType);
        c_declaration.temp_assigns &:= ")(itfCreate(itf[";
        c_declaration.temp_assigns &:= str(const_table[object_value]);
        c_declaration.temp_assigns &:= "]));\n";
      end if;
      process_destr_declaration(objectType, global_c_expr);
      param_name := "o_";
      create_name(current_object, param_name);
      process_destr_call(objectType, param_name, c_declaration.temp_frees);
    elsif valueCategory = TYPEOBJECT then
      c_declaration.temp_decls &:= "=";
      c_declaration.temp_decls &:= typeLiteral(getValue(object_value, type));
    elsif valueCategory = INTOBJECT then
      c_declaration.temp_decls &:= "=";
      c_declaration.temp_decls &:= str(getValue(object_value, integer));
    elsif valueCategory = BIGINTOBJECT then
      c_declaration.temp_assigns &:= diagnosticLine(current_object);
      c_declaration.temp_assigns &:= "o_";
      create_name(current_object, c_declaration.temp_assigns);
      c_declaration.temp_assigns &:= "=";
      process_big_create_call(getValue(object_value, bigInteger), c_declaration.temp_assigns);
      c_declaration.temp_frees &:= "bigDestr(o_";
      create_name(current_object, c_declaration.temp_frees);
      c_declaration.temp_frees &:= ");\n";
    elsif valueCategory = CHAROBJECT then
      c_declaration.temp_decls &:= "=";
      c_declaration.temp_decls &:= charLiteral(getValue(object_value, char));
    elsif valueCategory = FLOATOBJECT then
      c_declaration.temp_decls &:= "=";
      c_declaration.temp_decls &:= floatLiteral(getValue(object_value, float));
    elsif valueCategory = STRIOBJECT then
      c_declaration.temp_assigns &:= diagnosticLine(current_object);
      c_declaration.temp_assigns &:= "o_";
      create_name(current_object, c_declaration.temp_assigns);
      c_declaration.temp_assigns &:= "=";
      process_str_create_call(getValue(object_value, string), c_declaration.temp_assigns);
      c_declaration.temp_frees &:= "strDestr(o_";
      create_name(current_object, c_declaration.temp_frees);
      c_declaration.temp_frees &:= ");\n";
    elsif valueCategory = BSTRIOBJECT then
      c_declaration.temp_assigns &:= diagnosticLine(current_object);
      c_declaration.temp_assigns &:= "o_";
      create_name(current_object, c_declaration.temp_assigns);
      c_declaration.temp_assigns &:= "=bstCreate(";
      c_declaration.temp_assigns &:= bstriLiteral(getValue(object_value, bstring));
      c_declaration.temp_assigns &:= ");\n";
      c_declaration.temp_frees &:= "bstDestr(o_";
      create_name(current_object, c_declaration.temp_frees);
      c_declaration.temp_frees &:= ");\n";
    elsif valueCategory = SETOBJECT then
      c_declaration.temp_assigns &:= diagnosticLine(current_object);
      c_declaration.temp_assigns &:= "o_";
      create_name(current_object, c_declaration.temp_assigns);
      c_declaration.temp_assigns &:= "=setCreate(";
      c_declaration.temp_assigns &:= bitsetLiteral(getValue(object_value, bitset));
      c_declaration.temp_assigns &:= ");\n";
      c_declaration.temp_frees &:= "setDestr(o_";
      create_name(current_object, c_declaration.temp_frees);
      c_declaration.temp_frees &:= ");\n";
    elsif valueCategory = REFOBJECT then
      c_declaration.temp_decls &:= "=";
      reference_value(getValue(object_value, reference), c_value);
      c_declaration.temp_decls &:= c_value.expr;
    elsif valueCategory = REFLISTOBJECT then
      c_declaration.temp_decls &:= "=";
      ref_list_value(getValue(object_value, ref_list), c_value);
      c_declaration.temp_decls &:= c_value.expr;
      c_declaration.temp_frees &:= "rflDestr(o_";
      create_name(current_object, c_declaration.temp_frees);
      c_declaration.temp_frees &:= ");\n";
    elsif valueCategory = FILEOBJECT then
      c_declaration.temp_decls &:= "=NULL";
    elsif valueCategory = SOCKETOBJECT then
      c_declaration.temp_decls &:= "=-1";
    elsif valueCategory = POLLOBJECT then
      c_declaration.temp_decls &:= "=NULL";
    elsif valueCategory = ARRAYOBJECT then
      if object_value not in const_table then
        const_table @:= [object_value] length(const_table);
      end if;
      process_create_declaration(objectType, global_c_expr);
      process_destr_declaration(objectType, global_c_expr);
      c_declaration.temp_assigns &:= diagnosticLine(current_object);
      c_declaration.temp_assigns &:= "o_";
      create_name(current_object, c_declaration.temp_assigns);
      c_declaration.temp_assigns &:= "=";
      param_value := "arr[";
      param_value &:= str(const_table[object_value]);
      param_value &:= "]";
      process_create_call(objectType,
          param_value, c_declaration.temp_assigns);
      c_declaration.temp_assigns &:= ";\n";
      param_name := "o_";
      create_name(current_object, param_name);
      process_destr_call(objectType, param_name, c_declaration.temp_frees);
    elsif valueCategory = STRUCTOBJECT then
      if object_value not in const_table then
        const_table @:= [object_value] length(const_table);
      end if;
      process_create_declaration(objectType, global_c_expr);
      process_destr_declaration(objectType, global_c_expr);
      c_declaration.temp_assigns &:= diagnosticLine(current_object);
      c_declaration.temp_assigns &:= "o_";
      create_name(current_object, c_declaration.temp_assigns);
      c_declaration.temp_assigns &:= "=";
      param_value := "sct[";
      param_value &:= str(const_table[object_value]);
      param_value &:= "]";
      process_create_call(objectType,
          param_value, c_declaration.temp_assigns);
      c_declaration.temp_assigns &:= ";\n";
      param_name := "o_";
      create_name(current_object, param_name);
      process_destr_call(objectType, param_name, c_declaration.temp_frees);
    elsif valueCategory = HASHOBJECT then
      if length(hashKeysToList(object_value)) = 0 then
        process_destr_declaration(objectType, global_c_expr);
        incr(countOptimizations);
        c_declaration.temp_assigns &:= diagnosticLine(current_object);
        c_declaration.temp_assigns &:= "o_";
        create_name(current_object, c_declaration.temp_assigns);
        c_declaration.temp_assigns &:= "=hshEmpty();\n";
      else
        if object_value not in const_table then
          const_table @:= [object_value] length(const_table);
        end if;
        process_create_declaration(objectType, global_c_expr);
        process_destr_declaration(objectType, global_c_expr);
        c_declaration.temp_assigns &:= diagnosticLine(current_object);
        c_declaration.temp_assigns &:= "o_";
        create_name(current_object, c_declaration.temp_assigns);
        c_declaration.temp_assigns &:= "=";
        param_value := "hsh[";
        param_value &:= str(const_table[object_value]);
        param_value &:= "]";
        process_create_call(objectType,
            param_value, c_declaration.temp_assigns);
        c_declaration.temp_assigns &:= ";\n";
      end if;
      param_name := "o_";
      create_name(current_object, param_name);
      process_destr_call(objectType, param_name, c_declaration.temp_frees);
    elsif valueCategory = INTERFACEOBJECT then
      if object_value not in const_table then
        const_table @:= [object_value] length(const_table);
      end if;
      c_declaration.temp_assigns &:= diagnosticLine(current_object);
      c_declaration.temp_assigns &:= "o_";
      create_name(current_object, c_declaration.temp_assigns);
      c_declaration.temp_assigns &:= "=itf[";
      c_declaration.temp_assigns &:= str(const_table[object_value]);
      c_declaration.temp_assigns &:= "];\n";
      process_destr_declaration(objectType, global_c_expr);
      param_name := "o_";
      create_name(current_object, param_name);
      process_destr_call(objectType, param_name, c_declaration.temp_frees);
    elsif valueCategory = WINOBJECT then
      if getValue(object_value, PRIMITIVE_WINDOW) = PRIMITIVE_WINDOW.value then
        c_declaration.temp_decls &:= "=NULL";
      else
        c_declaration.temp_assigns &:= diagnosticLine(current_object);
        c_declaration.temp_assigns &:= "o_";
        create_name(current_object, c_declaration.temp_assigns);
        c_declaration.temp_assigns &:= "=winCreate(";
        c_declaration.temp_assigns &:= windowLiteral(getValue(object_value, PRIMITIVE_WINDOW));
        c_declaration.temp_assigns &:= ");\n";
      end if;
      c_declaration.temp_frees &:= "drwDestr(o_";
      create_name(current_object, c_declaration.temp_frees);
      c_declaration.temp_frees &:= ");\n";
    elsif valueCategory = PROGOBJECT then
      c_declaration.temp_decls &:= "=NULL";
      c_declaration.temp_frees &:= "prgDestr(o_";
      create_name(current_object, c_declaration.temp_frees);
      c_declaration.temp_frees &:= ");\n";
    elsif valueCategory = CONSTENUMOBJECT then
      c_declaration.temp_decls &:= "=";
      c_declaration.temp_decls &:= enum_value(getValue(object_value, reference));
    elsif valueCategory = VARENUMOBJECT then
      c_declaration.temp_decls &:= "=";
      c_declaration.temp_decls &:= enum_value(getValue(object_value, reference));
    elsif valueCategory = ENUMLITERALOBJECT then
      c_declaration.temp_decls &:= "=o_";
      create_name(object_value, c_declaration.temp_decls);
    elsif valueCategory = CALLOBJECT then
      param_name := "o_";
      create_name(current_object, param_name);
      c_value.temp_num := c_declaration.temp_num;
      getTemporaryToResultExpr(object_value, c_value);
      c_declaration.temp_num := c_value.temp_num;
      c_expr.temp_decls   &:= c_value.temp_decls;
      c_expr.temp_assigns &:= c_value.temp_assigns;
      c_expr.temp_frees   &:= c_value.temp_frees;
      c_expr.temp_to_null &:= c_value.temp_to_null;
      c_declaration.temp_assigns &:= diagnosticLine(current_object);
      c_declaration.temp_assigns &:= param_name;
      c_declaration.temp_assigns &:= "=(";
      c_declaration.temp_assigns &:= type_name(objectType);
      c_declaration.temp_assigns &:= ")(";
      c_declaration.temp_assigns &:= c_value.result_expr;
      c_declaration.temp_assigns &:= ");\n";
      process_destr_declaration(objectType, global_c_expr);
      process_destr_call(objectType, param_name, c_declaration.temp_frees);
    elsif valueCategory = BLOCKOBJECT then
      create_name(object_value, objNumber(object_value), param_name);
      c_value.temp_num := c_declaration.temp_num;
      processFuncValue(param_name, objectType, object_value, c_value);
      c_declaration.temp_num := c_value.temp_num;
      c_declaration.temp_decls &:= "=";
      c_declaration.temp_decls &:= c_value.expr;
      c_expr.temp_decls   &:= c_value.temp_decls;
      c_expr.temp_assigns &:= c_value.temp_assigns;
      c_expr.temp_frees   &:= c_value.temp_frees;
      c_expr.temp_to_null &:= c_value.temp_to_null;
      function_declared @:= [object_value] TRUE;
    elsif valueCategory = ACTOBJECT then
      c_declaration.temp_decls &:= "=NULL";
    else
      c_declaration.temp_decls &:= "/* ";
      c_declaration.temp_decls &:= str(valueCategory);
      c_declaration.temp_decls &:= " */";
    end if;
    c_declaration.temp_decls &:= ";\n";
    c_expr.temp_num := c_declaration.temp_num;
    c_expr.temp_decls   &:= c_declaration.temp_decls;
    c_expr.temp_assigns &:= c_declaration.temp_assigns;
    c_expr.temp_frees   &:= c_declaration.temp_frees;
    c_expr.temp_to_null &:= c_declaration.temp_to_null;
  end func;


const proc: process_local_var_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  local
    var ref_list: objects is ref_list.EMPTY;
    var reference: obj is NIL;
  begin
    objects := localVars(current_object);
    for obj range objects do
      process_local_declaration(obj, getValue(obj, reference), c_expr);
    end for;
  end func;


const proc: push_inline_param_value (in reference: obj, in reference: value) is func

  begin
    if obj not in inline_param_value then
      inline_param_value @:= [obj] ref_list.EMPTY;
    end if;
    incl(inline_param_value[obj], value);
  end func;


const proc: pop_inline_param_value (in reference: obj) is func

  begin
    inline_param_value @:= [obj] inline_param_value[obj][2 ..];
  end func;


const proc: assign_inline_param (in reference: formal_param,
    in reference: actual_param, inout expr_type: c_expr) is func

  local
    var integer: temp_num is 0;
  begin
    if isPointerParam(formal_param) then
      if category(actual_param) = REFPARAMOBJECT then
        if actual_param in inline_param then
          c_expr.expr &:= "par_";
          c_expr.expr &:= str(inline_param[actual_param][1]);
          c_expr.expr &:= "_";
        end if;
        c_expr.expr &:= "o_";
        create_name(actual_param, c_expr.expr);
      elsif canTakeAddress(actual_param) then
        c_expr.expr &:= "&(";
        process_expr(actual_param, c_expr);
        c_expr.expr &:= ")";
      else
        incr(c_expr.temp_num);
        temp_num := c_expr.temp_num;
        c_expr.temp_decls &:= type_name(getExprResultType(actual_param));
        c_expr.temp_decls &:= " tmp_";
        c_expr.temp_decls &:= str(temp_num);
        c_expr.temp_decls &:= ";\n";
        c_expr.expr &:= "(tmp_";
        c_expr.expr &:= str(temp_num);
        c_expr.expr &:= "=(";
        c_expr.expr &:= type_name(getExprResultType(actual_param));
        c_expr.expr &:= ")(";
        getAnyParamToExpr(actual_param, c_expr);
        c_expr.expr &:= "), &tmp_";
        c_expr.expr &:= str(temp_num);
        c_expr.expr &:= ")";
      end if;
    else
      getAnyParamToExpr(actual_param, c_expr);
    end if;
  end func;


const proc: push_inline_func_param (in reference: formal_param,
    in reference: actual_param, inout expr_type: c_expr) is func

  local
    var type: param_type is void;
    var string: param_name is "";
    var expr_type: actual_param_expr is expr_type.value;
    var integer: temp_num is 0;
  begin
    if category(formal_param) <> SYMBOLOBJECT then
      param_type := getType(formal_param);
      if isFunc(param_type) then
        c_expr.expr &:= "/* push proc param o_";
        create_name2(formal_param, c_expr.expr);
        c_expr.expr &:= " */\n";
        push_inline_param_value(formal_param, actual_param);
      else
        if not isVar(formal_param) and not isPointerParam(formal_param) then
          if useConstPrefix(param_type) then
            c_expr.temp_decls &:= "const_";
          end if;
        end if;
        c_expr.temp_decls &:= type_name(param_type);
        c_expr.temp_decls &:= " ";
        if isPointerParam(formal_param) then
          c_expr.temp_decls &:= "*";
        end if;
        incr(c_expr.temp_num);
        temp_num := c_expr.temp_num;
        if formal_param in inline_param then
          inline_param @:= [formal_param] [] (temp_num) & inline_param[formal_param];
        else
          inline_param @:= [formal_param] [] (temp_num);
        end if;
        c_expr.temp_decls &:= "par_";
        c_expr.temp_decls &:= str(temp_num);
        c_expr.temp_decls &:= "_o_";
        create_name(formal_param, c_expr.temp_decls);
        c_expr.temp_decls &:= ";\n";
        c_expr.expr &:= "par_";
        c_expr.expr &:= str(temp_num);
        c_expr.expr &:= "_";
        c_expr.expr &:= "o_";
        create_name(formal_param, c_expr.expr);
        c_expr.expr &:= "=";
        if isCopyParam(formal_param) then
          create_name(formal_param, param_name);
          prepareAnyParamTemporarys(actual_param, actual_param_expr, c_expr);
          if actual_param_expr.result_expr <> "" then
            c_expr.expr &:= actual_param_expr.result_expr;
          else
            process_create_declaration(getType(formal_param), global_c_expr);
            process_create_call(getType(formal_param),
                actual_param_expr.expr, c_expr.expr);
          end if;
          process_destr_declaration(getType(formal_param), global_c_expr);
          process_destr_call(getType(formal_param),
              "o_" & param_name, c_expr.temp_frees);
        else
          assign_inline_param(formal_param, actual_param, c_expr);
        end if;
        c_expr.expr &:= ",\n";
      end if;
    end if;
  end func;


const proc: push_inline_func_params (in ref_list: formal_params,
    in ref_list: actual_params, inout expr_type: c_expr) is func

  local
    var integer: number is 0;
  begin
    for number range 1 to length(formal_params) do
      push_inline_func_param(formal_params[number], actual_params[number], c_expr);
    end for;
  end func;


const proc: pop_inline_func_param (in reference: formal_param,
    inout string: expr) is func

  local
    var category: paramCategory is category.value;
    var type: param_type is void;
  begin
    paramCategory := category(formal_param);
    if paramCategory <> SYMBOLOBJECT then
      param_type := getType(formal_param);
      if isFunc(param_type) then
        expr &:= "/* pop proc param o_";
        create_name2(formal_param, expr);
        expr &:= " */\n";
        pop_inline_param_value(formal_param);
      else
        if length(inline_param[formal_param]) = 1 then
          excl(inline_param, formal_param);
        else
          inline_param @:= [formal_param] inline_param[formal_param][2 ..];
        end if;
      end if;
    end if;
  end func;


const proc: pop_inline_func_params (in ref_list: formal_params,
    inout string: expr) is func

  local
    var integer: number is 0;
  begin
    for number range 1 to length(formal_params) do
      pop_inline_func_param(formal_params[number], expr);
    end for;
  end func;


const proc: process_inline_func (in reference: function,
    in ref_list: actual_params, inout expr_type: c_expr) is func

  local
    var type: function_type is void;
    var type: result_type is void;
    var ref_list: formal_params is ref_list.EMPTY;
    var expr_type: inline_body is expr_type.value;
    var expr_type: inline_decls is expr_type.value;
    var reference: result_object is NIL;
  begin
    function_type := getType(function);
    result_type := resultType(function_type);
    formal_params := formalParams(function);
    inline_decls.temp_num := c_expr.temp_num;
    push_inline_func_params(formal_params, actual_params, inline_decls);
    process_local_var_declaration(function, inline_decls);
    result_object := resultVar(function);
    if result_object <> NIL then
      inline_decls.temp_decls &:= type_name(getType(result_object));
      inline_decls.temp_decls &:= " o_";
      create_name(result_object, inline_decls.temp_decls);
      inline_decls.temp_decls &:= ";\n";
    end if;
    c_expr.temp_num := inline_decls.temp_num;
    c_expr.temp_decls &:= inline_decls.temp_decls;
    c_expr.temp_frees &:= inline_decls.temp_frees;
    c_expr.temp_to_null &:= inline_decls.temp_to_null;
    prepareAnyParamTemporarys(body(function), inline_body, c_expr);
    if inline_body.result_expr <> "" then
      c_expr.result_expr &:= "\n/* ";
      if isVarfunc(function_type) then
        c_expr.result_expr &:= "var";
      end if;
      c_expr.result_expr &:= "inline func o_";
      create_name2(function, c_expr.result_expr);
      c_expr.result_expr &:= " */ ";
      if isVarfunc(function_type) then
        c_expr.result_expr &:= "*";
      end if;
      c_expr.result_expr &:= "((";
      c_expr.result_expr &:= type_name(result_type);
      if isVarfunc(function_type) then
        c_expr.result_expr &:= " *";
      end if;
      c_expr.result_expr &:= ")(\n";
      c_expr.result_expr &:= inline_decls.temp_assigns;
      c_expr.result_expr &:= inline_decls.expr;
      # c_expr.result_decl &:= inline_body.result_decl;
      # c_expr.result_free &:= inline_body.result_free;
      # c_expr.result_to_null &:= inline_body.result_to_null;
      if isVarfunc(function_type) then
        c_expr.result_expr &:= "&(";
        c_expr.result_expr &:= inline_body.expr;
        c_expr.result_expr &:= ")";
      else
        c_expr.result_expr &:= inline_body.result_expr;
      end if;
      c_expr.result_expr &:= "\n";
      pop_inline_func_params(formal_params, c_expr.result_expr);
      c_expr.result_expr &:= ")) /* ";
      if isVarfunc(function_type) then
        c_expr.result_expr &:= "var";
      end if;
      c_expr.result_expr &:= "inline func o_";
      create_name2(function, c_expr.result_expr);
      c_expr.result_expr &:= " */\n";
    else
      c_expr.expr &:= "\n/* ";
      if isVarfunc(function_type) then
        c_expr.expr &:= "var";
      end if;
      c_expr.expr &:= "inline func o_";
      create_name2(function, c_expr.expr);
      c_expr.expr &:= " */ ";
      if isVarfunc(function_type) then
        c_expr.expr &:= "*";
      end if;
      c_expr.expr &:= "((";
      c_expr.expr &:= type_name(result_type);
      if isVarfunc(function_type) then
        c_expr.expr &:= " *";
      end if;
      c_expr.expr &:= ")(\n";
      c_expr.expr &:= inline_decls.temp_assigns;
      c_expr.expr &:= inline_decls.expr;
      if isVarfunc(function_type) then
        c_expr.expr &:= "&(";
        c_expr.expr &:= inline_body.expr;
        c_expr.expr &:= ")";
      else
        c_expr.expr &:= inline_body.expr;
      end if;
      c_expr.expr &:= "\n";
      pop_inline_func_params(formal_params, c_expr.expr);
      c_expr.expr &:= ")) /* ";
      if isVarfunc(function_type) then
        c_expr.expr &:= "var";
      end if;
      c_expr.expr &:= "inline func o_";
      create_name2(function, c_expr.expr);
      c_expr.expr &:= " */\n";
    end if;
  end func;


const proc: push_inline_proc_param (in reference: formal_param,
    in reference: actual_param, inout expr_type: c_expr) is func

  local
    var type: param_type is void;
    var string: param_name is "";
    var expr_type: actual_param_expr is expr_type.value;
    var expr_type: assign_decls is expr_type.value;
  begin
    if category(formal_param) <> SYMBOLOBJECT then
      param_type := getType(formal_param);
      if isFunc(param_type) then
        c_expr.temp_decls &:= "/* push proc param o_";
        create_name2(formal_param, c_expr.temp_decls);
        c_expr.temp_decls &:= " */\n";
        push_inline_param_value(formal_param, actual_param);
      elsif isCopyParam(formal_param) then
        create_name(formal_param, param_name);
        if not isVar(formal_param) and useConstPrefix(param_type) then
          c_expr.temp_decls &:= "const_";
        end if;
        c_expr.temp_decls &:= type_name(param_type);
        c_expr.temp_decls &:= " o_";
        c_expr.temp_decls &:= param_name;
        c_expr.temp_decls &:= ";\n";
        c_expr.temp_assigns &:= "o_";
        c_expr.temp_assigns &:= param_name;
        c_expr.temp_assigns &:= "=";
        prepareAnyParamTemporarys(actual_param, actual_param_expr, c_expr);
        if actual_param_expr.result_expr <> "" then
          c_expr.temp_assigns &:= actual_param_expr.result_expr;
        else
          process_create_declaration(getType(formal_param), global_c_expr);
          process_create_call(getType(formal_param),
              actual_param_expr.expr, c_expr.temp_assigns);
        end if;
        c_expr.temp_assigns &:= ";\n";
        process_destr_declaration(getType(formal_param), global_c_expr);
        process_destr_call(getType(formal_param),
            "o_" & param_name, c_expr.temp_frees);
      else
        assign_decls.temp_num := c_expr.temp_num;
        assign_inline_param(formal_param, actual_param, assign_decls);
        c_expr.temp_num := assign_decls.temp_num;
        c_expr.temp_decls &:= assign_decls.temp_decls;
        c_expr.temp_assigns &:= assign_decls.temp_assigns;
        c_expr.temp_frees &:= assign_decls.temp_frees;
        if not isVar(formal_param) then
          c_expr.temp_decls &:= "const ";
          if not isPointerParam(formal_param) and useConstPrefix(param_type) then
            c_expr.temp_decls &:= "const_";
          end if;
        end if;
        c_expr.temp_decls &:= type_name(param_type);
        c_expr.temp_decls &:= " ";
        if isPointerParam(formal_param) then
          c_expr.temp_decls &:= "*const ";
        end if;
        c_expr.temp_decls &:= "o_";
        create_name(formal_param, c_expr.temp_decls);
        if assign_decls.expr <> "" then
          c_expr.temp_decls &:= "=";
          c_expr.temp_decls &:= assign_decls.expr;
        end if;
        c_expr.temp_decls &:= ";\n";
      end if;
    end if;
  end func;


const proc: push_inline_proc_params (in ref_list: formal_params,
    in ref_list: actual_params, inout expr_type: c_expr) is func

  local
    var integer: number is 0;
  begin
    for number range 1 to length(formal_params) do
      push_inline_proc_param(formal_params[number], actual_params[number], c_expr);
    end for;
  end func;


const proc: pop_inline_proc_param (in reference: formal_param,
    inout expr_type: c_expr) is func

  local
    var category: paramCategory is category.value;
    var type: param_type is void;
  begin
    paramCategory := category(formal_param);
    if paramCategory <> SYMBOLOBJECT then
      param_type := getType(formal_param);
      if isFunc(param_type) then
        c_expr.expr &:= "/* pop proc param o_";
        create_name2(formal_param, c_expr.expr);
        c_expr.expr &:= " */\n";
        pop_inline_param_value(formal_param);
      end if;
    end if;
  end func;


const proc: pop_inline_proc_params (in ref_list: formal_params,
    inout expr_type: c_expr) is func

  local
    var integer: number is 0;
  begin
    for number range 1 to length(formal_params) do
      pop_inline_proc_param(formal_params[number], c_expr);
    end for;
  end func;


const proc: process_inline_proc (in reference: function,
    in ref_list: actual_params, inout expr_type: c_expr) is func

  local
    var ref_list: formal_params is ref_list.EMPTY;
    var expr_type: inline_decls is expr_type.value;
  begin
    formal_params := formalParams(function);
    c_expr.expr &:= "/* inline proc o_";
    create_name2(function, c_expr.expr);
    c_expr.expr &:= " */ {\n";
    c_expr.expr &:= "/* inline params */\n";
    inline_decls.temp_num := c_expr.temp_num;
    push_inline_proc_params(formal_params, actual_params, inline_decls);
    inline_decls.temp_decls &:= "/* inline local_vars */\n";
    process_local_var_declaration(function, inline_decls);
    c_expr.temp_num := inline_decls.temp_num;
    AppendWithDiagnostic(inline_decls.temp_decls, c_expr);
    AppendWithDiagnostic(inline_decls.temp_assigns, c_expr);
    c_expr.expr &:= "/* inline body */\n";
    process_expr(body(function), c_expr);
    AppendWithDiagnostic(inline_decls.temp_frees, c_expr);
    pop_inline_proc_params(formal_params, c_expr);
    c_expr.expr &:= "\n} /* inline proc o_";
    create_name2(function, c_expr.expr);
    c_expr.expr &:= " */\n";
  end func;


const proc: process_inline (in reference: function,
    in ref_list: actual_params, inout expr_type: c_expr) is func

  begin
    if resultType(getType(function)) <> voidtype then
      process_inline_func(function, actual_params, c_expr);
    else
      process_inline_proc(function, actual_params, c_expr);
    end if;
  end func;


const proc: determineDataForActualFuncParam (in reference: current_expression,
    inout ref_list: data_list) is func

  local
    var category: paramCategory is category.value;
    var ref_list: params is ref_list.EMPTY;
    var reference: aParam is NIL;
  begin
    paramCategory := category(current_expression);
    if paramCategory = MATCHOBJECT or paramCategory = CALLOBJECT then
      params := getValue(current_expression, ref_list);
      for aParam range params do
        determineDataForActualFuncParam(aParam, data_list);
      end for;
    elsif paramCategory = LOCALVOBJECT or paramCategory = VALUEPARAMOBJECT or
        paramCategory = REFPARAMOBJECT or paramCategory = RESULTOBJECT then
      if current_expression not in data_list then
        data_list &:= make_list(current_expression);
      end if;
    end if;
  end func;


const func ref_list: determineDataForActualFuncParam (in reference: current_expression) is func

  result
    var ref_list: data_list is ref_list.EMPTY;
  begin
    determineDataForActualFuncParam(current_expression, data_list);
  end func;


const proc: defineActualFuncParam (in string: valueName, in reference: actual_param,
    in ref_list: data_list, inout expr_type: c_expr) is func

  local
    var funcparam_data_hash: funcparam_data_backup is funcparam_data_hash.EMPTY_HASH;
    var funcparam_data_hash: funcparam_reference_backup is funcparam_data_hash.EMPTY_HASH;
    var reference: dataItem is NIL;
    var string: data_value is "";
    var expr_type: c_func_body is expr_type.value;
  begin
    funcparam_data_backup := funcparam_data;
    funcparam_reference_backup := funcparam_reference;
    if data_list <> ref_list.EMPTY then
      c_expr.expr &:= "typedef struct {\n";
      c_expr.expr &:= type_name(resultType(getType(actual_param)));
      c_expr.expr &:= " (*func) (void *data_";
      c_expr.expr &:= valueName;
      c_expr.expr &:= ");\n";
      c_expr.expr &:= "struct {\n";
      for dataItem range data_list do
        c_expr.expr &:= type_name(getType(dataItem));
        if isFunc(getType(dataItem)) then
          c_expr.expr &:= " data_";
        else
          c_expr.expr &:= " *data_";
        end if;
        create_name(dataItem, c_expr.expr);
        c_expr.expr &:= ";\n";
        if isFunc(getType(dataItem)) then
          data_value := "((functype_";
          data_value &:= valueName;
          data_value &:= " *) data_";
          data_value &:= valueName;
          data_value &:= ")->data.data_";
          create_name(dataItem, data_value);
          data_value &:= "->func(((functype_";
          data_value &:= valueName;
          data_value &:= " *) data_";
          data_value &:= valueName;
          data_value &:= ")->data.data_";
          create_name(dataItem, data_value);
          data_value &:= ")";
          if getType(dataItem) = proctype then
            data_value &:= ";\n";
          end if;
        else
          data_value := "*((functype_";
          data_value &:= valueName;
          data_value &:= " *) data_";
          data_value &:= valueName;
          data_value &:= ")->data.data_";
          create_name(dataItem, data_value);
        end if;
        funcparam_data @:= [dataItem] data_value;
        data_value := "((functype_";
        data_value &:= valueName;
        data_value &:= " *) data_";
        data_value &:= valueName;
        data_value &:= ")->data.data_";
        create_name(dataItem, data_value);
        funcparam_reference @:= [dataItem] data_value;
      end for;
      c_expr.expr &:= "} data;\n";
      c_expr.expr &:= "} functype_";
      c_expr.expr &:= valueName;
      c_expr.expr &:= ";\n\n";
    end if;
    c_expr.expr &:= "static ";
    c_expr.expr &:= type_name(resultType(getType(actual_param)));
    c_expr.expr &:= " func_";
    c_expr.expr &:= valueName;
    c_expr.expr &:= " (void *data_";
    c_expr.expr &:= valueName;
    c_expr.expr &:= ")\n";
    c_expr.expr &:= "{\n";
    if category(actual_param) = BLOCKOBJECT then
      process_expr(body(actual_param), c_func_body);
    else
      process_expr(actual_param, c_func_body);
    end if;
    AppendWithDiagnostic(c_func_body.temp_decls, c_expr);
    AppendWithDiagnostic(c_func_body.temp_assigns, c_expr);
    if getType(actual_param) = proctype then
      c_expr.expr &:= c_func_body.expr;
      AppendWithDiagnostic(c_func_body.temp_frees, c_expr);
    else
      if c_func_body.temp_frees <> "" then
        c_expr.expr &:= type_name(resultType(getType(actual_param)));
        c_expr.expr &:= " result=";
      else
        c_expr.expr &:= diagnosticLine(actual_param);
        c_expr.expr &:= "return ";
      end if;
      if c_func_body.result_expr <> "" then
        c_expr.expr &:= c_func_body.result_expr;
      else
        c_expr.expr &:= c_func_body.expr;
      end if;
      c_expr.expr &:= ";\n";
      if c_func_body.temp_frees <> "" then
        AppendWithDiagnostic(c_func_body.temp_frees, c_expr);
        c_expr.expr &:= "return result;\n";
      end if;
    end if;
    c_expr.expr &:= "}\n\n";
    funcparam_data := funcparam_data_backup;
    funcparam_reference := funcparam_reference_backup;
  end func;


const proc: defineFuncValue (in string: valueName, in type: genericFuncType,
    in ref_list: data_list, inout expr_type: c_expr) is func

  local
    var reference: dataItem is NIL;
  begin
    incr(c_expr.temp_num);
    if data_list <> ref_list.EMPTY then
      c_expr.temp_decls &:= "functype_";
      c_expr.temp_decls &:= valueName;
    else
      c_expr.temp_decls &:= "struct_";
      c_expr.temp_decls &:= type_name(genericFuncType);
    end if;
    c_expr.temp_decls &:= " funcvalue_";
    c_expr.temp_decls &:= valueName;
    c_expr.temp_decls &:= ";\n\n";
    c_expr.temp_assigns &:= "funcvalue_";
    c_expr.temp_assigns &:= valueName;
    c_expr.temp_assigns &:= ".func = func_";
    c_expr.temp_assigns &:= valueName;
    c_expr.temp_assigns &:= ";\n";
    for dataItem range data_list do
      c_expr.temp_assigns &:= "funcvalue_";
      c_expr.temp_assigns &:= valueName;
      c_expr.temp_assigns &:= ".data.data_";
      create_name(dataItem, c_expr.temp_assigns);
      c_expr.temp_assigns &:= " = ";
      if isFunc(getType(dataItem)) then
        c_expr.temp_assigns &:= "o_";
        create_name(dataItem, c_expr.temp_assigns);
      else
        c_expr.temp_assigns &:= "&(";
        getAnyParamToTempAssigns(dataItem, c_expr);
        c_expr.temp_assigns &:= ")";
      end if;
      c_expr.temp_assigns &:= ";\n";
    end for;
  end func;


const proc: callActualFuncParam (in string: valueName, in type: genericFuncType,
    in ref_list: data_list, inout expr_type: c_expr) is func

  begin
    if data_list <> ref_list.EMPTY then
      c_expr.expr &:= "(";
      c_expr.expr &:= type_name(genericFuncType);
      c_expr.expr &:= " *)(";
    end if;
    c_expr.expr &:= "&funcvalue_";
    c_expr.expr &:= valueName;
    if data_list <> ref_list.EMPTY then
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: processFuncValue (in string: valueName, in type: genericFuncType,
    in reference: closure, inout expr_type: c_expr) is func

  local
    var ref_list: data_list is ref_list.EMPTY;
    var expr_type: function_c_expr is expr_type.value;
  begin
    declare_type_if_necessary(genericFuncType, global_c_expr);
    data_list := determineDataForActualFuncParam(closure);
    defineActualFuncParam(valueName, closure, data_list, function_c_expr);
    global_c_expr.expr  &:= function_c_expr.temp_decls;
    global_init.expr    &:= function_c_expr.temp_assigns;
    global_c_expr.expr  &:= function_c_expr.expr;
    defineFuncValue(valueName, genericFuncType, data_list, c_expr);
    if data_list <> ref_list.EMPTY then
      c_expr.expr &:= "(";
      c_expr.expr &:= type_name(genericFuncType);
      c_expr.expr &:= ")(";
    end if;
    c_expr.expr &:= "&funcvalue_";
    c_expr.expr &:= valueName;
    if data_list <> ref_list.EMPTY then
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: processFuncParam (in reference: formal_param,
    in reference: actual_param, inout expr_type: c_expr) is func

  local
    var string: valueName is "";
  begin
    create_name(formal_param, objNumber(actual_param), valueName);
    processFuncValue(valueName, getType(formal_param), actual_param, c_expr);
  end func;


const proc: call_params (in ref_list: formal_params,
    in ref_list: actual_params, inout expr_type: c_expr) is func

  local
    var integer: number is 0;
    var reference: formal_param is NIL;
    var reference: actual_param is NIL;
    var category: paramCategory is category.value;
    var boolean: first_element is TRUE;
    var integer: temp_num is 0;
  begin
#    for number range 1 to length(formal_params) do
    for number range 1 to length(actual_params) do
      formal_param := formal_params[number];
      actual_param := actual_params[number];
      paramCategory := category(formal_param);
      if paramCategory <> SYMBOLOBJECT then
        if paramCategory = TYPEOBJECT then
          c_expr.expr &:= "/* attr t_";
          c_expr.expr &:= str(typeNumber(getValue(formal_param, type)));
          c_expr.expr &:= " ";
          c_expr.expr &:= str(getValue(formal_param, type));
          c_expr.expr &:= "*/ ";
        else
          if first_element then
            first_element := FALSE;
          else
            c_expr.expr &:= ", ";
          end if;
          if isPointerParam(formal_param) then
            if category(actual_param) = REFPARAMOBJECT then
              if actual_param in inline_param then
                c_expr.expr &:= "par_";
                c_expr.expr &:= str(inline_param[actual_param][1]);
                c_expr.expr &:= "_";
              end if;
              if actual_param in funcparam_reference then
                c_expr.expr &:= funcparam_reference[actual_param];
              else
                c_expr.expr &:= "o_";
                create_name(actual_param, c_expr.expr);
              end if;
            elsif canTakeAddress(actual_param) then
              c_expr.expr &:= "&(";
              process_expr(actual_param, c_expr);
              c_expr.expr &:= ")";
            elsif category(actual_param) = MATCHOBJECT or
                category(actual_param) = BLOCKOBJECT then
              processFuncParam(formal_param, actual_param, c_expr);
            else
              c_expr.expr &:= "/* ";
              c_expr.expr &:= str(category(actual_param));
              c_expr.expr &:= " */";
              incr(c_expr.temp_num);
              temp_num := c_expr.temp_num;
              c_expr.temp_decls &:= type_name(getExprResultType(actual_param));
              c_expr.temp_decls &:= " tmp_";
              c_expr.temp_decls &:= str(temp_num);
              c_expr.temp_decls &:= ";\n";
              c_expr.expr &:= "(tmp_";
              c_expr.expr &:= str(temp_num);
              c_expr.expr &:= "=(";
              c_expr.expr &:= type_name(getExprResultType(actual_param));
              c_expr.expr &:= ")(";
              getAnyParamToExpr(actual_param, c_expr);
              c_expr.expr &:= "), &tmp_";
              c_expr.expr &:= str(temp_num);
              c_expr.expr &:= ")";
            end if;
          else
            getAnyParamToExpr(actual_param, c_expr);
          end if;
        end if;
      end if;
    end for;
  end func;


const proc: process_prototype_declaration (in reference: current_object,
    inout expr_type: c_expr) is forward;


const proc: process_const_func_call (in reference: function,
    in ref_list: actual_params, inout expr_type: c_expr) is func

  local
    var type: function_type is void;
    var type: result_type is void;
    var ref_list: formal_params is ref_list.EMPTY;
    var expr_type: c_params is expr_type.value;
  begin
    if function not in prototype_declared then
      process_prototype_declaration(function, global_c_expr);
      prototype_declared @:= [function] TRUE;
    end if;
    function_type := getType(function);
    result_type := resultType(function_type);
    formal_params := formalParams(function);
    if valueIsAtHeap(result_type) and
        not isVarfunc(function_type) and
        function not in return_ref_to_value then
      prepare_typed_result(result_type, c_expr);
      c_expr.result_expr := "o_";
      create_name(function, c_expr.result_expr);
      c_expr.result_expr &:= "(";
      c_params.temp_num := c_expr.temp_num;
      call_params(formal_params, actual_params, c_params);
      c_expr.temp_num := c_params.temp_num;
      c_expr.temp_decls &:= c_params.temp_decls;
      c_expr.temp_decls &:= c_params.temp_assigns;
      c_expr.temp_frees &:= c_params.temp_frees;
      c_expr.temp_to_null &:= c_params.temp_to_null;
      c_expr.result_expr &:= c_params.expr;
      c_expr.result_expr &:= ")";
    elsif result_type = voidtype then
      call_params(formal_params, actual_params, c_params);
      if c_params.temp_decls <> "" or c_params.temp_assigns <> "" then
        c_expr.expr &:= "{\n";
        AppendWithDiagnostic(c_params.temp_decls, c_expr);
        AppendWithDiagnostic(c_params.temp_assigns, c_expr);
      end if;
      setDiagnosticLine(c_expr);
      if isVarfunc(function_type) then
        c_expr.expr &:= "*o_";
      else
        c_expr.expr &:= "o_";
      end if;
      create_name(function, c_expr.expr);
      c_expr.expr &:= "(";
      c_expr.expr &:= c_params.expr;
      c_expr.expr &:= ")";
      c_expr.expr &:= ";\n";
      if c_params.temp_decls <> "" or c_params.temp_assigns <> "" then
        AppendWithDiagnostic(c_params.temp_frees, c_expr);
        c_expr.expr &:= "}\n";
      end if;
    else
      if isVarfunc(function_type) then
        c_expr.expr &:= "*o_";
      else
        c_expr.expr &:= "o_";
      end if;
      create_name(function, c_expr.expr);
      c_expr.expr &:= "(";
      call_params(formal_params, actual_params, c_expr);
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_func_call (in reference: function,
    in ref_list: actual_params, inout expr_type: c_expr) is func

  begin
    if isVar(function) then
      if getType(function) = proctype then
        setDiagnosticLine(c_expr);
      end if;
      c_expr.expr &:= "o_";
      create_name(function, c_expr.expr);
      c_expr.expr &:= "->func(o_";
      create_name(function, c_expr.expr);
      c_expr.expr &:= ")";
      if getType(function) = proctype then
        c_expr.expr &:= ";\n";
      end if;
    else
      process_const_func_call(function, actual_params, c_expr);
    end if;
  end func;


const proc: process_call (in reference: current_expression, inout expr_type: c_expr) is func

  local
    var ref_list: params is ref_list.EMPTY;
    var reference: function is NIL;
    var category: functionCategory is category.value;
    var reference: result_object is NIL;
    var reference: obj is NIL;
    var boolean: first_element is TRUE;
  begin
    c_expr.currentFile := file(current_expression);
    c_expr.currentLine := line(current_expression);
    # c_expr.expr &:= "/* ";
    # c_expr.expr &:= str(current_expression);
    # c_expr.expr &:= " */";
    params := getValue(current_expression, ref_list);
    function := params[1];
    params := params[2 ..];
    functionCategory := category(function);
    if functionCategory = ACTOBJECT then
      process_action(function, params, c_expr);
    elsif functionCategory = BLOCKOBJECT then
      result_object := resultVar(function);
      if function in function_declared or result_object <> NIL then
        process_func_call(function, params, c_expr);
      else
        process_inline(function, params, c_expr);
      end if;
    elsif functionCategory = LOCALVOBJECT then
      process_func_call(function, params, c_expr);
    elsif functionCategory = CONSTENUMOBJECT then
      (* process_constenumobject(function, params, c_expr); *)
      process_expr(function, c_expr);
    elsif functionCategory = VALUEPARAMOBJECT or
          functionCategory = REFPARAMOBJECT or
          functionCategory = INTOBJECT or
          functionCategory = BIGINTOBJECT or
          functionCategory = FLOATOBJECT or
          functionCategory = CHAROBJECT or
          functionCategory = STRIOBJECT or
          functionCategory = BSTRIOBJECT or
          functionCategory = ARRAYOBJECT or
          functionCategory = HASHOBJECT or
          functionCategory = SETOBJECT or
          functionCategory = STRUCTOBJECT or
          functionCategory = INTERFACEOBJECT or
          functionCategory = WINOBJECT or
          functionCategory = PROGOBJECT or
          functionCategory = ENUMLITERALOBJECT or
          functionCategory = TYPEOBJECT then
      process_expr(function, c_expr);
    elsif functionCategory = REFOBJECT then
      c_expr.expr &:= "o_";
      create_name(function, c_expr.expr);
    elsif functionCategory = REFLISTOBJECT then
      c_expr.expr &:= "o_";
      create_name(function, c_expr.expr);
    else
      c_expr.expr &:= "/*[ ";
      c_expr.expr &:= str(functionCategory);
      c_expr.expr &:= " ]*/";
      c_expr.expr &:= "o_";
      create_name(function, c_expr.expr);
      c_expr.expr &:= "(";
      for obj range params do
        if category(obj) <> SYMBOLOBJECT then
          if first_element then
            first_element := FALSE;
          else
            c_expr.expr &:= ", ";
          end if;
          process_expr(obj, c_expr);
        end if;
      end for;
      c_expr.expr &:= ")";
    end if;
  end func;


const proc: process_expr (in var reference: current_expression, inout expr_type: c_expr) is func

  local
    var reference: evaluated_expression is NIL;
    var category: exprCategory is category.value;
    var expr_type: c_body is expr_type.value;
  begin
    if evaluate_const_expr = 3 and isConstantExpr(current_expression) then
      block
        evaluated_expression := evaluate(prog, current_expression);
        if evaluated_expression <> NIL then
          incr(countEvaluations);
          c_expr.expr &:= "/* evaluate ";
          if category(getValue(current_expression, ref_list)[1]) = ACTOBJECT then
            c_expr.expr &:= str(getValue(getValue(current_expression, ref_list)[1], ACTION));
          elsif category(getValue(current_expression, ref_list)[1]) = BLOCKOBJECT then
            c_expr.expr &:= "o_";
            create_name2(getValue(current_expression, ref_list)[1], c_expr.expr);
          end if;
          c_expr.expr &:= " */ ";
          current_expression := evaluated_expression;
          if category(current_expression) = VARENUMOBJECT then
            current_expression := getValue(current_expression, reference);
          else
            setVar(current_expression, FALSE);
          end if;
        end if;
      exception
        catch NUMERIC_ERROR: c_expr.expr &:= "/* NUMERIC_ERROR */ "; # noop;
        catch RANGE_ERROR:   c_expr.expr &:= "/* RANGE_ERROR */ "; # noop;
        catch FILE_ERROR:    c_expr.expr &:= "/* FILE_ERROR */ "; # noop;
      end block;
    end if;
    exprCategory := category(current_expression);
    if exprCategory = MATCHOBJECT then
      process_call(current_expression, c_expr);
    elsif exprCategory = CALLOBJECT then
      process_call(current_expression, c_expr);
    elsif exprCategory = BLOCKOBJECT then
      c_expr.expr &:= "o_";
      create_name(current_expression, c_expr.expr);
      if not isVar(current_expression) then
        c_expr.expr &:= "()";
        if resultType(getType(current_expression)) = voidtype then
          c_expr.expr &:= ";\n";
        end if;
      end if;
    elsif exprCategory = ACTOBJECT then
      c_expr.expr &:= "/* process_expr ACTOBJECT ";
      c_expr.expr &:= str(getValue(current_expression, ACTION));
      c_expr.expr &:= " */";
      process_action(current_expression, ref_list.EMPTY, c_expr);
    elsif exprCategory = LOCALVOBJECT then
      if current_expression in funcparam_data then
        c_expr.expr &:= funcparam_data[current_expression];
      else
        c_expr.expr &:= "o_";
        create_name(current_expression, c_expr.expr);
      end if;
    elsif exprCategory = VALUEPARAMOBJECT then
      if current_expression in funcparam_data then
        c_expr.expr &:= funcparam_data[current_expression];
      else
        if current_expression in inline_param then
          c_expr.expr &:= "par_";
          c_expr.expr &:= str(inline_param[current_expression][1]);
          c_expr.expr &:= "_";
        end if;
        c_expr.expr &:= "o_";
        create_name(current_expression, c_expr.expr);
      end if;
    elsif exprCategory = REFPARAMOBJECT then
      if current_expression in funcparam_data then
        c_expr.expr &:= funcparam_data[current_expression];
      elsif isPointerParam(current_expression) then
        if current_expression in inline_param_value and
            length(inline_param_value[current_expression]) > 0 then
          if getType(current_expression) = proctype then
            c_expr.expr &:= "/* closure o_";
            create_name2(current_expression, c_expr.expr);
            c_expr.expr &:= "*/ {\n";
            process_expr(inline_param_value[current_expression][1], c_body);
            AppendWithDiagnostic(c_body.temp_decls, c_expr);
            AppendWithDiagnostic(c_body.temp_assigns, c_expr);
            c_expr.expr &:= c_body.expr;
            AppendWithDiagnostic(c_body.temp_frees, c_expr);
            c_expr.expr &:= "\n} /* closure o_";
            create_name2(current_expression, c_expr.expr);
            c_expr.expr &:= "*/\n";
          else
            c_body.temp_num := c_expr.temp_num;
            process_expr(inline_param_value[current_expression][1], c_body);
            c_expr.temp_num := c_body.temp_num;
            if c_body.result_expr <> "" then
              c_expr.result_expr &:= "/* closure o_";
              create_name2(current_expression, c_expr.result_expr);
              c_expr.result_expr &:= "*/ (";
              c_expr.result_expr &:= c_body.result_expr;
              c_expr.result_expr &:= ")";
              c_expr.temp_decls   &:= c_body.temp_decls;
              c_expr.temp_assigns &:= c_body.temp_assigns;
              c_expr.temp_frees   &:= c_body.temp_frees;
              c_expr.result_temp    := c_body.result_temp;
              c_expr.result_decl    := c_body.result_decl;
              c_expr.result_free    := c_body.result_free;
              c_expr.result_to_null := c_body.result_to_null;
              c_expr.result_intro   := c_body.result_intro;
              c_expr.result_finish  := c_body.result_finish;
            else
              c_expr.expr &:= "/* closure o_";
              create_name2(current_expression, c_expr.expr);
              c_expr.expr &:= "*/ (";
              c_expr.expr &:= c_body.expr;
              c_expr.expr &:= ")";
              c_expr.temp_decls   &:= c_body.temp_decls;
              c_expr.temp_assigns &:= c_body.temp_assigns;
              c_expr.temp_frees   &:= c_body.temp_frees;
            end if;
          end if;
        elsif isFunc(getType(current_expression)) then
          if getType(current_expression) = proctype then
            setDiagnosticLine(c_expr);
          end if;
          c_expr.expr &:= "o_";
          create_name(current_expression, c_expr.expr);
          c_expr.expr &:= "->func(o_";
          create_name(current_expression, c_expr.expr);
          c_expr.expr &:= ")";
          if getType(current_expression) = proctype then
            c_expr.expr &:= ";\n";
          end if;
        else
          c_expr.expr &:= "*";
          if current_expression in inline_param then
            c_expr.expr &:= "par_";
            c_expr.expr &:= str(inline_param[current_expression][1]);
            c_expr.expr &:= "_";
          end if;
          c_expr.expr &:= "o_";
          create_name(current_expression, c_expr.expr);
        end if;
      else
        if current_expression in inline_param then
          c_expr.expr &:= "par_";
          c_expr.expr &:= str(inline_param[current_expression][1]);
          c_expr.expr &:= "_";
        end if;
        c_expr.expr &:= "o_";
        create_name(current_expression, c_expr.expr);
      end if;
    elsif exprCategory = RESULTOBJECT then
      if current_expression in funcparam_data then
        c_expr.expr &:= funcparam_data[current_expression];
      else
        c_expr.expr &:= "o_";
        create_name(current_expression, c_expr.expr);
      end if;
    elsif exprCategory = TYPEOBJECT then
      if isVar(current_expression) then
        c_expr.expr &:= "o_";
        create_name(current_expression, c_expr.expr);
      else
        c_expr.expr &:= typeLiteral(getValue(current_expression, type));
      end if;
    elsif exprCategory = INTOBJECT then
      if isVar(current_expression) then
        c_expr.expr &:= "o_";
        create_name(current_expression, c_expr.expr);
      else
        c_expr.expr &:= integerLiteral(getValue(current_expression, integer));
      end if;
    elsif exprCategory = BIGINTOBJECT then
      if isVar(current_expression) then
        c_expr.expr &:= "o_";
        create_name(current_expression, c_expr.expr);
      else
        c_expr.expr &:= bigIntegerLiteral(getValue(current_expression, bigInteger));
      end if;
    elsif exprCategory = FLOATOBJECT then
      if isVar(current_expression) then
        c_expr.expr &:= "o_";
        create_name(current_expression, c_expr.expr);
      else
        c_expr.expr &:= floatLiteral(getValue(current_expression, float));
      end if;
    elsif exprCategory = CHAROBJECT then
      if isVar(current_expression) then
        c_expr.expr &:= "o_";
        create_name(current_expression, c_expr.expr);
      else
        c_expr.expr &:= charLiteral(getValue(current_expression, char));
      end if;
    elsif exprCategory = STRIOBJECT then
      if isVar(current_expression) then
        c_expr.expr &:= "o_";
        create_name(current_expression, c_expr.expr);
      else
        c_expr.expr &:= stringLiteral(getValue(current_expression, string));
      end if;
    elsif exprCategory = BSTRIOBJECT then
      if isVar(current_expression) then
        c_expr.expr &:= "o_";
        create_name(current_expression, c_expr.expr);
      else
        c_expr.expr &:= bstriLiteral(getValue(current_expression, bstring));
      end if;
    elsif exprCategory = SETOBJECT then
      if isVar(current_expression) then
        c_expr.expr &:= "o_";
        create_name(current_expression, c_expr.expr);
      else
        c_expr.expr &:= "(";
        c_expr.expr &:= type_name(getType(current_expression));
        c_expr.expr &:= ")(";
        c_expr.expr &:= bitsetLiteral(getValue(current_expression, bitset));
        c_expr.expr &:= ")";
      end if;
    elsif exprCategory = REFOBJECT then
      if isVar(current_expression) then
        c_expr.expr &:= "o_";
        create_name(current_expression, c_expr.expr);
      else
        if getValue(current_expression, reference) = NIL then
          c_expr.expr &:= "NULL";
        else
          c_expr.expr &:= "&(";
          process_expr(getValue(current_expression, reference), c_expr);
          c_expr.expr &:= ")";
        end if;
      end if;
    elsif exprCategory = REFLISTOBJECT then
      c_expr.expr &:= "o_";
      create_name(current_expression, c_expr.expr);
    elsif exprCategory = ARRAYOBJECT then
      if isVar(current_expression) then
        c_expr.expr &:= "o_";
        create_name(current_expression, c_expr.expr);
      else
        if current_expression not in const_table then
          const_table @:= [current_expression] length(const_table);
        end if;
        c_expr.expr &:= "arr[";
        c_expr.expr &:= str(const_table[current_expression]);
        c_expr.expr &:= "]";
      end if;
    elsif exprCategory = STRUCTOBJECT then
      if isVar(current_expression) then
        c_expr.expr &:= "o_";
        create_name(current_expression, c_expr.expr);
      else
        if current_expression not in const_table then
          const_table @:= [current_expression] length(const_table);
        end if;
        c_expr.expr &:= "sct[";
        c_expr.expr &:= str(const_table[current_expression]);
        c_expr.expr &:= "]";
      end if;
    elsif exprCategory = HASHOBJECT then
      if isVar(current_expression) then
        c_expr.expr &:= "o_";
        create_name(current_expression, c_expr.expr);
      else
        if current_expression not in const_table then
          const_table @:= [current_expression] length(const_table);
        end if;
        c_expr.expr &:= "hsh[";
        c_expr.expr &:= str(const_table[current_expression]);
        c_expr.expr &:= "]";
      end if;
    elsif exprCategory = INTERFACEOBJECT then
      if isVar(current_expression) then
        c_expr.expr &:= "o_";
        create_name(current_expression, c_expr.expr);
      else
        if current_expression not in const_table then
          const_table @:= [current_expression] length(const_table);
        end if;
        c_expr.expr &:= "itf[";
        c_expr.expr &:= str(const_table[current_expression]);
        c_expr.expr &:= "]";
      end if;
    elsif exprCategory = FILEOBJECT then
      c_expr.expr &:= "o_";
      create_name(current_expression, c_expr.expr);
    elsif exprCategory = SOCKETOBJECT then
      c_expr.expr &:= "o_";
      create_name(current_expression, c_expr.expr);
    elsif exprCategory = POLLOBJECT then
      c_expr.expr &:= "o_";
      create_name(current_expression, c_expr.expr);
    elsif exprCategory = WINOBJECT then
      if isVar(current_expression) then
        c_expr.expr &:= "o_";
        create_name(current_expression, c_expr.expr);
      else
        c_expr.expr &:= windowLiteral(getValue(current_expression, PRIMITIVE_WINDOW));
      end if;
    elsif exprCategory = PROGOBJECT then
      if isVar(current_expression) then
        c_expr.expr &:= "o_";
        create_name(current_expression, c_expr.expr);
      else
        if getValue(current_expression, program) = program.EMPTY then
          c_expr.expr &:= "/*program.EMPTY*/NULL";
        else
          c_expr.expr &:= "o_";
          create_name(current_expression, c_expr.expr);
        end if;
      end if;
    elsif exprCategory = CONSTENUMOBJECT then
      c_expr.expr &:= "o_";
      create_name(current_expression, c_expr.expr);
    elsif exprCategory = VARENUMOBJECT then
      c_expr.expr &:= "o_";
      create_name(current_expression, c_expr.expr);
    elsif exprCategory = ENUMLITERALOBJECT then
      c_expr.expr &:= "o_";
      create_name(current_expression, c_expr.expr);
    elsif exprCategory = EXPROBJECT then
      c_expr.expr &:= "o_";
      create_name(current_expression, c_expr.expr);
    elsif exprCategory = SYMBOLOBJECT then
      c_expr.expr &:= "/* SYMBOLOBJECT ";
      c_expr.expr &:= str(current_expression);
      c_expr.expr &:= " */";
    else
      c_expr.expr &:= "/* ";
      c_expr.expr &:= str(exprCategory);
      c_expr.expr &:= " */";
    end if;
  end func;


const proc: declare_types_of_params (in ref_list: formal_params, inout expr_type: c_expr) is func

  local
    var reference: formal_param is NIL;
    var category: paramCategory is category.value;
  begin
    for formal_param range formal_params do
      paramCategory := category(formal_param);
      if paramCategory <> SYMBOLOBJECT and paramCategory <> TYPEOBJECT then
        declare_type_if_necessary(getType(formal_param), c_expr);
      end if;
    end for;
  end func;


const proc: process_param_declaration (in reference: formal_param, inout expr_type: c_expr) is func

  local
    var type: param_type is void;
    var string: param_name is "";
  begin
    param_type := getType(formal_param);
    if isPointerParam(formal_param) then
      if isFunc(param_type) then
        c_expr.expr &:= type_name(param_type);
        c_expr.expr &:= " o_";
        create_name(formal_param, c_expr.expr);
      else
        if not isVar(formal_param) then
          c_expr.expr &:= "const ";
        end if;
        c_expr.expr &:= type_name(param_type);
        c_expr.expr &:= " *const o_";
        create_name(formal_param, c_expr.expr);
      end if;
    elsif isCopyParam(formal_param) then
      create_name(formal_param, param_name);
      c_expr.expr &:= "const ";
      if useConstPrefix(formal_param) then
        c_expr.expr &:= "const_";
      end if;
      c_expr.expr &:= type_name(param_type);
      c_expr.expr &:= " value_o_";
      c_expr.expr &:= param_name;
      if not isVar(formal_param) and useConstPrefix(param_type) then
        c_expr.temp_decls &:= "const_";
      end if;
      c_expr.temp_decls &:= type_name(param_type);
      c_expr.temp_decls &:= " o_";
      c_expr.temp_decls &:= param_name;
      c_expr.temp_decls &:= ";\n";
      c_expr.temp_assigns &:= "o_";
      c_expr.temp_assigns &:= param_name;
      c_expr.temp_assigns &:= "=";
      process_create_declaration(param_type, global_c_expr);
      process_create_call(param_type,
          "value_o_" & param_name, c_expr.temp_assigns);
      c_expr.temp_assigns &:= ";\n";
      process_destr_declaration(param_type, global_c_expr);
      process_destr_call(param_type,
          "o_" & param_name, c_expr.temp_frees);
    else
      if not isVar(formal_param) then
        c_expr.expr &:= "const ";
        if useConstPrefix(formal_param) then
          c_expr.expr &:= "const_";
        end if;
      end if;
      c_expr.expr &:= type_name(param_type);
      c_expr.expr &:= " o_";
      create_name(formal_param, c_expr.expr);
    end if;
  end func;


const proc: process_param_list_declaration (in ref_list: formal_params, inout expr_type: c_expr) is func

  local
    var reference: formal_param is NIL;
    var category: paramCategory is category.value;
    var boolean: first_element is TRUE;
  begin
    for formal_param range formal_params do
      paramCategory := category(formal_param);
      if paramCategory <> SYMBOLOBJECT then
        if paramCategory = TYPEOBJECT then
          c_expr.expr &:= "/* attr t_";
          c_expr.expr &:= str(typeNumber(getValue(formal_param, type)));
          c_expr.expr &:= " ";
          c_expr.expr &:= str(getValue(formal_param, type));
          c_expr.expr &:= "*/ ";
        else
          if first_element then
            first_element := FALSE;
          else
            c_expr.expr &:= ", ";
          end if;
          process_param_declaration(formal_param, c_expr);
        end if;
      end if;
    end for;
    if first_element then
      c_expr.expr &:= "void";
    end if;
  end func;


const proc: process_result_declaration (in reference: result_object, in reference: result_init,
    inout expr_type: c_expr) is func

  begin
    if result_object <> NIL then
      process_local_declaration(result_object, result_init, c_expr);
    end if;
  end func;


const proc: process_return (in reference: result_object,
    inout expr_type: c_expr) is func

  begin
    if result_object <> NIL then
      c_expr.expr &:= "return o_";
      create_name(result_object, c_expr.expr);
      c_expr.expr &:= ";\n";
    end if;
  end func;


const proc: process_return_value (in reference: function,
    in type: result_type, in expr_type: c_func_body,
    inout expr_type: c_expr) is func

  begin
    if isVarfunc(getType(function)) then
      c_expr.expr &:= "&(";
      if c_func_body.result_expr <> "" then
        c_expr.expr &:= c_func_body.result_expr;
      else
        c_expr.expr &:= c_func_body.expr;
      end if;
    else
      c_expr.expr &:= "(";
      if c_func_body.result_expr <> "" then
        c_expr.expr &:= c_func_body.result_expr;
      else
        if function in prototype_declared then
          process_create_declaration(result_type, global_c_expr);
          process_create_call(result_type, c_func_body.expr, c_expr.expr);
        else
          if valueIsAtHeap(result_type) then
            return_ref_to_value @:= [function] TRUE;
            c_expr.expr &:= "/*ref_to_value*/ ";
          end if;
          c_expr.expr &:= c_func_body.expr;
        end if;
      end if;
    end if;
    c_expr.expr &:= ")";
  end func;


const proc: process_local_consts (in reference: function,
    inout expr_type: c_expr) is forward;


const proc: process_const_func_declaration (in reference: function,
    inout expr_type: c_expr) is func

  local
    var expr_type: c_param_list is expr_type.value;
    var expr_type: c_result is expr_type.value;
    var expr_type: c_local_vars is expr_type.value;
    var expr_type: c_func_body is expr_type.value;
    var type: function_type is void;
    var type: result_type is void;
    var ref_list: param_list is ref_list.EMPTY;
    var reference: result_object is NIL;
    var reference: result_init is NIL;
  begin
    function_type := getType(function);
    result_type := resultType(function_type);
    param_list := formalParams(function);
    result_object := resultVar(function);
    if param_list_okay(param_list) or
        recursiveFunctionCall(function, body(function)) or
        result_object <> NIL then
      # Try to process the function declaration always.
      # The variable write_object_declaration is used to
      # decide if the function declaration should be written
      function_declared @:= [function] TRUE;
      declare_types_of_params(param_list, global_c_expr);
      process_local_consts(function, c_expr);
      c_expr.expr &:= diagnosticLine(function);
      c_expr.expr &:= "static ";
      c_expr.expr &:= type_name(result_type);
      if isVarfunc(getType(function)) then
        c_expr.expr &:= " /*varfunc*/ *o_";
      else
        c_expr.expr &:= " o_";
      end if;
      create_name(function, c_expr.expr);
      c_expr.expr &:= " (";
      process_param_list_declaration(param_list, c_param_list);
      c_expr.expr &:= c_param_list.expr;
      c_expr.expr &:= ")\n";
      c_expr.expr &:= "{\n";
      if function_type <> proctype and result_object = NIL then
        process_expr(body(function), c_func_body);
        if c_param_list.temp_decls <> "" or c_func_body.temp_decls <> "" then
          c_expr.currentFile := file(body(function));
          c_expr.currentLine := line(body(function));
          setDiagnosticLine(c_expr);
          c_expr.expr &:= type_name(result_type);
          if isVarfunc(getType(function)) then
            c_expr.expr &:= " *result;\n";
          else
            c_expr.expr &:= " result;\n";
          end if;
          AppendWithDiagnostic(c_param_list.temp_decls, c_expr);
          AppendWithDiagnostic(c_func_body.temp_decls, c_expr);
          AppendWithDiagnostic(c_param_list.temp_assigns, c_expr);
          AppendWithDiagnostic(c_func_body.temp_assigns, c_expr);
          setDiagnosticLine(c_expr);
          c_expr.expr &:= "result=(";
          c_expr.expr &:= type_name(result_type);
          if isVarfunc(getType(function)) then
            c_expr.expr &:= " *";
          end if;
          c_expr.expr &:= ")(";
          process_return_value(function, result_type, c_func_body, c_expr);
          c_expr.expr &:= ");\n";
          AppendWithDiagnostic(c_param_list.temp_frees, c_expr);
          AppendWithDiagnostic(c_func_body.temp_frees, c_expr);
          setDiagnosticLine(c_expr);
          c_expr.expr &:= "return result;\n";
        else
          c_expr.expr &:= diagnosticLine(body(function));
          c_expr.expr &:= "return (";
          c_expr.expr &:= type_name(result_type);
          if isVarfunc(getType(function)) then
            c_expr.expr &:= " *";
          end if;
          c_expr.expr &:= ")(";
          process_return_value(function, result_type, c_func_body, c_expr);
          c_expr.expr &:= ");\n";
        end if;
      else
        result_init := resultInitValue(function);
        process_result_declaration(result_object, result_init, c_result);
        process_local_var_declaration(function, c_local_vars);
        process_expr(body(function), c_func_body);
        c_expr.currentFile := file(function);
        c_expr.currentLine := line(function);
        AppendWithDiagnostic(c_param_list.temp_decls, c_expr);
        c_expr.expr &:= c_result.temp_decls;
        c_expr.expr &:= c_local_vars.temp_decls;
        AppendWithDiagnostic(c_func_body.temp_decls, c_expr);
        AppendWithDiagnostic(c_param_list.temp_assigns, c_expr);
        c_expr.expr &:= c_result.temp_assigns;
        c_expr.expr &:= c_local_vars.temp_assigns;
        AppendWithDiagnostic(c_func_body.temp_assigns, c_expr);
        c_expr.expr &:= c_func_body.expr;
        AppendWithDiagnostic(c_param_list.temp_frees, c_expr);
        AppendWithDiagnostic(c_local_vars.temp_frees, c_expr);
        AppendWithDiagnostic(c_func_body.temp_frees, c_expr);
        process_return(result_object, c_expr);
      end if;
      c_expr.expr &:= "}\n";
      c_expr.expr &:= noDiagnosticLine;
      c_expr.expr &:= "\n";
      if write_object_declaration then
        prototype_declared @:= [function] TRUE;
        count_declarations;
      else
        excl(function_declared, function);
        c_expr.expr &:= "/* declare inline o_";
        create_name2(function, c_expr.expr);
        c_expr.expr &:= "*/\n\n";
      end if;
    else
      c_expr.expr &:= "/* declare inline o_";
      create_name2(function, c_expr.expr);
      c_expr.expr &:= "*/\n\n";
    end if;
  end func;


const proc: process_library_initialisation (in reference: current_object,
    inout expr_type: c_expr) is func

  local
    var string: libraryName is "";
  begin
    libraryName := name(prog);
    c_expr.expr &:= "void init_";
    c_expr.expr &:= libraryName;
    c_expr.expr &:= " (void)\n";
    c_expr.expr &:= "{\n";
    c_expr.expr &:= "init_values();\n";
    c_expr.expr &:= "init_globals();\n";
    c_expr.expr &:= "}\n";
    c_expr.expr &:= "\n";
    prototype_declared @:= [current_object] TRUE;
    count_declarations;
  end func;


const proc: process_main_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  local
    var expr_type: c_local_vars is expr_type.value;
    var expr_type: c_func_body is expr_type.value;
    var string: main_prolog is "";
    var string: main_epilog is "";
  begin
    if category(current_object) = BLOCKOBJECT then
      function_declared @:= [current_object] TRUE;
      process_local_consts(current_object, c_expr);
      process_local_var_declaration(current_object, c_local_vars);
      process_expr(body(current_object), c_func_body);
    elsif category(current_object) = ACTOBJECT then
      process_expr(current_object, c_func_body);
    end if;
    c_expr.currentFile := file(current_object);
    c_expr.currentLine := line(current_object);
    if ccConf.USE_WMAIN then
      main_prolog := "int wmain (int argc, wchar_t **argv)\n";
    elsif ccConf.USE_WINMAIN then
      main_prolog := "int WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, char *lpCmdLine, int nShowCmd)\n";
    else
      main_prolog := "int main (int argc, char **argv)\n";
    end if;
    main_prolog &:= "\n";
    main_prolog &:= "{\n";
    main_prolog &:= "int fail_value;\n";
    main_prolog &:= "catch_stack_pos = 0;\n";
    main_prolog &:= "max_catch_stack = 128;\n";
    main_prolog &:= "catch_stack = (catch_type *)(malloc(max_catch_stack * sizeof(catch_type)));\n";
    main_prolog &:= "if ((fail_value = do_setjmp(catch_stack[catch_stack_pos])) == 0) {\n";
    if ccConf.USE_WINMAIN then
      main_prolog &:= "arg_v = getArgv(0, NULL, &arg_0, &programName, &programPath);\n";
    else
      main_prolog &:= "arg_v = getArgv(argc, argv, &arg_0, &programName, &programPath);\n";
    end if;
    main_prolog &:= "setupStack();\n";
    main_prolog &:= "setupFloat();\n";
    main_prolog &:= "init_values();\n";
    main_prolog &:= "activate_signal_handlers();\n";
    main_prolog &:= "init_globals();\n";
    main_prolog &:= "{\n";

    if ccConf.USE_WINMAIN then
      c_expr.expr &:= "typedef struct {\n";
      c_expr.expr &:= "    int dummy;\n";
      c_expr.expr &:= "  } HINSTANCE__;\n";
      c_expr.expr &:= "typedef HINSTANCE__* HINSTANCE;\n";
      c_expr.expr &:= "\n";
    end if;
    AppendWithDiagnostic(main_prolog, c_expr);
    c_expr.expr &:= c_local_vars.temp_decls;
    AppendWithDiagnostic(c_func_body.temp_decls, c_expr);
    c_expr.expr &:= c_local_vars.temp_assigns;
    AppendWithDiagnostic(c_func_body.temp_assigns, c_expr);
    c_expr.expr &:= c_func_body.expr;
    AppendWithDiagnostic(c_local_vars.temp_frees, c_expr);
    AppendWithDiagnostic(c_func_body.temp_frees, c_expr);
    c_expr.expr &:= "}\n";
    c_expr.expr &:= global_init.temp_frees;

    main_epilog := "return 0;\n";
    main_epilog &:= "} else {\n";
    main_epilog &:= "  printf(\"\\n*** Uncaught EXCEPTION \");\n";
    main_epilog &:= "  if (fail_value >= 0 && fail_value < sizeof(exception_name) / sizeof(char *)) {\n";
    main_epilog &:= "    printf(\"%s\", exception_name[fail_value]);\n";
    main_epilog &:= "  } else {\n";
    main_epilog &:= "    printf(\"%d\", fail_value);\n";
    main_epilog &:= "  }\n";
    main_epilog &:= "  printf(\" raised\");\n";
    main_epilog &:= "  if (error_file != NULL) {\n";
    main_epilog &:= "    printf(\" at %s(%d)\", error_file, error_line);\n";
    main_epilog &:= "  }\n";
    main_epilog &:= "  printf(\"\\n\");\n";
    main_epilog &:= "  return 1;\n";
    main_epilog &:= "}\n";
    main_epilog &:= "}\n";

    AppendWithDiagnostic(main_epilog, c_expr);
    c_expr.expr &:= noDiagnosticLine;
    c_expr.expr &:= "\n";
    prototype_declared @:= [current_object] TRUE;
    count_declarations;
  end func;


const proc: process_var_func_declaration (in reference: function,
    inout expr_type: c_expr) is func

  local
    var expr_type: c_value is expr_type.value;
    var string: valueName is "";
  begin
    declare_type_if_necessary(getType(function), global_c_expr);
    create_name(function, objNumber(function), valueName);
    processFuncValue(valueName, getType(function), function, c_value);
    c_expr.expr &:= c_value.temp_decls;
    global_init.expr &:= diagnosticLine(function);
    global_init.expr &:= c_value.temp_assigns;
    c_expr.expr &:= type_name(getType(function));
    c_expr.expr &:= " o_";
    create_name(function, c_expr.expr);
    c_expr.expr &:= " = ";
    c_expr.expr &:= c_value.expr;
    c_expr.expr &:= ";\n\n";
    function_declared @:= [function] TRUE;
  end func;


const proc: process_func_declaration (in reference: function,
    inout expr_type: c_expr) is func

  begin
    if isVar(function) then
      process_var_func_declaration(function, c_expr);
    else
      process_const_func_declaration(function, c_expr);
    end if;
  end func;


const proc: process_prototype_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  local
    var expr_type: c_param_list is expr_type.value;
    var type: current_type is void;
    var type: result_type is void;
    var ref_list: param_list is ref_list.EMPTY;
  begin
    current_type := getType(current_object);
    if isFunc(current_type) or isVarfunc(current_type) then
      result_type := resultType(current_type);
      param_list := formalParams(current_object);
      function_declared @:= [current_object] TRUE;
      declare_types_of_params(param_list, global_c_expr);
      c_expr.expr &:= "static ";
      c_expr.expr &:= type_name(result_type);
      if isVarfunc(current_type) then
        c_expr.expr &:= " *o_";
      else
        c_expr.expr &:= " o_";
      end if;
      create_name(current_object, c_expr.expr);
      c_expr.expr &:= " (";
      process_param_list_declaration(param_list, c_param_list);
      c_expr.expr &:= c_param_list.expr;
      c_expr.expr &:= ");\n\n";
    else
      c_expr.expr &:= "extern ";
      c_expr.expr &:= type_name(current_type);
      c_expr.expr &:= " o_";
      create_name(current_object, c_expr.expr);
      c_expr.expr &:= ";\n\n";
    end if;
  end func;


const proc: process_forward_declaration (in reference: fwd_ref,
    inout expr_type: c_expr) is func

  begin
    process_prototype_declaration(getValue(fwd_ref, reference), c_expr);
  end func;


const proc: process_type_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  local
    var type: aType is void;
  begin
    if isVar(current_object) then
      c_expr.expr &:= "typetype o_";
      create_name(current_object, c_expr.expr);
      c_expr.expr &:= ";\n\n";
      global_init.expr &:= diagnosticLine(current_object);
      global_init.expr &:= "o_";
      create_name(current_object, global_init.expr);
      global_init.expr &:= "=";
      global_init.expr &:= typeLiteral(getValue(current_object, type));
      global_init.expr &:= ";\n";
    else
      aType := getValue(current_object, type);
      declare_type_if_necessary(aType, c_expr);
    end if;
    count_declarations;
  end func;


const proc: process_int_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  begin
    if isVar(current_object) then
      c_expr.expr &:= "inttype o_";
      create_name(current_object, c_expr.expr);
      c_expr.expr &:= "=";
      c_expr.expr &:= integerLiteral(getValue(current_object, integer));
      c_expr.expr &:= ";\n\n";
      count_declarations;
    end if;
  end func;


const proc: process_bigint_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  begin
    if isVar(current_object) then
      c_expr.expr &:= "biginttype o_";
      create_name(current_object, c_expr.expr);
      c_expr.expr &:= ";\n\n";
      global_init.expr &:= diagnosticLine(current_object);
      global_init.expr &:= "o_";
      create_name(current_object, global_init.expr);
      global_init.expr &:= "=";
      process_big_create_call(getValue(current_object, bigInteger), global_init.expr);
      count_declarations;
    end if;
  end func;


const proc: process_char_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  begin
    if isVar(current_object) then
      c_expr.expr &:= "chartype o_";
      create_name(current_object, c_expr.expr);
      c_expr.expr &:= "=";
      c_expr.expr &:= charLiteral(getValue(current_object, char));
      c_expr.expr &:= ";\n\n";
      count_declarations;
    end if;
  end func;


const proc: process_stri_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  begin
    if isVar(current_object) then
      c_expr.expr &:= "stritype o_";
      create_name(current_object, c_expr.expr);
      c_expr.expr &:= ";\n\n";
      global_init.expr &:= diagnosticLine(current_object);
      global_init.expr &:= "o_";
      create_name(current_object, global_init.expr);
      global_init.expr &:= "=";
      process_str_create_call(getValue(current_object, string), global_init.expr);
      count_declarations;
    end if;
  end func;


const proc: process_bstri_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  begin
    if isVar(current_object) then
      c_expr.expr &:= "bstritype o_";
      create_name(current_object, c_expr.expr);
      c_expr.expr &:= ";\n\n";
      global_init.expr &:= diagnosticLine(current_object);
      global_init.expr &:= "o_";
      create_name(current_object, global_init.expr);
      global_init.expr &:= "=bstCreate(";
      global_init.expr &:= bstriLiteral(getValue(current_object, bstring));
      global_init.expr &:= ");\n";
      count_declarations;
    end if;
  end func;


const proc: process_float_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  begin
    if isVar(current_object) then
      c_expr.expr &:= "floattype o_";
      create_name(current_object, c_expr.expr);
      c_expr.expr &:= "=";
      c_expr.expr &:= floatLiteral(getValue(current_object, float));
      c_expr.expr &:= ";\n\n";
      count_declarations;
    end if;
  end func;


const proc: action_address (in reference: function, inout expr_type: c_expr) is func

  local
    var ACTION: current_action is action "PRC_NOOP";
    var string: action_name is "";
    var type: object_type is void;
  begin
    current_action := getValue(function, ACTION);
    action_name := str(current_action);
    if action_name = "ARR_CPY" then
      object_type := getType(formalParams(function)[1]);
      process_generic_cpy_declaration(object_type, global_c_expr);
      c_expr.expr &:= "&generic_cpy_";
      c_expr.expr &:= str(typeNumber(object_type));
    elsif action_name = "ARR_CREATE" then
      object_type := getType(formalParams(function)[1]);
      typeCategory @:= [object_type] ARRAYOBJECT;
      process_generic_create_declaration(object_type, global_c_expr);
      c_expr.expr &:= "&generic_create_";
      c_expr.expr &:= str(typeNumber(object_type));
    elsif action_name = "ARR_DESTR" then
      object_type := getType(formalParams(function)[1]);
      process_generic_destr_declaration(object_type, global_c_expr);
      c_expr.expr &:= "&generic_destr_";
      c_expr.expr &:= str(typeNumber(object_type));
    elsif action_name = "BIG_CMP" then
      c_expr.expr &:= "&bigCmpGeneric";
    elsif action_name = "BIG_CPY" then
      c_expr.expr &:= "&bigCpyGeneric";
    elsif action_name = "BIG_CREATE" then
      c_expr.expr &:= "&bigCreateGeneric";
    elsif action_name = "BIG_DESTR" then
      c_expr.expr &:= "&bigDestrGeneric";
    elsif action_name = "BLN_CPY" then
      c_expr.expr &:= "&genericCpy";
    elsif action_name = "BLN_CREATE" then
      c_expr.expr &:= "&genericCreate";
    elsif action_name = "BST_CMP" then
      c_expr.expr &:= "&bstCmpGeneric";
    elsif action_name = "BST_CPY" then
      c_expr.expr &:= "&bstCpyGeneric";
    elsif action_name = "BST_CREATE" then
      c_expr.expr &:= "&bstCreateGeneric";
    elsif action_name = "BST_DESTR" then
      c_expr.expr &:= "&bstDestrGeneric";
    elsif action_name = "CHR_CMP" then
      c_expr.expr &:= "&chrCmpGeneric";
    elsif action_name = "CHR_CPY" then
      c_expr.expr &:= "&genericCpy";
    elsif action_name = "CHR_CREATE" then
      c_expr.expr &:= "&genericCreate";
    elsif action_name = "DRW_CMP" then
      c_expr.expr &:= "&ptrCmpGeneric";
    elsif action_name = "DRW_CPY" then
      c_expr.expr &:= "&drwCpyGeneric";
    elsif action_name = "DRW_CREATE" then
      c_expr.expr &:= "&drwCreateGeneric";
    elsif action_name = "DRW_DESTR" then
      c_expr.expr &:= "&drwDestrGeneric";
    elsif action_name = "ENU_CPY" then
      c_expr.expr &:= "&genericCpy";
    elsif action_name = "ENU_CREATE" then
      c_expr.expr &:= "&genericCreate";
    elsif action_name = "FLT_CMP" then
      c_expr.expr &:= "&fltCmpGeneric";
    elsif action_name = "FLT_CPY" then
      c_expr.expr &:= "&fltCpyGeneric";
    elsif action_name = "FLT_CREATE" then
      c_expr.expr &:= "&genericCreate";
    elsif action_name = "GEN_DESTR" then
      c_expr.expr &:= "&genericDestr";
    elsif action_name = "INT_CMP" then
      c_expr.expr &:= "&intCmpGeneric";
    elsif action_name = "INT_CPY" then
      c_expr.expr &:= "&genericCpy";
    elsif action_name = "INT_CREATE" then
      c_expr.expr &:= "&genericCreate";
    elsif action_name = "ITF_CMP" then
      c_expr.expr &:= "&ptrCmpGeneric";
    elsif action_name = "ITF_CPY" then
      object_type := getType(formalParams(function)[1]);
      process_generic_cpy_declaration(object_type, global_c_expr);
      c_expr.expr &:= "&generic_cpy_";
      c_expr.expr &:= str(typeNumber(object_type));
    elsif action_name = "ITF_CREATE" then
      c_expr.expr &:= "&itfCreateGeneric";
    elsif action_name = "ITF_DESTR" then
      object_type := getType(formalParams(function)[1]);
      process_generic_destr_declaration(object_type, global_c_expr);
      c_expr.expr &:= "&generic_destr_";
      c_expr.expr &:= str(typeNumber(object_type));
    elsif action_name = "PRC_NOOP" then
      c_expr.expr &:= "&prcNoop";
    elsif action_name = "REF_CMP" then
      c_expr.expr &:= "&ptrCmpGeneric";
    elsif action_name = "REF_CPY" then
      c_expr.expr &:= "&ptrCpyGeneric";
    elsif action_name = "REF_CREATE" then
      c_expr.expr &:= "&ptrCreateGeneric";
    elsif action_name = "RFL_CMP" then
      c_expr.expr &:= "&rflCmpGeneric";
    elsif action_name = "RFL_CPY" then
      c_expr.expr &:= "&rflCpyGeneric";
    elsif action_name = "RFL_CREATE" then
      c_expr.expr &:= "&rflCreateGeneric";
    elsif action_name = "RFL_DESTR" then
      c_expr.expr &:= "&rflDestrGeneric";
    elsif action_name = "SCT_CPY" then
      object_type := getType(formalParams(function)[1]);
      process_generic_cpy_declaration(object_type, global_c_expr);
      c_expr.expr &:= "&generic_cpy_";
      c_expr.expr &:= str(typeNumber(object_type));
    elsif action_name = "SCT_CREATE" then
      object_type := getType(formalParams(function)[1]);
      typeCategory @:= [object_type] STRUCTOBJECT;
      process_generic_create_declaration(object_type, global_c_expr);
      c_expr.expr &:= "&generic_create_";
      c_expr.expr &:= str(typeNumber(object_type));
    elsif action_name = "SCT_DESTR" then
      object_type := getType(formalParams(function)[1]);
      process_generic_destr_declaration(object_type, global_c_expr);
      c_expr.expr &:= "&generic_destr_";
      c_expr.expr &:= str(typeNumber(object_type));
    elsif action_name = "SET_CMP" then
      c_expr.expr &:= "&setCmpGeneric";
    elsif action_name = "SET_CPY" then
      c_expr.expr &:= "&setCpyGeneric";
    elsif action_name = "SET_CREATE" then
      c_expr.expr &:= "&setCreateGeneric";
    elsif action_name = "SET_DESTR" then
      c_expr.expr &:= "&setDestrGeneric";
    elsif action_name = "STR_CMP" then
      c_expr.expr &:= "&strCmpGeneric";
    elsif action_name = "STR_CPY" then
      c_expr.expr &:= "&strCpyGeneric";
    elsif action_name = "STR_CREATE" then
      c_expr.expr &:= "&strCreateGeneric";
    elsif action_name = "STR_DESTR" then
      c_expr.expr &:= "&strDestrGeneric";
    elsif action_name = "TYP_CMP" then
      c_expr.expr &:= "&typCmpGeneric";
    elsif action_name = "TYP_CPY" then
      c_expr.expr &:= "&ptrCpyGeneric";
    elsif action_name = "TYP_CREATE" then
      c_expr.expr &:= "&ptrCreateGeneric";
    elsif action_name = "TYP_DESTR" then
      c_expr.expr &:= "&genericDestr";
    else
      c_expr.expr &:= "NULL /* ACTOBJECT { ";
      c_expr.expr &:= action_name;
      c_expr.expr &:= " }*/";
    end if;
  end func;


const proc: block_address (in reference: function, inout expr_type: c_expr) is func

  local
    var ref_list: formal_params is ref_list.EMPTY;
    var reference: formal_param is NIL;
    var type: object_type is void;
    var boolean: address_written is FALSE;
  begin
    formal_params := formalParams(function);
    if length(formal_params) = 3 and category(formal_params[2]) = SYMBOLOBJECT and
        str(formal_params[2]) = ":=" then
      formal_param := formal_params[1];
      object_type := getType(formal_param);
      process_generic_cpy_declaration(object_type, global_c_expr);
      c_expr.expr &:= "&generic_cpy_";
      c_expr.expr &:= str(typeNumber(object_type));
      address_written := TRUE;
    elsif length(formal_params) = 3 and category(formal_params[2]) = SYMBOLOBJECT and
        str(formal_params[2]) = "::=" then
      formal_param := formal_params[1];
      object_type := getType(formal_param);
      process_generic_create_declaration(object_type, global_c_expr);
      c_expr.expr &:= "&generic_create_";
      c_expr.expr &:= str(typeNumber(object_type));
      address_written := TRUE;
    elsif length(formal_params) = 2 and category(formal_params[2]) = SYMBOLOBJECT and
        str(formal_params[2]) = "destroy" then
      formal_param := formal_params[1];
      object_type := getType(formal_param);
      process_generic_destr_declaration(object_type, global_c_expr);
      c_expr.expr &:= "&generic_destr_";
      c_expr.expr &:= str(typeNumber(object_type));
      address_written := TRUE;
    elsif length(formal_params) = 3 and category(formal_params[3]) = SYMBOLOBJECT and
        str(formal_params[3]) = "compare" then
      formal_param := formal_params[1];
      object_type := getType(formal_param);
      process_generic_cmp_declaration(function, object_type, global_c_expr);
      c_expr.expr &:= "&generic_cmp_";
      c_expr.expr &:= str(typeNumber(object_type));
      address_written := TRUE;
    end if;
    if not address_written then
      c_expr.expr &:= "&o_";
      create_name(function, c_expr.expr);
    end if;
  end func;


const proc: object_address (in reference: current_object, inout expr_type: c_expr) is func

  local
    var reference: curr_expr is NIL;
    var category: exprCategory is category.value;
  begin
    curr_expr := getValue(current_object, reference);
    if curr_expr = NIL then
      c_expr.expr &:= "NULL";
    else
      exprCategory := category(curr_expr);
      if exprCategory = ACTOBJECT then
        action_address(curr_expr, c_expr);
      elsif exprCategory = BLOCKOBJECT then
        block_address(curr_expr, c_expr);
      else
        c_expr.expr &:= "/* ";
        c_expr.expr &:= str(exprCategory);
        c_expr.expr &:= " */";
        block
          c_expr.expr &:= "&(";
          process_expr(curr_expr, c_expr);
          c_expr.expr &:= ")";
        exception
          catch RANGE_ERROR:
            c_expr.expr &:= "/*RANGE_ERROR*/";
            writeln("] ");
            TRACE(curr_expr);
            writeln;
        end block;
      end if;
    end if;
  end func;


const proc: process_reference_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  begin
    (* if isVar(current_object) then *)
      c_expr.expr &:= "/* ";
      c_expr.expr &:= type_name2(getType(current_object));
      c_expr.expr &:= " */ ";
      if useFunctype(current_object) then
        c_expr.expr &:= "intfunctype o_";
      else
        c_expr.expr &:= "objreftype o_";
      end if;
      create_name(current_object, c_expr.expr);
      c_expr.expr &:= "=";
      if useFunctype(current_object) then
        c_expr.expr &:= "(intfunctype)(";
      else
        c_expr.expr &:= "(objreftype)(";
      end if;
      object_address(current_object, c_expr);
      c_expr.expr &:= ");\n\n";
      function_pointer_declared @:= [current_object] TRUE;
      count_declarations;
    (* end if; *)
  end func;


const proc: process_ref_list_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  local
    var ref_list: refListValue is ref_list.EMPTY;
    var integer: index is 0;
  begin
    refListValue := getValue(current_object, ref_list);
    for index range length(refListValue) downto 1 do
      c_expr.expr &:= "struct liststruct rec_";
      c_expr.expr &:= str(objNumber(current_object));
      c_expr.expr &:= "_";
      c_expr.expr &:= str(index);
      c_expr.expr &:= "={";
      if index = length(refListValue) then
        c_expr.expr &:= "NULL";
      else
        c_expr.expr &:= "&rec_";
        c_expr.expr &:= str(objNumber(current_object));
        c_expr.expr &:= "_";
        c_expr.expr &:= str(succ(index));
      end if;
      c_expr.expr &:= ", (objreftype) &(";
      process_expr(refListValue[index], c_expr);
      c_expr.expr &:= ")};\n";
    end for;
    c_expr.expr &:= "\n";
    c_expr.expr &:= type_name(getType(current_object));
    c_expr.expr &:= " o_";
    create_name(current_object, c_expr.expr);
    c_expr.expr &:= "=";
    if length(refListValue) = 0 then
      c_expr.expr &:= "NULL";
    else
      c_expr.expr &:= "&rec_";
      c_expr.expr &:= str(objNumber(current_object));
      c_expr.expr &:= "_1";
    end if;
    c_expr.expr &:= ";\n\n";
    count_declarations;
  end func;


const proc: process_file_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "filetype o_";
    create_name(current_object, c_expr.expr);
    c_expr.expr &:= "=NULL;\n\n";
    count_declarations;
  end func;


const proc: process_socket_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "sockettype o_";
    create_name(current_object, c_expr.expr);
    c_expr.expr &:= "=-1;\n\n";
    count_declarations;
  end func;


const proc: process_poll_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "polltype o_";
    create_name(current_object, c_expr.expr);
    c_expr.expr &:= ";\n\n";
    count_declarations;
  end func;


const proc: process_array_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  local
    var string: param_value is "";
  begin
    typeCategory @:= [getType(current_object)] ARRAYOBJECT;
    if isVar(current_object) then
      c_expr.expr &:= type_name(getType(current_object));
      c_expr.expr &:= " o_";
      create_name(current_object, c_expr.expr);
      c_expr.expr &:= ";\n\n";
      if current_object not in const_table then
        const_table @:= [current_object] length(const_table);
      end if;
      global_init.expr &:= diagnosticLine(current_object);
      global_init.expr &:= "o_";
      create_name(current_object, global_init.expr);
      global_init.expr &:= "=";
      param_value := "(";
      param_value &:= type_name(getType(current_object));
      param_value &:= ")(arr[";
      param_value &:= str(const_table[current_object]);
      param_value &:= "])";
      process_create_declaration(getType(current_object), global_c_expr);
      process_create_call(getType(current_object),
          param_value, global_init.expr);
      global_init.expr &:= ";\n";
      count_declarations;
    end if;
  end func;


const proc: process_hash_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  local
    var string: param_value is "";
  begin
    typeCategory @:= [getType(current_object)] HASHOBJECT;
    c_expr.expr &:= type_name(getType(current_object));
    c_expr.expr &:= " o_";
    create_name(current_object, c_expr.expr);
    c_expr.expr &:= ";\n\n";
    if current_object not in const_table then
      const_table @:= [current_object] length(const_table);
    end if;
    global_init.expr &:= diagnosticLine(current_object);
    global_init.expr &:= "o_";
    create_name(current_object, global_init.expr);
    global_init.expr &:= "=";
    param_value := "(";
    param_value &:= type_name(getType(current_object));
    param_value &:= ")(hsh[";
    param_value &:= str(const_table[current_object]);
    param_value &:= "])";
    if isVar(current_object) then
      process_create_declaration(getType(current_object), global_c_expr);
      process_create_call(getType(current_object),
          param_value, global_init.expr);
    else
      global_init.expr &:= param_value;
    end if;
    global_init.expr &:= ";\n";
    count_declarations;
  end func;


const proc: process_set_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  begin
    if isVar(current_object) then
      c_expr.expr &:= type_name(getType(current_object));
      c_expr.expr &:= " o_";
      create_name(current_object, c_expr.expr);
      c_expr.expr &:= ";\n\n";
      global_init.expr &:= diagnosticLine(current_object);
      global_init.expr &:= "o_";
      create_name(current_object, global_init.expr);
      global_init.expr &:= "=setCreate(";
      global_init.expr &:= bitsetLiteral(getValue(current_object, bitset));
      global_init.expr &:= ");\n";
      count_declarations;
    end if;
  end func;


const proc: process_struct_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  local
    var string: param_value is "";
    var string: init_expr is "";
  begin
    declare_type_if_necessary(getType(current_object), c_expr);
    c_expr.expr &:= type_name(getType(current_object));
    c_expr.expr &:= " o_";
    create_name(current_object, c_expr.expr);
    c_expr.expr &:= ";\n\n";
    if current_object not in const_table then
      const_table @:= [current_object] length(const_table);
    end if;
    init_expr &:= diagnosticLine(current_object);
    init_expr &:= "o_";
    create_name(current_object, init_expr);
    init_expr &:= "=";
    param_value := "(";
    param_value &:= type_name(getType(current_object));
    param_value &:= ")(sct[";
    param_value &:= str(const_table[current_object]);
    param_value &:= "])";
    if isVar(current_object) then
      process_create_declaration(getType(current_object), global_c_expr);
      process_create_call(getType(current_object),
          param_value, init_expr);
    else
      init_expr &:= param_value;
    end if;
    init_expr &:= ";\n";
    if current_object in globalInitalisations then
      globalInitalisations @:= [current_object] globalInitalisations[current_object] & init_expr;
    else
      globalInitalisations @:= [current_object] init_expr;
    end if;
    count_declarations;
  end func;


const proc: process_interface_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  local
    var reference: object_value is NIL;
    var category: valueCategory is category.value;
  begin
    c_expr.expr &:= type_name(getType(current_object));
    c_expr.expr &:= " o_";
    create_name(current_object, c_expr.expr);
    c_expr.expr &:= ";\n\n";
    object_value := interfaceToStruct(current_object);
    valueCategory := category(object_value);
    if current_object not in const_table then
      const_table @:= [current_object] length(const_table);
    end if;
    global_init.expr &:= diagnosticLine(current_object);
    global_init.expr &:= "o_";
    create_name(current_object, global_init.expr);
    global_init.expr &:= "=(";
    global_init.expr &:= type_name(getType(current_object));
    global_init.expr &:= ")(itfCreate(itf[";
    global_init.expr &:= str(const_table[current_object]);
    global_init.expr &:= "]));\n";
    count_declarations;
  end func;


const proc: process_win_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  begin
    if isVar(current_object) then
      c_expr.expr &:= "wintype o_";
      create_name(current_object, c_expr.expr);
      if getValue(current_object, PRIMITIVE_WINDOW) = PRIMITIVE_WINDOW.value then
        c_expr.expr &:= "=NULL;\n\n";
      else
        c_expr.expr &:= ";\n\n";
        global_init.expr &:= diagnosticLine(current_object);
        global_init.expr &:= "o_";
        create_name(current_object, global_init.expr);
        global_init.expr &:= "=drwCreate(";
        global_init.expr &:= windowLiteral(getValue(current_object, PRIMITIVE_WINDOW));
        global_init.expr &:= ");\n";
      end if;
      count_declarations;
    end if;
  end func;


const proc: process_prog_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  begin
    if isVar(current_object) then
      c_expr.expr &:= "progtype o_";
      create_name(current_object, c_expr.expr);
      c_expr.expr &:= "=NULL;\n\n";
      count_declarations;
    end if;
  end func;


const proc: process_enum_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  begin
    if isVar(current_object) or not isFunc(getType(current_object)) then
      if not isVar(current_object) then
        c_expr.expr &:= "const ";
      end if;
      declare_type_if_necessary(getType(current_object), c_expr);
      c_expr.expr &:= type_name(getType(current_object));
      c_expr.expr &:= " o_";
      create_name(current_object, c_expr.expr);
      c_expr.expr &:= "=";
      c_expr.expr &:= enum_value(getValue(current_object, reference));
      c_expr.expr &:= ";\n\n";
    end if;
    count_declarations;
  end func;


const proc: process_enum_literal_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  local
    var type: enum_type is void;
  begin
    enum_type := getType(current_object);
    if enum_type = voidtype then
      c_expr.expr &:= "/* do not declare: void o_4_empty */\n\n";
    else
      if enum_type not in enum_literal then
        enum_literal @:= [enum_type] element_number_hash.EMPTY_HASH;
      end if;
      if current_object not in enum_literal[enum_type] then
        enum_literal[enum_type] @:= [current_object] length(enum_literal[enum_type]);
      end if;
      c_expr.expr &:= "const ";
      declare_type_if_necessary(enum_type, c_expr);
      c_expr.expr &:= type_name(enum_type);
      c_expr.expr &:= " o_";
      create_name(current_object, c_expr.expr);
      c_expr.expr &:= "=";
      c_expr.expr &:= enum_value(current_object);
      c_expr.expr &:= ";\n\n";
    end if;
    count_declarations;
  end func;


const proc: print_parameter_list (in ref_list: formal_params,
    inout expr_type: c_expr) is func

  local
    var reference: formal_param is NIL;
    var category: paramCategory is category.value;
    var boolean: first_element is TRUE;
    var type: param_type is void;
    var type: implementationType is void;
  begin
    for formal_param range formal_params do
      paramCategory := category(formal_param);
      if paramCategory <> SYMBOLOBJECT then
        if first_element then
          first_element := FALSE;
        else
          c_expr.expr &:= " printf(\", \");\n";
        end if;
        param_type := getType(formal_param);
        if param_type in implements then
          c_expr.expr &:= " /*# ";
          for implementationType range implements[param_type] do
            c_expr.expr &:= type_name2(implementationType);
            c_expr.expr &:= "  ";
          end for;
          c_expr.expr &:= " */ ";
        end if;
        c_expr.expr &:= "printf(";
        c_expr.expr &:= c_literal(str(paramCategory) & " ");
        c_expr.expr &:= "); ";
        if param_type in typeCategory then
          case typeCategory[param_type] of
            when {INTOBJECT}:
              c_expr.expr &:= "printf(\"inttype \"); ";
              c_expr.expr &:= "printf(\"%ld\", ";
            when {FLOATOBJECT}:
              c_expr.expr &:= "printf(\"floattype \"); ";
              c_expr.expr &:= "printf(\"%f\", ";
            when {CHAROBJECT}:
              c_expr.expr &:= "printf(\"chartype \"); ";
              c_expr.expr &:= "printf(\"%c\", ";
            when {STRIOBJECT}:
              c_expr.expr &:= "printf(\"stritype \"); ";
              c_expr.expr &:= "filPrint(";
            when {TYPEOBJECT}:
              c_expr.expr &:= "printf(\"typetype \"); ";
              c_expr.expr &:= "printf(\"%X\", ";
            otherwise:
              c_expr.expr &:= "printf(\"";
              c_expr.expr &:= type_name(param_type);
              c_expr.expr &:= " \"); ";
              c_expr.expr &:= "printf(\"%X\", ";
          end case;
        else
          c_expr.expr &:= "printf(\"";
          c_expr.expr &:= type_name(param_type);
          c_expr.expr &:= " \"); ";
          c_expr.expr &:= "printf(\"%X\", ";
        end if;
        if isPointerParam(formal_param) then
          c_expr.expr &:= "(o_";
          create_name(formal_param, c_expr.expr);
          c_expr.expr &:= "?*o_";
          create_name(formal_param, c_expr.expr);
          c_expr.expr &:= ":0)";
        else
          c_expr.expr &:= "o_";
          create_name(formal_param, c_expr.expr);
        end if;
        c_expr.expr &:= ");";
      end if;
    end for;
  end func;


const proc: process_dynamic_parameter_list (in ref_list: actual_params,
    in reference: matched_object, inout expr_type: c_expr) is func

  local
    var ref_list: formal_params is ref_list.EMPTY;
    var reference: formal_param is NIL;
    var reference: actual_param is NIL;
    var category: paramCategory is category.value;
    var boolean: first_element is TRUE;
    var integer: number is 0;
  begin
    formal_params := formalParams(matched_object);
    for number range 1 to length(formal_params) do
      formal_param := formal_params[number];
      actual_param := actual_params[number];
      paramCategory := category(actual_param);
      if paramCategory <> SYMBOLOBJECT and
          category(formal_param) <> SYMBOLOBJECT then
        if first_element then
          first_element := FALSE;
        else
          c_expr.expr &:= ", ";
        end if;
        if not isVar(actual_param) and isInOutParam(formal_param) then
          c_expr.expr &:= "/* SHOULD NOT HAPPEN &o_";
          create_name(actual_param, c_expr.expr);
          c_expr.expr &:= " */";
        elsif isPointerParam(actual_param) = isPointerParam(formal_param) then
          c_expr.expr &:= "o_";
          create_name(actual_param, c_expr.expr);
        elsif isPointerParam(actual_param) and not isPointerParam(formal_param) then
          c_expr.expr &:= "*o_";
          create_name(actual_param, c_expr.expr);
        else # if isVar(actual_param) or not isInOutParam(formal_param) then
          c_expr.expr &:= "&o_";
          create_name(actual_param, c_expr.expr);
        end if;
      end if;
    end for;
  end func;


const proc: process_dynamic_action_call (in ref_list: actual_params,
    in reference: current_object, in reference: matched_object, inout expr_type: c_expr) is func

  local
    var expr_type: c_action_expr is expr_type.value;
  begin
    # c_expr.expr &:= "/* ";
    # c_expr.expr &:= str(getValue(matched_object, ACTION));
    # c_expr.expr &:= " */ ";
    c_action_expr.currentFile := file(current_object);
    c_action_expr.currentLine := line(current_object);
    c_action_expr.temp_num := c_expr.temp_num;
    process_action(matched_object, actual_params, c_action_expr);
    c_expr.temp_num := c_action_expr.temp_num;
    c_expr.temp_decls &:= c_action_expr.temp_decls;
    c_expr.temp_assigns &:= c_action_expr.temp_assigns;
    c_expr.temp_frees &:= c_action_expr.temp_frees;
    c_expr.temp_to_null &:= c_action_expr.temp_to_null;
    if c_action_expr.result_expr <> "" then
      c_expr.expr &:= c_action_expr.result_expr;
    else
      if isVarfunc(getType(current_object)) or
          getType(current_object) = proctype then
        c_expr.expr &:= c_action_expr.expr;
      else
        c_expr.expr &:= "/* copy ref_to_value */ ";
        process_create_declaration(resultType(getType(current_object)), global_c_expr);
        process_create_call(resultType(getType(current_object)),
            c_action_expr.expr, c_expr.expr);
      end if;
    end if;
  end func;


const proc: process_dynamic_call (in reference: current_object,
    in reference: matched_object, in ref_list: actual_params,
    inout expr_type: c_expr) is func

  local
    var category: objectCategory is category.value;
    var expr_type: resultExpr is expr_type.value;
  begin
    if matched_object <> NIL then
      c_expr.expr &:= diagnosticLine(current_object);
      objectCategory := category(matched_object);
      if objectCategory = BLOCKOBJECT then
        if resultType(getType(current_object)) <> voidtype then
          c_expr.expr &:= "return ";
        end if;
        resultExpr.expr &:= "o_";
        create_name(matched_object, resultExpr.expr);
        resultExpr.expr &:= "(";
        process_dynamic_parameter_list(actual_params, matched_object, resultExpr);
        resultExpr.expr &:= ")";
        if matched_object in return_ref_to_value then
          c_expr.expr &:= "/* copy ref_to_value */ ";
          process_create_declaration(resultType(getType(current_object)), global_c_expr);
          process_create_call(resultType(getType(current_object)),
              resultExpr.expr, c_expr.expr);
        else
          c_expr.expr &:= resultExpr.expr;
        end if;
        c_expr.temp_decls &:= resultExpr.temp_decls;
        c_expr.temp_assigns &:= resultExpr.temp_assigns;
        c_expr.temp_frees &:= resultExpr.temp_frees;
        c_expr.temp_to_null &:= resultExpr.temp_to_null;
        c_expr.expr &:= ";\n";
      elsif objectCategory = ACTOBJECT then
        if resultType(getType(current_object)) <> voidtype then
          c_expr.expr &:= "return ";
          if isVarfunc(getType(current_object)) then
            c_expr.expr &:= "&(";
          end if;
        end if;
        process_dynamic_action_call(actual_params, current_object, matched_object, c_expr);
        if resultType(getType(current_object)) <> voidtype then
          if isVarfunc(getType(current_object)) then
            c_expr.expr &:= ")";
          end if;
          c_expr.expr &:= ";\n";
        end if;
      elsif objectCategory = INTOBJECT or
          objectCategory = BIGINTOBJECT or
          objectCategory = FLOATOBJECT or
          objectCategory = CHAROBJECT or
          objectCategory = STRIOBJECT or
          objectCategory = BSTRIOBJECT or
          objectCategory = ARRAYOBJECT or
          objectCategory = STRUCTOBJECT or
          objectCategory = SETOBJECT or
          objectCategory = CONSTENUMOBJECT then
        c_expr.expr &:= "return ";
        getAnyParamToExpr(matched_object, resultExpr);
        process_create_declaration(getType(matched_object), global_c_expr);
        process_create_call(getType(matched_object),
            resultExpr.expr, c_expr.expr);
        c_expr.expr &:= ";\n";
      else
        c_expr.expr &:= "/* ";
        c_expr.expr &:= str(objectCategory);
        c_expr.expr &:= " */\n";
      end if;
    else
      c_expr.expr &:= "/* NOT FOUND */\n";
    end if;
  end func;


const proc: process_dynamic_condition (in reference: current_object,
    inout ref_list: formal_params, in var integer: paramNum,
    inout expr_type: c_expr) is forward;


const proc: process_dynamic_param_implements (in reference: current_object,
    inout ref_list: formal_params, in var integer: paramNum,
    in type: param_type, inout expr_type: c_expr) is func

  local
    var reference: formal_param is NIL;
    var type: implementationType is void;
  begin
    formal_param := formal_params[paramNum];
    c_expr.expr &:= diagnosticLine(current_object);
    for implementationType range implements[param_type] do
      c_expr.expr &:= "if (((interfacetype) ";
      if isPointerParam(formal_param) then
        c_expr.expr &:= "*o_";
      else
        c_expr.expr &:= "o_";
      end if;
      create_name(formal_param, c_expr.expr);
      c_expr.expr &:= ")->type_num==";
      c_expr.expr &:= str(typeNumber(implementationType));
      c_expr.expr &:= "/*";
      c_expr.expr &:= str(implementationType);
      c_expr.expr &:= "*/";
      c_expr.expr &:= ") {\n";

      setType(formal_params[paramNum], implementationType);
      process_dynamic_condition(current_object,
          formal_params, paramNum, c_expr);
      setType(formal_params[paramNum], param_type);
      c_expr.expr &:= diagnosticLine(current_object);
      c_expr.expr &:= "} else ";
    end for;
    c_expr.expr &:= "{\n";
    c_expr.expr &:= diagnosticLine(current_object);
    c_expr.expr &:= "raise_error(ACTION_ERROR);\n";
    (*
    c_expr.expr &:= diagnosticLine(current_object);
    c_expr.expr &:= "printf(\"type_num=%d\\n\", ";
    if isPointerParam(formal_param) then
      c_expr.expr &:= "((interfacetype) *o_";
    else
      c_expr.expr &:= "((interfacetype) o_";
    end if;
    create_name(formal_param, c_expr.expr);
    c_expr.expr &:= ")->type_num);\n";
    c_expr.expr &:= diagnosticLine(current_object);
    c_expr.expr &:= "printf(\"o_";
    create_name(current_object, c_expr.expr);
    c_expr.expr &:= "(\");\n";
    c_expr.expr &:= diagnosticLine(current_object);
    print_parameter_list(formal_params, c_expr);
    c_expr.expr &:= "printf(\")\\n\");\n";
    *)
    c_expr.expr &:= diagnosticLine(current_object);
    c_expr.expr &:= "}\n";
  end func;


const proc: process_dynamic_param_enumeration (in reference: current_object,
    inout ref_list: formal_params, in var integer: paramNum,
    in type: param_type, inout expr_type: c_expr) is func

  local
    var reference: formal_param is NIL;
    var number_element_hash: enumsByIntValue is number_element_hash.value;
    var integer: intValueOfEnum is 0;
    var reference: enumLiteral is NIL;
    var reference: backupParam is NIL;
  begin
    formal_param := formal_params[paramNum];
    c_expr.expr &:= diagnosticLine(current_object);
    c_expr.expr &:= "switch (";
    if isPointerParam(formal_param) then
      c_expr.expr &:= "*o_";
      create_name(formal_param, c_expr.expr);
    else
      c_expr.expr &:= "o_";
      create_name(formal_param, c_expr.expr);
    end if;
    c_expr.expr &:= ") {\n";
    enumsByIntValue := flip(enum_literal[param_type]);
    # Sort by integer values to always produce the same C code
    for intValueOfEnum range sort(keys(enumsByIntValue)) do
      c_expr.expr &:= diagnosticLine(current_object);
      c_expr.expr &:= "case ";
      c_expr.expr &:= str(intValueOfEnum);
      c_expr.expr &:= ": {\n";
      # If the enums are correct there will onle be one per integer value
      enumLiteral := enumsByIntValue[intValueOfEnum][1];
      backupParam := formal_params[paramNum];
      formal_params @:= [paramNum] enumLiteral;
      process_dynamic_condition(current_object,
          formal_params, paramNum, c_expr);
      formal_params @:= [paramNum] backupParam;
      c_expr.expr &:= diagnosticLine(current_object);
      c_expr.expr &:= "} break;\n";
    end for;
    c_expr.expr &:= diagnosticLine(current_object);
    c_expr.expr &:= "default: {\n";
    c_expr.expr &:= diagnosticLine(current_object);
    c_expr.expr &:= "raise_error(ACTION_ERROR);\n";
    (*
    c_expr.expr &:= "printf(\"literal_num=%d\\n\", ";
    if isPointerParam(formal_param) then
      c_expr.expr &:= "*o_";
      create_name(formal_param, c_expr.expr);
    else
      c_expr.expr &:= "o_";
      create_name(formal_param, c_expr.expr);
    end if;
    c_expr.expr &:= ");\n";
    c_expr.expr &:= "printf(\"o_";
    create_name(current_object, c_expr.expr);
    c_expr.expr &:= "(\");\n";
    print_parameter_list(formal_params, c_expr);
    c_expr.expr &:= "printf(\")\\n\");\n";
    *)
    c_expr.expr &:= "} break;\n";
    c_expr.expr &:= "}\n";
  end func;


const proc: process_dynamic_condition (in reference: current_object,
    inout ref_list: formal_params, in var integer: paramNum,
    inout expr_type: c_expr) is func

  local
    var reference: formal_param is NIL;
    var category: paramCategory is category.value;
    var type: param_type is void;
    var ref_list: param_list is ref_list.EMPTY;
    var reference: matched_object is NIL;
  begin
    incr(paramNum);
    if paramNum <= length(formal_params) then
      formal_param := formal_params[paramNum];
      paramCategory := category(formal_param);
      if paramCategory <> SYMBOLOBJECT then
        param_type := getType(formal_param);
        if param_type in implements then
          process_dynamic_param_implements(current_object,
              formal_params, paramNum, param_type, c_expr);
        elsif param_type in enum_literal then
          process_dynamic_param_enumeration(current_object,
              formal_params, paramNum, param_type, c_expr);
        else
          process_dynamic_condition(current_object,
              formal_params, paramNum, c_expr);
        end if;
      else
        process_dynamic_condition(current_object,
            formal_params, paramNum, c_expr);
      end if;
    else
      param_list := formal_params;
      matched_object := match(prog, param_list);
      if matched_object = NIL then
        c_expr.expr &:= "printf(\"NOT FOUND:\\n\");\n";
        for formal_param range formal_params do
          paramCategory := category(formal_param);
          if paramCategory <> SYMBOLOBJECT then
            param_type := getType(formal_param);
            if param_type in implements then
              c_expr.expr &:= "raise_error(ACTION_ERROR);\n";
              (*
              c_expr.expr &:= "printf(\"type_num=%d\\n\", ";
              if isPointerParam(formal_param) then
                c_expr.expr &:= "((interfacetype) *o_";
              else
                c_expr.expr &:= "((interfacetype) o_";
              end if;
              create_name(formal_param, c_expr.expr);
              c_expr.expr &:= ")->type_num);\n";
              *)
            elsif param_type in enum_literal then
              c_expr.expr &:= "raise_error(ACTION_ERROR);\n";
              (*
              c_expr.expr &:= "printf(\"literal_num=%d\\n\", ";
              if isPointerParam(formal_param) then
                c_expr.expr &:= "*o_";
              else
                c_expr.expr &:= "o_";
              end if;
              create_name(formal_param, c_expr.expr);
              c_expr.expr &:= ");\n";
              *)
            else
              c_expr.expr &:= "printf(\"other param_type\\n\");\n";
            end if;
          end if;
        end for;
      end if;
      process_dynamic_call(current_object, matched_object, formal_params, c_expr);
    end if;
  end func;


const proc: process_dynamic_decision (in reference: current_object,
    inout expr_type: c_expr) is func

  local
    var expr_type: c_param_list is expr_type.value;
    var expr_type: c_func_body is expr_type.value;
    var type: object_type is void;
    var type: result_type is void;
    var ref_list: param_list is ref_list.EMPTY;
  begin
    object_type := getType(current_object);
    if isFunc(object_type) or isVarfunc(object_type) then
      result_type := resultType(object_type);
      if result_type not in typeCategory or typeCategory[result_type] <> TYPEOBJECT then
        declare_types_of_params(param_list, global_c_expr);
        c_expr.expr &:= diagnosticLine(current_object);
        c_expr.expr &:= "/* DYNAMIC */ static ";
        c_expr.expr &:= type_name(result_type);
        if isVarfunc(object_type) then
          c_expr.expr &:= " *o_";
        else
          c_expr.expr &:= " o_";
        end if;
        create_name(current_object, c_expr.expr);
        param_list := formalParams(current_object);
        c_expr.expr &:= " (";
        process_param_list_declaration(param_list, c_param_list);
        c_expr.expr &:= c_param_list.expr;
        c_expr.expr &:= ")\n";
        c_expr.expr &:= diagnosticLine(current_object);
        c_expr.expr &:= "{\n";
        process_dynamic_condition(current_object,
            param_list, 0, c_func_body);
        AppendWithDiagnostic(c_param_list.temp_decls, c_expr);
        AppendWithDiagnostic(c_func_body.temp_decls, c_expr);
        c_expr.expr &:= c_param_list.temp_assigns;
        AppendWithDiagnostic(c_func_body.temp_assigns, c_expr);
        c_expr.expr &:= c_func_body.expr;
        AppendWithDiagnostic(c_param_list.temp_frees, c_expr);
        AppendWithDiagnostic(c_func_body.temp_frees, c_expr);
        c_expr.expr &:= diagnosticLine(current_object);
        c_expr.expr &:= "}\n\n";
      end if;
    end if;
  end func;


const proc: process_dynamic_decisions (inout expr_type: c_expr) is func

  local
    var reference: current_object is NIL;
  begin
    for current_object range dynamic_functions do
      process_dynamic_decision(current_object, c_expr);
    end for;
  end func;


const proc: process_dynamic_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  local
    var expr_type: c_param_list is expr_type.value;
    var type: object_type is void;
    var type: result_type is void;
    var ref_list: param_list is ref_list.EMPTY;
  begin
    object_type := getType(current_object);
    if isFunc(object_type) or isVarfunc(object_type) then
      result_type := resultType(object_type);
      if result_type not in typeCategory or typeCategory[result_type] <> TYPEOBJECT then
        dynamic_functions &:= make_list(current_object);
        declare_types_of_params(param_list, global_c_expr);
        c_expr.expr &:= "/* DYNAMIC */ static ";
        c_expr.expr &:= type_name(result_type);
        if isVarfunc(object_type) then
          c_expr.expr &:= " *o_";
        else
          c_expr.expr &:= " o_";
        end if;
        create_name(current_object, c_expr.expr);
        param_list := formalParams(current_object);
        c_expr.expr &:= " (";
        process_param_list_declaration(param_list, c_param_list);
        c_expr.expr &:= c_param_list.expr;
        c_expr.expr &:= ");\n";
        prototype_declared @:= [current_object] TRUE;
      end if;
    end if;
  end func;


const proc: process_hashcode (in reference: current_object, inout expr_type: c_expr) is func

  local
    var ref_list: param_list is ref_list.EMPTY;
    var reference: expression is NIL;
  begin
    c_expr := expr_type.value;
    setVar(current_object, FALSE);
    param_list := make_list(current_object);
    param_list &:= make_list(syobject(prog, "hashCode"));
    expression := matchExpr(prog, param_list);
    # TRACE_REF(expression);
    setCategory(expression, CALLOBJECT);
    process_expr(expression, c_expr);
  end func;


const func reference: keyCreateObj (in type: hash_type) is func

  result
    var reference: keyCreate is NIL;
  local
    var ref_list: param_list is ref_list.EMPTY;
  begin
    param_list := make_list(typeObject(hash_type));
    param_list &:= make_list(syobject(prog, "."));
    param_list &:= make_list(syobject(prog, "keyCreate"));
    keyCreate := match(prog, param_list);
  end func;


const func reference: keyCompareObj (in type: hash_type) is func

  result
    var reference: keyCompare is NIL;
  local
    var ref_list: param_list is ref_list.EMPTY;
  begin
    param_list := make_list(typeObject(hash_type));
    param_list &:= make_list(syobject(prog, "."));
    param_list &:= make_list(syobject(prog, "keyCompare"));
    keyCompare := match(prog, param_list);
  end func;


const func reference: dataCreateObj (in type: hash_type) is func

  result
    var reference: dataCreate is NIL;
  local
    var ref_list: param_list is ref_list.EMPTY;
  begin
    param_list := make_list(typeObject(hash_type));
    param_list &:= make_list(syobject(prog, "."));
    param_list &:= make_list(syobject(prog, "dataCreate"));
    dataCreate := match(prog, param_list);
  end func;


const func reference: dataCopyObj (in type: hash_type) is func

  result
    var reference: dataCopy is NIL;
  local
    var ref_list: param_list is ref_list.EMPTY;
  begin
    param_list := make_list(typeObject(hash_type));
    param_list &:= make_list(syobject(prog, "."));
    param_list &:= make_list(syobject(prog, "dataCopy"));
    dataCopy := match(prog, param_list);
  end func;


const proc: process_arr_cpy_declaration (in reference: current_object) is func

  local
    var ref_list: params is ref_list.EMPTY;
    var type: base_type is void;
    var type: object_type is void;
  begin
    params := formalParams(current_object);
    object_type := getType(params[1]);
    copyFunction @:= [object_type] current_object;
    typeCategory @:= [object_type] ARRAYOBJECT;
    base_type := base_type(object_type);
    if base_type <> void then
      if object_type not in array_element then
        array_element @:= [object_type] base_type;
      end if;
      if base_type not in array_type then
        array_type @:= [base_type] object_type;
      end if;
    end if;
  end func;


const proc: process_arr_create_declaration (in reference: current_object) is func

  local
    var ref_list: params is ref_list.EMPTY;
    var type: base_type is void;
    var type: object_type is void;
  begin
    params := formalParams(current_object);
    object_type := getType(params[1]);
    createFunction @:= [object_type] current_object;
    typeCategory @:= [object_type] ARRAYOBJECT;
    base_type := base_type(object_type);
    if base_type <> void then
      if object_type not in array_element then
        array_element @:= [object_type] base_type;
      end if;
      if base_type not in array_type then
        array_type @:= [base_type] object_type;
      end if;
    end if;
  end func;


const proc: process_arr_destr_declaration (in reference: current_object) is func

  local
    var ref_list: params is ref_list.EMPTY;
    var type: base_type is void;
    var type: object_type is void;
  begin
    params := formalParams(current_object);
    object_type := getType(params[1]);
    destrFunction @:= [object_type] current_object;
    typeCategory @:= [object_type] ARRAYOBJECT;
    base_type := base_type(object_type);
    if base_type <> void then
      if object_type not in array_element then
        array_element @:= [object_type] base_type;
      end if;
      if base_type not in array_type then
        array_type @:= [base_type] object_type;
      end if;
    end if;
  end func;


const proc: process_arr_gen_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  local
    var ref_list: params is ref_list.EMPTY;
    var type: result_type is void;
    var type: object_type is void;
  begin
    result_type := resultType(getType(current_object));
    params := formalParams(current_object);
    object_type := getType(params[1]);
    if result_type not in array_element then
      array_element @:= [result_type] object_type;
    end if;
    if object_type not in array_type then
      array_type @:= [object_type] result_type;
    end if;
    c_expr.expr &:= "/* ACTION ARR_GEN for type ";
    c_expr.expr &:= type_name2(result_type);
    c_expr.expr &:= " element is ";
    c_expr.expr &:= type_name2(object_type);
    c_expr.expr &:= " */\n\n";
  end func;


const proc: process_arr_idx_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  local
    var ref_list: params is ref_list.EMPTY;
    var type: result_type is void;
    var type: object_type is void;
  begin
    result_type := resultType(getType(current_object));
    params := formalParams(current_object);
    object_type := getType(params[1]);
    if object_type not in array_element then
      array_element @:= [object_type] result_type;
    end if;
    if result_type not in array_type then
      array_type @:= [result_type] object_type;
    end if;
    c_expr.expr &:= "/* ACTION ARR_IDX for type ";
    c_expr.expr &:= type_name2(object_type);
    c_expr.expr &:= " element is ";
    c_expr.expr &:= type_name2(result_type);
    c_expr.expr &:= " */\n\n";
  end func;


const proc: process_arr_times_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  local
    var string: diagnosticLine is "";
    var ref_list: params is ref_list.EMPTY;
    var type: result_type is void;
    var type: object_type is void;
  begin
    diagnosticLine := diagnosticLine(current_object);
    result_type := resultType(getType(current_object));
    params := formalParams(current_object);
    object_type := getType(params[3]);
    process_create_declaration(object_type, c_expr);
    c_expr.expr &:= diagnosticLine;
    # c_expr.expr &:= type_name(result_type);
    c_expr.expr &:= "static arraytype times_";
    c_expr.expr &:= str(typeNumber(result_type));
    c_expr.expr &:= " (inttype n, const ";
    if useConstPrefix(object_type) then
      c_expr.expr &:= "const_";
    end if;
    c_expr.expr &:= type_name(object_type);
    c_expr.expr &:= " b)\n";
    c_expr.expr &:= diagnosticLine;
    prototype_declared @:= [current_object] TRUE;
    c_expr.expr &:= "{\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "arraytype a;\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "memsizetype i;\n";
    if array_range_check then
      c_expr.expr &:= diagnosticLine;
      c_expr.expr &:= "if (n < 0) {\n";
      c_expr.expr &:= diagnosticLine;
      c_expr.expr &:= "raise_error(RANGE_ERROR);\n";
      c_expr.expr &:= diagnosticLine;
      c_expr.expr &:= "} else {\n";
    end if;
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "a=arrMalloc(1, n);\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "for (i = 0; i < (memsizetype)(n); i++) {\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "a->arr[i]";
    c_expr.expr &:= select_value_from_rtlObjectstruct(object_type);
    c_expr.expr &:= "=";
    process_create_call(object_type, "b", c_expr.expr);
    c_expr.expr &:= ";\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "}\n";
    if array_range_check then
      c_expr.expr &:= diagnosticLine;
      c_expr.expr &:= "}\n";
    end if;
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "return a;\n";
    c_expr.expr &:= diagnosticLine;
    c_expr.expr &:= "}\n";
    c_expr.expr &:= noDiagnosticLine;
    c_expr.expr &:= "\n";
  end func;


const proc: defineParam1TypeCategory (in reference: current_object,
    in category: param1Category) is func

  local
    var ref_list: params is ref_list.EMPTY;
    var type: param1Type is void;
  begin
    params := formalParams(current_object);
    param1Type := getType(params[1]);
    typeCategory @:= [param1Type] param1Category;
  end func;


const proc: addImplementationToInterface (in type: implementationType, in type: interfaceType) is func

  begin
    if interfaceType in implements then
      implements[interfaceType] &:= implementationType;
    else
      implements @:= [interfaceType] [] (implementationType);
    end if;
    if implementationType in interfaceOfType then
      interfaceOfType[implementationType] &:= interfaceType;
    else
      interfaceOfType @:= [implementationType] [] (interfaceType);
    end if;
  end func;


const proc: process_itf_cpy2_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  local
    var ref_list: params is ref_list.EMPTY;
    var type: interfaceType is void;
    var type: implementationType is void;
  begin
    params := formalParams(current_object);
    interfaceType := getType(params[1]);
    implementationType := getType(params[3]);
    addImplementationToInterface(implementationType, interfaceType);
    c_expr.expr &:= "/* itf_cpy2: ";
    c_expr.expr &:= type_name2(interfaceType);
    c_expr.expr &:= " := ";
    c_expr.expr &:= type_name2(implementationType);
    c_expr.expr &:= " */\n";
  end func;


const proc: process_itf_next_file_declaration (in reference: current_object) is func

  begin
    fileInterfaceType := resultType(getType(current_object));
  end func;


const proc: process_hsh_cpy_declaration (in reference: current_object) is func

  local
    var ref_list: params is ref_list.EMPTY;
    var type: hash_type is void;
  begin
    params := formalParams(current_object);
    hash_type := getType(params[1]);
    copyFunction @:= [hash_type] current_object;
    typeCategory @:= [hash_type] HASHOBJECT;
  end func;


const proc: process_hsh_create_declaration (in reference: current_object) is func

  local
    var ref_list: params is ref_list.EMPTY;
    var type: object_type is void;
  begin
    params := formalParams(current_object);
    object_type := getType(params[1]);
    createFunction @:= [object_type] current_object;
    typeCategory @:= [object_type] HASHOBJECT;
  end func;


const proc: process_hsh_destr_declaration (in reference: current_object) is func

  local
    var ref_list: params is ref_list.EMPTY;
    var type: object_type is void;
  begin
    params := formalParams(current_object);
    object_type := getType(params[1]);
    destrFunction @:= [object_type] current_object;
    typeCategory @:= [object_type] HASHOBJECT;
  end func;


const proc: addStructElem (in type: structType, in type: elemType, in reference: elementOfStruct) is func

  local
    var element_number_hash: element_number is element_number_hash.EMPTY_HASH;
    var element_type_hash: element_type is element_type_hash.EMPTY_HASH;
  begin
    if structType in struct_elements then
      if elementOfStruct not in struct_elements[structType] then
        struct_elements[structType] @:= [elementOfStruct] length(struct_elements[structType]);
      end if;
      if elementOfStruct not in struct_element_type[structType] then
        struct_element_type[structType] @:= [elementOfStruct] elemType;
      end if;
    else
      element_number @:= [elementOfStruct] 0;
      struct_elements @:= [structType] element_number;
      element_type @:= [elementOfStruct] elemType;
      struct_element_type @:= [structType] element_type;
    end if;
  end func;


const proc: process_sct_cpy_declaration (in reference: current_object) is func

  local
    var ref_list: params is ref_list.EMPTY;
    var type: sct_type is void;
    var type: meta_type is void;
    var type: interfaceType is void;
    var number_element_hash: elements is number_element_hash.EMPTY_HASH;
    var reference: elementOfStruct is NIL;
    var integer: number is 0;
  begin
    params := formalParams(current_object);
    sct_type := getType(params[1]);
    copyFunction @:= [sct_type] current_object;
    typeCategory @:= [sct_type] STRUCTOBJECT;
    if isDerived(sct_type) then
      meta_type := meta(sct_type);
      if meta_type in struct_elements then
        elements := flip(struct_elements[meta_type]);
        for number range 0 to pred(length(elements)) do
          elementOfStruct := elements[number][1];
          addStructElem(sct_type, struct_element_type[meta_type][elementOfStruct], elementOfStruct);
        end for;
      end if;
      if meta_type in interfaceOfType then
        for interfaceType range interfaceOfType[meta_type] do
          addImplementationToInterface(sct_type, interfaceType);
        end for;
      end if;
    end if;
  end func;


const proc: process_sct_create_declaration (in reference: current_object) is func

  local
    var ref_list: params is ref_list.EMPTY;
    var type: object_type is void;
  begin
    params := formalParams(current_object);
    object_type := getType(params[1]);
    createFunction @:= [object_type] current_object;
    typeCategory @:= [object_type] STRUCTOBJECT;
  end func;


const proc: process_sct_destr_declaration (in reference: current_object) is func

  local
    var ref_list: params is ref_list.EMPTY;
    var type: object_type is void;
  begin
    params := formalParams(current_object);
    object_type := getType(params[1]);
    destrFunction @:= [object_type] current_object;
    typeCategory @:= [object_type] STRUCTOBJECT;
  end func;


const proc: process_sct_select_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  local
    var ref_list: params is ref_list.EMPTY;
    var type: elemType is void;
    var type: structType is void;
    var reference: elementOfStruct is NIL;
  begin
    elemType := resultType(getType(current_object));
    params := formalParams(current_object);
    structType := getType(params[1]);
    elementOfStruct := params[3];
    addStructElem(structType, elemType, elementOfStruct);
    c_expr.expr &:= "/* struct element ";
    c_expr.expr &:= type_name2(elemType);
    c_expr.expr &:= " ** ";
    c_expr.expr &:= type_name2(structType);
    c_expr.expr &:= "->o_";
    create_name2(elementOfStruct, c_expr.expr);
    c_expr.expr &:= " = ";
    c_expr.expr &:= str(struct_elements[structType][elementOfStruct]);
    c_expr.expr &:= " */\n";
  end func;


const proc: process_ref_select_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  local
    var ref_list: params is ref_list.EMPTY;
    var type: elemType is void;
    var type: structType is void;
    var reference: elementOfStruct is NIL;
  begin
    elemType := resultType(getType(current_object));
    params := formalParams(current_object);
    structType := getType(params[1]);
    elementOfStruct := params[3];
    addStructElem(structType, elemType, elementOfStruct);
    c_expr.expr &:= "/* ref struct element ";
    c_expr.expr &:= type_name2(elemType);
    c_expr.expr &:= " ** ";
    c_expr.expr &:= type_name2(structType);
    c_expr.expr &:= "->o_";
    create_name2(elementOfStruct, c_expr.expr);
    c_expr.expr &:= " = ";
    c_expr.expr &:= str(struct_elements[structType][elementOfStruct]);
    c_expr.expr &:= " */\n";
  end func;


const proc: process_var_action_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  local
    var expr_type: c_value is expr_type.value;
    var string: valueName is "";
  begin
    create_name(current_object, objNumber(current_object), valueName);
    processFuncValue(valueName, getType(current_object), current_object, c_value);
    c_expr.expr &:= c_value.temp_decls;
    global_init.expr &:= diagnosticLine(current_object);
    global_init.expr &:= c_value.temp_assigns;
    c_expr.expr &:= type_name(getType(current_object));
    c_expr.expr &:= " o_";
    create_name(current_object, c_expr.expr);
    c_expr.expr &:= " = ";
    c_expr.expr &:= c_value.expr;
    c_expr.expr &:= ";\n\n";
    function_declared @:= [current_object] TRUE;
  end func;


const proc: process_action_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  local
    var ACTION: current_action is action "PRC_NOOP";
    var string: action_name is "";
  begin
    if isVar(current_object) then
      process_var_action_declaration(current_object, c_expr);
    else
      current_action := getValue(current_object, ACTION);
      action_name := str(current_action);
      if action_name = "PRC_DYNAMIC" then
        process_dynamic_declaration(current_object, c_expr);
        count_declarations;
      elsif action_name = "ACT_CPY" then
        defineParam1TypeCategory(current_object, ACTOBJECT);
        count_declarations;
      elsif action_name = "ARR_CPY" then
        process_arr_cpy_declaration(current_object);
        count_declarations;
      elsif action_name = "ARR_CREATE" then
        process_arr_create_declaration(current_object);
        count_declarations;
      elsif action_name = "ARR_DESTR" then
        process_arr_destr_declaration(current_object);
        count_declarations;
      elsif action_name = "ARR_GEN" then
        process_arr_gen_declaration(current_object, c_expr);
        count_declarations;
      elsif action_name = "ARR_IDX" then
        process_arr_idx_declaration(current_object, c_expr);
        count_declarations;
      elsif action_name = "ARR_TIMES" then
        process_arr_times_declaration(current_object, c_expr);
        count_declarations;
      elsif action_name = "BIG_CPY" or action_name = "BIG_CREATE" then
        defineParam1TypeCategory(current_object, BIGINTOBJECT);
        count_declarations;
      elsif action_name = "BLN_CPY" then
        defineParam1TypeCategory(current_object, BOOLOBJECT);
        count_declarations;
      elsif action_name = "BST_CPY" or action_name = "BST_CREATE" then
        defineParam1TypeCategory(current_object, BSTRIOBJECT);
        count_declarations;
      elsif action_name = "DRW_CPY" or action_name = "DRW_CREATE" then
        defineParam1TypeCategory(current_object, WINOBJECT);
        count_declarations;
      elsif action_name = "ENU_CPY" then
        defineParam1TypeCategory(current_object, ENUMOBJECT);
        count_declarations;
      elsif action_name = "FIL_CPY" or action_name = "FIL_CREATE" then
        defineParam1TypeCategory(current_object, FILEOBJECT);
        count_declarations;
      elsif action_name = "FLT_CPY" or action_name = "FLT_CREATE" then
        defineParam1TypeCategory(current_object, FLOATOBJECT);
        count_declarations;
      elsif action_name = "HSH_CPY" then
        process_hsh_cpy_declaration(current_object);
        count_declarations;
      elsif action_name = "HSH_CREATE" then
        process_hsh_create_declaration(current_object);
        count_declarations;
      elsif action_name = "HSH_DESTR" then
        process_hsh_destr_declaration(current_object);
        count_declarations;
      elsif action_name = "INT_CPY" or action_name = "INT_CREATE" then
        defineParam1TypeCategory(current_object, INTOBJECT);
        count_declarations;
      elsif action_name = "ITF_CPY" then
        defineParam1TypeCategory(current_object, INTERFACEOBJECT);
        count_declarations;
      elsif action_name = "ITF_CPY2" then
        process_itf_cpy2_declaration(current_object, c_expr);
        count_declarations;
      elsif action_name = "POL_CPY" or action_name = "POL_CREATE" then
        defineParam1TypeCategory(current_object, POLLOBJECT);
        count_declarations;
      elsif action_name = "POL_NEXT_FILE" then
        process_itf_next_file_declaration(current_object);
        count_declarations;
      elsif action_name = "PRG_CPY" or action_name = "PRG_CREATE" then
        defineParam1TypeCategory(current_object, PROGOBJECT);
        count_declarations;
      elsif action_name = "REF_CPY" or action_name = "REF_CREATE" then
        defineParam1TypeCategory(current_object, REFOBJECT);
        count_declarations;
      elsif action_name = "REF_SELECT" then
        process_ref_select_declaration(current_object, c_expr);
        count_declarations;
      elsif action_name = "RFL_CPY" or action_name = "RFL_CREATE" then
        defineParam1TypeCategory(current_object, REFLISTOBJECT);
        count_declarations;
      elsif action_name = "SCT_CPY" then
        process_sct_cpy_declaration(current_object);
        count_declarations;
      elsif action_name = "SCT_CREATE" then
        process_sct_create_declaration(current_object);
        count_declarations;
      elsif action_name = "SCT_DESTR" then
        process_sct_destr_declaration(current_object);
        count_declarations;
      elsif action_name = "SCT_SELECT" then
        process_sct_select_declaration(current_object, c_expr);
        count_declarations;
      elsif action_name = "SET_CPY" or action_name = "SET_CREATE" then
        defineParam1TypeCategory(current_object, SETOBJECT);
        count_declarations;
      elsif action_name = "SOC_CPY" or action_name = "SOC_CREATE" then
        defineParam1TypeCategory(current_object, SOCKETOBJECT);
        count_declarations;
(*
      else
        c_expr.expr &:= "/* ACTION ";
        c_expr.expr &:= action_name;
        c_expr.expr &:= " */";
*)
      end if;
    end if;
  end func;


const proc: process_object_declaration (in reference: current_object,
    inout expr_type: c_expr) is func

  local
    var category: objectCategory is category.value;
  begin
    objectCategory := category(current_object);
    if current_object = main_object then
      if category(current_object) = FORWARDOBJECT then
        process_library_initialisation(current_object, c_expr);
      else
        process_main_declaration(current_object, c_expr);
      end if;
    elsif objectCategory = BLOCKOBJECT then
      process_func_declaration(current_object, c_expr);
    elsif objectCategory = TYPEOBJECT then
      process_type_declaration(current_object, c_expr);
    elsif objectCategory = INTOBJECT then
      process_int_declaration(current_object, c_expr);
    elsif objectCategory = BIGINTOBJECT then
      process_bigint_declaration(current_object, c_expr);
    elsif objectCategory = CHAROBJECT then
      process_char_declaration(current_object, c_expr);
    elsif objectCategory = STRIOBJECT then
      process_stri_declaration(current_object, c_expr);
    elsif objectCategory = BSTRIOBJECT then
      process_bstri_declaration(current_object, c_expr);
    elsif objectCategory = FLOATOBJECT then
      process_float_declaration(current_object, c_expr);
    elsif objectCategory = REFOBJECT then
      process_reference_declaration(current_object, c_expr);
    elsif objectCategory = REFLISTOBJECT then
      process_ref_list_declaration(current_object, c_expr);
    elsif objectCategory = FILEOBJECT then
      process_file_declaration(current_object, c_expr);
    elsif objectCategory = SOCKETOBJECT then
      process_socket_declaration(current_object, c_expr);
    elsif objectCategory = POLLOBJECT then
      process_poll_declaration(current_object, c_expr);
    elsif objectCategory = ARRAYOBJECT then
      process_array_declaration(current_object, c_expr);
    elsif objectCategory = HASHOBJECT then
      process_hash_declaration(current_object, c_expr);
    elsif objectCategory = SETOBJECT then
      process_set_declaration(current_object, c_expr);
    elsif objectCategory = STRUCTOBJECT then
      process_struct_declaration(current_object, c_expr);
    elsif objectCategory = INTERFACEOBJECT then
      process_interface_declaration(current_object, c_expr);
    elsif objectCategory = WINOBJECT then
      process_win_declaration(current_object, c_expr);
    elsif objectCategory = PROGOBJECT then
      process_prog_declaration(current_object, c_expr);
    elsif objectCategory = CONSTENUMOBJECT then
      process_enum_declaration(current_object, c_expr);
    elsif objectCategory = VARENUMOBJECT then
      process_enum_declaration(current_object, c_expr);
    elsif objectCategory = ENUMLITERALOBJECT then
      process_enum_literal_declaration(current_object, c_expr);
    elsif objectCategory = ACTOBJECT then
      process_action_declaration(current_object, c_expr);
    elsif objectCategory = FWDREFOBJECT then
      process_forward_declaration(current_object, c_expr);
    else
      c_expr.expr &:= "/* ";
      c_expr.expr &:= str(objectCategory);
      c_expr.expr &:= ": ";
      create_name2(current_object, c_expr.expr);
      c_expr.expr &:= " */\n";
    end if;
  end func;


const proc: replaceLocalsFromOutside (in reference: local_function,
    inout reference: current_expression, in ref_list: local_objects,
    inout ref_list: additional_act_params, inout ref_list: additional_form_params) is func

  local
    var ref_list: params is ref_list.EMPTY;
    var integer: paramNum is 0;
    var reference: aParam is NIL;
    var category: paramCategory is category.value;
    var reference: formalRefParam is NIL;
  begin
    params := getValue(current_expression, ref_list);
    for paramNum range 2 to length(params) do
      aParam := params[paramNum];
      paramCategory := category(aParam);
      if paramCategory = MATCHOBJECT or paramCategory = CALLOBJECT then
        replaceLocalsFromOutside(local_function, aParam, local_objects,
            additional_act_params, additional_form_params);
      elsif paramCategory = LOCALVOBJECT or paramCategory = VALUEPARAMOBJECT or
          paramCategory = REFPARAMOBJECT or paramCategory = RESULTOBJECT then
        if aParam not in local_objects then
          if aParam in additional_act_params then
            formalRefParam := additional_form_params[pos(additional_act_params, aParam)];
          elsif local_function in params_added and
              aParam in params_added[local_function] then
            formalRefParam := params_added[local_function][aParam];
          else
            additional_act_params &:= make_list(aParam);
            formalRefParam := alloc(aParam);
            setCategory(formalRefParam, REFPARAMOBJECT);
            additional_form_params &:= make_list(formalRefParam);
          end if;
          params @:= [paramNum] formalRefParam;
        end if;
      end if;
    end for;
    setValue(current_expression, params);
  end func;


const proc: changeCallsOfLocalFunction (inout reference: current_expression,
    in reference: local_function, in ref_list: additional_params) is func

  local
    var ref_list: params is ref_list.EMPTY;
    var integer: paramNum is 0;
    var reference: aParam is NIL;
    var category: paramCategory is category.value;
  begin
    params := getValue(current_expression, ref_list);
    for paramNum range 2 to length(params) do
      aParam := params[paramNum];
      paramCategory := category(aParam);
      if paramCategory = MATCHOBJECT or paramCategory = CALLOBJECT then
        changeCallsOfLocalFunction(aParam, local_function, additional_params);
      elsif aParam = local_function then
        aParam := alloc(aParam);
        setCategory(aParam, MATCHOBJECT);
        setValue(aParam, make_list(params[paramNum]) & additional_params);
        params @:= [paramNum] aParam;
        setValue(current_expression, params);
      end if;
    end for;
    if params[1] = local_function then
      params &:= additional_params;
      setValue(current_expression, params);
    end if;
  end func;


const proc: changeCallsFromSubFunctions (in reference: parent_function,
    in reference: local_function, in ref_list: additional_params) is func

  local
    var reference: parent_body is NIL;
    var reference: obj is NIL;
  begin
    if parent_function <> local_function then
      parent_body := body(parent_function);
      changeCallsOfLocalFunction(parent_body, local_function, additional_params);
    end if;
    for obj range localConsts(parent_function) do
      if category(obj) = BLOCKOBJECT then
        changeCallsFromSubFunctions(obj, local_function, additional_params);
      end if;
    end for;
  end func;


const proc: adjustParamsToAdd (in reference: local_function,
    inout ref_list: additional_act_params, inout ref_list: additional_form_params) is func

  local
    var integer: paramNum is 0;
    var reference: actParam is NIL;
    var reference: formParam is NIL;
  begin
    if length(additional_act_params) <> 0 then
      if local_function not in params_added then
        params_added @:= [local_function] act_to_form_param_hash.value;
      end if;
      paramNum := 1;
      while paramNum <= length(additional_act_params) do
        actParam := additional_act_params[paramNum];
        if actParam in params_added[local_function] then
          additional_act_params := additional_act_params[.. pred(paramNum)] &
                                   additional_act_params[succ(paramNum) ..];
          additional_form_params := additional_form_params[.. pred(paramNum)] &
                                    additional_form_params[succ(paramNum) ..];
        else
          incr(paramNum);
        end if;
      end while;
      for paramNum range 1 to length(additional_act_params) do
        actParam := additional_act_params[paramNum];
        formParam := additional_form_params[paramNum];
        if actParam not in params_added[local_function] then
          params_added[local_function] @:= [actParam] formParam;
        end if;
      end for;
    end if;
  end func;


const func boolean: fixLocalFunction (in reference: parent_function,
    in reference: local_function) is func

  result
    var boolean: fix_done is FALSE;
  local
    var reference: body_expression is NIL;
    var category: bodyCategory is category.value;
    var ref_list: local_objects is ref_list.EMPTY;
    var ref_list: additional_act_params is ref_list.EMPTY;
    var ref_list: additional_form_params is ref_list.EMPTY;
  begin
    body_expression := body(local_function);
    bodyCategory := category(body_expression);
    if bodyCategory = MATCHOBJECT or bodyCategory = CALLOBJECT then
      local_objects := formalParams(local_function) & localVars(local_function) &
          make_list(resultVar(local_function));
      replaceLocalsFromOutside(local_function, body_expression, local_objects,
          additional_act_params, additional_form_params);
      adjustParamsToAdd(local_function, additional_act_params, additional_form_params);
      if length(additional_act_params) <> 0 then
        setFormalParams(local_function, formalParams(local_function) & additional_form_params);
        changeCallsOfLocalFunction(body_expression, local_function, additional_form_params);
        changeCallsFromSubFunctions(parent_function, local_function, additional_act_params);
        fix_done := TRUE;
      end if;
    end if;
  end func;


const proc: processLocalFunctions (in reference: current_object) is func

  local
    var ref_list: objects is ref_list.EMPTY;
    var reference: obj is NIL;
    var boolean: fix_done is FALSE;
  begin
    objects := localConsts(current_object);
    repeat
      fix_done := FALSE;
      for obj range objects do
        if category(obj) = BLOCKOBJECT then
          processLocalFunctions(obj);
          if fixLocalFunction(current_object, obj) then
            fix_done := TRUE;
          end if;
        end if;
      end for;
    until not fix_done;
  end func;


const proc: addTypeCategoryForLocalVars (in reference: function) is func

  local
    var ref_list: objects is ref_list.EMPTY;
    var reference: obj is NIL;
    var reference: object_value is NIL;
    var type: objectType is void;
    var category: valueCategory is category.value;
  begin
    objects := localVars(function);
    for obj range objects do
      object_value := getValue(obj, reference);
      valueCategory := category(object_value);
      objectType := getType(obj);
      if objectType = getType(object_value) and objectType not in typeCategory then
        typeCategory @:= [objectType] valueCategory;
      end if;
    end for;
  end func;


const proc: process_local_consts (in reference: function,
    inout expr_type: c_expr) is func

  local
    var ref_list: objects is ref_list.EMPTY;
    var reference: obj is NIL;
  begin
    addTypeCategoryForLocalVars(function);
    processLocalFunctions(function);
    objects := localConsts(function);
    for obj range objects do
      if category(obj) <> FWDREFOBJECT then
        declare_type_if_necessary(getType(obj), global_c_expr);
      end if;
      process_object_declaration(obj, c_expr);
    end for;
  end func;


const proc: process_object (in reference: current_object) is func

  local
    var expr_type: c_expr is expr_type.value;
  begin
    write_object_declaration := TRUE;
    process_object_declaration(current_object, c_expr);
    write(c_prog, global_c_expr.expr);
    if write_object_declaration then
      # writeln(c_prog, "/* " <& countDeclarations <& " */");
      write(c_prog, c_expr.expr);
(*
    else
      write(c_prog, "#ifdef WRITE_OBJECT_DECLARATION\n");
      write(c_prog, c_expr.expr);
      write(c_prog, "#endif\n");
*)
    end if;
    flush(c_prog);
    global_c_expr := expr_type.value;
  end func;


const proc: process_library_import_object (in reference: current_object) is func

  local
    var expr_type: c_expr is expr_type.value;
  begin
    process_object_declaration(current_object, c_expr);
    global_c_expr := expr_type.value;
  end func;


const proc: write_file_head is func

  begin
    writeln(c_prog, temp_marker);
    writeln(c_prog, "#include <stdlib.h>");
    writeln(c_prog, "#include <stdio.h>");
    writeln(c_prog, "#include <string.h>");
    writeln(c_prog, "#include <math.h>");
    writeln(c_prog, "#include <setjmp.h>");
    writeln(c_prog, "#include <signal.h>");
    writeln(c_prog, "typedef " <& ccConf.INT32TYPE <& " int32type;");
    writeln(c_prog, "typedef " <& ccConf.UINT32TYPE <& " uint32type;");
    writeln(c_prog, "typedef " <& ccConf.INT64TYPE <& " int64type;");
    writeln(c_prog, "typedef " <& ccConf.UINT64TYPE <& " uint64type;");
    if ccConf.TWOS_COMPLEMENT_INTTYPE then
      writeln(c_prog, "#define INT32TYPE_MIN ((int32type) -2147483648" <&
          ccConf.INT32TYPE_LITERAL_SUFFIX <& ")");
    else
      writeln(c_prog, "#define INT32TYPE_MIN             (-2147483647" <&
          ccConf.INT32TYPE_LITERAL_SUFFIX <& ")");
    end if;
    writeln(c_prog, "#define INT32TYPE_MAX               2147483647" <&
        ccConf.INT32TYPE_LITERAL_SUFFIX);
    if ccConf.INTTYPE_SIZE = 64 then
      writeln(c_prog, "typedef int64type inttype;");
      writeln(c_prog, "typedef uint64type uinttype;");
    elsif ccConf.INTTYPE_SIZE = 32 then
      writeln(c_prog, "typedef int32type inttype;");
      writeln(c_prog, "typedef uint32type uinttype;");
    end if;
    writeln(c_prog, "typedef int booltype;");
    writeln(c_prog, "typedef int enumtype;");
    if ccConf.FLOATTYPE_DOUBLE then
      writeln(c_prog, "typedef double floattype;");
    else
      writeln(c_prog, "typedef float floattype;");
    end if;
    writeln(c_prog, "typedef uint32type chartype;");
    writeln(c_prog, "typedef int32type schartype;");
    writeln(c_prog, "typedef uint32type strelemtype;");
    writeln(c_prog, "typedef uinttype bitsettype;");
    writeln(c_prog, "typedef uint" <& ccConf.POINTER_SIZE <& "type memsizetype;");
    writeln(c_prog, "typedef unsigned char *ustritype;");
    writeln(c_prog, "typedef const unsigned char *const_ustritype;");
    writeln(c_prog, "typedef struct stristruct {");
    writeln(c_prog, "  memsizetype size;");
    if ccConf.WITH_STRI_CAPACITY then
      writeln(c_prog, "  memsizetype capacity;");
    end if;
    if ccConf.ALLOW_STRITYPE_SLICES then
      writeln(c_prog, "  strelemtype *mem;");
      writeln(c_prog, "  strelemtype  mem1[1];");
    else
      writeln(c_prog, "  strelemtype mem[1];");
    end if;
    writeln(c_prog, "} *stritype;");
    writeln(c_prog, "typedef const struct stristruct  *const_stritype;");
    writeln(c_prog, "typedef struct bstristruct {");
    writeln(c_prog, "  memsizetype size;");
    writeln(c_prog, "  unsigned char mem[1];");
    writeln(c_prog, "} *bstritype;");
    writeln(c_prog, "typedef const struct bstristruct  *const_bstritype;");
    writeln(c_prog, "typedef struct setstruct {");
    writeln(c_prog, "  inttype min_position;");
    writeln(c_prog, "  inttype max_position;");
    writeln(c_prog, "  bitsettype bitset[1];");
    writeln(c_prog, "} *settype;");
    writeln(c_prog, "typedef const struct setstruct  *const_settype;");
    writeln(c_prog, "typedef struct bigintstruct {");
    writeln(c_prog, "  int dummy;");
    writeln(c_prog, "} *biginttype;");
    writeln(c_prog, "typedef const struct bigintstruct *const_biginttype;");
    writeln(c_prog, "typedef struct pollstruct {");
    writeln(c_prog, "  int dummy;");
    writeln(c_prog, "} *polltype;");
    writeln(c_prog, "typedef const struct pollstruct *const_polltype;");
    writeln(c_prog, "typedef struct winstruct {");
    writeln(c_prog, "  uinttype usage_count;");
    writeln(c_prog, "} *wintype;");
    writeln(c_prog, "typedef const struct winstruct *const_wintype;");
    writeln(c_prog, "typedef struct progstruct {");
    writeln(c_prog, "  uinttype usage_count;");
    writeln(c_prog, "} *progtype;");
    writeln(c_prog, "typedef const struct progstruct *const_progtype;");
    writeln(c_prog, "typedef struct typestruct *typetype;");
    writeln(c_prog, "typedef const struct typestruct *const_typetype;");
    writeln(c_prog, "typedef struct rtlArraystruct *arraytype;");
    writeln(c_prog, "typedef const struct rtlArraystruct *const_arraytype;");
    writeln(c_prog, "typedef struct rtlHashstruct *hashtype;");
    writeln(c_prog, "typedef const struct rtlHashstruct *const_hashtype;");
    writeln(c_prog, "typedef struct rtlStructstruct *structtype;");
    writeln(c_prog, "typedef const struct rtlStructstruct *const_structtype;");
    writeln(c_prog, "typedef struct rtlStructstruct *interfacetype;");
    writeln(c_prog, "typedef const struct rtlStructstruct *const_interfacetype;");
    writeln(c_prog, "typedef struct objectstruct *objreftype;");
    writeln(c_prog, "typedef const struct objectstruct *const_objreftype;");
    writeln(c_prog, "typedef struct liststruct *listtype;");
    writeln(c_prog, "typedef const struct liststruct *const_listtype;");
    writeln(c_prog, "typedef objreftype (*acttype) (listtype);");
    writeln(c_prog, "typedef FILE *filetype;");
    writeln(c_prog, "typedef int sockettype;");
    writeln(c_prog, "typedef uint" <& ccConf.GENERIC_SIZE <& "type generictype;");
    writeln(c_prog, "typedef union {");
    writeln(c_prog, "  generictype   genericvalue;");
    writeln(c_prog, "  typetype      typevalue;");
    writeln(c_prog, "  booltype      boolvalue;");
    writeln(c_prog, "  enumtype      enumvalue;");
    writeln(c_prog, "  inttype       intvalue;");
    writeln(c_prog, "  biginttype    bigintvalue;");
    writeln(c_prog, "  floattype     floatvalue;");
    writeln(c_prog, "  chartype      charvalue;");
    writeln(c_prog, "  stritype      strivalue;");
    writeln(c_prog, "  bstritype     bstrivalue;");
    writeln(c_prog, "  filetype      filevalue;");
    writeln(c_prog, "  sockettype    socketvalue;");
    writeln(c_prog, "  polltype      pollvalue;");
    writeln(c_prog, "  settype       setvalue;");
    writeln(c_prog, "  wintype       winvalue;");
    writeln(c_prog, "  progtype      progvalue;");
    writeln(c_prog, "  arraytype     arrayvalue;");
    writeln(c_prog, "  hashtype      hashvalue;");
    writeln(c_prog, "  structtype    structvalue;");
    writeln(c_prog, "  interfacetype interfacevalue;");
    writeln(c_prog, "  objreftype    objrefvalue;");
    writeln(c_prog, "  listtype      listvalue;");
    writeln(c_prog, "  acttype       actvalue;");
    writeln(c_prog, "} rtlValueunion;");
    writeln(c_prog, "typedef union {");
    writeln(c_prog, "  generictype         genericvalue;");
    writeln(c_prog, "  const_typetype      typevalue;");
    writeln(c_prog, "  booltype            boolvalue;");
    writeln(c_prog, "  enumtype            enumvalue;");
    writeln(c_prog, "  inttype             intvalue;");
    writeln(c_prog, "  const_biginttype    bigintvalue;");
    writeln(c_prog, "  floattype           floatvalue;");
    writeln(c_prog, "  chartype            charvalue;");
    writeln(c_prog, "  const_stritype      strivalue;");
    writeln(c_prog, "  const_bstritype     bstrivalue;");
    writeln(c_prog, "  filetype            filevalue;");
    writeln(c_prog, "  sockettype          socketvalue;");
    writeln(c_prog, "  const_polltype      pollvalue;");
    writeln(c_prog, "  const_settype       setvalue;");
    writeln(c_prog, "  const_wintype       winvalue;");
    writeln(c_prog, "  const_progtype      progvalue;");
    writeln(c_prog, "  const_arraytype     arrayvalue;");
    writeln(c_prog, "  const_hashtype      hashvalue;");
    writeln(c_prog, "  const_structtype    structvalue;");
    writeln(c_prog, "  const_interfacetype interfacevalue;");
    writeln(c_prog, "  const_objreftype    objrefvalue;");
    writeln(c_prog, "  const_listtype      listvalue;");
    writeln(c_prog, "  acttype             actvalue;");
    writeln(c_prog, "} const_rtlValueunion;");
    writeln(c_prog, "typedef struct rtlObjectstruct {");
    writeln(c_prog, "  rtlValueunion value;");
    writeln(c_prog, "} rtlObjecttype;");
    writeln(c_prog, "typedef const struct rtlObjectstruct const_rtlObjecttype;");
    writeln(c_prog, "typedef inttype (*intfunctype)();");
    writeln(c_prog, "typedef unsigned int categorytype;");
    writeln(c_prog, "struct objectstruct {");
    writeln(c_prog, "  typetype type_of;");
    writeln(c_prog, "  uint" <& ccConf.POINTER_SIZE <& "type descriptor;");
    writeln(c_prog, "  rtlValueunion value;");
    writeln(c_prog, "  categorytype objcategory;");
    writeln(c_prog, "};");
    writeln(c_prog, "struct typestruct {");
    writeln(c_prog, "  int dummy;");
    writeln(c_prog, "};");
    writeln(c_prog, "struct liststruct {");
    writeln(c_prog, "  listtype next;");
    writeln(c_prog, "  objreftype obj;");
    writeln(c_prog, "};");
    writeln(c_prog, "struct rtlArraystruct {");
    writeln(c_prog, "  inttype min_position;");
    writeln(c_prog, "  inttype max_position;");
    writeln(c_prog, "  rtlObjecttype arr[1];");
    writeln(c_prog, "};");
    writeln(c_prog, "struct rtlStructstruct {");
    writeln(c_prog, "  memsizetype usage_count;");
    writeln(c_prog, "  uint32type type_num;");
    writeln(c_prog, "  rtlObjecttype stru[1];");
    writeln(c_prog, "};");
    writeln(c_prog, "typedef struct rtlHelemstruct *helemtype;");
    writeln(c_prog, "typedef const struct rtlHelemstruct *const_helemtype;");
    writeln(c_prog, "typedef struct rtlHelemstruct *const helemtype_const;");
    writeln(c_prog, "struct rtlHelemstruct {");
    writeln(c_prog, "  helemtype next_less;");
    writeln(c_prog, "  helemtype next_greater;");
    writeln(c_prog, "  rtlObjecttype key;");
    writeln(c_prog, "  rtlObjecttype data;");
    writeln(c_prog, "};");
    writeln(c_prog, "struct rtlHashstruct {");
    writeln(c_prog, "  unsigned int bits;");
    writeln(c_prog, "  unsigned int mask;");
    writeln(c_prog, "  unsigned int table_size;");
    writeln(c_prog, "  memsizetype size;");
    writeln(c_prog, "  helemtype table[1];");
    writeln(c_prog, "};");
    writeln(c_prog, "typedef struct helemlist {");
    writeln(c_prog, "  struct helemlist *next;");
    writeln(c_prog, "  helemtype obj;");
    writeln(c_prog, "} *helemlisttype;");
    writeln(c_prog, "typedef inttype (*comparetype) (generictype, generictype);");
    writeln(c_prog, "typedef generictype (*createfunctype) (generictype);");
    writeln(c_prog, "typedef void (*destrfunctype) (generictype);");
    writeln(c_prog, "typedef void (*copyfunctype) (generictype *, generictype);");
    writeln(c_prog, "#define bitset_shift " <& log2(ccConf.INTTYPE_SIZE));
    writeln(c_prog, "#define bitset_mask  ((1 << bitset_shift) - 1)");
    if ccConf.RSHIFT_DOES_SIGN_EXTEND then
      writeln(c_prog, "#define bitset_pos(number) ((number)>>bitset_shift)");
    else
      writeln(c_prog, "#define bitset_pos(number) ((number)<0?~(~(number)>>bitset_shift):(number)>>bitset_shift)");
    end if;
    writeln(c_prog, "stritype          arg_0;");
    writeln(c_prog, "stritype          programName;");
    writeln(c_prog, "stritype          programPath;");
    writeln(c_prog, "arraytype         arg_v;");
    if ccConf.ALLOW_STRITYPE_SLICES then
      writeln(c_prog, "extern struct stristruct str[];");
    else
      writeln(c_prog, "extern stritype   str[];");
    end if;
    writeln(c_prog, "extern bstritype  bst[];");
    writeln(c_prog, "extern settype    set[];");
    writeln(c_prog, "extern typetype   typ[];");
    writeln(c_prog, "biginttype       *big;");
    writeln(c_prog, "wintype          *win;");
    writeln(c_prog, "arraytype        *arr;");
    writeln(c_prog, "structtype       *sct;");
    writeln(c_prog, "hashtype         *hsh;");
    writeln(c_prog, "interfacetype    *itf;");
    writeln(c_prog, "rtlValueunion     flt2int;");
    writeln(c_prog, "extern memsizetype hs;");
    writeln(c_prog);
    writeln(c_prog, "static const inttype fact[] = {");
    writeln(c_prog, "    1, 1, 2, 6, 24, 120, 720, 5040, 40320,");
    writeln(c_prog, "    362880, 3628800, 39916800, 479001600,");
    if ccConf.INTTYPE_SIZE = 64 then
      writeln(c_prog, "    6227020800, 87178291200, 1307674368000, 20922789888000,");
      writeln(c_prog, "    355687428096000, 6402373705728000, 121645100408832000,");
      writeln(c_prog, "    2432902008176640000");
    end if;
    writeln(c_prog, "  };");
    if ccConf.FLOAT_ZERO_DIV_ERROR then
      writeln(c_prog, "extern const rtlValueunion f_const[];");
      writeln(c_prog, "#define NOT_A_NUMBER      f_const[0].floatvalue");
      writeln(c_prog, "#define POSITIVE_INFINITY f_const[1].floatvalue");
      writeln(c_prog, "#define NEGATIVE_INFINITY f_const[2].floatvalue");
    else
      writeln(c_prog, "#define NOT_A_NUMBER      ( 0.0 / 0.0)");
      writeln(c_prog, "#define POSITIVE_INFINITY ( 1.0 / 0.0)");
      writeln(c_prog, "#define NEGATIVE_INFINITY (-1.0 / 0.0)");
    end if;
    if ccConf.ISNAN_WITH_UNDERLINE then
      writeln(c_prog, "#define isnan(number) _isnan(number)");
    end if;
    writeln(c_prog, "extern const floattype negativeZero;");
    writeln(c_prog, "#define OKAY_NO_ERROR 0");
    writeln(c_prog, "#define MEMORY_ERROR  1");
    writeln(c_prog, "#define NUMERIC_ERROR 2");
    writeln(c_prog, "#define RANGE_ERROR   3");
    writeln(c_prog, "#define FILE_ERROR    4");
    writeln(c_prog, "#define ACTION_ERROR  5");
    writeln(c_prog, "#define CREATE_ERROR  6");
    writeln(c_prog, "#define DESTROY_ERROR 7");
    writeln(c_prog, "#define COPY_ERROR    8");
    writeln(c_prog, "#define IN_ERROR      9");
    writeln(c_prog, "static const char *exception_name[] = {");
    writeln(c_prog, "    \"OKAY_NO_ERROR\",");
    writeln(c_prog, "    \"MEMORY_ERROR\",");
    writeln(c_prog, "    \"NUMERIC_ERROR\",");
    writeln(c_prog, "    \"RANGE_ERROR\",");
    writeln(c_prog, "    \"FILE_ERROR\",");
    writeln(c_prog, "    \"ACTION_ERROR\",");
    writeln(c_prog, "    \"CREATE_ERROR\",");
    writeln(c_prog, "    \"DESTROY_ERROR\",");
    writeln(c_prog, "    \"COPY_ERROR\",");
    writeln(c_prog, "    \"IN_ERROR\",");
    writeln(c_prog, "  };");
    writeln(c_prog, "#define push_stack(stack,elem) \\");
    writeln(c_prog, "{\\");
    writeln(c_prog, "  helemlisttype new_head = (helemlisttype)(malloc(sizeof(struct helemlist)));\\");
    writeln(c_prog, "  if (new_head == NULL) {\\");
    writeln(c_prog, "    raise_error(MEMORY_ERROR);\\");
    writeln(c_prog, "  } else {\\");
    writeln(c_prog, "    new_head->next = stack;\\");
    writeln(c_prog, "    new_head->obj = elem;\\");
    writeln(c_prog, "    stack = new_head;\\");
    writeln(c_prog, "  }\\");
    writeln(c_prog, "}");
    writeln(c_prog, "#define pop_stack(stack,elem) \\");
    writeln(c_prog, "{\\");
    writeln(c_prog, "  helemlisttype old_head = stack;\\");
    writeln(c_prog, "  if (old_head == NULL) {\\");
    writeln(c_prog, "    elem = NULL;\\");
    writeln(c_prog, "  } else {\\");
    writeln(c_prog, "    stack = old_head->next;\\");
    writeln(c_prog, "    elem = old_head->obj;\\");
    writeln(c_prog, "    free(old_head);\\");
    writeln(c_prog, "  }\\");
    writeln(c_prog, "}");
    if ccConf.HAS_SIGSETJMP then
      writeln(c_prog, "#define do_setjmp(jump_buf) sigsetjmp(jump_buf, -1)");
      writeln(c_prog, "typedef sigjmp_buf catch_type;");
    else
      writeln(c_prog, "#define do_setjmp(jump_buf) setjmp(jump_buf)");
      writeln(c_prog, "typedef jmp_buf catch_type;");
    end if;
    writeln(c_prog, "catch_type *catch_stack;");
    writeln(c_prog, "size_t catch_stack_pos;");
    writeln(c_prog, "size_t max_catch_stack;");
    writeln(c_prog, "const char *error_file = NULL;");
    writeln(c_prog, "int error_line = 0;");
  end func;


const proc: declareExtern (in string: prototype) is func

  begin
    write(c_prog, "extern ");
    if declare_with_extern_c then
      write(c_prog, "\"C\" ");
    end if;
    writeln(c_prog, prototype);
  end func;


const proc: write_prototypes is func

  begin
    declareExtern("acttype     actIConv (inttype);");
    declareExtern("inttype     actOrd (acttype);");
    declareExtern("stritype    actStr (acttype);");
    declareExtern("acttype     actValue (objreftype);");
    declareExtern("void        arrAppend (arraytype *const, const arraytype);");
    declareExtern("arraytype   arrArrlit2 (inttype, arraytype);");
    declareExtern("arraytype   arrBaselit (const generictype);");
    declareExtern("arraytype   arrBaselit2 (inttype, const generictype);");
    declareExtern("arraytype   arrCat (arraytype, const arraytype);");
    declareExtern("arraytype   arrExtend (arraytype, const generictype);");
    declareExtern("void        arrFree (arraytype);");
    declareExtern("arraytype   arrGen (const generictype, const generictype);");
    declareExtern("arraytype   arrHead (const const_arraytype, inttype);");
    declareExtern("arraytype   arrHeadTemp (arraytype *, inttype);");
    declareExtern("generictype arrIdxTemp (arraytype *, inttype);");
    declareExtern("arraytype   arrMalloc (inttype, inttype);");
    declareExtern("void        arrPush (arraytype *const, const generictype);");
    declareExtern("arraytype   arrRange (const const_arraytype, inttype, inttype);");
    declareExtern("arraytype   arrRangeTemp (arraytype *, inttype, inttype);");
    declareExtern("arraytype   arrRealloc (arraytype, memsizetype, memsizetype);");
    declareExtern("generictype arrRemove (arraytype *, inttype);");
    declareExtern("arraytype   arrSort (arraytype, comparetype);");
    declareExtern("arraytype   arrSubarr (const const_arraytype, inttype, inttype);");
    declareExtern("arraytype   arrSubarrTemp (arraytype *, inttype, inttype);");
    declareExtern("arraytype   arrTail (const const_arraytype, inttype);");
    declareExtern("arraytype   arrTailTemp (arraytype *, inttype);");
    declareExtern("biginttype  bigAbs (const const_biginttype);");
    declareExtern("biginttype  bigAdd (const_biginttype, const_biginttype);");
    declareExtern("biginttype  bigAddTemp (biginttype, const const_biginttype);");
    declareExtern("biginttype  bigAnd (const_biginttype, const_biginttype);");
    declareExtern("inttype     bigBitLength (const const_biginttype);");
    declareExtern("stritype    bigCLit (const const_biginttype);");
    declareExtern("inttype     bigCmp (const const_biginttype, const const_biginttype);");
    declareExtern("inttype     bigCmpGeneric (const generictype, const generictype);");
    declareExtern("inttype     bigCmpSignedDigit (const const_biginttype, inttype);");
    declareExtern("void        bigCpy (biginttype *const, const const_biginttype);");
    declareExtern("void        bigCpyGeneric (generictype *const, const generictype);");
    declareExtern("biginttype  bigCreate (const const_biginttype);");
    declareExtern("generictype bigCreateGeneric (const generictype);");
    declareExtern("void        bigDecr (biginttype *const);");
    declareExtern("void        bigDestr (const biginttype);");
    declareExtern("void        bigDestrGeneric (const generictype);");
    declareExtern("biginttype  bigDiv (const const_biginttype, const const_biginttype);");
    declareExtern("booltype    bigEq (const const_biginttype, const const_biginttype);");
    declareExtern("booltype    bigEqSignedDigit (const const_biginttype, inttype);");
    if ccConf.INTTYPE_SIZE = 64 then
      declareExtern("biginttype  bigFromInt64 (inttype);");
      writeln(c_prog, "#define     bigIConv bigFromInt64");
    elsif ccConf.INTTYPE_SIZE = 32 then
      declareExtern("biginttype  bigFromInt32 (inttype);");
      writeln(c_prog, "#define     bigIConv bigFromInt32");
    end if;
    declareExtern("biginttype  bigFromBStriBe (const const_bstritype);");
    declareExtern("biginttype  bigFromBStriLe (const const_bstritype);");
    declareExtern("biginttype  bigGcd (const const_biginttype, const const_biginttype);");
    declareExtern("void        bigGrow (biginttype *const, const const_biginttype);");
    declareExtern("inttype     bigHashCode (const const_biginttype);");
    declareExtern("char       *bigHexCStri (const const_biginttype);");
    declareExtern("biginttype  bigImport (const const_ustritype);");
    declareExtern("void        bigIncr (biginttype *const);");
    declareExtern("biginttype  bigIPow (const const_biginttype, inttype);");
    declareExtern("biginttype  bigLog2 (const const_biginttype);");
    declareExtern("biginttype  bigLowerBits (const const_biginttype, const inttype);");
    declareExtern("biginttype  bigLowerBitsTemp (const biginttype, const inttype);");
    declareExtern("inttype     bigLowestSetBit (const const_biginttype);");
    declareExtern("biginttype  bigLShift (const const_biginttype, const inttype);");
    declareExtern("void        bigLShiftAssign (biginttype *const, inttype);");
    declareExtern("biginttype  bigLShiftOne (const inttype);");
    declareExtern("biginttype  bigLog2BaseIPow (const inttype, const inttype);");
    declareExtern("biginttype  bigMDiv (const const_biginttype, const const_biginttype);");
    declareExtern("biginttype  bigMod (const const_biginttype, const const_biginttype);");
    declareExtern("biginttype  bigMult (const_biginttype, const_biginttype);");
    declareExtern("void        bigMultAssign (biginttype *const, const_biginttype);");
    declareExtern("biginttype  bigMultSignedDigit (const_biginttype, inttype);");
    declareExtern("biginttype  bigNegate (const const_biginttype);");
    declareExtern("biginttype  bigNegateTemp (biginttype);");
    declareExtern("booltype    bigOdd (const const_biginttype);");
    if ccConf.INTTYPE_SIZE = 64 then
      declareExtern("inttype     bigToInt64 (const const_biginttype);");
      writeln(c_prog, "#define     bigOrd bigToInt64");
    elsif ccConf.INTTYPE_SIZE = 32 then
      declareExtern("inttype     bigToInt32 (const const_biginttype);");
      writeln(c_prog, "#define     bigOrd bigToInt32");
    end if;
    declareExtern("biginttype  bigOr (const_biginttype, const_biginttype);");
    declareExtern("biginttype  bigParse (const const_stritype);");
    declareExtern("biginttype  bigParseBased (const const_stritype, inttype);");
    declareExtern("biginttype  bigPred (const const_biginttype);");
    declareExtern("biginttype  bigPredTemp (biginttype);");
    declareExtern("biginttype  bigRand (const const_biginttype, const const_biginttype);");
    declareExtern("biginttype  bigRem (const const_biginttype, const const_biginttype);");
    declareExtern("biginttype  bigRShift (const const_biginttype, const inttype);");
    declareExtern("void        bigRShiftAssign (biginttype *const, inttype);");
    declareExtern("biginttype  bigSbtr (const const_biginttype, const const_biginttype);");
    declareExtern("biginttype  bigSbtrTemp (biginttype, const_biginttype);");
    declareExtern("void        bigShrink (biginttype *const, const const_biginttype);");
    declareExtern("biginttype  bigSquare (const_biginttype);");
    declareExtern("stritype    bigStr (const const_biginttype);");
    declareExtern("biginttype  bigSucc (const const_biginttype);");
    declareExtern("biginttype  bigSuccTemp (biginttype);");
    declareExtern("bstritype   bigToBStriBe (const const_biginttype);");
    declareExtern("bstritype   bigToBStriLe (const const_biginttype);");
    declareExtern("biginttype  bigValue (objreftype);");
    declareExtern("biginttype  bigXor (const_biginttype, const_biginttype);");
    declareExtern("biginttype  bigZero (void);");
    declareExtern("void        blnCpy (booltype *, booltype);");
    declareExtern("booltype    blnValue (objreftype);");
    declareExtern("void        bstAppend (bstritype *const, const_bstritype);");
    declareExtern("bstritype   bstCat (const_bstritype, const_bstritype);");
    declareExtern("inttype     bstCmp (const const_bstritype, const const_bstritype);");
    declareExtern("inttype     bstCmpGeneric (const generictype, const generictype);");
    declareExtern("void        bstCpy (bstritype *const, const const_bstritype);");
    declareExtern("void        bstCpyGeneric (generictype *const, const generictype);");
    declareExtern("bstritype   bstCreate (const const_bstritype);");
    declareExtern("generictype bstCreateGeneric (const generictype);");
    declareExtern("void        bstDestr (const const_bstritype);");
    declareExtern("void        bstDestrGeneric (const generictype);");
    declareExtern("inttype     bstHashCode (const const_bstritype);");
    declareExtern("bstritype   bstParse (const const_stritype);");
    declareExtern("stritype    bstStr (const const_bstritype);");
    declareExtern("bstritype   bstValue (objreftype);");
    declareExtern("stritype    chrCLit (chartype);");
    declareExtern("stritype    chrCLitToBuffer (chartype, stritype);");
    declareExtern("inttype     chrCmp (chartype, chartype);");
    declareExtern("inttype     chrCmpGeneric (const generictype, const generictype);");
    declareExtern("void        chrCpy (chartype *, chartype);");
    declareExtern("chartype    chrLow (chartype);");
    declareExtern("stritype    chrStr (chartype);");
    if ccConf.ALLOW_STRITYPE_SLICES then
      writeln(c_prog, "#define     chrStrMacro(ch,str) (str.size=1,str.mem=str.mem1,str.mem1[0]=(strelemtype)(ch),&str)");
    else
      writeln(c_prog, "#define     chrStrMacro(ch,str) (str.size=1,str.mem[0]=(strelemtype)(ch),&str)");
    end if;
    declareExtern("chartype    chrUp (chartype);");
    declareExtern("chartype    chrValue (objreftype);");
    declareExtern("biginttype  cmdBigFileSize (const const_stritype);");
    declareExtern("void        cmdChdir (const const_stritype);");
    declareExtern("void        cmdCloneFile (const const_stritype, const const_stritype);");
    declareExtern("stritype    cmdConfigValue (const const_stritype);");
    declareExtern("void        cmdCopyFile (const const_stritype, const const_stritype);");
    declareExtern("arraytype   cmdEnvironment (void);");
    declareExtern("settype     cmdFileMode (const const_stritype);");
    declareExtern("inttype     cmdFileSize (const const_stritype);");
    declareExtern("inttype     cmdFileType (const const_stritype);");
    declareExtern("inttype     cmdFileTypeSL (const const_stritype);");
    declareExtern("stritype    cmdGetcwd (void);");
    declareExtern("stritype    cmdGetenv (const const_stritype);");
    declareExtern("void        cmdGetATime (const const_stritype, inttype *, inttype *, inttype *, inttype *, inttype *, inttype *, inttype *, inttype *, booltype *);");
    declareExtern("void        cmdGetCTime (const const_stritype, inttype *, inttype *, inttype *, inttype *, inttype *, inttype *, inttype *, inttype *, booltype *);");
    declareExtern("void        cmdGetMTime (const const_stritype, inttype *, inttype *, inttype *, inttype *, inttype *, inttype *, inttype *, inttype *, booltype *);");
    declareExtern("arraytype   cmdGetSearchPath (void);");
    declareExtern("stritype    cmdHomeDir (void);");
    declareExtern("arraytype   cmdLs (const const_stritype);");
    declareExtern("void        cmdMkdir (const const_stritype);");
    declareExtern("void        cmdMove (const const_stritype, const const_stritype);");
    declareExtern("stritype    cmdReadlink (const const_stritype);");
    declareExtern("void        cmdRemove (const const_stritype);");
    declareExtern("void        cmdRemoveAnyFile (const const_stritype);");
    declareExtern("void        cmdSetenv (const const_stritype, const const_stritype);");
    declareExtern("void        cmdSetATime (const const_stritype, inttype, inttype, inttype, inttype, inttype, inttype, inttype, inttype);");
    declareExtern("void        cmdSetFileMode (const const_stritype, const const_settype);");
    declareExtern("void        cmdSetMTime (const const_stritype, inttype, inttype, inttype, inttype, inttype, inttype, inttype, inttype);");
    declareExtern("inttype     cmdShell (const const_stritype, const const_stritype);");
    declareExtern("stritype    cmdShellEscape (const const_stritype);");
    declareExtern("void        cmdPipe2 (const const_stritype, const const_arraytype, filetype *, filetype *);");
    declareExtern("void        cmdPty (const const_stritype, const const_arraytype, filetype *, filetype *);");
    declareExtern("void        cmdStartProcess (const const_stritype, const const_arraytype);");
    declareExtern("void        cmdSymlink (const_stritype, const_stritype);");
    declareExtern("stritype    cmdToOsPath (const const_stritype);");
    declareExtern("void        conClear (inttype, inttype, inttype, inttype);");
    declareExtern("void        conCursor (booltype);");
    declareExtern("void        conFlush (void);");
    declareExtern("int         conHeight (void);");
    declareExtern("void        conHScroll (inttype, inttype, inttype, inttype, inttype);");
    declareExtern("int         conOpen (void);");
    declareExtern("void        conSetpos (inttype, inttype);");
    declareExtern("void        conShut (void);");
    declareExtern("void        conVScroll (inttype, inttype, inttype, inttype, inttype);");
    declareExtern("int         conWidth (void);");
    declareExtern("void        conWrite (const_stritype);");
    declareExtern("inttype     drwPointerXpos (const_wintype);");
    declareExtern("inttype     drwPointerYpos (const_wintype);");
    declareExtern("void        drwArc (const_wintype, inttype, inttype, inttype, floattype, floattype);");
    declareExtern("void        drwArc2 (const_wintype, inttype, inttype, inttype, inttype, inttype);");
    declareExtern("void        drwBackground (inttype);");
    declareExtern("void        drwCircle (const_wintype, inttype, inttype, inttype);");
    declareExtern("void        drwClear (wintype, inttype);");
    declareExtern("void        drwColor (inttype);");
    declareExtern("void        drwCopyArea (const_wintype, const_wintype, inttype, inttype, inttype, inttype, inttype, inttype);");
    declareExtern("void        drwCpy (wintype *, wintype);");
    declareExtern("void        drwCpyGeneric (generictype *const, const generictype);");
    declareExtern("wintype     drwCreate (wintype);");
    declareExtern("generictype drwCreateGeneric (const generictype);");
    declareExtern("void        drwDestr (wintype);");
    declareExtern("void        drwDestrGeneric (const generictype);");
    declareExtern("void        drwFArcChord (const_wintype, inttype, inttype, inttype, floattype, floattype);");
    declareExtern("void        drwFArcPieSlice (const_wintype, inttype, inttype, inttype, floattype, floattype);");
    declareExtern("void        drwFCircle (const_wintype, inttype, inttype, inttype);");
    declareExtern("void        drwFEllipse (const_wintype, inttype, inttype, inttype, inttype);");
    declareExtern("void        drwFlush (void);");
    declareExtern("bstritype   drwGenPointList (const const_arraytype);");
    declareExtern("wintype     drwGet (const_wintype, inttype, inttype, inttype, inttype);");
    declareExtern("bstritype   drwGetImage (const_wintype);");
    declareExtern("inttype     drwGetImagePixel (const_bstritype, inttype, inttype, inttype, inttype);");
    declareExtern("inttype     drwGetPixel (const_wintype, inttype, inttype);");
    declareExtern("inttype     drwHeight (const_wintype);");
    declareExtern("wintype     drwImage (int32type *, memsizetype, memsizetype);");
    declareExtern("void        drwLine (const_wintype, inttype, inttype, inttype, inttype);");
    declareExtern("wintype     drwNewPixmap (inttype, inttype);");
    declareExtern("wintype     drwOpen (inttype, inttype, inttype, inttype, const const_stritype);");
    declareExtern("wintype     drwOpenSubWindow (const_wintype, inttype, inttype, inttype, inttype);");
    declareExtern("void        drwPArc (const_wintype, inttype, inttype, inttype, floattype, floattype, inttype);");
    declareExtern("void        drwPCircle (const_wintype, inttype, inttype, inttype, inttype);");
    declareExtern("void        drwPFArcChord (const_wintype, inttype, inttype, inttype, floattype, floattype, inttype);");
    declareExtern("void        drwPFArcPieSlice (const_wintype, inttype, inttype, inttype, floattype, floattype, inttype);");
    declareExtern("void        drwPFCircle (const_wintype, inttype, inttype, inttype, inttype);");
    declareExtern("void        drwPFEllipse (const_wintype, inttype, inttype, inttype, inttype, inttype);");
    declareExtern("void        drwPixelToRgb (inttype, inttype *, inttype *, inttype *);");
    declareExtern("void        drwPLine (const_wintype, inttype, inttype, inttype, inttype, inttype);");
    declareExtern("void        drwPoint (const_wintype, inttype, inttype);");
    declareExtern("void        drwPPoint (const_wintype, inttype, inttype, inttype);");
    declareExtern("void        drwPRect (const_wintype, inttype, inttype, inttype, inttype, inttype);");
    declareExtern("void        drwPolyLine (const_wintype, inttype, inttype, bstritype, inttype);");
    declareExtern("void        drwFPolyLine (const_wintype, inttype, inttype, bstritype, inttype);");
    declareExtern("void        drwPut (const_wintype, const_wintype, inttype, inttype);");
    declareExtern("void        drwRect (const_wintype, inttype, inttype, inttype, inttype);");
    declareExtern("inttype     drwRgbColor (inttype, inttype, inttype);");
    declareExtern("wintype     drwRtlImage (const_arraytype);");
    declareExtern("void        drwSetContent (const_wintype, const_wintype);");
    declareExtern("void        drwSetPos (const_wintype, inttype, inttype);");
    declareExtern("void        drwSetTransparentColor (wintype, inttype);");
    declareExtern("void        drwText (const_wintype, inttype, inttype, const const_stritype, inttype, inttype);");
    declareExtern("void        drwToBottom (const_wintype);");
    declareExtern("void        drwToTop (const_wintype);");
    declareExtern("wintype     drwValue (objreftype);");
    declareExtern("inttype     drwWidth (const_wintype);");
    declareExtern("inttype     drwXPos (const_wintype);");
    declareExtern("inttype     drwYPos (const_wintype);");
    declareExtern("biginttype  filBigLng (filetype);");
    declareExtern("void        filBigSeek (filetype, const const_biginttype);");
    declareExtern("biginttype  filBigTell (filetype);");
    declareExtern("void        filClose (filetype);");
    declareExtern("stritype    filGets (filetype, inttype);");
    declareExtern("booltype    filHasNext (filetype);");
    declareExtern("booltype    filInputReady (filetype);");
    declareExtern("stritype    filLineRead (filetype, chartype *);");
    declareExtern("stritype    filLit (filetype);");
    declareExtern("inttype     filLng (filetype);");
    declareExtern("filetype    filOpen (const const_stritype, const const_stritype);");
    declareExtern("void        filPclose (filetype);");
    declareExtern("filetype    filPopen (const const_stritype, const const_stritype, const const_stritype);");
    declareExtern("void        filPrint (const const_stritype);");
    declareExtern("void        filSeek (filetype, inttype);");
    declareExtern("void        filSetbuf (filetype, inttype, inttype);");
    declareExtern("inttype     filTell (filetype);");
    declareExtern("stritype    filWordRead (filetype, chartype *);");
    declareExtern("void        filWrite (filetype, const const_stritype);");
    declareExtern("filetype    filValue (objreftype);");
    declareExtern("inttype     fltCmp (floattype, floattype);");
    declareExtern("inttype     fltCmpGeneric (const generictype, const generictype);");
    declareExtern("void        fltCpyGeneric (generictype *const, const generictype);");
    declareExtern("stritype    fltDgts (floattype, inttype);");
    if ccConf.NAN_COMPARISON_WRONG then
      declareExtern("booltype    fltEq (floattype, floattype);");
      declareExtern("booltype    fltGe (floattype, floattype);");
      declareExtern("booltype    fltGt (floattype, floattype);");
    end if;
    declareExtern("floattype   fltIPow (floattype, inttype);");
    declareExtern("booltype    fltIsNegativeZero (floattype);");
    writeln(c_prog, "#define     fltIsNegativeZeroMacro(number) (memcmp(&(number), &negativeZero, sizeof(floattype)) == 0)");
    if ccConf.NAN_COMPARISON_WRONG then
      declareExtern("booltype    fltLe (floattype, floattype);");
      declareExtern("booltype    fltLt (floattype, floattype);");
    end if;
    declareExtern("floattype   fltParse (const const_stritype);");
    if ccConf.POWER_OF_ZERO_WRONG then
      declareExtern("floattype   fltPow (floattype, floattype);");
    end if;
    declareExtern("floattype   fltRand (floattype, floattype);");
    declareExtern("stritype    fltSci (floattype, inttype);");
    declareExtern("stritype    fltStr (floattype);");
    declareExtern("floattype   fltValue (objreftype);");
    declareExtern("booltype    gkbButtonPressed (chartype);");
    declareExtern("inttype     gkbButtonXpos (void);");
    declareExtern("inttype     gkbButtonYpos (void);");
    declareExtern("chartype    gkbGetc (void);");
    declareExtern("stritype    gkbGets (inttype);");
    declareExtern("booltype    gkbKeyPressed (void);");
    declareExtern("stritype    gkbLineRead (chartype *);");
    declareExtern("chartype    gkbRawGetc (void);");
    declareExtern("wintype     gkbWindow (void);");
    declareExtern("stritype    gkbWordRead (chartype *);");
    declareExtern("booltype    hshContains (const const_hashtype, const generictype, inttype, comparetype);");
    declareExtern("void        hshCpy (hashtype *const, const const_hashtype, const createfunctype, const destrfunctype, const createfunctype, const destrfunctype);");
    declareExtern("hashtype    hshCreate (const const_hashtype, const createfunctype, const destrfunctype, const createfunctype, const destrfunctype);");
    declareExtern("void        hshDestr (const const_hashtype, const destrfunctype, const destrfunctype);");
    declareExtern("hashtype    hshEmpty (void);");
    declareExtern("void        hshExcl (const hashtype, const generictype, inttype, comparetype, const destrfunctype, const destrfunctype);");
    declareExtern("generictype hshIdx (const const_hashtype, const generictype, inttype, comparetype);");
    declareExtern("rtlObjecttype *hshIdxAddr (const const_hashtype, const generictype, inttype, comparetype);");
    declareExtern("rtlObjecttype *hshIdxAddr2 (const const_hashtype, const generictype, inttype, comparetype);");
    declareExtern("void        hshIncl (const hashtype, const generictype, const generictype, inttype, comparetype, const createfunctype, const createfunctype, const copyfunctype);");
    declareExtern("arraytype   hshKeys (const const_hashtype, const createfunctype, const destrfunctype);");
    declareExtern("generictype hshUpdate (const hashtype, const generictype, const generictype, inttype, comparetype, const createfunctype, const createfunctype);");
    declareExtern("arraytype   hshValues (const const_hashtype, const createfunctype, const destrfunctype);");
    declareExtern("inttype     intBinom (inttype, inttype);");
    declareExtern("inttype     intBitLength (inttype);");
    declareExtern("inttype     intCmp (inttype, inttype);");
    declareExtern("inttype     intCmpGeneric (const generictype, const generictype);");
    declareExtern("void        intCpy (inttype *, inttype);");
    declareExtern("inttype     intLog2 (inttype);");
    declareExtern("inttype     intLowestSetBit (inttype);");
    declareExtern("stritype    intLpad0 (inttype, const inttype);");
    declareExtern("inttype     intParse (const const_stritype);");
    declareExtern("inttype     intPow (inttype, inttype);");
    declareExtern("stritype    intRadix (inttype, inttype, booltype);");
    declareExtern("stritype    intRadixPow2 (inttype, int, int, booltype);");
    declareExtern("inttype     intRand (inttype, inttype);");
    declareExtern("inttype     intSqrt (inttype);");
    declareExtern("stritype    intStr (inttype);");
    declareExtern("stritype    intStrToBuffer (inttype, stritype);");
    declareExtern("bstritype   intToBStriBe (inttype);");
    declareExtern("bstritype   intToBStriLe (inttype);");
    declareExtern("inttype     intValue (objreftype);");
    declareExtern("interfacetype itfCreate (const interfacetype);");
    declareExtern("generictype itfCreateGeneric (const generictype);");
    declareExtern("chartype    kbdGetc (void);");
    declareExtern("stritype    kbdGets (inttype);");
    declareExtern("booltype    kbdKeyPressed (void);");
    declareExtern("stritype    kbdLineRead (chartype *);");
    declareExtern("chartype    kbdRawGetc (void);");
    declareExtern("stritype    kbdWordRead (chartype *);");
    declareExtern("void        polAddCheck (const polltype, const sockettype, inttype, const generictype);");
    declareExtern("void        polClear (const polltype);");
    declareExtern("void        polCpy (const polltype, const const_polltype);");
    declareExtern("polltype    polCreate (const const_polltype);");
    declareExtern("void        polDestr (const polltype);");
    declareExtern("polltype    polEmpty (void);");
    declareExtern("inttype     polGetCheck (const const_polltype, const sockettype);");
    declareExtern("inttype     polGetFinding (const const_polltype, const sockettype);");
    declareExtern("booltype    polHasNext (const polltype);");
    declareExtern("void        polIterChecks (const polltype, inttype);");
    declareExtern("void        polIterFindings (const polltype, inttype);");
    declareExtern("generictype polNextFile (const polltype, const generictype);");
    declareExtern("void        polPoll (const polltype);");
    declareExtern("void        polRemoveCheck (const polltype, const sockettype, inttype);");
    declareExtern("polltype    polValue (objreftype);");
    declareExtern("inttype     heapsize (void);");
    declareExtern("void        prcNoop (void)                                {}");
    declareExtern("void        prgCpy (progtype *const, const progtype);");
    declareExtern("progtype    prgCreate (const progtype);");
    declareExtern("void        prgDestr (progtype);");
    declareExtern("inttype     prgErrorCount (const const_progtype);");
    declareExtern("objreftype  prgEval (progtype, objreftype);");
    declareExtern("void        prgExec (const const_progtype, const const_arraytype, const_settype, const_stritype);");
    declareExtern("progtype    prgFilParse (const const_stritype, const_settype, const const_arraytype, const_stritype);");
    declareExtern("listtype    prgGlobalObjects (const const_progtype);");
    declareExtern("objreftype  prgMatch (const const_progtype, listtype);");
    declareExtern("objreftype  prgMatchExpr (const const_progtype, listtype);");
    declareExtern("const_stritype prgName (const const_progtype);");
    declareExtern("const_stritype prgPath (const const_progtype);");
    declareExtern("progtype    prgStrParse (const const_stritype, const_settype, const const_arraytype, const_stritype);");
    declareExtern("objreftype  prgSyobject (const progtype, const const_stritype);");
    declareExtern("objreftype  prgSysvar (const const_progtype, const const_stritype);");
    declareExtern("progtype    prgValue (objreftype);");
    declareExtern("objreftype  refAlloc (objreftype);");
    declareExtern("inttype     refArrMaxIdx (objreftype);");
    declareExtern("inttype     refArrMinIdx (objreftype);");
    declareExtern("listtype    refArrToList (objreftype);");
    declareExtern("objreftype  refBody (objreftype);");
    declareExtern("inttype     refCategory (objreftype);");
    declareExtern("stritype    refCatStr (inttype);");
    declareExtern("stritype    refFile (objreftype);");
    declareExtern("listtype    refHshDataToList (objreftype);");
    declareExtern("listtype    refHshKeysToList (objreftype);");
    declareExtern("booltype    refIsVar (objreftype);");
    declareExtern("objreftype  refItfToSct (objreftype);");
    declareExtern("inttype     refLine (objreftype);");
    declareExtern("listtype    refLocalConsts (objreftype);");
    declareExtern("listtype    refLocalVars (objreftype);");
    declareExtern("inttype     refNum (objreftype);");
    declareExtern("listtype    refParams (objreftype);");
    declareExtern("objreftype  refResini (objreftype);");
    declareExtern("objreftype  refResult (objreftype);");
    declareExtern("listtype    refSctToList (objreftype);");
    declareExtern("void        refSetCategory (objreftype, inttype);");
    declareExtern("void        refSetParams (objreftype, const_listtype);");
    declareExtern("void        refSetType (objreftype, typetype);");
    declareExtern("void        refSetVar (objreftype, booltype);");
    declareExtern("stritype    refStr (objreftype);");
    declareExtern("typetype    refType (objreftype);");
    declareExtern("objreftype  refValue (objreftype);");
    declareExtern("void        rflAppend (listtype *const, const listtype);");
    declareExtern("listtype    rflCat (listtype, const listtype);");
    declareExtern("inttype     rflCmpGeneric (const generictype, const generictype);");
    declareExtern("void        rflCpy (listtype *const, const const_listtype);");
    declareExtern("void        rflCpyGeneric (generictype *const, const generictype);");
    declareExtern("listtype    rflCreate (const const_listtype);");
    declareExtern("generictype rflCreateGeneric (const generictype);");
    declareExtern("void        rflDestr (const listtype);");
    declareExtern("void        rflDestrGeneric (const generictype);");
    declareExtern("booltype    rflElem (const const_objreftype, const_listtype);");
    declareExtern("void        rflElemcpy (listtype, inttype, objreftype);");
    declareExtern("booltype    rflEq (const_listtype, const_listtype);");
    declareExtern("listtype    rflHead (const listtype, inttype);");
    declareExtern("objreftype  rflIdx (const_listtype, inttype);");
    declareExtern("void        rflIncl (listtype *, objreftype);");
    declareExtern("inttype     rflIpos (listtype, objreftype, inttype);");
    declareExtern("inttype     rflLng (const_listtype);");
    declareExtern("listtype    rflMklist (objreftype);");
    declareExtern("inttype     rflPos (const_listtype, const const_objreftype);");
    declareExtern("void        rflSetvalue (objreftype, listtype);");
    declareExtern("listtype    rflTail (const_listtype, inttype);");
    declareExtern("listtype    rflValue (objreftype);");
    declareExtern("settype     setArrlit (const_arraytype);");
    declareExtern("settype     setBaselit (const inttype);");
    declareExtern("inttype     setCard (const const_settype);");
    declareExtern("inttype     setCmp (const const_settype, const const_settype);");
    declareExtern("inttype     setCmpGeneric (const generictype, const generictype);");
    declareExtern("void        setCpy (settype *const, const const_settype);");
    declareExtern("void        setCpyGeneric (generictype *const, const generictype);");
    declareExtern("settype     setCreate (const const_settype);");
    declareExtern("generictype setCreateGeneric (const generictype);");
    declareExtern("void        setDestr (const const_settype);");
    declareExtern("void        setDestrGeneric (const generictype);");
    declareExtern("settype     setDiff (const const_settype, const const_settype);");
    declareExtern("booltype    setElem (const inttype, const const_settype);");
    declareExtern("booltype    setEq (const const_settype, const const_settype);");
    declareExtern("void        setExcl (settype *const, const inttype);");
    declareExtern("inttype     setHashCode (const const_settype);");
    declareExtern("settype     setIConv (inttype);");
    declareExtern("void        setIncl (settype *const, const inttype);");
    declareExtern("settype     setIntersect (const const_settype, const const_settype);");
    declareExtern("booltype    setIsEmpty (const const_settype);");
    declareExtern("booltype    setIsProperSubset (const const_settype, const const_settype);");
    declareExtern("booltype    setIsSubset (const const_settype, const const_settype);");
    declareExtern("inttype     setMax (const const_settype);");
    declareExtern("inttype     setMin (const const_settype);");
    declareExtern("inttype     setNext (const const_settype, const inttype);");
    declareExtern("inttype     setRand (const const_settype);");
    declareExtern("settype     setRangelit (const inttype, const inttype);");
    declareExtern("inttype     setSConv (const const_settype);");
    declareExtern("settype     setSymdiff (const const_settype, const const_settype);");
    declareExtern("settype     setUnion (const const_settype, const const_settype);");
    declareExtern("settype     setValue (objreftype);");
    declareExtern("sockettype  socAccept (sockettype, bstritype *);");
    declareExtern("inttype     socAddrFamily (const const_bstritype);");
    declareExtern("stritype    socAddrNumeric (const const_bstritype);");
    declareExtern("stritype    socAddrService (const const_bstritype);");
    declareExtern("void        socBind (sockettype, const_bstritype);");
    declareExtern("void        socClose (sockettype);");
    declareExtern("void        socConnect (sockettype, const_bstritype);");
    declareExtern("chartype    socGetc (sockettype, chartype *);");
    declareExtern("stritype    socGets (sockettype, inttype, chartype *);");
    declareExtern("bstritype   socGetAddr (sockettype);");
    declareExtern("stritype    socGetHostname(void);");
    declareExtern("booltype    socHasNext (sockettype);");
    declareExtern("bstritype   socInetAddr (const const_stritype, inttype);");
    declareExtern("bstritype   socInetLocalAddr (inttype);");
    declareExtern("bstritype   socInetServAddr (inttype);");
    declareExtern("booltype    socInputReady (sockettype, inttype, inttype);");
    declareExtern("stritype    socLineRead (sockettype, chartype *);");
    declareExtern("void        socListen (sockettype, inttype);");
    declareExtern("inttype     socRecv (sockettype, stritype *, inttype, inttype);");
    declareExtern("inttype     socRecvfrom (sockettype, stritype *, inttype, inttype, bstritype *);");
    declareExtern("inttype     socSend (sockettype, const_stritype, inttype);");
    declareExtern("inttype     socSendto (sockettype, const_stritype, inttype, bstritype);");
    declareExtern("sockettype  socSocket (inttype, inttype, inttype);");
    declareExtern("stritype    socWordRead (sockettype, chartype *);");
    declareExtern("void        socWrite (sockettype, const const_stritype);");
    declareExtern("void        strAppend (stritype *const, const_stritype);");
    declareExtern("void        strAppendTemp (stritype *const, const stritype);");
    declareExtern("inttype     strChIPos (const const_stritype, const chartype, const inttype);");
    declareExtern("stritype    strChMult (const chartype, const inttype);");
    declareExtern("inttype     strChPos (const const_stritype, const chartype);");
    declareExtern("arraytype   strChSplit (const const_stritype, const chartype);");
    declareExtern("inttype     strCmpGeneric (const generictype, const generictype);");
    declareExtern("inttype     strCompare (const const_stritype, const const_stritype);");
    declareExtern("stritype    strConcat (const const_stritype, const const_stritype);");
    declareExtern("stritype    strConcatN (const const_stritype[], memsizetype);");
    declareExtern("stritype    strConcatTemp (stritype, const const_stritype);");
    declareExtern("stritype    strCLit (const const_stritype);");
    declareExtern("void        strCopy (stritype *const, const const_stritype);");
    declareExtern("void        strCpyGeneric (generictype *const, const generictype);");
    declareExtern("stritype    strCreate (const const_stritype);");
    declareExtern("generictype strCreateGeneric (const generictype);");
    declareExtern("void        strDestr (const const_stritype);");
    declareExtern("void        strDestrGeneric (const generictype);");
    declareExtern("stritype    strEmpty(void);");
    declareExtern("booltype    strGe (const const_stritype, const const_stritype);");
    declareExtern("booltype    strGt (const const_stritype, const const_stritype);");
    declareExtern("inttype     strHashCode (const const_stritype);");
    declareExtern("stritype    strHead (const_stritype, inttype);");
    declareExtern("void        strHeadSlice (const const_stritype, const inttype, stritype);");
    declareExtern("stritype    strHeadTemp (const stritype, const inttype);");
    declareExtern("inttype     strIPos (const const_stritype, const const_stritype, const inttype);");
    declareExtern("booltype    strLe (const const_stritype, const const_stritype);");
    declareExtern("stritype    strLit (const const_stritype);");
    declareExtern("stritype    strLow (const const_stritype);");
    declareExtern("stritype    strLowTemp (const stritype);");
    declareExtern("stritype    strLpad (const const_stritype, const inttype);");
    declareExtern("stritype    strLpadTemp (const stritype, const inttype);");
    declareExtern("stritype    strLpad0 (const const_stritype, const inttype);");
    declareExtern("stritype    strLpad0Temp (const stritype, const inttype);");
    declareExtern("booltype    strLt (const const_stritype, const const_stritype);");
    declareExtern("stritype    strLtrim (const const_stritype);");
    declareExtern("stritype    strMult (const const_stritype, const inttype);");
    declareExtern("inttype     strPos (const const_stritype, const const_stritype);");
    declareExtern("void        strPush (stritype *const, const chartype);");
    declareExtern("stritype    strRange (const_stritype, inttype, inttype);");
    declareExtern("void        strRangeSlice (const const_stritype, inttype, inttype, stritype);");
    declareExtern("inttype     strRChIPos (const const_stritype, const chartype, const inttype);");
    declareExtern("inttype     strRChPos (const const_stritype, const chartype);");
    declareExtern("stritype    strRepl (const const_stritype, const const_stritype, const const_stritype);");
    declareExtern("inttype     strRIPos (const const_stritype, const const_stritype, const inttype);");
    declareExtern("stritype    strRpad (const const_stritype, const inttype);");
    declareExtern("inttype     strRPos (const const_stritype, const const_stritype);");
    declareExtern("stritype    strRtrim (const const_stritype);");
    declareExtern("arraytype   strSplit (const const_stritype, const const_stritype);");
    declareExtern("stritype    strSubstr (const_stritype, inttype, inttype);");
    declareExtern("void        strSubstrSlice (const const_stritype, inttype, inttype, stritype);");
    declareExtern("stritype    strTail (const_stritype, inttype);");
    declareExtern("void        strTailSlice (const const_stritype, inttype, stritype);");
    declareExtern("stritype    strToUtf8 (const const_stritype);");
    declareExtern("stritype    strTrim (const const_stritype);");
    declareExtern("stritype    strUp (const const_stritype);");
    declareExtern("stritype    strUpTemp (const stritype);");
    declareExtern("stritype    strUtf8ToStri (const_stritype);");
    declareExtern("stritype    strValue (objreftype);");
    declareExtern("stritype    cstri8_or_cstri_to_stri (char *);");
    declareExtern("void        timAwait (inttype, inttype, inttype, inttype, inttype, inttype, inttype, inttype);");
    declareExtern("void        timFromIntTimestamp (inttype, inttype *, inttype *, inttype *, inttype *, inttype *, inttype *, inttype *, inttype *, booltype *);");
    declareExtern("void        timNow (inttype *, inttype *, inttype *, inttype *, inttype *, inttype *, inttype *, inttype *, booltype *);");
    declareExtern("void        timSetLocalTZ (inttype, inttype, inttype, inttype, inttype, inttype, inttype *, booltype *);");
    declareExtern("inttype     typCmp (const const_typetype, const const_typetype);");
    declareExtern("inttype     typCmpGeneric (generictype, generictype);");
    declareExtern("typetype    typFunc (typetype);");
    declareExtern("booltype    typIsDerived (typetype);");
    declareExtern("booltype    typIsFunc (typetype);");
    declareExtern("booltype    typIsVarfunc (typetype);");
    declareExtern("objreftype  typMatchobj (typetype);");
    declareExtern("typetype    typMeta (typetype);");
    declareExtern("inttype     typNum (typetype);");
    declareExtern("typetype    typResult (typetype);");
    declareExtern("stritype    typStr (typetype);");
    declareExtern("typetype    typValue (objreftype);");
    declareExtern("chartype    ut8Getc (filetype);");
    declareExtern("stritype    ut8Gets (filetype, inttype);");
    declareExtern("stritype    ut8LineRead (filetype, chartype *);");
    declareExtern("void        ut8Seek (filetype, inttype);");
    declareExtern("stritype    ut8WordRead (filetype, chartype *);");
    declareExtern("void        ut8Write (filetype, const const_stritype);");
    if ccConf.USE_WMAIN then
      declareExtern("arraytype   getArgv (const int, wchar_t *const *const, stritype *, stritype *, stritype *);");
    else
      declareExtern("arraytype   getArgv (const int, char *const *const, stritype *, stritype *, stritype *);");
    end if;
    declareExtern("void        setupStack (void);");
    declareExtern("void        setupFloat (void);");
    writeln(c_prog, "static void        init_values (void);");
    writeln(c_prog, "static void        init_globals (void);");
    declareExtern("void        initPollOperations (const createfunctype, const destrfunctype);");
    declareExtern("void        genericCpy (generictype *const, const generictype);");
    declareExtern("generictype genericCreate (generictype);");
    declareExtern("void        genericDestr (generictype);");
    declareExtern("inttype     ptrCmp (const void *const, const void *const);");
    declareExtern("inttype     ptrCmpGeneric (const generictype, const generictype);");
    declareExtern("void        ptrCpyGeneric (generictype *const, const generictype);");
    declareExtern("generictype ptrCreateGeneric (const generictype);");
    declareExtern("void        raise_error2 (int, const char *, int);");
    writeln(c_prog, "#define raise_error(num) raise_error2(num, __FILE__, __LINE__)\n");
(*
    declareExtern("inttype     enuValue (objreftype a)                         {printf(\"enuValue\\n\");}");
    declareExtern("inttype     enuValue (objreftype);");
    declareExtern("inttype     heapsize (void);");
    declareExtern("void        prcNoop (void);");
*)
  end func;


const proc: write_signal_handlers is func

  begin
    writeln(c_prog);
    writeln(c_prog);
    writeln(c_prog, "static void activate_signal_handlers (void);");
    writeln(c_prog);
    writeln(c_prog);
    writeln(c_prog, "static void handle_signals (int sig_num)");
    writeln(c_prog);
    writeln(c_prog, "  {");
    writeln(c_prog, "    int ch;");
    writeln(c_prog, "    char *sig_name;");
    writeln(c_prog, "    char buffer[20];");
    writeln(c_prog);
    writeln(c_prog, "#ifdef SIGALRM");
    writeln(c_prog, "    signal(SIGALRM, SIG_IGN);");
    writeln(c_prog, "#endif");
    writeln(c_prog, "    if (sig_num == SIGABRT) {");
    writeln(c_prog, "      sig_name = \"ABORT\";");
    writeln(c_prog, "    } else if (sig_num == SIGFPE) {");
    writeln(c_prog, "      sig_name = \"FPE\";");
    writeln(c_prog, "    } else if (sig_num == SIGILL) {");
    writeln(c_prog, "      sig_name = \"ILL\";");
    writeln(c_prog, "    } else if (sig_num == SIGINT) {");
    writeln(c_prog, "      sig_name = \"INTR\";");
    writeln(c_prog, "    } else if (sig_num == SIGSEGV) {");
    writeln(c_prog, "      sig_name = \"SEGV\";");
    writeln(c_prog, "    } else if (sig_num == SIGTERM) {");
    writeln(c_prog, "      sig_name = \"TERM\";");
    writeln(c_prog, "    } else {");
    writeln(c_prog, "      sprintf(buffer, \"%d\", sig_num);");
    writeln(c_prog, "      sig_name = buffer;");
    writeln(c_prog, "    } /* if */");
    writeln(c_prog, "    printf(\"\\n*** SIGNAL %s RAISED\\n\", sig_name);");
    if trace_signal then
      writeln(c_prog, "    printf(\"\\n*** (Type RETURN to continue or '*' to terminate)\\n\");");
      writeln(c_prog, "    ch = fgetc(stdin);");
      writeln(c_prog, "    if (ch == '*') {");
      writeln(c_prog, "      exit(1);");
      writeln(c_prog, "    } /* if */");
      writeln(c_prog, "    activate_signal_handlers();");
    else
      writeln(c_prog, "    exit(1);");
    end if;
    writeln(c_prog, "  }");
    writeln(c_prog);
    writeln(c_prog);
    writeln(c_prog, "static void handle_term_signal (int sig_num)");
    writeln(c_prog);
    writeln(c_prog, "  {");
    writeln(c_prog, "    printf(\"\\n*** SIGNAL TERM RAISED\\n\");");
    writeln(c_prog, "    printf(\"\\n*** Program terminated\\n\");");
    writeln(c_prog, "    exit(1);");
    writeln(c_prog, "  }");
    writeln(c_prog);
    writeln(c_prog);
    writeln(c_prog, "static void handle_numeric_error (int sig_num)");
    writeln(c_prog);
    writeln(c_prog, "  {");
    if not ccConf.HAS_SIGSETJMP then
      writeln(c_prog, "    signal(SIGFPE, handle_numeric_error);");
    end if;
    writeln(c_prog, "    raise_error(NUMERIC_ERROR);");
    writeln(c_prog, "  }");
    writeln(c_prog);
    writeln(c_prog);
    writeln(c_prog, "static void activate_signal_handlers (void)");
    writeln(c_prog);
    writeln(c_prog, "  {");
    writeln(c_prog, "    signal(SIGABRT, handle_signals);");
    writeln(c_prog, "    signal(SIGFPE, handle_numeric_error);");
    if ccConf.SIGILL_ON_OVERFLOW then
      writeln(c_prog, "    signal(SIGILL, handle_numeric_error);");
    else
      writeln(c_prog, "    signal(SIGILL, handle_signals);");
    end if;
    writeln(c_prog, "    signal(SIGINT, handle_signals);");
    writeln(c_prog, "    signal(SIGSEGV, handle_signals);");
    writeln(c_prog, "    signal(SIGTERM, handle_term_signal);");
    writeln(c_prog, "#ifdef SIGPIPE");
    writeln(c_prog, "    signal(SIGPIPE, SIG_IGN);");
    writeln(c_prog, "#endif");
    writeln(c_prog, "  }");
    writeln(c_prog);
    writeln(c_prog);
    writeln(c_prog, "static void resize_catch_stack (void)");
    writeln(c_prog);
    writeln(c_prog, "  {");
    writeln(c_prog, "    catch_type *resized_stack;");
    writeln(c_prog);
    writeln(c_prog, "    max_catch_stack += 128;");
    writeln(c_prog, "    resized_stack = (catch_type *)(realloc(catch_stack, max_catch_stack));");
    writeln(c_prog, "    if (resized_stack == NULL) {");
    writeln(c_prog, "      catch_stack_pos--;");
    writeln(c_prog, "      raise_error(MEMORY_ERROR);");
    writeln(c_prog, "    } else {");
    writeln(c_prog, "      catch_stack = resized_stack;");
    writeln(c_prog, "    }");
    writeln(c_prog, "  }");
    writeln(c_prog);
    writeln(c_prog);
    writeln(c_prog, "static inttype int_raise_error (int fail_value, const char *file_name, int line_number)");
    writeln(c_prog, "{");
    writeln(c_prog, "  raise_error2(fail_value, file_name, line_number);");
    writeln(c_prog, "  return 0;");
    writeln(c_prog, "}");
    writeln(c_prog);
    writeln(c_prog);
  end func;


const proc: initPollOperations (inout expr_type: c_expr) is func

  begin
    if fileInterfaceType <> void then
      c_expr.expr &:= "initPollOperations((createfunctype)(&itfCreate), ";
      process_destr_declaration(fileInterfaceType, global_c_expr);
      c_expr.expr &:= "(destrfunctype)(&destr_";
      c_expr.expr &:= str(typeNumber(fileInterfaceType));
      c_expr.expr &:= "));\n";
    end if;
  end func;


const func boolean: identical_values (in reference: object1, in reference: object2) is func

  result
    var boolean: isIdentical is FALSE;
  local
    var category: objectCategory is category.value;
    var reference: element1 is NIL;
    var ref_list: element_list2 is ref_list.EMPTY;
    var integer: index2 is 0;
  begin
    objectCategory := category(object1);
    if objectCategory = INTOBJECT then
      isIdentical := getValue(object1, integer) = getValue(object2, integer);
    elsif objectCategory = BIGINTOBJECT then
      isIdentical := getValue(object1, bigInteger) = getValue(object2, bigInteger);
    elsif objectCategory = CHAROBJECT then
      isIdentical := getValue(object1, char) = getValue(object2, char);
    elsif objectCategory = STRIOBJECT then
      isIdentical := getValue(object1, string) = getValue(object2, string);
    elsif objectCategory = BSTRIOBJECT then
      isIdentical := getValue(object1, bstring) = getValue(object2, bstring);
    elsif objectCategory = SETOBJECT then
      isIdentical := getValue(object1, bitset) = getValue(object2, bitset);
    elsif objectCategory = FLOATOBJECT then
      isIdentical := getValue(object1, float) = getValue(object2, float);
    elsif objectCategory = REFOBJECT then
      isIdentical := getValue(object1, reference) = getValue(object2, reference);
    elsif objectCategory = FILEOBJECT then
      isIdentical := getValue(object1, clib_file) = getValue(object2, clib_file);
    elsif objectCategory = CONSTENUMOBJECT or objectCategory = VARENUMOBJECT then
      isIdentical := getValue(object1, reference) = getValue(object2, reference);
    elsif objectCategory = ARRAYOBJECT then
      if arrayMinIdx(object1) = arrayMinIdx(object2) and
          arrayMaxIdx(object1) = arrayMaxIdx(object2) then
        isIdentical := TRUE;
        element_list2 := arrayToList(object2);
        index2 := 1;
        for element1 range arrayToList(object1) until not isIdentical do
          isIdentical := identical_values(element1, element_list2[index2]);
          incr(index2);
        end for;
      end if;
    elsif objectCategory = STRUCTOBJECT then
      isIdentical := TRUE;
      element_list2 := structToList(object2);
      index2 := 1;
      for element1 range structToList(object1) until not isIdentical do
        isIdentical := identical_values(element1, element_list2[index2]);
        incr(index2);
      end for;
    end if;
  end func;


const func ref_list: determine_multiple_array_elements (in ref_list: array_list) is func

  result
    var ref_list: elements_to_walk is ref_list.EMPTY;
  local
    var reference: element is NIL;
    var reference: previous_element is NIL;
    var reference: repeat_block_element is NIL;
    var integer: repeat_count is 0;
  begin
    for element range array_list do
      if previous_element <> NIL then
        if identical_values(previous_element, element) then
          if repeat_block_element = NIL then
            repeat_block_element := previous_element;
            repeat_count := 2;
          else
            incr(repeat_count);
          end if;
        else
          elements_to_walk &:= make_list(element);
          if repeat_block_element <> NIL then
            element_repeat_count @:= [repeat_block_element] repeat_count;
            repeat_block_element := NIL;
          end if;
        end if;
      else
        elements_to_walk &:= make_list(element);
      end if;
      previous_element := element;
    end for;
    if repeat_block_element <> NIL then
      element_repeat_count @:= [repeat_block_element] repeat_count;
    end if;
  end func;


const proc: walk_const_list (in ref_list: const_list, inout ref_list: sorted_list) is func

  local
    var reference: current_object is NIL;
    var reference: struct_of_interface is NIL;
    var category: objectCategory is category.value;
    var ref_list: elements_to_walk is ref_list.EMPTY;
  begin
    for current_object range const_list do
      objectCategory := category(current_object);
      if objectCategory = BIGINTOBJECT then
        if getValue(current_object, bigInteger) not in bigint_const_table then
          bigint_const_table @:= [getValue(current_object, bigInteger)] length(bigint_const_table);
        end if;
      elsif objectCategory = STRIOBJECT then
        if getValue(current_object, string) not in stri_const_table then
          stri_const_table @:= [getValue(current_object, string)] length(stri_const_table);
        end if;
      elsif objectCategory = BSTRIOBJECT then
        if getValue(current_object, bstring) not in bstri_const_table then
          bstri_const_table @:= [getValue(current_object, bstring)] length(bstri_const_table);
        end if;
      elsif objectCategory = SETOBJECT then
        if getValue(current_object, bitset) not in set_const_table then
          set_const_table @:= [getValue(current_object, bitset)] length(set_const_table);
        end if;
      elsif objectCategory = ARRAYOBJECT then
        if current_object not in const_table then
          const_table @:= [current_object] length(const_table);
        end if;
        elements_to_walk := determine_multiple_array_elements(arrayToList(current_object));
        walk_const_list(elements_to_walk, sorted_list);
        sorted_list &:= make_list(current_object);
      elsif objectCategory = STRUCTOBJECT then
        if current_object not in const_table then
          const_table @:= [current_object] length(const_table);
        end if;
        walk_const_list(structToList(current_object), sorted_list);
        sorted_list &:= make_list(current_object);
      elsif objectCategory = HASHOBJECT then
        if current_object not in const_table then
          const_table @:= [current_object] length(const_table);
        end if;
        walk_const_list(hashKeysToList(current_object), sorted_list);
        walk_const_list(hashDataToList(current_object), sorted_list);
        sorted_list &:= make_list(current_object);
      elsif objectCategory = INTERFACEOBJECT then
        if current_object not in const_table then
          const_table @:= [current_object] length(const_table);
        end if;
        struct_of_interface := interfaceToStruct(current_object);
        if struct_of_interface not in const_table then
          const_table @:= [struct_of_interface] length(const_table);
          walk_const_list(structToList(struct_of_interface), sorted_list);
          sorted_list &:= make_list(struct_of_interface);
        elsif const_table[struct_of_interface] >= const_table[current_object] then
          sorted_list &:= make_list(struct_of_interface);
        end if;
        sorted_list &:= make_list(current_object);
      elsif objectCategory = MATCHOBJECT or objectCategory = ACTOBJECT then
        if current_object not in const_table then
          const_table @:= [current_object] length(const_table);
        end if;
        sorted_list &:= make_list(current_object);
      end if;
    end for;
  end func;


const proc: prepare_func_literal (in reference: current_object,
    inout expr_type: c_expr) is func

  local
    var expr_type: c_value is expr_type.value;
    var string: valueName is "";
  begin
    create_name(current_object, objNumber(current_object), valueName);
    processFuncValue(valueName, getType(current_object), current_object, c_value);
    global_c_expr.expr &:= c_value.temp_decls;
    global_init.expr &:= diagnosticLine(current_object);
    global_init.expr &:= c_value.temp_assigns;
    function_declared @:= [current_object] TRUE;
  end func;


const proc: process_func_literal (in reference: current_object,
    inout expr_type: c_expr) is func

  local
    var string: valueName is "";
  begin
    create_name(current_object, objNumber(current_object), valueName);
    c_expr.expr &:= "&funcvalue_";
    c_expr.expr &:= valueName;
  end func;


const proc: process_pollData_literal (in var pollData: aPollData,
    inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "polEmpty()";
  end func;


const proc: init_const_value (in reference: current_object, inout expr_type: c_expr) is func

  local
    var category: objectCategory is category.value;
  begin
    objectCategory := category(current_object);
    if objectCategory = INTOBJECT then
      c_expr.expr &:= ".value.intvalue=";
      c_expr.expr &:= str(getValue(current_object, integer));
    elsif objectCategory = BIGINTOBJECT then
      c_expr.expr &:= ".value.bigintvalue=";
      c_expr.expr &:= bigIntegerLiteral(getValue(current_object, bigInteger));
    elsif objectCategory = CHAROBJECT then
      c_expr.expr &:= ".value.charvalue=";
      c_expr.expr &:= charLiteral(getValue(current_object, char));
    elsif objectCategory = STRIOBJECT then
      c_expr.expr &:= ".value.strivalue=";
      c_expr.expr &:= stringLiteral(getValue(current_object, string));
    elsif objectCategory = BSTRIOBJECT then
      c_expr.expr &:= ".value.bstrivalue=";
      c_expr.expr &:= bstriLiteral(getValue(current_object, bstring));
    elsif objectCategory = SETOBJECT then
      c_expr.expr &:= ".value.setvalue=";
      c_expr.expr &:= bitsetLiteral(getValue(current_object, bitset));
    elsif objectCategory = FLOATOBJECT then
      c_expr.expr &:= ".value.floatvalue=";
      c_expr.expr &:= floatLiteral(getValue(current_object, float));
    elsif objectCategory = REFOBJECT then
      c_expr.expr &:= ".value.objrefvalue=";
      if getValue(current_object, reference) = NIL then
        c_expr.expr &:= "NULL";
      else
        c_expr.expr &:= "(objreftype)(&(";
        process_expr(getValue(current_object, reference), c_expr);
        c_expr.expr &:= "))";
      end if;
    elsif objectCategory = FILEOBJECT then
      c_expr.expr &:= ".value.filevalue=";
      c_expr.expr &:= literal(getValue(current_object, clib_file));
    elsif objectCategory = SOCKETOBJECT then
      c_expr.expr &:= ".value.intvalue=";
      c_expr.expr &:= "-1";
    elsif objectCategory = POLLOBJECT then
      c_expr.expr &:= ".value.pollvalue=";
      process_pollData_literal(getValue(current_object, pollData), c_expr);
    elsif objectCategory = WINOBJECT then
      c_expr.expr &:= ".value.winvalue=";
      c_expr.expr &:= windowLiteral(getValue(current_object, PRIMITIVE_WINDOW));
    elsif objectCategory = CONSTENUMOBJECT then
      c_expr.expr &:= select_value_from_rtlObjectstruct(
          getType(getValue(current_object, reference)));
      c_expr.expr &:= "=";
      c_expr.expr &:= enum_value(getValue(current_object, reference));
    elsif objectCategory = VARENUMOBJECT then
      c_expr.expr &:= select_value_from_rtlObjectstruct(
          getType(getValue(current_object, reference)));
      c_expr.expr &:= "=";
      c_expr.expr &:= enum_value(getValue(current_object, reference));
    elsif objectCategory = ARRAYOBJECT then
      c_expr.expr &:= ".value.arrayvalue=";
      c_expr.expr &:= "arr[";
      c_expr.expr &:= str(const_table[current_object]);
      c_expr.expr &:= "]";
    elsif objectCategory = STRUCTOBJECT then
      c_expr.expr &:= ".value.structvalue=";
      c_expr.expr &:= "sct[";
      c_expr.expr &:= str(const_table[current_object]);
      c_expr.expr &:= "]";
    elsif objectCategory = HASHOBJECT then
      c_expr.expr &:= ".value.hashvalue=";
      c_expr.expr &:= "hsh[";
      c_expr.expr &:= str(const_table[current_object]);
      c_expr.expr &:= "]";
    elsif objectCategory = INTERFACEOBJECT then
      c_expr.expr &:= ".value.interfacevalue=itfCreate(itf[";
      c_expr.expr &:= str(const_table[current_object]);
      c_expr.expr &:= "])";
    elsif objectCategory = MATCHOBJECT or objectCategory = ACTOBJECT then
      c_expr.expr &:= ".value.genericvalue=";
      process_func_literal(current_object, c_expr);
    else
      c_expr.expr &:= "/* ";
      c_expr.expr &:= str(objectCategory);
      c_expr.expr &:= " */";
    end if;
  end func;


const func string: int32AsFourBytes (in integer: number) is func
  result
    var string: stri is "";
  begin
    if ccConf.LITTLE_ENDIAN_INTTYPE then
      stri := str(chr( number        mod 256)) &
              str(chr((number >>  8) mod 256)) &
              str(chr((number >> 16) mod 256)) &
              str(chr((number >> 24) mod 256));
    else
      stri := str(chr((number >> 24) mod 256)) &
              str(chr((number >> 16) mod 256)) &
              str(chr((number >>  8) mod 256)) &
              str(chr( number        mod 256));
    end if;
  end func;


const func string: int64AsEightBytes (in integer: number) is func
  result
    var string: stri is "";
  begin
    if ccConf.LITTLE_ENDIAN_INTTYPE then
      stri := str(chr( number        mod 256)) &
              str(chr((number >>  8) mod 256)) &
              str(chr((number >> 16) mod 256)) &
              str(chr((number >> 24) mod 256));
      if ccConf.INTTYPE_SIZE = 64 then
        stri &:= str(chr((number >> 32) mod 256)) &
                 str(chr((number >> 40) mod 256)) &
                 str(chr((number >> 48) mod 256)) &
                 str(chr((number >> 56) mod 256));
      else
        stri &:= "\0\\0\\0\\0\";
      end if;
    else
      if ccConf.INTTYPE_SIZE = 64 then
        stri := str(chr((number >> 56) mod 256)) &
                str(chr((number >> 48) mod 256)) &
                str(chr((number >> 40) mod 256)) &
                str(chr((number >> 32) mod 256));
      else
        stri := "\0\\0\\0\\0\";
      end if;
      stri &:= str(chr((number >> 24) mod 256)) &
               str(chr((number >> 16) mod 256)) &
               str(chr((number >>  8) mod 256)) &
               str(chr( number        mod 256));
    end if;
  end func;


const func string: int64AsTwoInt32 (in bigInteger: number) is func

  result
    var string: literals is "";
  begin
    if ccConf.LITTLE_ENDIAN_INTTYPE then
      literals  := str( number        mod 4294967295_);
      literals &:= ",";
      literals &:= str((number >> 32) mod 4294967295_);
      literals &:= ",";
    else
      literals  := str((number >> 32) mod 4294967295_);
      literals &:= ",";
      literals &:= str( number        mod 4294967295_);
      literals &:= ",";
    end if;
  end func;


const proc: init_bigint_constants (inout expr_type: c_expr) is func

  local
    var bigint_index_hash: bigint_index is bigint_index_hash.EMPTY_HASH;
    var integer: number is 0;
    var bigInteger: big1 is bigInteger.value;
    var string: literal is "";
    var integer: pos is 0;
  begin
    bigint_index := flip(bigint_const_table);
    for number range sort(keys(bigint_index)) do
      big1 := bigint_index[number][1];
      literal := c_literal(big1);
      c_expr.expr &:= "/* big[";
      c_expr.expr &:= str(number);
      c_expr.expr &:= "] */ static const unsigned char big_";
      c_expr.expr &:= str(number);
      c_expr.expr &:= "[]=";
      c_expr.expr &:= literal[.. 41];
      for pos range 42 to length(literal) step 80 do
        c_expr.expr &:= "\n";
        c_expr.expr &:= literal[pos len 80];
      end for;
      c_expr.expr &:= ";\n";
    end for;
  end func;


const proc: assign_bigint_constants (inout expr_type: c_expr) is func

  local
    var bigint_index_hash: bigint_index is bigint_index_hash.EMPTY_HASH;
    var bigInteger: big1 is bigInteger.value;
    var integer: number is 0;
  begin
    if length(bigint_const_table) = 0 then
      c_expr.expr &:= "big = NULL;\n";
    else
      c_expr.expr &:= "big = (biginttype *)(malloc(";
      c_expr.expr &:= str(length(bigint_const_table));
      c_expr.expr &:= " * sizeof(biginttype)));\n";
      bigint_index := flip(bigint_const_table);
      for number range sort(keys(bigint_index)) do
        big1 := bigint_index[number][1];
        c_expr.expr &:= "big[";
        c_expr.expr &:= str(number);
        c_expr.expr &:= "]=bigImport(big_";
        c_expr.expr &:= str(number);
        c_expr.expr &:= ");";
        if bitLength(big1) <= MAX_SHOWN_BIGINT_LITERAL_BITLENGTH then
          c_expr.expr &:= " /* ";
          c_expr.expr &:= str(big1);
          c_expr.expr &:= " */";
        end if;
        c_expr.expr &:= "\n";
      end for;
    end if;
  end func;


const proc: init_win_constants (inout expr_type: c_expr) is func

  local
    var win_index_hash: win_index is win_index_hash.EMPTY_HASH;
    var integer: number is 0;
    var integer: line is 0;
    var integer: column is 0;
    var pixel: pix is pixel.value;
    var string: image is "";
    var bstring: bImage is bstring.value;
  begin
    win_index := flip(win_const_table);
    for number range sort(keys(win_index)) do
      bImage := getImage(win_index[number][1]);
      if bImage not in bstri_const_table then
        bstri_const_table @:= [bImage] length(bstri_const_table);
      end if;
      win_bstri_table @:= [number] bstri_const_table[bImage];
    end for;
  end func;


const proc: assign_win_constants (inout expr_type: c_expr) is func

  local
    var win_index_hash: win_index is win_index_hash.EMPTY_HASH;
    var PRIMITIVE_WINDOW: win1 is PRIMITIVE_WINDOW.value;
    var integer: number is 0;
  begin
    if length(win_const_table) = 0 then
      c_expr.expr &:= "win = NULL;\n";
    else
      c_expr.expr &:= "win = (wintype *)(malloc(";
      c_expr.expr &:= str(length(win_const_table));
      c_expr.expr &:= " * sizeof(wintype)));\n";
      win_index := flip(win_const_table);
      for number range sort(keys(win_index)) do
        win1 := win_index[number][1];
        c_expr.expr &:= "win[";
        c_expr.expr &:= str(number);
        c_expr.expr &:= "]=drwImage((int32type *)(bst[";
        c_expr.expr &:= str(win_bstri_table[number]);
        c_expr.expr &:= "]->mem), ";
        c_expr.expr &:= str(width(win1));
        c_expr.expr &:= ", ";
        c_expr.expr &:= str(height(win1));
        c_expr.expr &:= ");\n";
      end for;
    end if;
  end func;


const proc: init_string_constants_with_slices (in stri_index_hash: stri_index,
    inout expr_type: c_expr) is func

  local
    var stringLengthHash: stringLengths is stringLengthHash.value;
    var lengthToStriNumHash: lengthToStriNum is lengthToStriNumHash.value;
    var array integer: lengthList is 0 times 0;
    var integer: lengthIndex is 0;
    var integer: length is 0;
    var array integer: stringPosition is 0 times 0;
    var integer: number is 0;
    var string: stri is "";
    var string: striChars is "";
    var integer: striPos is 0;
    var integer: striIndex is 0;
    var boolean: found is FALSE;
    var integer: countChars is 0;
    var char: ch is ' ';
  begin
    stringPosition := [0 .. pred(length(stri_const_table))] times 0;
    for number range 0 to pred(length(stri_const_table)) do
      stringLengths @:= [number] length(stri_index[number][1]);
    end for;
    lengthToStriNum := flip(stringLengths);
    lengthList := sort(keys(lengthToStriNum));
    for lengthIndex range maxIdx(lengthList) downto minIdx(lengthList) do
      length := lengthList[lengthIndex];
      if length in lengthToStriNum then
        for number range lengthToStriNum[length] do
          stri := stri_index[number][1];
          striPos := pos(striChars, stri);
          if striPos = 0 then
            found := FALSE;
            if length(striChars) > length(stri) then
              striIndex := rpos(stri, striChars[length(striChars)]);
              while striIndex <> 0 and not found do
                if stri[.. striIndex] = striChars[succ(length(striChars) - striIndex) ..] then
                  stringPosition[number] := succ(length(striChars) - striIndex);
                  striChars &:= stri[succ(striIndex) ..];
                  found := TRUE;
                else
                  striIndex := rpos(stri, striChars[length(striChars)], pred(striIndex));
                end if;
              end while;
            end if;
            if not found then
              stringPosition[number] := succ(length(striChars));
              striChars &:= stri;
            end if;
          else
            stringPosition[number] := striPos;
          end if;
        end for;
      end if;
    end for;
    c_expr.expr &:= "static strelemtype striChars[";
    c_expr.expr &:= str(length(striChars));
    c_expr.expr &:= "]={\n";
    for ch range striChars do
      c_expr.expr &:= c_literal(ch);
      c_expr.expr &:= ",";
      incr(countChars);
      if countChars = 20 then
        c_expr.expr &:= "\n";
        countChars := 0;
      end if;
    end for;
    c_expr.expr &:= "};\n\n";
    c_expr.expr &:= "struct stristruct str[]={\n";
    if length(stri_const_table) > 0 then
      for number range 0 to pred(length(stri_const_table)) do
        stri := stri_index[number][1];
        c_expr.expr &:= "/* str[";
        c_expr.expr &:= str(number);
        c_expr.expr &:= "] */ {";
        c_expr.expr &:= str(length(stri));
        c_expr.expr &:= ",";
        if ccConf.WITH_STRI_CAPACITY then
          c_expr.expr &:= str(length(stri));
          c_expr.expr &:= ",";
        end if;
        if stri = "" then
          c_expr.expr &:= "NULL";
        else
          c_expr.expr &:= "&striChars[";
          c_expr.expr &:= str(pred(stringPosition[number]));
          c_expr.expr &:= "]";
        end if;
        c_expr.expr &:= "},";
        c_expr.expr &:= stringInComment(stri);
        c_expr.expr &:= "\n";
      end for;
    else
      c_expr.expr &:= "/* dummy */ {0,";
      if ccConf.WITH_STRI_CAPACITY then
        c_expr.expr &:= "0,";
      end if;
      c_expr.expr &:= "NULL}";
    end if;
    c_expr.expr &:= "};\n\n";
  end func;


const proc: init_string_constants_no_slices (in stri_index_hash: stri_index,
    inout expr_type: c_expr) is func

  local
    var integer: number is 0;
    var string: stri is "";
    var char: ch is ' ';
  begin
    for number range sort(keys(stri_index)) do
      stri := stri_index[number][1];
      c_expr.expr &:= "/* str[";
      c_expr.expr &:= str(number);
      c_expr.expr &:= "] */ static strelemtype stri_";
      c_expr.expr &:= str(number);
      c_expr.expr &:= "[]={";
      if ccConf.POINTER_SIZE = 32 then
        c_expr.expr &:= str(length(stri));
        c_expr.expr &:= ",";
        if ccConf.WITH_STRI_CAPACITY then
          c_expr.expr &:= str(length(stri));
          c_expr.expr &:= ",";
        end if;
      elsif ccConf.POINTER_SIZE = 64 then
        c_expr.expr &:= int64AsTwoInt32(bigInteger conv length(stri));
        if ccConf.WITH_STRI_CAPACITY then
          c_expr.expr &:= int64AsTwoInt32(bigInteger conv length(stri));
        end if;
      end if;
      for ch range stri do
        c_expr.expr &:= c_literal(ch);
        c_expr.expr &:= ",";
      end for;
      c_expr.expr &:= "};\n";
    end for;
    c_expr.expr &:= "stritype str[]={\n";
    if length(stri_const_table) > 0 then
      for number range sort(keys(stri_index)) do
        stri := stri_index[number][1];
        c_expr.expr &:= "(stritype) stri_";
        c_expr.expr &:= str(number);
        c_expr.expr &:= ",";
        c_expr.expr &:= stringInComment(stri);
        c_expr.expr &:= "\n";
      end for;
    else
      c_expr.expr &:= "(stritype) NULL";
    end if;
    c_expr.expr &:= "};\n\n";
  end func;


const proc: init_string_constants (inout expr_type: c_expr) is func

  local
    var stri_index_hash: stri_index is stri_index_hash.EMPTY_HASH;
  begin
    stri_index := flip(stri_const_table);
    if ccConf.ALLOW_STRITYPE_SLICES then
      init_string_constants_with_slices(stri_index, c_expr);
    else
      init_string_constants_no_slices(stri_index, c_expr);
    end if;
  end func;


const proc: init_bstri_constants (inout expr_type: c_expr) is func

  local
    var bstri_index_hash: bstri_index is bstri_index_hash.EMPTY_HASH;
    var bstring: bstri is bstring.value;
    var integer: number is 0;
    var string: lengthAsChars is "";
    var string: stri is "";
    var integer: countChars is 0;
    var char: ch is ' ';
  begin
    bstri_index := flip(bstri_const_table);
    for number range sort(keys(bstri_index)) do
      bstri := bstri_index[number][1];
      c_expr.expr &:= "/* bst[";
      c_expr.expr &:= str(number);
      c_expr.expr &:= "] */ static const unsigned char bstri_";
      c_expr.expr &:= str(number);
      if ccConf.POINTER_SIZE = 32 then
        lengthAsChars := int32AsFourBytes(length(bstri));
      elsif ccConf.POINTER_SIZE = 64 then
        lengthAsChars := int64AsEightBytes(length(bstri));
      end if;
      countChars := 0;
      if ccConf.LIMITED_CSTRI_LITERAL_LEN then
        c_expr.expr &:= "[]={";
        for ch range lengthAsChars do
          c_expr.expr &:= c_literal(ch);
          c_expr.expr &:= ",";
        end for;
        c_expr.expr &:= "\n";
        for ch range bstri do
          c_expr.expr &:= c_literal(ch);
          c_expr.expr &:= ",";
          incr(countChars);
          if countChars = 20 then
            c_expr.expr &:= "\n";
            countChars := 0;
          end if;
        end for;
        c_expr.expr &:= "};\n";
      else
        c_expr.expr &:= "[]=";
        c_expr.expr &:= c_literal(lengthAsChars);
        if length(bstri) <> 0 then
          stri := str(bstri);
          for countChars range 1 to length(stri) step 40 do
            c_expr.expr &:= "\n";
            c_expr.expr &:= c_literal(stri[countChars len 40]);
          end for;
        end if;
        c_expr.expr &:= ";\n";
      end if;
    end for;
    c_expr.expr &:= "bstritype bst[]={\n";
    if length(bstri_const_table) > 0 then
      for number range sort(keys(bstri_index)) do
        c_expr.expr &:= "(bstritype) bstri_";
        c_expr.expr &:= str(number);
        c_expr.expr &:= ",\n";
      end for;
    else
      c_expr.expr &:= "(bstritype) NULL";
    end if;
    c_expr.expr &:= "};\n\n";
  end func;


const proc: init_set_constants (inout expr_type: c_expr) is func

  local
    var set_index_hash: set_index is set_index_hash.EMPTY_HASH;
    var bitset: set1 is EMPTY_SET;
    var integer: min_position is 0;
    var integer: max_position is 0;
    var integer: number is 0;
    var integer: elem_num is 0;
    var integer: columnsFree is 0;
  begin
    set_index := flip(set_const_table);
    for number range sort(keys(set_index)) do
      set1 := set_index[number][1];
      c_expr.expr &:= "/* set[";
      c_expr.expr &:= str(number);
      c_expr.expr &:= "] */ static bitsettype set_";
      c_expr.expr &:= str(number);
      c_expr.expr &:= "[]={";
      if set1 = EMPTY_SET then
        c_expr.expr &:= "0,0,0,";
      else
        min_position := min(set1) mdiv ccConf.INTTYPE_SIZE;
        max_position := max(set1) mdiv ccConf.INTTYPE_SIZE;
        c_expr.expr &:= str(min_position);
        c_expr.expr &:= ",";
        c_expr.expr &:= str(max_position);
        c_expr.expr &:= ",";
        columnsFree := 4;
        for elem_num range min_position to max_position do
          if columnsFree = 0 then
            c_expr.expr &:= "\n";
            columnsFree := 6;
          end if;
          c_expr.expr &:= bitsetElemAsHex(set1, elem_num * ccConf.INTTYPE_SIZE);
          c_expr.expr &:= ",";
          decr(columnsFree);
        end for;
      end if;
      c_expr.expr &:= "};\n";
    end for;
    c_expr.expr &:= "settype set[]={\n";
    if length(set_const_table) > 0 then
      for number range sort(keys(set_index)) do
        c_expr.expr &:= "(settype) set_";
        c_expr.expr &:= str(number);
        c_expr.expr &:= ",\n";
      end for;
    else
      c_expr.expr &:= "(settype) NULL";
    end if;
    c_expr.expr &:= "};\n\n";
  end func;


const proc: init_type_constants (inout expr_type: c_expr) is func

  local
    var type_index_hash: type_index is type_index_hash.EMPTY_HASH;
    var type: aType is void;
    var integer: number is 0;
  begin
    type_index := flip(type_const_table);
    for number range sort(keys(type_index)) do
      aType := type_index[number][1];
      c_expr.expr &:= "/* typ[";
      c_expr.expr &:= str(number);
      c_expr.expr &:= "] */ static unsigned char typ_";
      c_expr.expr &:= str(number);
      c_expr.expr &:= "[]={";
      c_expr.expr &:= "0, 0, 0, 0, 0, 0, 0";
      #% c_expr.expr &:= c_literal(aType);
      c_expr.expr &:= "};\n";
    end for;
    c_expr.expr &:= "typetype typ[]={\n";
    if length(type_const_table) > 0 then
      for number range sort(keys(type_index)) do
        aType := type_index[number][1];
        c_expr.expr &:= "(typetype) typ_";
        c_expr.expr &:= str(number);
        c_expr.expr &:= ", /* ";
        c_expr.expr &:= type_name2(aType);
        c_expr.expr &:= " */\n";
      end for;
    else
      c_expr.expr &:= "(typetype) NULL";
    end if;
    c_expr.expr &:= "};\n\n";
  end func;


const proc: init_array_constants (in reference: const_object, inout expr_type: c_expr) is func

  local
    var ref_list: array_list is ref_list.EMPTY;
    var integer: number is 0;
    var integer: elem_num is 0;
    var integer: elem_after_repeat_block is 0;
    var reference: element is NIL;
  begin
    number := const_table[const_object];
    array_list := arrayToList(const_object);
    c_expr.expr &:= "arr[";
    c_expr.expr &:= str(number);
    c_expr.expr &:= "]=arrMalloc(";
    c_expr.expr &:= str(arrayMinIdx(const_object));
    c_expr.expr &:= ", ";
    c_expr.expr &:= str(pred(arrayMinIdx(const_object) + length(array_list)));
    c_expr.expr &:= ");\n";
    elem_num := 0;
    elem_after_repeat_block := 0;
    for element range array_list do
      if element in element_repeat_count then
        c_expr.expr &:= "{\n";
        c_expr.expr &:= "int idx;\n";
        c_expr.expr &:= "for (idx=";
        c_expr.expr &:= str(elem_num);
        c_expr.expr &:= "; idx < ";
        c_expr.expr &:= str(elem_num + element_repeat_count[element]);
        c_expr.expr &:= "; idx++) {\n";
        c_expr.expr &:= "arr[";
        c_expr.expr &:= str(number);
        c_expr.expr &:= "]->arr[idx]";
        init_const_value(element, c_expr);
        c_expr.expr &:= ";\n";
        c_expr.expr &:= "}\n";
        c_expr.expr &:= "}\n";
        elem_after_repeat_block := elem_num + element_repeat_count[element];
      elsif elem_num >= elem_after_repeat_block then
        c_expr.expr &:= "arr[";
        c_expr.expr &:= str(number);
        c_expr.expr &:= "]->arr[";
        c_expr.expr &:= str(elem_num);
        c_expr.expr &:= "]";
        init_const_value(element, c_expr);
        c_expr.expr &:= ";\n";
      end if;
      incr(elem_num);
    end for;
  end func;


const proc: malloc_struct (in reference: const_object, inout expr_type: c_expr) is func

  local
    var ref_list: struct_list is ref_list.EMPTY;
    var integer: number is 0;
    var integer: elem_num is 0;
    var reference: element is NIL;
  begin
    number := const_table[const_object];
    struct_list := structToList(const_object);
    c_expr.expr &:= "sct[";
    c_expr.expr &:= str(number);
    c_expr.expr &:= "]=(structtype)(malloc(sizeof(struct rtlStructstruct) - sizeof(rtlObjecttype) +\n  ";
    c_expr.expr &:= str(length(struct_list));
    c_expr.expr &:= " * sizeof(rtlObjecttype)));\n";
  end func;


const proc: init_struct_constants (in reference: const_object, inout expr_type: c_expr) is func

  local
    var ref_list: struct_list is ref_list.EMPTY;
    var integer: number is 0;
    var integer: elem_num is 0;
    var reference: element is NIL;
  begin
    number := const_table[const_object];
    struct_list := structToList(const_object);
    c_expr.expr &:= "sct[";
    c_expr.expr &:= str(number);
    c_expr.expr &:= "]->usage_count=0;\n";
    c_expr.expr &:= "sct[";
    c_expr.expr &:= str(number);
    c_expr.expr &:= "]->type_num=";
    c_expr.expr &:= str(typeNumber(getType(const_object)));
    c_expr.expr &:= "/*";
    c_expr.expr &:= str(getType(const_object));
    c_expr.expr &:= "*/";
    c_expr.expr &:= ";\n";
    elem_num := 1;
    for element range struct_list do
      c_expr.expr &:= "sct[";
      c_expr.expr &:= str(number);
      c_expr.expr &:= "]->stru[";
      c_expr.expr &:= str(pred(elem_num));
      c_expr.expr &:= "]";
      init_const_value(element, c_expr);
      c_expr.expr &:= ";\n";
      incr(elem_num);
    end for;
    if const_object in globalInitalisations then
      c_expr.expr &:= globalInitalisations[const_object];
    end if;
  end func;


const proc: init_hash_constants (in reference: const_object, inout expr_type: c_expr) is func

  local
    var ref_list: hash_key_list is ref_list.EMPTY;
    var ref_list: hash_data_list is ref_list.EMPTY;
    var integer: number is 0;
    var integer: elem_num is 0;
    var reference: key_element is NIL;
    var expr_type: hashcode_expr is expr_type.value;
  begin
    number := const_table[const_object];
    hash_key_list := hashKeysToList(const_object);
    hash_data_list := hashDataToList(const_object);
    c_expr.expr &:= "hsh[";
    c_expr.expr &:= str(number);
    c_expr.expr &:= "]=hshEmpty();\n";
    if length(hash_key_list) <> 0 then
      c_expr.expr &:= "{\n";
      c_expr.expr &:= "rtlObjecttype hash_key;\n";
      c_expr.expr &:= "rtlObjecttype hash_data;\n";
      elem_num := 1;
      for key_element range hash_key_list do
        c_expr.expr &:= "hash_key";
        init_const_value(key_element, c_expr);
        c_expr.expr &:= ";\n";
        c_expr.expr &:= "hash_data";
        init_const_value(hash_data_list[elem_num], c_expr);
        c_expr.expr &:= ";\n";
        process_hashcode(key_element, hashcode_expr);
        if hashcode_expr.temp_decls <> "" then
          c_expr.expr &:= "{\n";
          c_expr.expr &:= hashcode_expr.temp_decls;
          c_expr.expr &:= hashcode_expr.temp_assigns;
        end if;
        c_expr.expr &:= "hshIncl(hsh[";
        c_expr.expr &:= str(number);
        c_expr.expr &:= "], hash_key.value.genericvalue, hash_data.value.genericvalue, ";
        c_expr.expr &:= hashcode_expr.expr;
        c_expr.expr &:= ", (comparetype)(";
        object_address(keyCompareObj(getType(const_object)), c_expr);
        c_expr.expr &:= "), (createfunctype)(";
        object_address(keyCreateObj(getType(const_object)), c_expr);
        c_expr.expr &:= "), (createfunctype)(";
        object_address(dataCreateObj(getType(const_object)), c_expr);
        c_expr.expr &:= "), (copyfunctype)(";
        object_address(dataCopyObj(getType(const_object)), c_expr);
        c_expr.expr &:= "));\n";
        if hashcode_expr.temp_decls <> "" then
          c_expr.expr &:= hashcode_expr.temp_frees;
          c_expr.expr &:= "}\n";
        end if;
        incr(elem_num);
      end for;
      c_expr.expr &:= "}\n";
    end if;
  end func;


const proc: init_interface_constants (in reference: const_object, inout expr_type: c_expr) is func

  local
    var reference: struct_of_interface is NIL;
    var integer: number is 0;
  begin
    number := const_table[const_object];
    struct_of_interface := interfaceToStruct(const_object);
    c_expr.expr &:= "itf[";
    c_expr.expr &:= str(number);
    c_expr.expr &:= "]";
    if isVar(struct_of_interface) and struct_of_interface in globalInitalisations then
      c_expr.expr &:= "=o_";
      create_name(struct_of_interface, c_expr.expr);
    elsif category(struct_of_interface) = STRUCTOBJECT then
      c_expr.expr &:= "=sct[";
      c_expr.expr &:= str(const_table[struct_of_interface]);
      c_expr.expr &:= "]";
    else
      c_expr.expr &:= " /* = ";
      c_expr.expr &:= str(category(struct_of_interface));
      c_expr.expr &:= " */";
    end if;
    c_expr.expr &:= ";\n";
  end func;


const proc: init_values (inout expr_type: c_expr) is func

  local
    var const_index_hash: const_index is const_index_hash.EMPTY_HASH;
    var ref_list: sorted_list is ref_list.EMPTY;
    var reference: struct_of_interface is NIL;
    var reference: const_object is NIL;
    var integer: number is 0;
    var ref_list: elements_to_walk is ref_list.EMPTY;
  begin
    const_index := flip(const_table);
    for number range sort(keys(const_index)) do
      const_object := const_index[number][1];
      if category(const_object) = ARRAYOBJECT then
        elements_to_walk := determine_multiple_array_elements(arrayToList(const_object));
        walk_const_list(elements_to_walk, sorted_list);
        sorted_list &:= make_list(const_object);
      elsif category(const_object) = STRUCTOBJECT then
        walk_const_list(structToList(const_object), sorted_list);
        sorted_list &:= make_list(const_object);
      elsif category(const_object) = HASHOBJECT then
        walk_const_list(hashKeysToList(const_object), sorted_list);
        walk_const_list(hashDataToList(const_object), sorted_list);
        sorted_list &:= make_list(const_object);
      elsif category(const_object) = INTERFACEOBJECT then
        if const_object not in const_table then
          const_table @:= [const_object] length(const_table);
        end if;
        struct_of_interface := interfaceToStruct(const_object);
        if struct_of_interface not in const_table then
          const_table @:= [struct_of_interface] length(const_table);
          walk_const_list(structToList(struct_of_interface), sorted_list);
          sorted_list &:= make_list(struct_of_interface);
        elsif const_table[struct_of_interface] >= const_table[const_object] then
          sorted_list &:= make_list(struct_of_interface);
        end if;
        sorted_list &:= make_list(const_object);
      end if;
    end for;
    writeln("after walk_const_list");

    for const_object range sorted_list do
      if category(const_object) = MATCHOBJECT or category(const_object) = ACTOBJECT then
        prepare_func_literal(const_object, c_expr);
      end if;
    end for;

    init_bigint_constants(c_expr);
    init_win_constants(c_expr);
    init_string_constants(c_expr);
    init_bstri_constants(c_expr);
    init_set_constants(c_expr);
    init_type_constants(c_expr);

    c_expr.expr &:= "static void init_values (void)\n";
    c_expr.expr &:= "{\n";
    initPollOperations(c_expr);
    assign_bigint_constants(c_expr);
    assign_win_constants(c_expr);
    c_expr.expr &:= "arr = (arraytype *)(malloc(";
    c_expr.expr &:= str(length(const_table));
    c_expr.expr &:= " * sizeof(arraytype)));\n";
    c_expr.expr &:= "sct = (structtype *)(arr);\n";
    c_expr.expr &:= "hsh = (hashtype *)(arr);\n";
    c_expr.expr &:= "itf = (interfacetype *)(arr);\n";
    for const_object range sorted_list do
      if category(const_object) = STRUCTOBJECT then
        malloc_struct(const_object, c_expr);
      end if;
    end for;
    for const_object range sorted_list do
      if category(const_object) = ARRAYOBJECT then
        init_array_constants(const_object, c_expr);
      elsif category(const_object) = STRUCTOBJECT then
        init_struct_constants(const_object, c_expr);
      elsif category(const_object) = HASHOBJECT then
        init_hash_constants(const_object, c_expr);
      elsif category(const_object) = INTERFACEOBJECT then
        init_interface_constants(const_object, c_expr);
      elsif category(const_object) <> MATCHOBJECT and
            category(const_object) <> ACTOBJECT then
        number := const_table[const_object];
        c_expr.expr &:= "/* const ";
        c_expr.expr &:= str(category(const_object));
        c_expr.expr &:= " [";
        c_expr.expr &:= str(number);
        c_expr.expr &:= "] */\n";
      end if;
    end for;
    c_expr.expr &:= "}\n\n";
  end func;


const proc: declare_raise_error2 (inout expr_type: c_expr) is func

  begin
    if compilerLibraryUsed then
      writeln(c_prog, "extern booltype in_analyze;");
      declareExtern("void raise_error3 (int, const char *, int);");
    end if;
    c_expr.expr &:= "void raise_error2 (int fail_value, const char *file_name, int line_number)\n";
    c_expr.expr &:= "{\n";
    if trace_exception then
      c_expr.expr &:= "  int ch;\n";
      c_expr.expr &:= "  if (fail_value >= 0 && fail_value < sizeof(exception_name) / sizeof(char *)) {\n";
      c_expr.expr &:= "    printf(\"*** EXCEPTION %s\", exception_name[fail_value]);\n";
      c_expr.expr &:= "  } else {\n";
      c_expr.expr &:= "    printf(\"*** EXCEPTION %d\", fail_value);\n";
      c_expr.expr &:= "  }\n";
      c_expr.expr &:= "  printf(\" raised at %s(%d)\\n\", file_name, line_number);\n";
      c_expr.expr &:= "  printf(\"\\n*** (Type RETURN to continue or '*' to terminate)\\n\");\n";
      c_expr.expr &:= "  ch = fgetc(stdin);\n";
      c_expr.expr &:= "  if (ch == (int) '*') {\n";
      c_expr.expr &:= "    exit(1);\n";
      c_expr.expr &:= "  }\n";
    end if;
    if compilerLibraryUsed then
      c_expr.expr &:= "if (in_analyze) {\n";
      c_expr.expr &:= "  raise_error3(fail_value, file_name, line_number);\n";
      c_expr.expr &:= "} else {\n";
    end if;
    c_expr.expr &:= "  error_file = file_name;\n";
    c_expr.expr &:= "  error_line = line_number;\n";
    if signal_exception then
      c_expr.expr &:= "  if (catch_stack_pos == 0) {\n";
      c_expr.expr &:= "    printf(\"\\n*** Uncaught EXCEPTION \");\n";
      c_expr.expr &:= "    if (fail_value >= 0 && fail_value < sizeof(exception_name) / sizeof(char *)) {\n";
      c_expr.expr &:= "      printf(\"%s\", exception_name[fail_value]);\n";
      c_expr.expr &:= "    } else {\n";
      c_expr.expr &:= "      printf(\"%d\", fail_value);\n";
      c_expr.expr &:= "    }\n";
      c_expr.expr &:= "    printf(\" raised at %s(%d)\\n\", file_name, line_number);\n";
      c_expr.expr &:= "    signal(SIGFPE, SIG_DFL);\n";
#     c_expr.expr &:= "    signal(SIGINT, SIG_DFL);\n";
#     c_expr.expr &:= "    signal(SIGSEGV, SIG_DFL);\n";
      if ccConf.DO_SIGFPE_WITH_DIV_BY_ZERO then
        # Under Windows it is necessary to trigger SIGFPE this way
        # to assure that the debugger can catch it.
        c_expr.expr &:= "    flt2int.intvalue = fail_value / (error_line - line_number); /* trigger SIGFPE on purpose */\n";
      else
        c_expr.expr &:= "    raise(SIGFPE);\n";
      end if;
#     c_expr.expr &:= "    raise(SIGTRAP);\n";
#     c_expr.expr &:= "    raise(SIGFPE);\n";
#     c_expr.expr &:= "    raise(SIGINT);\n";
#     c_expr.expr &:= "    raise(SIGSEGV);\n";
#     c_expr.expr &:= "    printf(\"after signal handler\\n\");\n";
#     c_expr.expr &:= "    fflush(stdout);\n";
#     c_expr.expr &:= "    activate_signal_handlers();\n";
#     c_expr.expr &:= "    signal(SIGFPE, SIG_DFL);\n";
      c_expr.expr &:= "  }\n";
    end if;
    if ccConf.HAS_SIGSETJMP then
      c_expr.expr &:= "  siglongjmp(catch_stack[catch_stack_pos], fail_value);\n";
    else
      c_expr.expr &:= "  longjmp(catch_stack[catch_stack_pos], fail_value);\n";
    end if;
    if compilerLibraryUsed then
      c_expr.expr &:= "}\n";
    end if;
    c_expr.expr &:= "}\n";
    c_expr.expr &:= "\n";
  end func;


const proc: init_globals (inout expr_type: c_expr) is func

  begin
    c_expr.expr &:= "static void init_globals (void)\n";
    c_expr.expr &:= "{\n";
    c_expr.expr &:= global_init.temp_decls;
    c_expr.expr &:= global_init.temp_assigns;
    c_expr.expr &:= global_init.expr;
    c_expr.expr &:= "}\n\n";
  end func;


const proc: process_global_declarations (in program: prog) is func

  local

    var expr_type: c_expr is expr_type.value;
  begin
    if not compDataLibraryUsed then
      declareExtern("inttype heapsize (void) {return 0;}");
      declareExtern("typetype refType (objreftype a) {printf(\"refType\\n\"); return NULL;}");
      declareExtern("typetype typValue (objreftype a) {printf(\"typValue\\n\"); return NULL;}");
      writeln(c_prog);
    end if;
    if compDataLibraryUsed and not compilerLibraryUsed then
      declareExtern("stritype get_file_name (unsigned int a) {return " <& stringLiteral("") <& ";}");
      declareExtern("const unsigned char *get_file_name_ustri (unsigned int a) {return (unsigned char *) \"?\";}");
      declareExtern("void *get_param_list (const_listtype a, int *b) {printf(\"get_param_list\\n\"); return NULL;}");
      declareExtern("void *create_parameter_list (listtype a, int *b) {printf(\"create_parameter_list\\n\"); return NULL;}");
      writeln(c_prog);
    end if;
    declare_raise_error2(c_expr);
    process_dynamic_decisions(c_expr);
    declare_missing_create_declarations(c_expr);
    declare_missing_destr_declarations(c_expr);
    init_values(c_expr);
    init_globals(c_expr);
    write(c_prog, global_c_expr.expr);
    write(c_prog, c_expr.expr);
    count_declarations;
  end func;


const proc: init_systypes (in program: prog) is func

  local
    var reference: type_ref is NIL;
    var reference: ref_to_empty is NIL;
    var type: type_type is void;
    var type: int_type is void;
    var type: float_type is void;
    var type: bigint_type is void;
    var type: char_type is void;
    var type: stri_type is void;
  begin
    type_ref := sysVar(prog, "type");
    if type_ref <> NIL then
      type_type := getValue(type_ref, type);
      typeCategory @:= [type_type] TYPEOBJECT;
    end if;
    type_ref := sysVar(prog, "proc");
    if type_ref <> NIL then
      proctype := getValue(type_ref, type);
    end if;
    type_ref := sysVar(prog, "integer");
    if type_ref <> NIL then
      int_type := getValue(type_ref, type);
      typeCategory @:= [int_type] INTOBJECT;
    end if;
    type_ref := sysVar(prog, "bigInteger");
    if type_ref <> NIL then
      bigint_type := getValue(type_ref, type);
      typeCategory @:= [bigint_type] BIGINTOBJECT;
    end if;
    type_ref := sysVar(prog, "float");
    if type_ref <> NIL then
      float_type := getValue(type_ref, type);
      typeCategory @:= [float_type] FLOATOBJECT;
    end if;
    type_ref := sysVar(prog, "char");
    if type_ref <> NIL then
      char_type := getValue(type_ref, type);
      typeCategory @:= [char_type] CHAROBJECT;
    end if;
    type_ref := sysVar(prog, "string");
    if type_ref <> NIL then
      stri_type := getValue(type_ref, type);
      typeCategory @:= [stri_type] STRIOBJECT;
    end if;
    ref_to_empty := sysVar(prog, "empty");
    if ref_to_empty <> NIL then
      voidtype := getType(ref_to_empty);
      typeCategory @:= [voidtype] VOIDOBJECT;
    end if;
  end func;


const func string: temp_name (in string: source) is func
  result
    var string: tempName is "";
  begin
    if rpos(source, "/") = 0 then
      tempName := "tmp_" & source;
    else
      tempName := source[.. rpos(source, "/")] &
          "tmp_" & source[succ(rpos(source, "/")) ..];
    end if;
  end func;


const proc: pass_1 (in string: source, inout program: prog,
    inout boolean: okay) is func

  begin
    if source <> "" then
      writeln("Compiling the program ...");
      if "-r" in compiler_option then
        array_range_check := FALSE;
        conversion_range_check := FALSE;
        integer_shift_check := FALSE;
      end if;
      if "-g" in compiler_option then
        source_debug_info := compiler_option["-g"] <> "-debug_c";
      end if;
      if "-t" in compiler_option then
        trace_exception := compiler_option["-t"] = "e";
        trace_signal := compiler_option["-t"] = "s";
      end if;
      if "-e" in compiler_option then
        signal_exception := TRUE;
      end if;
      if "-o" in compiler_option and compiler_option["-o"] in {"c0", "c1", "c2", "c3"} then
        evaluate_const_expr := integer parse (compiler_option["-o"][2 ..]);
      end if;
      if "-c" in compiler_option then
        generate_c_plus_plus := compiler_option["-c"] = "++";
        declare_with_extern_c := generate_c_plus_plus;
      end if;
      block
        prog := parseFile(source, parseOptions.value, libraryDirs);
      exception
        catch RANGE_ERROR:
          prog := program.EMPTY;
      end block;
      if prog = program.EMPTY then
        writeln("*** File " <& literal(source) <& " not found");
        okay := FALSE;
      elsif errorCount(prog) <> 0 then
        write(errorCount(prog) <& " error");
        if errorCount(prog) > 1 then
          write("s");
        end if;
        writeln(" found");
        okay := FALSE;
      end if;
    else
      okay := FALSE;
    end if;
  end func;


const proc: pass_2 (in string: source, in program: prog,
    inout boolean: okay) is func

  local
    var string: temporaryFileName is "";
    var ref_list: globalObjects is ref_list.EMPTY;
    var reference: obj is NIL;
  begin
    if okay then
      main_object := sysVar(prog, "main");
      if main_object <> NIL then
        compileLibrary := category(main_object) = FORWARDOBJECT;
        if generate_c_plus_plus then
          temporaryFileName := temp_name(source) & ".cpp";
        else
          temporaryFileName := temp_name(source) & ".c";
        end if;
        # The temporary tmp_*.c file is marked with a temp_marker.
        # The temp_marker is checked, before the file is overwritten.
        c_prog := open(temporaryFileName, "r");
        if c_prog <> STD_NULL then
          if getln(c_prog) <> temp_marker then
            write("*** The file ");
            write(literal(temporaryFileName));
            writeln(" was not created by the compiler.");
            write("*** Remove the file ");
            write(literal(temporaryFileName));
            writeln(" manually and restart the compiler.");
            okay := FALSE;
          end if;
          close(c_prog);
        end if;
        if okay then
          c_prog := open(temporaryFileName, "w");
          if c_prog <> STD_NULL then
            writeln("Generating code ...");
            init_systypes(prog);
            write_file_head;
            write_prototypes;
            write_signal_handlers;
            globalObjects := globalObjects(prog);
            if compileLibrary then
              writeln("Compile library");
              for obj range globalObjects do
                if endsWith(path(prog), file(obj)) then
                  process_object(obj);
                else
                  process_library_import_object(obj);
                end if;
              end for;
            else
              for obj range globalObjects do
                process_object(obj);
              end for;
            end if;
            process_global_declarations(prog);
            close(c_prog);
            writeln(countDeclarations  <& " declarations processed");
            writeln(countOptimizations <& " optimizations done");
            writeln(countEvaluations   <& " evaluations done");
          else
            write("*** Cannot open temp file ");
            write(literal(temporaryFileName));
            writeln(".");
            okay := FALSE;
          end if;
        end if;
      else
        writeln("*** main not found.");
        okay := FALSE;
      end if;
    end if;
  end func;


const proc: pass_3 (in string: sourcePath, in string: sourceExtension, in program: prog,
    inout boolean: okay) is func

  local
    var string: s7_lib_dir     is "";
    var string: seed7_lib      is "";
    var string: console_lib    is "";
    var string: draw_lib       is "";
    var string: comp_data_lib  is "";
    var string: compiler_lib   is "";
    var string: cwd            is "";
    var string: workDir        is "";
    var string: sourceFile     is "";
    var string: cSourceFile    is "";
    var string: cErrorFile     is "";
    var string: objectFile     is "";
    var string: linkErrFile    is "";
    var string: tempExeFile    is "";
    var string: executableFile is "";
    var string: compile_cmd    is "";
    var string: compile_params is "";
    var string: link_cmd       is "";
    var string: link_params    is "";
  begin
    if okay then
      writeln("Calling the C compiler ...");
      if "-b" in compiler_option then
        s7_lib_dir := convDosPath(compiler_option["-b"]);
      else
        s7_lib_dir := ccConf.S7_LIB_DIR;
      end if;
      seed7_lib     := s7_lib_dir & "/" & ccConf.SEED7_LIB;
      console_lib   := s7_lib_dir & "/" & ccConf.CONSOLE_LIB;
      draw_lib      := s7_lib_dir & "/" & ccConf.DRAW_LIB;
      comp_data_lib := s7_lib_dir & "/" & ccConf.COMP_DATA_LIB;
      compiler_lib  := s7_lib_dir & "/" & ccConf.COMPILER_LIB;
      cwd := getcwd();
      if rpos(sourcePath, "/") = 0 then
        sourceFile := sourcePath;
      else
        if rpos(sourcePath, "/") = 1 then
          chdir("/");
        else
          chdir(sourcePath[.. pred(rpos(sourcePath, "/"))]);
        end if;
        workDir := sourcePath[.. rpos(sourcePath, "/")];
        sourceFile := sourcePath[succ(rpos(sourcePath, "/")) ..];
      end if;
      if generate_c_plus_plus then
        cSourceFile  := "tmp_" & sourceFile & ".cpp";
      else
        cSourceFile  := "tmp_" & sourceFile & ".c";
      end if;
      cErrorFile     := "tmp_" & sourceFile & ".cerrs";
      objectFile     := "tmp_" & sourceFile & ccConf.OBJECT_FILE_EXTENSION;
      linkErrFile    := "tmp_" & sourceFile & ".lerrs";
      tempExeFile    := "tmp_" & sourceFile & ccConf.EXECUTABLE_FILE_EXTENSION;
      if sourceExtension = "" and ccConf.EXECUTABLE_FILE_EXTENSION = "" then
        executableFile :=        sourceFile & "_exe";
      else
        executableFile :=        sourceFile & ccConf.EXECUTABLE_FILE_EXTENSION;
      end if;
      if fileType(objectFile) = FILE_REGULAR then
        removeFile(objectFile);
      end if;
      if generate_c_plus_plus then
        compile_cmd := ccConf.CPLUSPLUS_COMPILER;
      else
        compile_cmd := ccConf.C_COMPILER;
      end if;
      compile_params := " " & ccConf.CC_OPT_NO_WARNINGS;
      if "-O" in compiler_option then
        compile_params &:= " -O" & compiler_option["-O"];
      end if;
      if "-g" in compiler_option then
        compile_params &:= " " & ccConf.CC_OPT_DEBUG_INFO;
        if compiler_option["-g"] <> "" and compiler_option["-g"] <> "-debug_c" then
          compile_params &:= " " & compiler_option["-g"];
        end if;
      end if;
      if ccConf.CC_FLAGS <> "" then
        compile_params &:= " " & ccConf.CC_FLAGS;
      end if;
      compile_params &:= " -c " & toShellPath(cSourceFile);
      if ccConf.REDIRECT_C_ERRORS <> "" then
        compile_params &:= " " & ccConf.REDIRECT_C_ERRORS & toShellPath(cErrorFile);
      end if;
      writeln(compile_cmd <& compile_params);
      flush(OUT);
      cmd_sh(compile_cmd, compile_params);
      if fileType(cErrorFile) = FILE_REGULAR and
          fileSize(cErrorFile) = 0 then
        removeFile(cErrorFile);
      end if;
      if fileType(objectFile) <> FILE_REGULAR then
        if fileType(cErrorFile) = FILE_REGULAR then
          writeln("*** Errors in " <& literal(workDir & cSourceFile) <&
              " - see " <& literal(workDir & cErrorFile));
        elsif ccConf.REDIRECT_C_ERRORS = "" then
          writeln("*** Compilation terminated");
        else
          writeln("*** Compilation terminated without error messages");
        end if;
        okay := FALSE;
      elsif fileType(cErrorFile) = FILE_REGULAR then
        removeFile(cErrorFile);
      end if;
      if okay then
        if "-g" not in compiler_option then
          removeFile(cSourceFile);
        end if;
        if compilerLibraryUsed then
          consoleLibraryUsed := TRUE;
          drawLibraryUsed := TRUE;
        end if;
        if fileType(seed7_lib) <> FILE_REGULAR then
          writeln("*** Seed7 library " <& literal(seed7_lib) <& " missing");
          okay := FALSE;
        end if;
        if consoleLibraryUsed and fileType(console_lib) <> FILE_REGULAR then
          writeln("*** Console library " <& literal(console_lib) <& " missing");
          okay := FALSE;
        end if;
        if drawLibraryUsed and fileType(draw_lib) <> FILE_REGULAR then
          writeln("*** Draw library " <& literal(draw_lib) <& " missing");
          okay := FALSE;
        end if;
        if compilerLibraryUsed and fileType(compiler_lib) <> FILE_REGULAR then
          writeln("*** Compiler library " <& literal(compiler_lib) <& " missing");
          okay := FALSE;
        end if;
        if compDataLibraryUsed and fileType(comp_data_lib) <> FILE_REGULAR then
          writeln("*** Compiler data library " <& literal(comp_data_lib) <& " missing");
          okay := FALSE;
        end if;
        if okay and not compileLibrary then
          if fileType(executableFile) = FILE_REGULAR then
            block
              removeFile(executableFile);
            exception
              catch FILE_ERROR:
                writeln("*** Cannot remove old executable: " <&
                    literal(executableFile));
            end block;
          end if;
          if fileType(executableFile) = FILE_ABSENT then
            writeln("Calling the linker ...");
            if generate_c_plus_plus then
              link_cmd := ccConf.CPLUSPLUS_COMPILER;
            else
              link_cmd := ccConf.C_COMPILER;
            end if;
            if "-g" in compiler_option then
              if ccConf.LINKER_OPT_DEBUG_INFO <> "" then
                link_params &:= " " & ccConf.LINKER_OPT_DEBUG_INFO;
              end if;
            else
              if ccConf.LINKER_OPT_NO_DEBUG_INFO <> "" then
                link_params &:= " " & ccConf.LINKER_OPT_NO_DEBUG_INFO;
              end if;
            end if;
            if ccConf.LINKER_FLAGS <> "" then
              link_params &:= " " & ccConf.LINKER_FLAGS;
            end if;
            if ccConf.LINKER_OPT_OUTPUT_FILE <> "" then
              link_params &:= " " & ccConf.LINKER_OPT_OUTPUT_FILE &
                  toShellPath(executableFile);
            end if;
            link_params &:= " " & toShellPath(objectFile);
            if compilerLibraryUsed then
              link_params &:= " " & toShellPath(compiler_lib);
            end if;
            if compDataLibraryUsed then
              link_params &:= " " & toShellPath(comp_data_lib);
            end if;
            if consoleLibraryUsed then
              link_params &:= " " & toShellPath(console_lib);
            end if;
            if drawLibraryUsed then
              link_params &:= " " & toShellPath(draw_lib);
            end if;
            link_params &:= " " & toShellPath(seed7_lib);
            if consoleLibraryUsed then
              link_params &:= " " & ccConf.SYSTEM_CONSOLE_LIBS;
            end if;
            if drawLibraryUsed then
              link_params &:= " " & ccConf.SYSTEM_DRAW_LIBS;
            end if;
            link_params &:= " " & ccConf.SYSTEM_LIBS;
            if ccConf.REDIRECT_C_ERRORS <> "" then
              link_params &:= " " & ccConf.REDIRECT_C_ERRORS & toShellPath(linkErrFile);
            end if;
            writeln(link_cmd <& link_params);
            flush(OUT);
            cmd_sh(link_cmd, link_params);
            if ccConf.LINKER_OPT_OUTPUT_FILE = "" and
                fileType(tempExeFile) = FILE_REGULAR then
              moveFile(tempExeFile, executableFile);
            end if;
            if fileType(executableFile) <> FILE_REGULAR then
              if fileType(linkErrFile) = FILE_REGULAR and
                  fileSize(linkErrFile) = 0 then
                removeFile(linkErrFile);
              end if;
              if fileType(linkErrFile) = FILE_REGULAR then
                writeln("*** Linker errors with " <& literal(workDir & objectFile) <&
                    " - see " <& literal(workDir & linkErrFile));
              elsif ccConf.REDIRECT_C_ERRORS = "" then
                writeln("*** Linking terminated");
              else
                writeln("*** Linking terminated without error messages");
              end if;
            elsif fileType(linkErrFile) = FILE_REGULAR then
              removeFile(linkErrFile);
            end if;
            if "-g" not in compiler_option then
              removeFile(objectFile);
            end if;
          end if;
        end if;
      end if;
      chdir(cwd);
    end if;
  end func;


const proc: writeHelp is func
  begin
    writeln("usage: s7c [options] source");
    writeln;
    writeln("Options:");
    writeln("  -?   Write Seed7 compiler usage.");
    writeln("  -O and -O2  Tell the C compiler to optimize.");
    writeln("  -b   Specify the directory of the Seed7 runtime libraries (e.g.: -b ../bin).");
    writeln("  -e   Generate code which sends a signal, when an uncaught exception occurs.");
    writeln("       This option allows debuggers to handle uncaught Seed7 exceptions.");
    writeln("  -g   Tell the C compiler to generate an executable with debug information.");
    writeln("       This way the debugger will refer to Seed7 source files and line numbers.");
    writeln("       To generate debug information which refers to the temporary C program");
    writeln("       the option -g-debug_c can be used.");
    writeln("  -l   Add a directory to the include library search path (e.g.: -l ../lib).");
    writeln("  -ocn Optimize constants with level n. E.g.: -oc3 Where n is a digit");
    writeln("       between 0 and 3:");
    writeln("         0 Do no optimizations with constants.");
    writeln("         1 Use literals and named constants to simplify expressions (default).");
    writeln("         2 Evaluate constant expressions to simplify expressions.");
    writeln("         3 Like -oc2 and additionally evaluate all constant expressions.");
    writeln("  -r   Suppress the generation of range checks for strings and arrays.");
    writeln("  -te  Generate code to trace exceptions. This option works in the same way");
    writeln("       as the interpreter option -te: Every exception will write a message");
    writeln("       to stdout and the user will be asked to continue (with enter) or to");
    writeln("       terminate (with * ).");
    writeln;
  end func;


const proc: main is func

  local
    var integer: index is 0;
    var string: curr_arg is "";
    var string: source is "";
    var string: sourcePath is "";
    var string: sourceExtension is "";
    var boolean: okay is TRUE;

  begin
    OUT := STD_UTF8_OUT;
    writeln("SEED7 COMPILER Version 2.1  Copyright (c) 1990-2013 Thomas Mertes");
    if length(argv(PROGRAM)) = 0 then
      writeln("This is free software; see the source for copying conditions.  There is NO");
      writeln("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
      writeln("S7c is written in the Seed7 programming language");
      writeln("Homepage: http://seed7.sourceforge.net");
      writeln;
      writeln("usage: s7c [options] source");
      writeln;
      writeln("Use  s7c -?  to get more information about s7c.");
      writeln;
    else
      for index range 1 to length(argv(PROGRAM)) do
        curr_arg := argv(PROGRAM)[index];
        if length(curr_arg) >= 2 and curr_arg[1] = '-' then
          if curr_arg in {"-b"} and index < length(argv(PROGRAM)) then
            incr(index);
            compiler_option @:= [curr_arg] argv(PROGRAM)[index];
          elsif curr_arg in {"-l"} and index < length(argv(PROGRAM)) then
            incr(index);
            libraryDirs &:= convDosPath(argv(PROGRAM)[index]);
          elsif curr_arg[.. 2] in {"-?", "-r", "-g", "-t", "-e", "-o", "-c", "-O", "-b"} then
            compiler_option @:= [curr_arg[.. 2]] curr_arg[3 ..];
          else
            writeln("*** Ignore unsupported option: " <& curr_arg);
          end if;
        elsif source = "" then
          source := convDosPath(curr_arg);
        else
          writeln("*** Ignore superfluous parameter: " <& curr_arg);
        end if;
      end for;
      if "-?" in compiler_option then
        writeHelp;
      elsif source = "" then
        writeln("*** Sourcefile missing");
      else
        writeln("Source: " <& source);
        pass_1(source, prog, okay);
        if okay then
          sourcePath := path(prog);
          if  endsWith(sourcePath, ".sd7") or
              endsWith(sourcePath, ".s7i") then
            sourceExtension := sourcePath[length(sourcePath) - 3 ..];
            sourcePath := sourcePath[.. length(sourcePath) - 4];
          end if;
        end if;
        pass_2(sourcePath, prog, okay);
        pass_3(sourcePath, sourceExtension, prog, okay);
      end if;
    end if;
  end func;
