1
2(********************************************************************)
3(*                                                                  *)
4(*  s7c.sd7       Seed7 compiler - Compiles Seed7 to C              *)
5(*  Copyright (C) 1990 - 1994, 2004 - 2021  Thomas Mertes           *)
6(*                                                                  *)
7(*  This program is free software; you can redistribute it and/or   *)
8(*  modify it under the terms of the GNU General Public License as  *)
9(*  published by the Free Software Foundation; either version 2 of  *)
10(*  the License, or (at your option) any later version.             *)
11(*                                                                  *)
12(*  This program is distributed in the hope that it will be useful, *)
13(*  but WITHOUT ANY WARRANTY; without even the implied warranty of  *)
14(*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   *)
15(*  GNU General Public License for more details.                    *)
16(*                                                                  *)
17(*  You should have received a copy of the GNU General Public       *)
18(*  License along with this program; if not, write to the           *)
19(*  Free Software Foundation, Inc., 51 Franklin Street,             *)
20(*  Fifth Floor, Boston, MA  02110-1301, USA.                       *)
21(*                                                                  *)
22(********************************************************************)
23
24
25$ message "Compiling the compiler ...";
26$ include "seed7_05.s7i";
27  include "stdio.s7i";
28  include "osfiles.s7i";
29  include "scanstri.s7i";
30  include "unicode.s7i";
31  include "bigint.s7i";
32  include "float.s7i";
33  include "math.s7i";
34  include "bytedata.s7i";
35  include "bin64.s7i";
36  include "keybd.s7i";
37  include "progs.s7i";
38  include "shell.s7i";
39  include "cc_conf.s7i";
40  include "inifile.s7i";
41  include "comp/config.s7i";
42  include "comp/type.s7i";
43  include "comp/expr.s7i";
44  include "comp/debug.s7i";
45  include "comp/destr.s7i";
46  include "comp/create.s7i";
47  include "comp/copy.s7i";
48  include "comp/expr_utl.s7i";
49  include "comp/stat.s7i";
50  include "comp/inline.s7i";
51  include "comp/const.s7i";
52  include "comp/literal.s7i";
53  include "comp/intrange.s7i";
54  include "comp/error.s7i";
55  include "comp/library.s7i";
56  include "comp/action.s7i";
57
58const string: temp_marker is "/* Seed7 compiler temp file */";
59
60const boolean: SHOW_STATISTIC is FALSE;
61
62const type: option_hash is hash [string] string;
63
64var option_hash: compiler_option is option_hash.value;
65var boolean: compileLibrary is FALSE;
66
67var array string: libraryDirs is 0 times "";
68
69var reference: main_object is NIL;
70var file: c_prog is STD_NULL;
71
72var integer: countDeclarations is 0;
73var expr_type: global_init is expr_type.value;
74
75const type: globalInitHash is hash [reference] string;
76
77var globalInitHash: globalInitalisations is globalInitHash.EMPTY_HASH;
78
79const type: interface_hash is hash [type] array type;
80const type: enum_literal_hash is hash [type] element_number_hash;
81const type: act_to_form_param_hash is hash [reference] reference;
82const type: params_added_hash is hash [reference] act_to_form_param_hash;
83const type: setOfCategory is set of category;
84const type: setOfString is set of string;
85const type: funcparam_data_hash is hash [reference] string;
86const type: element_repeat_count_hash is hash [reference] integer;
87const type: stringLengthHash is hash [integer] integer;
88const type: lengthToStriNumHash is hash [integer] array integer;
89const type: profiledFunctionsHash is hash [integer] reference;
90
91var boolean_type_hash: generic_cpy_declared is boolean_type_hash.EMPTY_HASH;
92var boolean_type_hash: generic_create_declared is boolean_type_hash.EMPTY_HASH;
93var boolean_type_hash: generic_destr_declared is boolean_type_hash.EMPTY_HASH;
94var boolean_type_hash: generic_cmp_declared is boolean_type_hash.EMPTY_HASH;
95var boolean_obj_hash: return_ref_to_value is boolean_obj_hash.EMPTY_HASH;
96var boolean_obj_hash: function_declared is boolean_obj_hash.EMPTY_HASH;
97var boolean_obj_hash: function_var_declared is boolean_obj_hash.EMPTY_HASH;
98var ref_list: dynamic_functions is ref_list.EMPTY;
99var interface_hash: interfaceOfType is interface_hash.EMPTY_HASH;
100var enum_literal_hash: enum_literal is enum_literal_hash.EMPTY_HASH;
101var params_added_hash: params_added is params_added_hash.EMPTY_HASH;
102var boolean_obj_hash: definedActualFuncParams is boolean_obj_hash.EMPTY_HASH;
103var funcparam_data_hash: funcparam_data is funcparam_data_hash.EMPTY_HASH;
104var funcparam_data_hash: funcparam_reference is funcparam_data_hash.EMPTY_HASH;
105var element_repeat_count_hash: element_repeat_count is element_repeat_count_hash.EMPTY_HASH;
106var profiledFunctionsHash: profiledFunctions is profiledFunctionsHash.value;
107
108
109const func boolean: isFuncParamData (in reference: currExpr) is
110  return currExpr in funcparam_data;
111
112
113const proc: count_declarations (inout expr_type: c_expr) is func
114
115  begin
116    incr(countDeclarations);
117    c_expr.expr &:= "/* ";
118    c_expr.expr &:= str(countDeclarations);
119    c_expr.expr &:= " */\n";
120    write(OUT, countDeclarations);
121    write(OUT, "\r");
122    flush(OUT);
123  end func;
124
125
126const proc: process_generic_cpy_declaration (in type: object_type,
127    inout expr_type: c_expr) is func
128
129  begin
130    if object_type not in generic_cpy_declared then
131      process_cpy_declaration(object_type, c_expr);
132      c_expr.expr &:= "static void generic_cpy_";
133      c_expr.expr &:= str(typeNumber(object_type));
134      c_expr.expr &:= " (genericType *a, const genericType b)\n";
135      c_expr.expr &:= "{\n";
136      process_cpy_call(object_type,
137          "((const_rtlObjectType *) a)->value." & raw_type_value(object_type),
138          "((const_rtlObjectType *) &b)->value." & raw_type_value(object_type),
139          c_expr.expr);
140      c_expr.expr &:= ";\n";
141      c_expr.expr &:= "}\n\n";
142      generic_cpy_declared @:= [object_type] TRUE;
143    end if;
144  end func;
145
146
147const proc: process_generic_create_declaration (in type: object_type,
148    inout expr_type: c_expr) is func
149
150  begin
151    if object_type not in generic_create_declared then
152      process_create_declaration(object_type, c_expr);
153      c_expr.expr &:= "static genericType generic_create_";
154      c_expr.expr &:= str(typeNumber(object_type));
155      c_expr.expr &:= " (const genericType b)\n";
156      c_expr.expr &:= "{\n";
157      c_expr.expr &:= "rtlObjectType result;\n";
158      c_expr.expr &:= "result.value.";
159      c_expr.expr &:= raw_type_value(object_type);
160      c_expr.expr &:= "=";
161      process_create_call(object_type,
162          "((const_rtlObjectType *) &b)->value." & raw_type_value(object_type),
163          c_expr.expr);
164      c_expr.expr &:= ";\n";
165      c_expr.expr &:= "return result.value.genericValue;\n";
166      c_expr.expr &:= "}\n\n";
167      generic_create_declared @:= [object_type] TRUE;
168    end if;
169  end func;
170
171
172const proc: process_generic_destr_declaration (in type: object_type,
173    inout expr_type: c_expr) is func
174
175  begin
176    if object_type not in generic_destr_declared then
177      process_destr_declaration(object_type, c_expr);
178      c_expr.expr &:= "static void generic_destr_";
179      c_expr.expr &:= str(typeNumber(object_type));
180      c_expr.expr &:= " (const genericType b)\n";
181      c_expr.expr &:= "{\n";
182      process_destr_call(object_type,
183          "((const_rtlObjectType *) &b)->value." & raw_type_value(object_type),
184          c_expr.expr);
185      c_expr.expr &:= "}\n\n";
186      generic_destr_declared @:= [object_type] TRUE;
187    end if;
188  end func;
189
190
191const proc: process_generic_cmp_declaration (in reference: function,
192    in type: object_type, inout expr_type: c_expr) is func
193
194  begin
195    if object_type not in generic_cmp_declared then
196      process_cpy_declaration(object_type, c_expr);
197      c_expr.expr &:= "static intType generic_cmp_";
198      c_expr.expr &:= str(typeNumber(object_type));
199      c_expr.expr &:= " (const genericType a, const genericType b)\n";
200      c_expr.expr &:= "{\n";
201      c_expr.expr &:= "return o_";
202      create_name(function, c_expr.expr);
203      c_expr.expr &:= "(((const_rtlObjectType *) &a)->value.";
204      c_expr.expr &:= raw_type_value(object_type);
205      c_expr.expr &:= ", ((const_rtlObjectType *) &b)->value.";
206      c_expr.expr &:= raw_type_value(object_type);
207      c_expr.expr &:= ");\n";
208      c_expr.expr &:= "}\n\n";
209      generic_cmp_declared @:= [object_type] TRUE;
210    end if;
211  end func;
212
213
214const proc: process_big_create_call (in bigInteger: number, inout string: expr) is func
215
216  begin
217    if number = 0_ then
218      incr(countOptimizations);
219      expr &:= "bigZero(); /* 0_ */\n";
220    else
221      expr &:= "bigCreate(";
222      expr &:= bigIntegerLiteral(number);
223      expr &:= ");\n";
224    end if;
225  end func;
226
227
228const proc: process_str_create_call (in string: stri, inout string: expr) is func
229
230  local
231    var char: ch is ' ';
232    var integer: index is 2;
233  begin
234    if stri = "" then
235      incr(countOptimizations);
236      expr &:= "strEmpty(); /* \"\" */\n";
237    elsif length(stri) = 1 then
238      incr(countOptimizations);
239      expr &:= "chrStr(";
240      expr &:= charLiteral(stri[1]);
241      expr &:= "); /* ";
242      expr &:= literal(stri);
243      expr &:= " */\n";
244    else
245      ch := stri[1];
246      while index <= length(stri) and ch = stri[index] do
247        incr(index);
248      end while;
249      if index > length(stri) then
250        incr(countOptimizations);
251        if ch = '\0;' then
252          expr &:= "strZero(";
253        else
254          expr &:= "strChMult(";
255          expr &:= charLiteral(ch);
256          expr &:= ", ";
257        end if;
258        expr &:= integerLiteral(length(stri));
259        expr &:= ");\n";
260      else
261        expr &:= "strCreate(";
262        expr &:= stringLiteral(stri);
263        expr &:= ");\n";
264      end if;
265    end if;
266  end func;
267
268
269const proc: getAnyParamToTempAssigns (in expr_type: c_param, inout expr_type: c_expr) is func
270
271  begin
272    if c_param.result_expr <> "" then
273      c_expr.temp_decls &:= c_param.result_decl;
274      c_expr.temp_frees &:= c_param.result_free;
275      c_expr.temp_to_null &:= c_param.result_to_null;
276      c_expr.temp_assigns &:= c_param.result_intro;
277      c_expr.temp_assigns &:= c_param.result_expr;
278      c_expr.temp_assigns &:= c_param.result_finish;
279    else
280      c_expr.temp_assigns &:= c_param.expr;
281    end if;
282  end func;
283
284
285const proc: getAnyParamToTempAssigns (in reference: aParam, inout expr_type: c_expr) is func
286
287  local
288    var category: exprCategory is category.value;
289    var reference: paramValue is NIL;
290    var string: variableName is "";
291    var expr_type: c_param is expr_type.value;
292  begin
293    prepareAnyParamTemporarys(aParam, c_param, c_expr);
294    if aParam not in funcparam_data and
295        not isFunc(getType(aParam)) and
296        aParam in inlineParam and
297        inlineParam[aParam][1].paramValue <> NIL then
298      paramValue := inlineParam[aParam][1].paramValue;
299      exprCategory := category(paramValue);
300      if not isVar(paramValue) and
301          (exprCategory = INTOBJECT or
302           exprCategory = FLOATOBJECT or
303           exprCategory = CHAROBJECT or
304           exprCategory = STRIOBJECT or
305           exprCategory = BSTRIOBJECT) then
306        incr(c_expr.temp_num);
307        variableName := "tmp_" & str(c_expr.temp_num);
308        c_expr.temp_decls &:= type_name(getType(paramValue));
309        c_expr.temp_decls &:= " ";
310        c_expr.temp_decls &:= variableName;
311        c_expr.temp_decls &:= ";\n";
312        c_expr.temp_assigns &:= "(";
313        c_expr.temp_assigns &:= variableName;
314        c_expr.temp_assigns &:= "=";
315        getAnyParamToTempAssigns(c_param, c_expr);
316        c_expr.temp_assigns &:= ", &";
317        c_expr.temp_assigns &:= variableName;
318        c_expr.temp_assigns &:= ")";
319      else
320        c_expr.temp_assigns &:= "&(";
321        getAnyParamToTempAssigns(c_param, c_expr);
322        c_expr.temp_assigns &:= ")";
323      end if;
324    else
325      c_expr.temp_assigns &:= "&(";
326      getAnyParamToTempAssigns(c_param, c_expr);
327      c_expr.temp_assigns &:= ")";
328    end if;
329  end func;
330
331
332const func string: enum_value (in reference: current_object) is func
333
334  result
335    var string: enumValue is "";
336  local
337    var type: enum_type is void;
338    var string: object_name is "";
339  begin
340    enum_type := getType(current_object);
341    if enum_type in typeCategory and typeCategory[enum_type] = BOOLOBJECT then
342      object_name := str(current_object);
343      if object_name = "FALSE" then
344        enumValue := "0/*FALSE*/";
345      elsif object_name = "TRUE" then
346        enumValue := "1/*TRUE*/";
347      end if;
348    else
349      enumValue := "/*" & str(current_object) & "*/";
350      if enum_type in enum_literal and
351          current_object in enum_literal[enum_type] then
352        enumValue &:= str(enum_literal[enum_type][current_object]);
353      else
354        enumValue &:= str(objNumber(current_object));
355      end if;
356    end if;
357  end func;
358
359
360const proc: reference_value (in reference: current_value,
361    inout expr_type: c_expr) is func
362
363  begin
364    if current_value = NIL then
365      c_expr.expr &:= "NULL";
366    else
367      c_expr.expr &:= "&(";
368      process_expr(current_value, c_expr);
369      c_expr.expr &:= ")";
370    end if;
371  end func;
372
373
374const proc: ref_list_value (in ref_list: current_value,
375    inout expr_type: c_expr) is func
376
377  local
378    var reference: element is NIL;
379    var boolean: first_element is TRUE;
380  begin
381    if length(current_value) = 0 then
382      c_expr.expr &:= "NULL";
383    else
384      c_expr.expr &:= "{";
385      for element range current_value do
386        if first_element then
387          first_element := FALSE;
388        else
389          c_expr.expr &:= ", ";
390        end if;
391        c_expr.expr &:= "&(";
392        process_expr(element, c_expr);
393        c_expr.expr &:= ")";
394      end for;
395      c_expr.expr &:= "}";
396    end if;
397  end func;
398
399
400const func string: getExprValue (in reference: current_expression, attr string) is func
401  result
402    var string: exprValue is "";
403  local
404    var reference: evaluated_expression is NIL;
405  begin
406    if category(current_expression) = STRIOBJECT then
407      exprValue := getValue(current_expression, string);
408    else
409      evaluated_expression := evaluate(prog, current_expression);
410      if evaluated_expression <> NIL then
411        exprValue := getValue(evaluated_expression, string);
412      end if;
413    end if;
414  end func;
415
416
417const func boolean: isPointerParam (in reference: a_param) is
418  return category(a_param) = REFPARAMOBJECT and
419        (not valueIsAtHeap(a_param) or isVar(a_param));
420
421
422const func boolean: isCopyParam (in reference: a_param) is
423  return category(a_param) = VALUEPARAMOBJECT and
424        valueIsAtHeap(a_param);
425
426
427const func boolean: isInOutParam (in reference: a_param) is
428  return category(a_param) = REFPARAMOBJECT and isVar(a_param);
429
430
431const func boolean: canTakeAddress (in reference: an_expression) is func
432
433  result
434    var boolean: canTakeAddress is TRUE;
435  local
436    var category: exprCategory is category.value;
437    var string: action_name is "";
438  begin
439    exprCategory := category(an_expression);
440    if (exprCategory = INTOBJECT or
441        exprCategory = CHAROBJECT or
442        exprCategory = CONSTENUMOBJECT or
443        exprCategory = FLOATOBJECT) and
444        not isVar(an_expression) then
445      canTakeAddress := FALSE;
446    end if;
447    if isFunc(getType(an_expression)) then
448      canTakeAddress := FALSE;
449    end if;
450    if exprCategory = CALLOBJECT then
451      if category(getValue(an_expression, ref_list)[1]) = ACTOBJECT then
452        action_name := str(getValue(getValue(an_expression, ref_list)[1], ACTION));
453        if  action_name = "ARR_IDX" or
454            action_name = "SCT_SELECT" then
455          canTakeAddress := TRUE;
456        end if;
457      end if;
458    end if;
459  end func;
460
461
462const proc: process_constenumobject (in reference: function, in ref_list: params,
463    inout expr_type: c_expr) is func
464
465  begin
466    c_expr.expr &:= "/*constenumobject*/";
467    noop_params(formalParams(function), params, c_expr);
468  end func;
469
470
471const func boolean: param_list_okay (in ref_list: formal_params) is func
472
473  result
474    var boolean: okay is TRUE;
475  local
476    var reference: obj is NIL;
477    var category: paramCategory is category.value;
478  begin
479    for obj range formal_params do
480      paramCategory := category(obj);
481      if paramCategory <> SYMBOLOBJECT and paramCategory <> TYPEOBJECT then
482        if isFunc(getType(obj)) then
483          okay := FALSE;
484        end if;
485      end if;
486    end for;
487  end func;
488
489
490const func boolean: containsFunctionCall (in reference: function,
491    in reference: current_expression) is func
492
493  result
494    var boolean: containsCall is FALSE;
495  local
496    var category: exprCategory is category.value;
497    var ref_list: params is ref_list.EMPTY;
498    var reference: currentFunction is NIL;
499    var integer: paramNum is 0;
500  begin
501    exprCategory := category(current_expression);
502    if exprCategory = MATCHOBJECT or exprCategory = CALLOBJECT then
503      params := getValue(current_expression, ref_list);
504      currentFunction := params[1];
505      if currentFunction = function then
506        containsCall := TRUE;
507      else
508        paramNum := 2;
509        while paramNum <= length(params) and not containsCall do
510          containsCall := containsFunctionCall(function, params[paramNum]);
511          incr(paramNum);
512        end while;
513      end if;
514    elsif exprCategory = BLOCKOBJECT then
515      containsCall := current_expression = function;
516    end if;
517  end func;
518
519
520const func boolean: recursiveFunctionCall (in reference: function,
521    in reference: current_expression) is func
522
523  result
524    var boolean: recursiveCall is FALSE;
525  local
526    var reference: obj is NIL;
527  begin
528    recursiveCall := containsFunctionCall(function, current_expression);
529    if not recursiveCall then
530      for obj range localConsts(function) do
531        if not recursiveCall and category(obj) = BLOCKOBJECT then
532          recursiveCall := containsFunctionCall(function, body(obj));
533        end if;
534      end for;
535    end if;
536  end func;
537
538
539const func boolean: identical_values (in reference: object1, in reference: object2) is func
540
541  result
542    var boolean: isIdentical is FALSE;
543  local
544    var reference: element1 is NIL;
545    var ref_list: element_list2 is ref_list.EMPTY;
546    var integer: index2 is 0;
547  begin
548    case category(object1) of
549      when {INTOBJECT}:
550        isIdentical := getValue(object1, integer) = getValue(object2, integer);
551      when {BIGINTOBJECT}:
552        isIdentical := getValue(object1, bigInteger) = getValue(object2, bigInteger);
553      when {CHAROBJECT}:
554        isIdentical := getValue(object1, char) = getValue(object2, char);
555      when {STRIOBJECT}:
556        isIdentical := getValue(object1, string) = getValue(object2, string);
557      when {BSTRIOBJECT}:
558        isIdentical := getValue(object1, bstring) = getValue(object2, bstring);
559      when {SETOBJECT}:
560        isIdentical := getValue(object1, bitset) = getValue(object2, bitset);
561      when {FLOATOBJECT}:
562        isIdentical := getValue(object1, float) = getValue(object2, float);
563      when {REFOBJECT}:
564        isIdentical := getValue(object1, reference) = getValue(object2, reference);
565      when {FILEOBJECT}:
566        isIdentical := getValue(object1, clib_file) = getValue(object2, clib_file);
567      when {CONSTENUMOBJECT, VARENUMOBJECT}:
568        isIdentical := getValue(object1, reference) = getValue(object2, reference);
569      when {ARRAYOBJECT}:
570        if arrayMinIdx(object1) = arrayMinIdx(object2) and
571            arrayMaxIdx(object1) = arrayMaxIdx(object2) then
572          isIdentical := TRUE;
573          element_list2 := arrayToList(object2);
574          index2 := 1;
575          for element1 range arrayToList(object1) until not isIdentical do
576            isIdentical := identical_values(element1, element_list2[index2]);
577            incr(index2);
578          end for;
579        end if;
580      when {STRUCTOBJECT}:
581        isIdentical := TRUE;
582        element_list2 := structToList(object2);
583        index2 := 1;
584        for element1 range structToList(object1) until not isIdentical do
585          isIdentical := identical_values(element1, element_list2[index2]);
586          incr(index2);
587        end for;
588    end case;
589  end func;
590
591
592const func boolean: canUseArrTimes (in type: objectType, in reference: arrayValue,
593    inout reference: repeatedElement) is func
594
595  result
596    var boolean: canUseArrTimes is FALSE;
597  local
598    var type: elementType is void;
599    var ref_list: array_list is ref_list.EMPTY;
600    var reference: element is NIL;
601    var reference: previous_element is NIL;
602    var integer: repeat_count is 1;
603  begin
604    if objectType in array_element then
605      elementType := array_element[objectType];
606      if elementType in typeCategory and
607          typeCategory[elementType] in simpleValueType then
608        array_list := arrayToList(arrayValue);
609        for element range array_list do
610          if previous_element <> NIL then
611            if identical_values(previous_element, element) then
612              incr(repeat_count);
613            end if;
614          end if;
615          previous_element := element;
616        end for;
617        if repeat_count = succ(arrayMaxIdx(arrayValue) - arrayMinIdx(arrayValue)) then
618          canUseArrTimes := TRUE;
619          repeatedElement := array_list[1];
620        end if;
621      end if;
622    end if;
623  end func;
624
625
626const proc: assignArrayValue (in type: objectType, in reference: arrayValue,
627    inout expr_type: c_declaration) is func
628
629  local
630    var integer: arraySize is 0;
631    var reference: repeatedElement is NIL;
632    var string: variableName is "";
633    var string: param_value is "";
634  begin
635    arraySize := succ(arrayMaxIdx(arrayValue) - arrayMinIdx(arrayValue));
636    if evaluate_const_expr >= 2 and
637        arrayMinIdx(arrayValue) > arrayMaxIdx(arrayValue) then
638      if FALSE and inlineFunctions then
639        incr(c_declaration.temp_num);
640        variableName := "new_arr" <& c_declaration.temp_num;
641        c_declaration.temp_decls &:= ";\n";
642        c_declaration.temp_decls &:= "arrayType ";
643        c_declaration.temp_decls &:= variableName;
644        c_declaration.temp_assigns &:= "(";
645        c_declaration.temp_assigns &:= variableName;
646        c_declaration.temp_assigns &:= " = (arrayType) malloc(sizeof(struct rtlArrayStruct) - sizeof(rtlObjectType)), (unlikely(";
647        c_declaration.temp_assigns &:= variableName;
648        c_declaration.temp_assigns &:= " == NULL) ? ";
649        c_declaration.temp_assigns &:= "intRaiseError(MEMORY_ERROR) ";
650        c_declaration.temp_assigns &:= ": 0), ";
651        c_declaration.temp_assigns &:= variableName;
652        c_declaration.temp_assigns &:= "->min_position = ";
653        c_declaration.temp_assigns &:= integerLiteral(arrayMinIdx(arrayValue));
654        c_declaration.temp_assigns &:= ", ";
655        c_declaration.temp_assigns &:= variableName;
656        c_declaration.temp_assigns &:= "->max_position = ";
657        c_declaration.temp_assigns &:= integerLiteral(arrayMaxIdx(arrayValue));
658        c_declaration.temp_assigns &:= ", ";
659        c_declaration.temp_assigns &:= variableName;
660        c_declaration.temp_assigns &:= ");\n";
661      else
662        c_declaration.temp_assigns &:= "arrMalloc(";
663        c_declaration.temp_assigns &:= integerLiteral(arrayMinIdx(arrayValue));
664        c_declaration.temp_assigns &:= ", ";
665        c_declaration.temp_assigns &:= integerLiteral(arrayMaxIdx(arrayValue));
666        c_declaration.temp_assigns &:= ");\n";
667      end if;
668    elsif evaluate_const_expr >= 2 and
669        canUseArrTimes(objectType, arrayValue, repeatedElement) and
670        category(repeatedElement) = INTOBJECT then
671      if getValue(repeatedElement, integer) = 0 then
672        incr(c_declaration.temp_num);
673        variableName := "new_arr" <& c_declaration.temp_num;
674        c_declaration.temp_decls &:= ";\n";
675        c_declaration.temp_decls &:= "arrayType ";
676        c_declaration.temp_decls &:= variableName;
677        c_declaration.temp_assigns &:= "(";
678        c_declaration.temp_assigns &:= variableName;
679        if inlineFunctions and
680            arrayMinIdx(arrayValue) >= -100000000 and arrayMinIdx(arrayValue) <= 100000000 and
681            arraySize <= 100000000 then
682          # The indices are okay and the size given to malloc() will not overflow.
683          c_declaration.temp_assigns &:= " = (arrayType) malloc(sizeof(struct rtlArrayStruct) + ";
684          c_declaration.temp_assigns &:= integerLiteral(pred(arraySize));
685          c_declaration.temp_assigns &:= " * sizeof(rtlObjectType)), (unlikely(";
686          c_declaration.temp_assigns &:= variableName;
687          c_declaration.temp_assigns &:= " == NULL) ? ";
688          c_declaration.temp_assigns &:= "intRaiseError(MEMORY_ERROR) ";
689          c_declaration.temp_assigns &:= ": 0), ";
690          c_declaration.temp_assigns &:= variableName;
691          c_declaration.temp_assigns &:= "->min_position = ";
692          c_declaration.temp_assigns &:= integerLiteral(arrayMinIdx(arrayValue));
693          c_declaration.temp_assigns &:= ", ";
694          c_declaration.temp_assigns &:= variableName;
695          c_declaration.temp_assigns &:= "->max_position = ";
696          c_declaration.temp_assigns &:= integerLiteral(arrayMaxIdx(arrayValue));
697        else
698          # Use arrMalloc(), as it has detailed checks for indices and array size.
699          c_declaration.temp_assigns &:= " = arrMalloc(";
700          c_declaration.temp_assigns &:= integerLiteral(arrayMinIdx(arrayValue));
701          c_declaration.temp_assigns &:= ", ";
702          c_declaration.temp_assigns &:= integerLiteral(arrayMaxIdx(arrayValue));
703          c_declaration.temp_assigns &:= ")";
704        end if;
705        c_declaration.temp_assigns &:= ", memset(";
706        c_declaration.temp_assigns &:= variableName;
707        c_declaration.temp_assigns &:= "->arr, 0, ";
708        c_declaration.temp_assigns &:= integerLiteral(arraySize);
709        c_declaration.temp_assigns &:= " * sizeof(rtlObjectType)), ";
710        c_declaration.temp_assigns &:= variableName;
711        c_declaration.temp_assigns &:= ");\n";
712      else
713        c_declaration.temp_assigns &:= "arrTimes(";
714        c_declaration.temp_assigns &:= integerLiteral(arrayMinIdx(arrayValue));
715        c_declaration.temp_assigns &:= ", ";
716        c_declaration.temp_assigns &:= integerLiteral(arrayMaxIdx(arrayValue));
717        c_declaration.temp_assigns &:= ", (genericType)(";
718        c_declaration.temp_assigns &:= integerLiteral(getValue(repeatedElement, integer));
719        c_declaration.temp_assigns &:= "));\n";
720      end if;
721    else
722      if arrayValue not in const_table then
723        const_table @:= [arrayValue] length(const_table);
724      end if;
725      process_create_declaration(objectType, global_c_expr);
726      param_value := "arr[";
727      param_value &:= str(const_table[arrayValue]);
728      param_value &:= "]";
729      process_create_call(objectType,
730          param_value, c_declaration.temp_assigns);
731      c_declaration.temp_assigns &:= ";\n";
732    end if;
733  end func;
734
735
736const proc: process_local_declaration (in reference: current_object, in var reference: object_value,
737    inout expr_type: c_expr) is func
738
739  local
740    var type: objectType is void;
741    var category: valueCategory is category.value;
742    var expr_type: c_declaration is expr_type.value;
743    var expr_type: c_value is expr_type.value;
744    var string: param_name is "";
745    var string: param_value is "";
746  begin
747    c_declaration.temp_num := c_expr.temp_num;
748    valueCategory := category(object_value);
749    objectType := getType(current_object);
750    if objectType = getType(object_value) and objectType not in typeCategory then
751      typeCategory @:= [objectType] valueCategory;
752    end if;
753    declare_type_if_necessary(objectType, global_c_expr);
754    c_declaration.temp_decls &:= diagnosticLine(current_object);
755    c_declaration.temp_decls &:= type_name(objectType);
756    c_declaration.temp_decls &:= " o_";
757    create_name(current_object, c_declaration.temp_decls);
758    if objectType in typeCategory and typeCategory[objectType] = INTERFACEOBJECT then
759      if valueCategory = INTERFACEOBJECT then
760        object_value := interfaceToStruct(object_value);
761        valueCategory := category(object_value);
762      end if;
763      if isVar(object_value) then
764        c_declaration.temp_assigns &:= diagnosticLine(current_object);
765        c_declaration.temp_assigns &:= "o_";
766        create_name(current_object, c_declaration.temp_assigns);
767        c_declaration.temp_assigns &:= "=itfCreate(o_";
768        create_name(object_value, c_declaration.temp_assigns);
769        c_declaration.temp_assigns &:= "/* ";
770        c_declaration.temp_assigns &:= str(valueCategory);
771        c_declaration.temp_assigns &:= " */);\n";
772      else
773        if object_value not in const_table then
774          const_table @:= [object_value] length(const_table);
775        end if;
776        c_declaration.temp_assigns &:= diagnosticLine(current_object);
777        c_declaration.temp_assigns &:= "o_";
778        create_name(current_object, c_declaration.temp_assigns);
779        c_declaration.temp_assigns &:= "=(";
780        c_declaration.temp_assigns &:= type_name(objectType);
781        c_declaration.temp_assigns &:= ")(itfCreate(itf[";
782        c_declaration.temp_assigns &:= str(const_table[object_value]);
783        c_declaration.temp_assigns &:= "]));\n";
784      end if;
785      process_destr_declaration(objectType, global_c_expr);
786      param_name := "o_";
787      create_name(current_object, param_name);
788      process_destr_call(objectType, param_name, c_declaration.temp_frees);
789    elsif valueCategory = TYPEOBJECT then
790      c_declaration.temp_decls &:= "=";
791      c_declaration.temp_decls &:= typeLiteral(getValue(object_value, type));
792    elsif valueCategory = INTOBJECT then
793      c_declaration.temp_decls &:= "=";
794      c_declaration.temp_decls &:= str(getValue(object_value, integer));
795    elsif valueCategory = BIGINTOBJECT then
796      c_declaration.temp_assigns &:= diagnosticLine(current_object);
797      c_declaration.temp_assigns &:= "o_";
798      create_name(current_object, c_declaration.temp_assigns);
799      c_declaration.temp_assigns &:= "=";
800      process_big_create_call(getValue(object_value, bigInteger), c_declaration.temp_assigns);
801      c_declaration.temp_frees &:= "bigDestr(o_";
802      create_name(current_object, c_declaration.temp_frees);
803      c_declaration.temp_frees &:= ");\n";
804    elsif valueCategory = CHAROBJECT then
805      c_declaration.temp_decls &:= "=";
806      c_declaration.temp_decls &:= charLiteral(getValue(object_value, char));
807    elsif valueCategory = FLOATOBJECT then
808      c_declaration.temp_decls &:= "=";
809      c_declaration.temp_decls &:= floatLiteral(getValue(object_value, float));
810    elsif valueCategory = STRIOBJECT then
811      c_declaration.temp_assigns &:= diagnosticLine(current_object);
812      c_declaration.temp_assigns &:= "o_";
813      create_name(current_object, c_declaration.temp_assigns);
814      c_declaration.temp_assigns &:= "=";
815      process_str_create_call(getValue(object_value, string), c_declaration.temp_assigns);
816      c_declaration.temp_frees &:= "strDestr(o_";
817      create_name(current_object, c_declaration.temp_frees);
818      c_declaration.temp_frees &:= ");\n";
819    elsif valueCategory = BSTRIOBJECT then
820      c_declaration.temp_assigns &:= diagnosticLine(current_object);
821      c_declaration.temp_assigns &:= "o_";
822      create_name(current_object, c_declaration.temp_assigns);
823      c_declaration.temp_assigns &:= "=bstCreate(";
824      c_declaration.temp_assigns &:= bstriLiteral(getValue(object_value, bstring));
825      c_declaration.temp_assigns &:= ");\n";
826      c_declaration.temp_frees &:= "bstDestr(o_";
827      create_name(current_object, c_declaration.temp_frees);
828      c_declaration.temp_frees &:= ");\n";
829    elsif valueCategory = SETOBJECT then
830      c_declaration.temp_assigns &:= diagnosticLine(current_object);
831      c_declaration.temp_assigns &:= "o_";
832      create_name(current_object, c_declaration.temp_assigns);
833      c_declaration.temp_assigns &:= "=setCreate(";
834      c_declaration.temp_assigns &:= bitsetLiteral(getValue(object_value, bitset));
835      c_declaration.temp_assigns &:= ");\n";
836      c_declaration.temp_frees &:= "setDestr(o_";
837      create_name(current_object, c_declaration.temp_frees);
838      c_declaration.temp_frees &:= ");\n";
839    elsif valueCategory = REFOBJECT then
840      c_declaration.temp_decls &:= "=";
841      reference_value(getValue(object_value, reference), c_value);
842      c_declaration.temp_decls &:= c_value.expr;
843    elsif valueCategory = REFLISTOBJECT then
844      c_declaration.temp_decls &:= "=";
845      ref_list_value(getValue(object_value, ref_list), c_value);
846      c_declaration.temp_decls &:= c_value.expr;
847      c_declaration.temp_frees &:= "rflDestr(o_";
848      create_name(current_object, c_declaration.temp_frees);
849      c_declaration.temp_frees &:= ");\n";
850    elsif valueCategory = FILEOBJECT then
851      c_declaration.temp_decls &:= "=&";
852      c_declaration.temp_decls &:= lower(literal(getValue(object_value, clib_file)));
853      c_declaration.temp_decls &:= "FileRecord";
854      c_declaration.temp_frees &:= "filDestr(o_";
855      create_name(current_object, c_declaration.temp_frees);
856      c_declaration.temp_frees &:= ");\n";
857    elsif valueCategory = SOCKETOBJECT then
858      c_declaration.temp_decls &:= "=-1";
859    elsif valueCategory = POLLOBJECT then
860      c_declaration.temp_decls &:= "=NULL";
861    elsif valueCategory = ARRAYOBJECT then
862      c_declaration.temp_assigns &:= diagnosticLine(current_object);
863      c_declaration.temp_assigns &:= "o_";
864      create_name(current_object, c_declaration.temp_assigns);
865      c_declaration.temp_assigns &:= "=";
866      assignArrayValue(objectType, object_value, c_declaration);
867      process_destr_declaration(objectType, global_c_expr);
868      param_name := "o_";
869      create_name(current_object, param_name);
870      process_destr_call(objectType, param_name, c_declaration.temp_frees);
871    elsif valueCategory = STRUCTOBJECT then
872      if object_value not in const_table then
873        const_table @:= [object_value] length(const_table);
874      end if;
875      process_create_declaration(objectType, global_c_expr);
876      process_destr_declaration(objectType, global_c_expr);
877      c_declaration.temp_assigns &:= diagnosticLine(current_object);
878      c_declaration.temp_assigns &:= "o_";
879      create_name(current_object, c_declaration.temp_assigns);
880      c_declaration.temp_assigns &:= "=";
881      param_value := "sct[";
882      param_value &:= str(const_table[object_value]);
883      param_value &:= "]";
884      process_create_call(objectType,
885          param_value, c_declaration.temp_assigns);
886      c_declaration.temp_assigns &:= ";\n";
887      param_name := "o_";
888      create_name(current_object, param_name);
889      process_destr_call(objectType, param_name, c_declaration.temp_frees);
890    elsif valueCategory = HASHOBJECT then
891      if length(hashKeysToList(object_value)) = 0 then
892        process_destr_declaration(objectType, global_c_expr);
893        incr(countOptimizations);
894        c_declaration.temp_assigns &:= diagnosticLine(current_object);
895        c_declaration.temp_assigns &:= "o_";
896        create_name(current_object, c_declaration.temp_assigns);
897        c_declaration.temp_assigns &:= "=hshEmpty();\n";
898      else
899        if object_value not in const_table then
900          const_table @:= [object_value] length(const_table);
901        end if;
902        process_create_declaration(objectType, global_c_expr);
903        process_destr_declaration(objectType, global_c_expr);
904        c_declaration.temp_assigns &:= diagnosticLine(current_object);
905        c_declaration.temp_assigns &:= "o_";
906        create_name(current_object, c_declaration.temp_assigns);
907        c_declaration.temp_assigns &:= "=";
908        param_value := "hsh[";
909        param_value &:= str(const_table[object_value]);
910        param_value &:= "]";
911        process_create_call(objectType,
912            param_value, c_declaration.temp_assigns);
913        c_declaration.temp_assigns &:= ";\n";
914      end if;
915      param_name := "o_";
916      create_name(current_object, param_name);
917      process_destr_call(objectType, param_name, c_declaration.temp_frees);
918    elsif valueCategory = INTERFACEOBJECT then
919      if object_value not in const_table then
920        const_table @:= [object_value] length(const_table);
921      end if;
922      c_declaration.temp_assigns &:= diagnosticLine(current_object);
923      c_declaration.temp_assigns &:= "o_";
924      create_name(current_object, c_declaration.temp_assigns);
925      c_declaration.temp_assigns &:= "=itf[";
926      c_declaration.temp_assigns &:= str(const_table[object_value]);
927      c_declaration.temp_assigns &:= "];\n";
928      process_destr_declaration(objectType, global_c_expr);
929      param_name := "o_";
930      create_name(current_object, param_name);
931      process_destr_call(objectType, param_name, c_declaration.temp_frees);
932    elsif valueCategory = WINOBJECT then
933      c_declaration.temp_assigns &:= diagnosticLine(current_object);
934      c_declaration.temp_assigns &:= "o_";
935      create_name(current_object, c_declaration.temp_assigns);
936      c_declaration.temp_assigns &:= "=drwCreate(";
937      c_declaration.temp_assigns &:= windowLiteral(getValue(object_value, PRIMITIVE_WINDOW));
938      c_declaration.temp_assigns &:= ");\n";
939      c_declaration.temp_frees &:= "drwDestr(o_";
940      create_name(current_object, c_declaration.temp_frees);
941      c_declaration.temp_frees &:= ");\n";
942    elsif valueCategory = PROCESSOBJECT then
943      c_declaration.temp_decls &:= "=NULL";
944      c_declaration.temp_frees &:= "pcsDestr(o_";
945      create_name(current_object, c_declaration.temp_frees);
946      c_declaration.temp_frees &:= ");\n";
947    elsif valueCategory = PROGOBJECT then
948      c_declaration.temp_decls &:= "=NULL";
949      c_declaration.temp_frees &:= "prgDestr(o_";
950      create_name(current_object, c_declaration.temp_frees);
951      c_declaration.temp_frees &:= ");\n";
952    elsif valueCategory = DATABASEOBJECT then
953      c_declaration.temp_decls &:= "=NULL";
954      c_declaration.temp_frees &:= "sqlDestrDb(o_";
955      create_name(current_object, c_declaration.temp_frees);
956      c_declaration.temp_frees &:= ");\n";
957    elsif valueCategory = SQLSTMTOBJECT then
958      c_declaration.temp_decls &:= "=NULL";
959      c_declaration.temp_frees &:= "sqlDestrStmt(o_";
960      create_name(current_object, c_declaration.temp_frees);
961      c_declaration.temp_frees &:= ");\n";
962    elsif valueCategory = CONSTENUMOBJECT then
963      c_declaration.temp_decls &:= "=";
964      c_declaration.temp_decls &:= enum_value(getValue(object_value, reference));
965    elsif valueCategory = VARENUMOBJECT then
966      c_declaration.temp_decls &:= "=";
967      c_declaration.temp_decls &:= enum_value(getValue(object_value, reference));
968    elsif valueCategory = ENUMLITERALOBJECT then
969      c_declaration.temp_decls &:= "=o_";
970      create_name(object_value, c_declaration.temp_decls);
971    elsif valueCategory = CALLOBJECT then
972      param_name := "o_";
973      create_name(current_object, param_name);
974      c_value.temp_num := c_declaration.temp_num;
975      getTemporaryToResultExpr(object_value, c_value);
976      c_declaration.temp_num := c_value.temp_num;
977      c_expr.temp_decls   &:= c_value.temp_decls;
978      c_expr.temp_assigns &:= c_value.temp_assigns;
979      c_expr.temp_frees   &:= c_value.temp_frees;
980      c_expr.temp_to_null &:= c_value.temp_to_null;
981      c_declaration.temp_assigns &:= diagnosticLine(current_object);
982      c_declaration.temp_assigns &:= param_name;
983      c_declaration.temp_assigns &:= "=(";
984      c_declaration.temp_assigns &:= type_name(objectType);
985      c_declaration.temp_assigns &:= ")(";
986      c_declaration.temp_assigns &:= c_value.result_expr;
987      c_declaration.temp_assigns &:= ");\n";
988      process_destr_declaration(objectType, global_c_expr);
989      process_destr_call(objectType, param_name, c_declaration.temp_frees);
990    elsif valueCategory = BLOCKOBJECT then
991      create_name(object_value, objNumber(object_value), param_name);
992      c_value.temp_num := c_declaration.temp_num;
993      processFuncValue(param_name, objectType, object_value, c_value);
994      c_declaration.temp_num := c_value.temp_num;
995      c_declaration.temp_decls &:= "=";
996      c_declaration.temp_decls &:= c_value.expr;
997      c_expr.temp_decls   &:= c_value.temp_decls;
998      c_expr.temp_assigns &:= c_value.temp_assigns;
999      c_expr.temp_frees   &:= c_value.temp_frees;
1000      c_expr.temp_to_null &:= c_value.temp_to_null;
1001      function_declared @:= [object_value] TRUE;
1002      function_var_declared @:= [current_object] TRUE;
1003    elsif valueCategory = ACTOBJECT then
1004      c_declaration.temp_decls &:= "=NULL";
1005    else
1006      c_declaration.temp_decls &:= "/* ";
1007      c_declaration.temp_decls &:= str(valueCategory);
1008      c_declaration.temp_decls &:= " */";
1009    end if;
1010    c_declaration.temp_decls &:= ";\n";
1011    c_expr.temp_num := c_declaration.temp_num;
1012    c_expr.temp_decls   &:= c_declaration.temp_decls;
1013    c_expr.temp_assigns &:= c_declaration.temp_assigns;
1014    c_expr.temp_frees   &:= c_declaration.temp_frees;
1015    c_expr.temp_to_null &:= c_declaration.temp_to_null;
1016  end func;
1017
1018
1019const proc: process_local_var_declaration (in reference: current_object,
1020    inout expr_type: c_expr) is func
1021
1022  local
1023    var ref_list: objects is ref_list.EMPTY;
1024    var reference: obj is NIL;
1025  begin
1026    objects := localVars(current_object);
1027    for obj range objects do
1028      process_local_declaration(obj, getValue(obj, reference), c_expr);
1029    end for;
1030  end func;
1031
1032
1033const proc: determineDataForActualFuncParam (in reference: current_expression,
1034    inout ref_list: data_list) is func
1035
1036  local
1037    var category: paramCategory is category.value;
1038    var ref_list: params is ref_list.EMPTY;
1039    var reference: aParam is NIL;
1040  begin
1041    paramCategory := category(current_expression);
1042    if paramCategory = MATCHOBJECT or paramCategory = CALLOBJECT then
1043      params := getValue(current_expression, ref_list);
1044      for aParam range params do
1045        determineDataForActualFuncParam(aParam, data_list);
1046      end for;
1047    elsif paramCategory = LOCALVOBJECT or
1048          paramCategory = VALUEPARAMOBJECT or
1049          paramCategory = REFPARAMOBJECT or
1050          paramCategory = RESULTOBJECT then
1051      if current_expression not in data_list then
1052        data_list &:= make_list(current_expression);
1053      end if;
1054    end if;
1055  end func;
1056
1057
1058const func ref_list: determineDataForActualFuncParam (in reference: current_expression) is func
1059
1060  result
1061    var ref_list: data_list is ref_list.EMPTY;
1062  begin
1063    determineDataForActualFuncParam(current_expression, data_list);
1064  end func;
1065
1066
1067const proc: defineFunctype (in string: valueName, in reference: actual_param,
1068    in ref_list: data_list, inout expr_type: c_expr) is func
1069  local
1070    var reference: dataItem is NIL;
1071    var string: data_value is "";
1072  begin
1073    c_expr.expr &:= "typedef struct {\n";
1074    c_expr.expr &:= type_name(resultType(getType(actual_param)));
1075    c_expr.expr &:= " (*func) (void *data_";
1076    c_expr.expr &:= valueName;
1077    c_expr.expr &:= ");\n";
1078    c_expr.expr &:= "struct {\n";
1079    for dataItem range data_list do
1080      if not isVar(dataItem) then
1081        c_expr.expr &:= "const ";
1082        if useConstPrefix(dataItem) then
1083          c_expr.expr &:= "const_";
1084        end if;
1085      end if;
1086      c_expr.expr &:= type_name(getType(dataItem));
1087      if isFunc(getType(dataItem)) then
1088        c_expr.expr &:= " data_";
1089      else
1090        c_expr.expr &:= " *data_";
1091      end if;
1092      create_name(dataItem, c_expr.expr);
1093      c_expr.expr &:= ";\n";
1094      if isFunc(getType(dataItem)) then
1095        data_value := "((functype_";
1096        data_value &:= valueName;
1097        data_value &:= " *) data_";
1098        data_value &:= valueName;
1099        data_value &:= ")->data.data_";
1100        create_name(dataItem, data_value);
1101        data_value &:= "->func(((functype_";
1102        data_value &:= valueName;
1103        data_value &:= " *) data_";
1104        data_value &:= valueName;
1105        data_value &:= ")->data.data_";
1106        create_name(dataItem, data_value);
1107        data_value &:= ")";
1108        if getType(dataItem) = proctype then
1109          data_value &:= ";\n";
1110        end if;
1111      else
1112        data_value := "*((functype_";
1113        data_value &:= valueName;
1114        data_value &:= " *) data_";
1115        data_value &:= valueName;
1116        data_value &:= ")->data.data_";
1117        create_name(dataItem, data_value);
1118      end if;
1119      funcparam_data @:= [dataItem] data_value;
1120      data_value := "((functype_";
1121      data_value &:= valueName;
1122      data_value &:= " *) data_";
1123      data_value &:= valueName;
1124      data_value &:= ")->data.data_";
1125      create_name(dataItem, data_value);
1126      funcparam_reference @:= [dataItem] data_value;
1127    end for;
1128    c_expr.expr &:= "} data;\n";
1129    c_expr.expr &:= "} functype_";
1130    c_expr.expr &:= valueName;
1131    c_expr.expr &:= ";\n\n";
1132  end func;
1133
1134
1135const proc: defineActualFuncParam (in type: resultType, in string: valueName,
1136    in reference: actual_param, in ref_list: data_list, inout expr_type: c_expr) is func
1137
1138  local
1139    var funcparam_data_hash: funcparam_data_backup is funcparam_data_hash.EMPTY_HASH;
1140    var funcparam_data_hash: funcparam_reference_backup is funcparam_data_hash.EMPTY_HASH;
1141    var expr_type: c_func_body is expr_type.value;
1142  begin
1143    funcparam_data_backup := funcparam_data;
1144    funcparam_reference_backup := funcparam_reference;
1145    if data_list <> ref_list.EMPTY then
1146      defineFunctype(valueName, actual_param, data_list, c_expr);
1147    end if;
1148    c_expr.expr &:= "static ";
1149    c_expr.expr &:= type_name(resultType);
1150    c_expr.expr &:= " func_";
1151    c_expr.expr &:= valueName;
1152    c_expr.expr &:= " (void *data_";
1153    c_expr.expr &:= valueName;
1154    c_expr.expr &:= ")\n";
1155    c_expr.expr &:= "{\n";
1156    c_func_body.demand := REQUIRE_RESULT;
1157    if category(actual_param) = BLOCKOBJECT then
1158      process_call_by_name_expr(body(actual_param), c_func_body);
1159    else
1160      process_call_by_name_expr(actual_param, c_func_body);
1161    end if;
1162    appendWithDiagnostic(c_func_body.temp_decls, c_expr);
1163    appendWithDiagnostic(c_func_body.temp_assigns, c_expr);
1164    if getType(actual_param) = proctype then
1165      c_expr.expr &:= c_func_body.expr;
1166      appendWithDiagnostic(c_func_body.temp_frees, c_expr);
1167    else
1168      if c_func_body.temp_frees <> "" then
1169        c_expr.expr &:= type_name(resultType);
1170        c_expr.expr &:= " result=";
1171      else
1172        c_expr.expr &:= diagnosticLine(actual_param);
1173        c_expr.expr &:= "return ";
1174      end if;
1175      if c_func_body.result_expr <> "" then
1176        c_expr.expr &:= c_func_body.result_expr;
1177      elsif valueIsAtHeap(resultType) then
1178        process_create_declaration(resultType, global_c_expr);
1179        process_create_call(resultType, c_func_body.expr, c_expr.expr);
1180      else
1181        c_expr.expr &:= c_func_body.expr;
1182      end if;
1183      c_expr.expr &:= ";\n";
1184      if c_func_body.temp_frees <> "" then
1185        appendWithDiagnostic(c_func_body.temp_frees, c_expr);
1186        c_expr.expr &:= "return result;\n";
1187      end if;
1188    end if;
1189    c_expr.expr &:= "}\n\n";
1190    funcparam_data := funcparam_data_backup;
1191    funcparam_reference := funcparam_reference_backup;
1192  end func;
1193
1194
1195const proc: defineFuncValue (in string: valueName, in type: genericFuncType,
1196    in ref_list: data_list, inout expr_type: c_expr) is func
1197
1198  local
1199    var reference: dataItem is NIL;
1200  begin
1201    incr(c_expr.temp_num);
1202    if data_list <> ref_list.EMPTY then
1203      c_expr.temp_decls &:= "functype_";
1204      c_expr.temp_decls &:= valueName;
1205    else
1206      c_expr.temp_decls &:= "struct_";
1207      c_expr.temp_decls &:= type_name(genericFuncType);
1208    end if;
1209    c_expr.temp_decls &:= " funcvalue_";
1210    c_expr.temp_decls &:= valueName;
1211    c_expr.temp_decls &:= ";\n\n";
1212    c_expr.temp_assigns &:= "funcvalue_";
1213    c_expr.temp_assigns &:= valueName;
1214    c_expr.temp_assigns &:= ".func = func_";
1215    c_expr.temp_assigns &:= valueName;
1216    c_expr.temp_assigns &:= ";\n";
1217    for dataItem range data_list do
1218      c_expr.temp_assigns &:= "funcvalue_";
1219      c_expr.temp_assigns &:= valueName;
1220      c_expr.temp_assigns &:= ".data.data_";
1221      create_name(dataItem, c_expr.temp_assigns);
1222      c_expr.temp_assigns &:= " = ";
1223      if isFunc(getType(dataItem)) then
1224        c_expr.temp_assigns &:= "o_";
1225        create_name(dataItem, c_expr.temp_assigns);
1226      else
1227        getAnyParamToTempAssigns(dataItem, c_expr);
1228      end if;
1229      c_expr.temp_assigns &:= ";\n";
1230    end for;
1231  end func;
1232
1233
1234const proc: callActualFuncParam (in string: valueName, in type: genericFuncType,
1235    in ref_list: data_list, inout expr_type: c_expr) is func
1236
1237  begin
1238    if data_list <> ref_list.EMPTY then
1239      c_expr.expr &:= "(";
1240      c_expr.expr &:= type_name(genericFuncType);
1241      c_expr.expr &:= " *)(";
1242    end if;
1243    c_expr.expr &:= "&funcvalue_";
1244    c_expr.expr &:= valueName;
1245    if data_list <> ref_list.EMPTY then
1246      c_expr.expr &:= ")";
1247    end if;
1248  end func;
1249
1250
1251const proc: processFuncValue (in string: valueName, in type: genericFuncType,
1252    in reference: closure, inout expr_type: c_expr) is func
1253
1254  local
1255    var ref_list: data_list is ref_list.EMPTY;
1256    var expr_type: function_c_expr is expr_type.value;
1257  begin
1258    declare_type_if_necessary(genericFuncType, global_c_expr);
1259    data_list := determineDataForActualFuncParam(closure);
1260    if closure not in definedActualFuncParams then
1261      function_c_expr.currentFile := file(closure);
1262      function_c_expr.currentLine := line(closure);
1263      defineActualFuncParam(resultType(genericFuncType), valueName, closure,
1264                            data_list, function_c_expr);
1265      global_c_expr.expr  &:= function_c_expr.temp_decls;
1266      global_init.expr    &:= function_c_expr.temp_assigns;
1267      global_c_expr.expr  &:= function_c_expr.expr;
1268      definedActualFuncParams @:= [closure] TRUE;
1269    end if;
1270    defineFuncValue(valueName, genericFuncType, data_list, c_expr);
1271    if data_list <> ref_list.EMPTY then
1272      c_expr.expr &:= "(";
1273      c_expr.expr &:= type_name(genericFuncType);
1274      c_expr.expr &:= ")(";
1275    end if;
1276    c_expr.expr &:= "&funcvalue_";
1277    c_expr.expr &:= valueName;
1278    if data_list <> ref_list.EMPTY then
1279      c_expr.expr &:= ")";
1280    end if;
1281  end func;
1282
1283
1284const proc: processFuncParam (in reference: formal_param,
1285    in reference: actual_param, inout expr_type: c_expr) is func
1286
1287  local
1288    var string: valueName is "";
1289  begin
1290    create_name(formal_param, objNumber(actual_param), valueName);
1291    processFuncValue(valueName, getType(formal_param), actual_param, c_expr);
1292  end func;
1293
1294
1295const proc: call_params (in ref_list: formal_params,
1296    in ref_list: actual_params, inout expr_type: c_expr) is func
1297
1298  local
1299    var integer: number is 0;
1300    var reference: formal_param is NIL;
1301    var reference: actual_param is NIL;
1302    var category: paramCategory is category.value;
1303    var boolean: first_element is TRUE;
1304    var integer: temp_num is 0;
1305  begin
1306#    for number range 1 to length(formal_params) do
1307    for number range 1 to length(actual_params) do
1308      formal_param := formal_params[number];
1309      actual_param := actual_params[number];
1310      paramCategory := category(formal_param);
1311      if paramCategory <> SYMBOLOBJECT then
1312        if paramCategory = TYPEOBJECT then
1313          c_expr.expr &:= "/* attr t_";
1314          c_expr.expr &:= str(typeNumber(getValue(formal_param, type)));
1315          c_expr.expr &:= " ";
1316          c_expr.expr &:= str(getValue(formal_param, type));
1317          c_expr.expr &:= "*/ ";
1318        elsif getType(formal_param) <> voidtype then
1319          if first_element then
1320            first_element := FALSE;
1321          else
1322            c_expr.expr &:= ", ";
1323          end if;
1324          if isPointerParam(formal_param) then
1325            if category(actual_param) = REFPARAMOBJECT then
1326              if actual_param in inlineParam and
1327                  inlineParam[actual_param][1].paramNum <> 0 then
1328                c_expr.expr &:= "par_";
1329                c_expr.expr &:= str(inlineParam[actual_param][1].paramNum);
1330                c_expr.expr &:= "_";
1331              end if;
1332              if actual_param in funcparam_reference then
1333                c_expr.expr &:= funcparam_reference[actual_param];
1334              else
1335                c_expr.expr &:= "o_";
1336                create_name(actual_param, c_expr.expr);
1337              end if;
1338            elsif category(actual_param) = MATCHOBJECT then
1339              if getValue(actual_param, ref_list)[1] in function_var_declared then
1340                c_expr.expr &:= "o_";
1341                create_name(getValue(actual_param, ref_list)[1], c_expr.expr);
1342              else
1343                processFuncParam(formal_param, actual_param, c_expr);
1344              end if;
1345            elsif category(actual_param) = BLOCKOBJECT then
1346              if actual_param in function_var_declared then
1347                c_expr.expr &:= "o_";
1348                create_name(actual_param, c_expr.expr);
1349              else
1350                processFuncParam(formal_param, actual_param, c_expr);
1351              end if;
1352            elsif category(actual_param) = LOCALVOBJECT and
1353                actual_param in function_var_declared then
1354              c_expr.expr &:= "o_";
1355              create_name(actual_param, c_expr.expr);
1356            elsif canTakeAddress(actual_param) then
1357              c_expr.expr &:= "&(";
1358              process_expr(actual_param, c_expr);
1359              c_expr.expr &:= ")";
1360            else
1361              c_expr.expr &:= "/* ";
1362              c_expr.expr &:= str(category(actual_param));
1363              c_expr.expr &:= " */";
1364              incr(c_expr.temp_num);
1365              temp_num := c_expr.temp_num;
1366              c_expr.temp_decls &:= type_name(getExprResultType(actual_param));
1367              c_expr.temp_decls &:= " tmp_";
1368              c_expr.temp_decls &:= str(temp_num);
1369              c_expr.temp_decls &:= ";\n";
1370              c_expr.expr &:= "(tmp_";
1371              c_expr.expr &:= str(temp_num);
1372              c_expr.expr &:= "=(";
1373              c_expr.expr &:= type_name(getExprResultType(actual_param));
1374              c_expr.expr &:= ")(";
1375              getAnyParamToExpr(actual_param, c_expr);
1376              c_expr.expr &:= "), &tmp_";
1377              c_expr.expr &:= str(temp_num);
1378              c_expr.expr &:= ")";
1379            end if;
1380          else
1381            getAnyParamToExpr(actual_param, c_expr);
1382          end if;
1383        end if;
1384      end if;
1385    end for;
1386  end func;
1387
1388
1389const proc: process_prototype_declaration (in reference: current_object,
1390    inout expr_type: c_expr) is forward;
1391
1392
1393const proc: process_const_func_call (in reference: function,
1394    in ref_list: actual_params, inout expr_type: c_expr) is func
1395
1396  local
1397    var type: function_type is void;
1398    var type: result_type is void;
1399    var ref_list: formal_params is ref_list.EMPTY;
1400    var expr_type: c_params is expr_type.value;
1401  begin
1402    if function not in prototype_declared then
1403      process_prototype_declaration(function, global_c_expr);
1404      prototype_declared @:= [function] TRUE;
1405    end if;
1406    function_type := getType(function);
1407    result_type := resultType(function_type);
1408    formal_params := formalParams(function);
1409    if valueIsAtHeap(result_type) and
1410        not isVarfunc(function_type) and
1411        function not in return_ref_to_value then
1412      prepare_typed_result(result_type, c_expr);
1413      c_expr.result_expr := "o_";
1414      create_name(function, c_expr.result_expr);
1415      c_expr.result_expr &:= "(";
1416      c_params.temp_num := c_expr.temp_num;
1417      call_params(formal_params, actual_params, c_params);
1418      c_expr.temp_num := c_params.temp_num;
1419      c_expr.temp_decls &:= c_params.temp_decls;
1420      c_expr.temp_assigns &:= c_params.temp_assigns;
1421      c_expr.temp_frees &:= c_params.temp_frees;
1422      c_expr.temp_to_null &:= c_params.temp_to_null;
1423      c_expr.result_expr &:= c_params.expr;
1424      c_expr.result_expr &:= ")";
1425    elsif result_type = voidtype then
1426      c_params.temp_num := c_expr.temp_num;
1427      call_params(formal_params, actual_params, c_params);
1428      c_expr.temp_num := c_params.temp_num;
1429      if c_params.temp_decls <> "" or c_params.temp_assigns <> "" then
1430        setDiagnosticLine(c_expr);
1431        c_expr.expr &:= "{\n";
1432        appendWithDiagnostic(c_params.temp_decls, c_expr);
1433        appendWithDiagnostic(c_params.temp_assigns, c_expr);
1434      end if;
1435      setDiagnosticLine(c_expr);
1436      if isVarfunc(function_type) then
1437        c_expr.expr &:= "*o_";
1438      else
1439        c_expr.expr &:= "o_";
1440      end if;
1441      create_name(function, c_expr.expr);
1442      c_expr.expr &:= "(";
1443      c_expr.expr &:= c_params.expr;
1444      c_expr.expr &:= ")";
1445      c_expr.expr &:= ";\n";
1446      if c_params.temp_decls <> "" or c_params.temp_assigns <> "" then
1447        appendWithDiagnostic(c_params.temp_frees, c_expr);
1448        setDiagnosticLine(c_expr);
1449        c_expr.expr &:= "}\n";
1450      end if;
1451    else
1452      if isVarfunc(function_type) then
1453        c_expr.expr &:= "*o_";
1454      else
1455        c_expr.expr &:= "o_";
1456      end if;
1457      create_name(function, c_expr.expr);
1458      c_expr.expr &:= "(";
1459      call_params(formal_params, actual_params, c_expr);
1460      c_expr.expr &:= ")";
1461    end if;
1462  end func;
1463
1464
1465const proc: process_func_call (in reference: function,
1466    in ref_list: actual_params, inout expr_type: c_expr) is func
1467
1468  local
1469    var type: result_type is void;
1470  begin
1471    if isVar(function) then
1472      if getType(function) = proctype then
1473        setDiagnosticLine(c_expr);
1474      end if;
1475      result_type := resultType(getType(function));
1476      if valueIsAtHeap(result_type) then
1477        prepare_typed_result(result_type, c_expr);
1478        c_expr.result_expr &:= "o_";
1479        create_name(function, c_expr.result_expr);
1480        c_expr.result_expr &:= "->func(o_";
1481        create_name(function, c_expr.result_expr);
1482        c_expr.result_expr &:= ")";
1483      else
1484        c_expr.expr &:= "o_";
1485        create_name(function, c_expr.expr);
1486        c_expr.expr &:= "->func(o_";
1487        create_name(function, c_expr.expr);
1488        c_expr.expr &:= ")";
1489        if getType(function) = proctype then
1490          c_expr.expr &:= ";\n";
1491        end if;
1492      end if;
1493    else
1494      process_const_func_call(function, actual_params, c_expr);
1495    end if;
1496  end func;
1497
1498
1499const proc: process_call (in reference: current_expression, inout expr_type: c_expr) is func
1500
1501  local
1502    var ref_list: params is ref_list.EMPTY;
1503    var reference: function is NIL;
1504    var category: functionCategory is category.value;
1505    var reference: result_object is NIL;
1506    var reference: obj is NIL;
1507    var boolean: first_element is TRUE;
1508  begin
1509    c_expr.currentFile := file(current_expression);
1510    c_expr.currentLine := line(current_expression);
1511    params := getValue(current_expression, ref_list);
1512    function := params[1];
1513    params := params[2 ..];
1514    functionCategory := category(function);
1515    # c_expr.expr &:= "/* process_call ";
1516    # c_expr.expr &:= str(current_expression);
1517    # c_expr.expr &:= " ";
1518    # c_expr.expr &:= str(function);
1519    # c_expr.expr &:= " */";
1520    if functionCategory = ACTOBJECT then
1521      process_action(function, params, c_expr);
1522    elsif functionCategory = BLOCKOBJECT then
1523      result_object := resultVar(function);
1524      if function in function_declared or result_object <> NIL then
1525        process_func_call(function, params, c_expr);
1526      else
1527        process_inline(function, params, c_expr);
1528      end if;
1529    elsif functionCategory = LOCALVOBJECT then
1530      process_func_call(function, params, c_expr);
1531    elsif functionCategory = CONSTENUMOBJECT then
1532      (* process_constenumobject(function, params, c_expr); *)
1533      process_expr(function, c_expr);
1534    elsif functionCategory = REFPARAMOBJECT then
1535      if isFunc(getType(function)) or
1536          isVarfunc(getType(function)) then
1537        if function in inlineParam then
1538          process_inline_param(function, c_expr);
1539        else
1540          if getType(function) = proctype then
1541            setDiagnosticLine(c_expr);
1542          end if;
1543          c_expr.expr &:= "o_";
1544          create_name(function, c_expr.expr);
1545          c_expr.expr &:= "->func(o_";
1546          create_name(function, c_expr.expr);
1547          c_expr.expr &:= ")";
1548          if getType(function) = proctype then
1549            c_expr.expr &:= ";\n";
1550          end if;
1551        end if;
1552      else
1553        process_expr(function, c_expr);
1554      end if;
1555    elsif functionCategory = VALUEPARAMOBJECT or
1556          functionCategory = INTOBJECT or
1557          functionCategory = BIGINTOBJECT or
1558          functionCategory = FLOATOBJECT or
1559          functionCategory = CHAROBJECT or
1560          functionCategory = STRIOBJECT or
1561          functionCategory = BSTRIOBJECT or
1562          functionCategory = ARRAYOBJECT or
1563          functionCategory = HASHOBJECT or
1564          functionCategory = SETOBJECT or
1565          functionCategory = STRUCTOBJECT or
1566          functionCategory = INTERFACEOBJECT or
1567          functionCategory = WINOBJECT or
1568          functionCategory = PROCESSOBJECT or
1569          functionCategory = PROGOBJECT or
1570          functionCategory = DATABASEOBJECT or
1571          functionCategory = SQLSTMTOBJECT or
1572          functionCategory = ENUMLITERALOBJECT or
1573          functionCategory = TYPEOBJECT then
1574      process_expr(function, c_expr);
1575    elsif functionCategory = REFOBJECT then
1576      c_expr.expr &:= "o_";
1577      create_name(function, c_expr.expr);
1578    elsif functionCategory = REFLISTOBJECT then
1579      c_expr.expr &:= "o_";
1580      create_name(function, c_expr.expr);
1581    elsif functionCategory = FORWARDOBJECT then
1582      error(FORWARD_CALLED, current_expression, function);
1583    else
1584      c_expr.expr &:= "/*[ ";
1585      c_expr.expr &:= str(functionCategory);
1586      c_expr.expr &:= " ]*/";
1587      c_expr.expr &:= "o_";
1588      create_name(function, c_expr.expr);
1589      c_expr.expr &:= "(";
1590      for obj range params do
1591        if category(obj) <> SYMBOLOBJECT then
1592          if first_element then
1593            first_element := FALSE;
1594          else
1595            c_expr.expr &:= ", ";
1596          end if;
1597          process_expr(obj, c_expr);
1598        end if;
1599      end for;
1600      c_expr.expr &:= ")";
1601    end if;
1602  end func;
1603
1604
1605const proc: process_match (in reference: current_expression, inout expr_type: c_expr) is func
1606
1607  local
1608    var ref_list: params is ref_list.EMPTY;
1609    var reference: function is NIL;
1610    var category: functionCategory is category.value;
1611    var reference: result_object is NIL;
1612    var reference: obj is NIL;
1613    var boolean: first_element is TRUE;
1614  begin
1615    c_expr.currentFile := file(current_expression);
1616    c_expr.currentLine := line(current_expression);
1617    # c_expr.expr &:= "/* process_match ";
1618    # c_expr.expr &:= str(current_expression);
1619    # c_expr.expr &:= " */";
1620    params := getValue(current_expression, ref_list);
1621    function := params[1];
1622    params := params[2 ..];
1623    functionCategory := category(function);
1624    if functionCategory = ACTOBJECT then
1625      global_c_expr.expr &:= "objRefType ";
1626      global_c_expr.expr &:= lower(str(getValue(function, ACTION)));
1627      global_c_expr.expr &:= " (listType arguments);\n";
1628      c_expr.expr &:= "&";
1629      c_expr.expr &:= lower(str(getValue(function, ACTION)));
1630    elsif functionCategory = BLOCKOBJECT then
1631      c_expr.expr &:= "o_";
1632      create_name(function, c_expr.expr);
1633    else
1634      raise RANGE_ERROR;
1635      c_expr.expr &:= "/*[ ";
1636      c_expr.expr &:= str(functionCategory);
1637      c_expr.expr &:= " ]*/";
1638      c_expr.expr &:= "o_";
1639      create_name(function, c_expr.expr);
1640      c_expr.expr &:= "(";
1641      for obj range params do
1642        if category(obj) <> SYMBOLOBJECT then
1643          if first_element then
1644            first_element := FALSE;
1645          else
1646            c_expr.expr &:= ", ";
1647          end if;
1648          process_expr(obj, c_expr);
1649        end if;
1650      end for;
1651      c_expr.expr &:= ")";
1652    end if;
1653  end func;
1654
1655
1656const proc: optimize_constant_expressions (inout reference: current_expression,
1657    inout expr_type: c_expr) is func
1658
1659  local
1660    var reference: evaluated_expression is NIL;
1661  begin
1662    if evaluate_const_expr = 3 and isConstantExpr(current_expression) then
1663      block
1664        evaluated_expression := evaluate(prog, current_expression);
1665        if evaluated_expression <> NIL and evaluated_expression <> current_expression then
1666          incr(countEvaluations);
1667          c_expr.expr &:= "/* evaluate ";
1668          if category(getValue(current_expression, ref_list)[1]) = ACTOBJECT then
1669            c_expr.expr &:= str(getValue(getValue(current_expression, ref_list)[1], ACTION));
1670          elsif category(getValue(current_expression, ref_list)[1]) = BLOCKOBJECT then
1671            c_expr.expr &:= "o_";
1672            create_name2(getValue(current_expression, ref_list)[1], c_expr.expr);
1673          end if;
1674          c_expr.expr &:= " */ ";
1675          current_expression := evaluated_expression;
1676          if category(current_expression) = VARENUMOBJECT then
1677            current_expression := getValue(current_expression, reference);
1678          else
1679            setVar(current_expression, FALSE);
1680          end if;
1681        end if;
1682      exception
1683        catch NUMERIC_ERROR:  c_expr.expr &:= "/* NUMERIC_ERROR */ "; # noop;
1684        catch OVERFLOW_ERROR: c_expr.expr &:= "/* OVERFLOW_ERROR */ "; # noop;
1685        catch RANGE_ERROR:    c_expr.expr &:= "/* RANGE_ERROR */ "; # noop;
1686        catch INDEX_ERROR:    c_expr.expr &:= "/* INDEX_ERROR */ "; # noop;
1687        catch FILE_ERROR:     c_expr.expr &:= "/* FILE_ERROR */ "; # noop;
1688        catch DATABASE_ERROR: c_expr.expr &:= "/* DATABASE_ERROR */ "; # noop;
1689      end block;
1690    end if;
1691  end func;
1692
1693
1694const proc: process_expr (in var reference: current_expression, inout expr_type: c_expr) is func
1695
1696  local
1697    var category: exprCategory is category.value;
1698  begin
1699    optimize_constant_expressions(current_expression, c_expr);
1700    exprCategory := category(current_expression);
1701    if exprCategory = MATCHOBJECT then
1702      process_match(current_expression, c_expr);
1703    elsif exprCategory = CALLOBJECT then
1704      process_call(current_expression, c_expr);
1705    elsif exprCategory = BLOCKOBJECT then
1706      c_expr.expr &:= "o_";
1707      create_name(current_expression, c_expr.expr);
1708      if not isVar(current_expression) then
1709        c_expr.expr &:= "()";
1710        if resultType(getType(current_expression)) = voidtype then
1711          c_expr.expr &:= ";\n";
1712        end if;
1713      end if;
1714    elsif exprCategory = ACTOBJECT then
1715      global_c_expr.expr &:= "objRefType ";
1716      global_c_expr.expr &:= lower(str(getValue(current_expression, ACTION)));
1717      global_c_expr.expr &:= " (listType arguments);\n";
1718      c_expr.expr &:= "&";
1719      c_expr.expr &:= lower(str(getValue(current_expression, ACTION)));
1720    elsif exprCategory = LOCALVOBJECT then
1721      if current_expression in funcparam_data then
1722        c_expr.expr &:= funcparam_data[current_expression];
1723      else
1724        c_expr.expr &:= "o_";
1725        create_name(current_expression, c_expr.expr);
1726      end if;
1727    elsif exprCategory = VALUEPARAMOBJECT then
1728      if current_expression in funcparam_data then
1729        c_expr.expr &:= funcparam_data[current_expression];
1730      elsif current_expression in inlineParam and
1731          inlineParam[current_expression][1].paramValue <> NIL then
1732        process_expr(inlineParam[current_expression][1].paramValue, c_expr);
1733      else
1734        if current_expression in inlineParam and
1735            inlineParam[current_expression][1].paramNum <> 0 then
1736          c_expr.expr &:= "par_";
1737          c_expr.expr &:= str(inlineParam[current_expression][1].paramNum);
1738          c_expr.expr &:= "_";
1739        end if;
1740        c_expr.expr &:= "o_";
1741        create_name(current_expression, c_expr.expr);
1742      end if;
1743    elsif exprCategory = REFPARAMOBJECT then
1744      if current_expression in funcparam_data then
1745        c_expr.expr &:= funcparam_data[current_expression];
1746      elsif isFunc(getType(current_expression)) or
1747          isVarfunc(getType(current_expression)) then
1748        if current_expression in inlineParam then
1749          process_inline_param(current_expression, c_expr);
1750        else
1751          if getType(current_expression) = proctype then
1752            setDiagnosticLine(c_expr);
1753          end if;
1754          c_expr.expr &:= "o_";
1755          create_name(current_expression, c_expr.expr);
1756          c_expr.expr &:= "->func(o_";
1757          create_name(current_expression, c_expr.expr);
1758          c_expr.expr &:= ")";
1759          if getType(current_expression) = proctype then
1760            c_expr.expr &:= ";\n";
1761          end if;
1762        end if;
1763      elsif current_expression in inlineParam and
1764          inlineParam[current_expression][1].paramValue <> NIL then
1765        process_expr(inlineParam[current_expression][1].paramValue, c_expr);
1766      else
1767        if isPointerParam(current_expression) then
1768          c_expr.expr &:= "*";
1769        end if;
1770        if current_expression in inlineParam and
1771            inlineParam[current_expression][1].paramNum <> 0 then
1772          c_expr.expr &:= "par_";
1773          c_expr.expr &:= str(inlineParam[current_expression][1].paramNum);
1774          c_expr.expr &:= "_";
1775        end if;
1776        c_expr.expr &:= "o_";
1777        create_name(current_expression, c_expr.expr);
1778      end if;
1779    elsif exprCategory = RESULTOBJECT then
1780      if current_expression in funcparam_data then
1781        c_expr.expr &:= funcparam_data[current_expression];
1782      else
1783        c_expr.expr &:= "o_";
1784        create_name(current_expression, c_expr.expr);
1785      end if;
1786    elsif exprCategory = TYPEOBJECT then
1787      if isVar(current_expression) then
1788        c_expr.expr &:= "o_";
1789        create_name(current_expression, c_expr.expr);
1790      else
1791        c_expr.expr &:= typeLiteral(getValue(current_expression, type));
1792      end if;
1793    elsif exprCategory = INTOBJECT then
1794      if isVar(current_expression) then
1795        c_expr.expr &:= "o_";
1796        create_name(current_expression, c_expr.expr);
1797      else
1798        c_expr.expr &:= integerLiteral(getValue(current_expression, integer));
1799      end if;
1800    elsif exprCategory = BIGINTOBJECT then
1801      if isVar(current_expression) then
1802        c_expr.expr &:= "o_";
1803        create_name(current_expression, c_expr.expr);
1804      else
1805        c_expr.expr &:= bigIntegerLiteral(getValue(current_expression, bigInteger));
1806      end if;
1807    elsif exprCategory = FLOATOBJECT then
1808      if isVar(current_expression) then
1809        c_expr.expr &:= "o_";
1810        create_name(current_expression, c_expr.expr);
1811      else
1812        c_expr.expr &:= floatLiteral(getValue(current_expression, float));
1813      end if;
1814    elsif exprCategory = CHAROBJECT then
1815      if isVar(current_expression) then
1816        c_expr.expr &:= "o_";
1817        create_name(current_expression, c_expr.expr);
1818      else
1819        c_expr.expr &:= charLiteral(getValue(current_expression, char));
1820      end if;
1821    elsif exprCategory = STRIOBJECT then
1822      if isVar(current_expression) then
1823        c_expr.expr &:= "o_";
1824        create_name(current_expression, c_expr.expr);
1825      else
1826        c_expr.expr &:= stringLiteral(getValue(current_expression, string));
1827      end if;
1828    elsif exprCategory = BSTRIOBJECT then
1829      if isVar(current_expression) then
1830        c_expr.expr &:= "o_";
1831        create_name(current_expression, c_expr.expr);
1832      else
1833        c_expr.expr &:= bstriLiteral(getValue(current_expression, bstring));
1834      end if;
1835    elsif exprCategory = SETOBJECT then
1836      if isVar(current_expression) then
1837        c_expr.expr &:= "o_";
1838        create_name(current_expression, c_expr.expr);
1839      else
1840        c_expr.expr &:= "(";
1841        c_expr.expr &:= type_name(getType(current_expression));
1842        c_expr.expr &:= ")(";
1843        c_expr.expr &:= bitsetLiteral(getValue(current_expression, bitset));
1844        c_expr.expr &:= ")";
1845      end if;
1846    elsif exprCategory = REFOBJECT then
1847      if isVar(current_expression) then
1848        c_expr.expr &:= "o_";
1849        create_name(current_expression, c_expr.expr);
1850      else
1851        if getValue(current_expression, reference) = NIL then
1852          c_expr.expr &:= "NULL";
1853        else
1854          c_expr.expr &:= "&(";
1855          process_expr(getValue(current_expression, reference), c_expr);
1856          c_expr.expr &:= ")";
1857        end if;
1858      end if;
1859    elsif exprCategory = REFLISTOBJECT then
1860      c_expr.expr &:= "o_";
1861      create_name(current_expression, c_expr.expr);
1862    elsif exprCategory = ARRAYOBJECT then
1863      if isVar(current_expression) then
1864        c_expr.expr &:= "o_";
1865        create_name(current_expression, c_expr.expr);
1866      else
1867        if current_expression not in const_table then
1868          const_table @:= [current_expression] length(const_table);
1869        end if;
1870        c_expr.expr &:= "arr[";
1871        c_expr.expr &:= str(const_table[current_expression]);
1872        c_expr.expr &:= "]";
1873      end if;
1874    elsif exprCategory = STRUCTOBJECT then
1875      if isVar(current_expression) then
1876        c_expr.expr &:= "o_";
1877        create_name(current_expression, c_expr.expr);
1878      else
1879        if current_expression not in const_table then
1880          const_table @:= [current_expression] length(const_table);
1881        end if;
1882        c_expr.expr &:= "sct[";
1883        c_expr.expr &:= str(const_table[current_expression]);
1884        c_expr.expr &:= "]";
1885      end if;
1886    elsif exprCategory = HASHOBJECT then
1887      if isVar(current_expression) then
1888        c_expr.expr &:= "o_";
1889        create_name(current_expression, c_expr.expr);
1890      else
1891        if current_expression not in const_table then
1892          const_table @:= [current_expression] length(const_table);
1893        end if;
1894        c_expr.expr &:= "hsh[";
1895        c_expr.expr &:= str(const_table[current_expression]);
1896        c_expr.expr &:= "]";
1897      end if;
1898    elsif exprCategory = INTERFACEOBJECT then
1899      if isVar(current_expression) then
1900        c_expr.expr &:= "o_";
1901        create_name(current_expression, c_expr.expr);
1902      else
1903        if current_expression not in const_table then
1904          const_table @:= [current_expression] length(const_table);
1905        end if;
1906        c_expr.expr &:= "itf[";
1907        c_expr.expr &:= str(const_table[current_expression]);
1908        c_expr.expr &:= "]";
1909      end if;
1910    elsif exprCategory = FILEOBJECT then
1911      c_expr.expr &:= "o_";
1912      create_name(current_expression, c_expr.expr);
1913    elsif exprCategory = SOCKETOBJECT then
1914      c_expr.expr &:= "o_";
1915      create_name(current_expression, c_expr.expr);
1916    elsif exprCategory = POLLOBJECT then
1917      c_expr.expr &:= "o_";
1918      create_name(current_expression, c_expr.expr);
1919    elsif exprCategory = WINOBJECT then
1920      if isVar(current_expression) then
1921        c_expr.expr &:= "o_";
1922        create_name(current_expression, c_expr.expr);
1923      else
1924        c_expr.expr &:= windowLiteral(getValue(current_expression, PRIMITIVE_WINDOW));
1925      end if;
1926    elsif exprCategory = PROCESSOBJECT then
1927      if isVar(current_expression) then
1928        c_expr.expr &:= "o_";
1929        create_name(current_expression, c_expr.expr);
1930      else
1931        if getValue(current_expression, process) = process.EMPTY then
1932          c_expr.expr &:= "/*process.EMPTY*/NULL";
1933        else
1934          c_expr.expr &:= "o_";
1935          create_name(current_expression, c_expr.expr);
1936        end if;
1937      end if;
1938    elsif exprCategory = PROGOBJECT then
1939      if isVar(current_expression) then
1940        c_expr.expr &:= "o_";
1941        create_name(current_expression, c_expr.expr);
1942      else
1943        if getValue(current_expression, program) = program.EMPTY then
1944          c_expr.expr &:= "/*program.EMPTY*/NULL";
1945        else
1946          c_expr.expr &:= "o_";
1947          create_name(current_expression, c_expr.expr);
1948        end if;
1949      end if;
1950    elsif exprCategory = DATABASEOBJECT then
1951      if isVar(current_expression) then
1952        c_expr.expr &:= "o_";
1953        create_name(current_expression, c_expr.expr);
1954      else
1955        c_expr.expr &:= "/*database.value*/NULL";
1956      end if;
1957    elsif exprCategory = SQLSTMTOBJECT then
1958      if isVar(current_expression) then
1959        c_expr.expr &:= "o_";
1960        create_name(current_expression, c_expr.expr);
1961      else
1962        c_expr.expr &:= "/*sqlStatement.value*/NULL";
1963      end if;
1964    elsif exprCategory = CONSTENUMOBJECT then
1965      if isVar(current_expression) then
1966        c_expr.expr &:= "o_";
1967        create_name(current_expression, c_expr.expr);
1968      else
1969        c_expr.expr &:= enum_value(getValue(current_expression, reference));
1970      end if;
1971    elsif exprCategory = VARENUMOBJECT then
1972      if current_expression in funcparam_data then
1973        c_expr.expr &:= funcparam_data[current_expression];
1974      else
1975        c_expr.expr &:= "o_";
1976        create_name(current_expression, c_expr.expr);
1977      end if;
1978    elsif exprCategory = ENUMLITERALOBJECT then
1979      if getType(current_expression) = voidtype then
1980        c_expr.expr &:= "/* empty */\n";
1981      else
1982        c_expr.expr &:= "o_";
1983        create_name(current_expression, c_expr.expr);
1984      end if;
1985    elsif exprCategory = EXPROBJECT then
1986      c_expr.expr &:= "o_";
1987      create_name(current_expression, c_expr.expr);
1988    elsif exprCategory = SYMBOLOBJECT then
1989      c_expr.expr &:= "/* SYMBOLOBJECT ";
1990      c_expr.expr &:= str(current_expression);
1991      c_expr.expr &:= " */";
1992    else
1993      c_expr.expr &:= "/* ";
1994      c_expr.expr &:= str(exprCategory);
1995      c_expr.expr &:= " */";
1996    end if;
1997  end func;
1998
1999
2000const proc: process_call_by_name_expr (in var reference: current_expression, inout expr_type: c_expr) is func
2001
2002  local
2003    var reference: evaluated_expression is NIL;
2004    var category: exprCategory is category.value;
2005  begin
2006    exprCategory := category(current_expression);
2007    if exprCategory = MATCHOBJECT then
2008      process_call(current_expression, c_expr);
2009    elsif exprCategory = LOCALVOBJECT then
2010      if isFunc(getType(current_expression)) or
2011          isVarfunc(getType(current_expression)) then
2012        process_func_call(current_expression, ref_list.EMPTY, c_expr);
2013      else
2014        process_expr(current_expression, c_expr);
2015      end if;
2016    elsif exprCategory = BLOCKOBJECT then
2017      c_expr.expr &:= "o_";
2018      create_name(current_expression, c_expr.expr);
2019      if not isVar(current_expression) then
2020        c_expr.expr &:= "()";
2021        if resultType(getType(current_expression)) = voidtype then
2022          c_expr.expr &:= ";\n";
2023        end if;
2024      end if;
2025    elsif exprCategory = ACTOBJECT then
2026      c_expr.expr &:= "/* process_call_by_name_expr ACTOBJECT ";
2027      c_expr.expr &:= str(getValue(current_expression, ACTION));
2028      c_expr.expr &:= " */";
2029      process_action(current_expression, ref_list.EMPTY, c_expr);
2030    else
2031      process_expr(current_expression, c_expr);
2032    end if;
2033  end func;
2034
2035
2036const proc: declare_types_of_params (in ref_list: formal_params, inout expr_type: c_expr) is func
2037
2038  local
2039    var reference: formal_param is NIL;
2040    var category: paramCategory is category.value;
2041  begin
2042    for formal_param range formal_params do
2043      paramCategory := category(formal_param);
2044      if paramCategory <> SYMBOLOBJECT and paramCategory <> TYPEOBJECT then
2045        declare_type_if_necessary(getType(formal_param), c_expr);
2046      end if;
2047    end for;
2048  end func;
2049
2050
2051const proc: process_param_declaration (in reference: formal_param, inout expr_type: c_expr) is func
2052
2053  local
2054    var type: param_type is void;
2055    var string: param_name is "";
2056  begin
2057    param_type := getType(formal_param);
2058    if isPointerParam(formal_param) then
2059      if isFunc(param_type) or isVarfunc(param_type) then
2060        c_expr.expr &:= type_name(param_type);
2061        c_expr.expr &:= " o_";
2062        create_name(formal_param, c_expr.expr);
2063      else
2064        if not isVar(formal_param) then
2065          c_expr.expr &:= "const ";
2066        end if;
2067        c_expr.expr &:= type_name(param_type);
2068        c_expr.expr &:= " *const o_";
2069        create_name(formal_param, c_expr.expr);
2070      end if;
2071    elsif isCopyParam(formal_param) then
2072      create_name(formal_param, param_name);
2073      c_expr.expr &:= "const ";
2074      if useConstPrefix(formal_param) then
2075        c_expr.expr &:= "const_";
2076      end if;
2077      c_expr.expr &:= type_name(param_type);
2078      c_expr.expr &:= " value_o_";
2079      c_expr.expr &:= param_name;
2080      if not isVar(formal_param) and useConstPrefix(param_type) then
2081        c_expr.temp_decls &:= "const_";
2082      end if;
2083      c_expr.temp_decls &:= type_name(param_type);
2084      c_expr.temp_decls &:= " o_";
2085      c_expr.temp_decls &:= param_name;
2086      c_expr.temp_decls &:= ";\n";
2087      c_expr.temp_assigns &:= "o_";
2088      c_expr.temp_assigns &:= param_name;
2089      c_expr.temp_assigns &:= "=";
2090      process_create_declaration(param_type, global_c_expr);
2091      process_create_call(param_type,
2092          "value_o_" & param_name, c_expr.temp_assigns);
2093      c_expr.temp_assigns &:= ";\n";
2094      process_destr_declaration(param_type, global_c_expr);
2095      process_destr_call(param_type,
2096          "o_" & param_name, c_expr.temp_frees);
2097    else
2098      if not isVar(formal_param) then
2099        c_expr.expr &:= "const ";
2100        if useConstPrefix(formal_param) then
2101          c_expr.expr &:= "const_";
2102        end if;
2103      end if;
2104      c_expr.expr &:= type_name(param_type);
2105      c_expr.expr &:= " o_";
2106      create_name(formal_param, c_expr.expr);
2107    end if;
2108  end func;
2109
2110
2111const proc: process_param_list_declaration (in ref_list: formal_params, inout expr_type: c_expr) is func
2112
2113  local
2114    var reference: formal_param is NIL;
2115    var category: paramCategory is category.value;
2116    var boolean: first_element is TRUE;
2117  begin
2118    for formal_param range formal_params do
2119      paramCategory := category(formal_param);
2120      if paramCategory <> SYMBOLOBJECT then
2121        if paramCategory = TYPEOBJECT then
2122          c_expr.expr &:= "/* attr t_";
2123          c_expr.expr &:= str(typeNumber(getValue(formal_param, type)));
2124          c_expr.expr &:= " ";
2125          c_expr.expr &:= str(getValue(formal_param, type));
2126          c_expr.expr &:= "*/ ";
2127        elsif getType(formal_param) <> voidtype then
2128          if first_element then
2129            first_element := FALSE;
2130          else
2131            c_expr.expr &:= ", ";
2132          end if;
2133          process_param_declaration(formal_param, c_expr);
2134        end if;
2135      end if;
2136    end for;
2137    if first_element then
2138      c_expr.expr &:= "void";
2139    end if;
2140  end func;
2141
2142
2143const proc: process_result_declaration (in reference: result_object,
2144    in var reference: result_init, inout expr_type: c_expr) is func
2145
2146  local
2147    var reference: evaluatedExpr is NIL;
2148  begin
2149    if result_object <> NIL then
2150      if evaluate_const_expr >= 2 and isConstant(result_init) then
2151        block
2152          evaluatedExpr := evaluate(prog, result_init);
2153          if evaluatedExpr <> NIL then
2154            incr(countEvaluations);
2155            result_init := evaluatedExpr;
2156          end if;
2157        exception
2158          catch NUMERIC_ERROR:  noop;
2159          catch OVERFLOW_ERROR: noop;
2160          catch RANGE_ERROR:    noop;
2161          catch INDEX_ERROR:    noop;
2162          catch FILE_ERROR:     noop;
2163          catch DATABASE_ERROR: noop;
2164        end block;
2165      end if;
2166      process_local_declaration(result_object, result_init, c_expr);
2167    end if;
2168  end func;
2169
2170
2171const proc: process_return (in reference: result_object,
2172    inout expr_type: c_expr) is func
2173
2174  begin
2175    if result_object <> NIL then
2176      c_expr.expr &:= "return o_";
2177      create_name(result_object, c_expr.expr);
2178      c_expr.expr &:= ";\n";
2179    end if;
2180  end func;
2181
2182
2183const proc: process_return_value (in reference: function,
2184    in type: result_type, in expr_type: c_func_body,
2185    inout expr_type: c_expr) is func
2186
2187  begin
2188    if isVarfunc(getType(function)) then
2189      c_expr.expr &:= "&(";
2190      if c_func_body.result_expr <> "" then
2191        c_expr.expr &:= c_func_body.result_expr;
2192      else
2193        c_expr.expr &:= c_func_body.expr;
2194      end if;
2195    else
2196      c_expr.expr &:= "(";
2197      if c_func_body.result_expr <> "" then
2198        c_expr.expr &:= c_func_body.result_expr;
2199      else
2200        if function in prototype_declared then
2201          process_create_declaration(result_type, global_c_expr);
2202          process_create_call(result_type, c_func_body.expr, c_expr.expr);
2203        else
2204          if valueIsAtHeap(result_type) then
2205            return_ref_to_value @:= [function] TRUE;
2206            c_expr.expr &:= "/*ref_to_value*/ ";
2207          end if;
2208          c_expr.expr &:= c_func_body.expr;
2209        end if;
2210      end if;
2211    end if;
2212    c_expr.expr &:= ")";
2213  end func;
2214
2215
2216const proc: process_local_consts (in reference: function,
2217    inout expr_type: c_expr) is forward;
2218
2219
2220const proc: process_const_func_declaration (in reference: function,
2221    inout expr_type: c_expr) is func
2222
2223  local
2224    var expr_type: c_local_consts is expr_type.value;
2225    var expr_type: c_param_list is expr_type.value;
2226    var expr_type: c_result is expr_type.value;
2227    var expr_type: c_local_vars is expr_type.value;
2228    var expr_type: c_func_body is expr_type.value;
2229    var type: function_type is void;
2230    var type: result_type is void;
2231    var ref_list: param_list is ref_list.EMPTY;
2232    var reference: result_object is NIL;
2233    var reference: result_init is NIL;
2234  begin
2235    function_type := getType(function);
2236    result_type := resultType(function_type);
2237    param_list := formalParams(function);
2238    result_object := resultVar(function);
2239    if param_list_okay(param_list) or
2240        recursiveFunctionCall(function, body(function)) or
2241        result_object <> NIL then
2242      # Try to process the function declaration always.
2243      # The variable write_object_declaration is used to
2244      # decide if the function declaration should be written
2245      function_declared @:= [function] TRUE;
2246      declare_types_of_params(param_list, global_c_expr);
2247      c_local_consts.currentFile := c_expr.currentFile;
2248      c_local_consts.currentLine := c_expr.currentLine;
2249      process_local_consts(function, c_local_consts);
2250      global_c_expr.expr  &:= c_local_consts.temp_decls;
2251      global_init.expr    &:= c_local_consts.temp_assigns;
2252      global_c_expr.expr  &:= c_local_consts.expr;
2253      c_expr.expr &:= diagnosticLine(function);
2254      c_expr.expr &:= "static ";
2255      c_expr.expr &:= type_name(result_type);
2256      if isVarfunc(getType(function)) then
2257        c_expr.expr &:= " /*varfunc*/ *o_";
2258      else
2259        c_expr.expr &:= " o_";
2260      end if;
2261      create_name(function, c_expr.expr);
2262      c_expr.expr &:= " (";
2263      process_param_list_declaration(param_list, c_param_list);
2264      c_expr.expr &:= c_param_list.expr;
2265      c_expr.expr &:= ")\n";
2266      c_expr.expr &:= "{\n";
2267      if function_type <> proctype and result_object = NIL then
2268        if isFunctionCallingSpecialAction(function) then
2269          write_object_declaration := FALSE;
2270        end if;
2271        c_func_body.demand := REQUIRE_RESULT;
2272        currentProfiledFunction := function;
2273        process_expr(body(function), c_func_body);
2274        if c_param_list.temp_decls <> "" or c_func_body.temp_decls <> "" or
2275            trace_function or profile_function then
2276          c_expr.currentFile := file(body(function));
2277          c_expr.currentLine := line(body(function));
2278          setDiagnosticLine(c_expr);
2279          c_expr.expr &:= type_name(result_type);
2280          if isVarfunc(getType(function)) then
2281            c_expr.expr &:= " *result;\n";
2282          else
2283            c_expr.expr &:= " result;\n";
2284          end if;
2285          appendWithDiagnostic(c_param_list.temp_decls, c_expr);
2286          appendWithDiagnostic(c_func_body.temp_decls, c_expr);
2287          if trace_function then
2288            c_expr.expr &:= "printf(\"-> ";
2289            create_name(function, c_expr.expr);
2290            c_expr.expr &:= "\\n\");\n";
2291            c_expr.expr &:= "fflush(stdout);\n";
2292          end if;
2293          if profile_function then
2294            profiledFunctions @:= [objNumber(function)] function;
2295            c_expr.expr &:= "profile[";
2296            c_expr.expr &:= str(objNumber(function));
2297            c_expr.expr &:= "].count++;\n";
2298            c_expr.expr &:= "if (profile[";
2299            c_expr.expr &:= str(objNumber(function));
2300            c_expr.expr &:= "].depth == 0) {\n";
2301            c_expr.expr &:= "  profile[";
2302            c_expr.expr &:= str(objNumber(function));
2303            c_expr.expr &:= "].time -= timMicroSec();\n";
2304            c_expr.expr &:= "}\n";
2305            c_expr.expr &:= "profile[";
2306            c_expr.expr &:= str(objNumber(function));
2307            c_expr.expr &:= "].depth++;\n";
2308          end if;
2309          appendWithDiagnostic(c_param_list.temp_assigns, c_expr);
2310          appendWithDiagnostic(c_func_body.temp_assigns, c_expr);
2311          setDiagnosticLine(c_expr);
2312          c_expr.expr &:= "result=(";
2313          c_expr.expr &:= type_name(result_type);
2314          if isVarfunc(getType(function)) then
2315            c_expr.expr &:= " *";
2316          end if;
2317          c_expr.expr &:= ")(";
2318          process_return_value(function, result_type, c_func_body, c_expr);
2319          c_expr.expr &:= ");\n";
2320          appendWithDiagnostic(c_param_list.temp_frees, c_expr);
2321          appendWithDiagnostic(c_func_body.temp_frees, c_expr);
2322          if profile_function then
2323            c_expr.expr &:= "profile[";
2324            c_expr.expr &:= str(objNumber(function));
2325            c_expr.expr &:= "].depth--;\n";
2326            c_expr.expr &:= "if (profile[";
2327            c_expr.expr &:= str(objNumber(function));
2328            c_expr.expr &:= "].depth == 0) {\n";
2329            c_expr.expr &:= "  profile[";
2330            c_expr.expr &:= str(objNumber(function));
2331            c_expr.expr &:= "].time += timMicroSec();\n";
2332            c_expr.expr &:= "}\n";
2333          end if;
2334          if trace_function then
2335            c_expr.expr &:= "printf(\"<- ";
2336            create_name(function, c_expr.expr);
2337            c_expr.expr &:= "\\n\");\n";
2338            c_expr.expr &:= "fflush(stdout);\n";
2339          end if;
2340          setDiagnosticLine(c_expr);
2341          c_expr.expr &:= "return result;\n";
2342        else
2343          c_expr.expr &:= diagnosticLine(body(function));
2344          c_expr.expr &:= "return (";
2345          c_expr.expr &:= type_name(result_type);
2346          if isVarfunc(getType(function)) then
2347            c_expr.expr &:= " *";
2348          end if;
2349          c_expr.expr &:= ")(";
2350          process_return_value(function, result_type, c_func_body, c_expr);
2351          c_expr.expr &:= ");\n";
2352        end if;
2353      else
2354        result_init := resultInitValue(function);
2355        c_result.temp_num := c_expr.temp_num;
2356        process_result_declaration(result_object, result_init, c_result);
2357        c_local_vars.temp_num := c_result.temp_num;
2358        process_local_var_declaration(function, c_local_vars);
2359        c_expr.temp_num := c_local_vars.temp_num;
2360        currentProfiledFunction := function;
2361        process_expr(body(function), c_func_body);
2362        c_expr.currentFile := file(function);
2363        c_expr.currentLine := line(function);
2364        appendWithDiagnostic(c_param_list.temp_decls, c_expr);
2365        c_expr.expr &:= c_result.temp_decls;
2366        c_expr.expr &:= c_local_vars.temp_decls;
2367        appendWithDiagnostic(c_func_body.temp_decls, c_expr);
2368        if trace_function then
2369          c_expr.expr &:= "printf(\"-> ";
2370          create_name(function, c_expr.expr);
2371          c_expr.expr &:= "\\n\");\n";
2372          c_expr.expr &:= "fflush(stdout);\n";
2373        end if;
2374        if profile_function then
2375          profiledFunctions @:= [objNumber(function)] function;
2376          c_expr.expr &:= "profile[";
2377          c_expr.expr &:= str(objNumber(function));
2378          c_expr.expr &:= "].count++;\n";
2379          c_expr.expr &:= "if (profile[";
2380          c_expr.expr &:= str(objNumber(function));
2381          c_expr.expr &:= "].depth == 0) {\n";
2382          c_expr.expr &:= "  profile[";
2383          c_expr.expr &:= str(objNumber(function));
2384          c_expr.expr &:= "].time -= timMicroSec();\n";
2385          c_expr.expr &:= "}\n";
2386          c_expr.expr &:= "profile[";
2387          c_expr.expr &:= str(objNumber(function));
2388          c_expr.expr &:= "].depth++;\n";
2389        end if;
2390        appendWithDiagnostic(c_param_list.temp_assigns, c_expr);
2391        c_expr.expr &:= c_result.temp_assigns;
2392        c_expr.expr &:= c_local_vars.temp_assigns;
2393        appendWithDiagnostic(c_func_body.temp_assigns, c_expr);
2394        c_expr.expr &:= c_func_body.expr;
2395        appendWithDiagnostic(c_param_list.temp_frees, c_expr);
2396        appendWithDiagnostic(c_local_vars.temp_frees, c_expr);
2397        appendWithDiagnostic(c_func_body.temp_frees, c_expr);
2398        if profile_function then
2399          c_expr.expr &:= "profile[";
2400          c_expr.expr &:= str(objNumber(function));
2401          c_expr.expr &:= "].depth--;\n";
2402          c_expr.expr &:= "if (profile[";
2403          c_expr.expr &:= str(objNumber(function));
2404          c_expr.expr &:= "].depth == 0) {\n";
2405          c_expr.expr &:= "  profile[";
2406          c_expr.expr &:= str(objNumber(function));
2407          c_expr.expr &:= "].time += timMicroSec();\n";
2408          c_expr.expr &:= "}\n";
2409        end if;
2410        if trace_function then
2411          c_expr.expr &:= "printf(\"<- ";
2412          create_name(function, c_expr.expr);
2413          c_expr.expr &:= "\\n\");\n";
2414          c_expr.expr &:= "fflush(stdout);\n";
2415        end if;
2416        process_return(result_object, c_expr);
2417      end if;
2418      c_expr.expr &:= "}\n";
2419      c_expr.expr &:= noDiagnosticLine;
2420      c_expr.expr &:= "\n";
2421      if write_object_declaration then
2422        prototype_declared @:= [function] TRUE;
2423        count_declarations(c_expr);
2424      else
2425        excl(function_declared, function);
2426        c_expr.expr &:= "/* declare inline o_";
2427        create_name2(function, c_expr.expr);
2428        c_expr.expr &:= "*/\n\n";
2429      end if;
2430    else
2431      c_expr.expr &:= "/* declare inline o_";
2432      create_name2(function, c_expr.expr);
2433      c_expr.expr &:= "*/\n\n";
2434    end if;
2435  end func;
2436
2437
2438const proc: process_library_initialisation (in reference: current_object,
2439    inout expr_type: c_expr) is func
2440
2441  local
2442    var string: libraryName is "";
2443  begin
2444    libraryName := name(prog);
2445    c_expr.expr &:= "void init_";
2446    c_expr.expr &:= libraryName;
2447    c_expr.expr &:= " (void)\n";
2448    c_expr.expr &:= "{\n";
2449    c_expr.expr &:= "init_values();\n";
2450    c_expr.expr &:= "init_globals();\n";
2451    c_expr.expr &:= "}\n";
2452    c_expr.expr &:= "\n";
2453    prototype_declared @:= [current_object] TRUE;
2454    count_declarations(c_expr);
2455  end func;
2456
2457
2458const proc: process_main_declaration (in reference: current_object,
2459    inout expr_type: c_expr) is func
2460
2461  local
2462    var expr_type: c_local_vars is expr_type.value;
2463    var expr_type: c_func_body is expr_type.value;
2464    var string: main_prolog is "";
2465    var string: main_epilog is "";
2466  begin
2467    if category(current_object) = BLOCKOBJECT then
2468      function_declared @:= [current_object] TRUE;
2469      process_local_consts(current_object, c_expr);
2470      c_local_vars.temp_num := c_expr.temp_num;
2471      process_local_var_declaration(current_object, c_local_vars);
2472      currentProfiledFunction := main_object;
2473      c_func_body.temp_num := c_local_vars.temp_num;
2474      process_expr(body(current_object), c_func_body);
2475      c_expr.temp_num := c_func_body.temp_num;
2476    elsif category(current_object) = ACTOBJECT then
2477      currentProfiledFunction := main_object;
2478      c_func_body.temp_num := c_local_vars.temp_num;
2479      process_expr(current_object, c_func_body);
2480      c_expr.temp_num := c_func_body.temp_num;
2481    end if;
2482    c_expr.currentFile := file(current_object);
2483    c_expr.currentLine := line(current_object);
2484    if ccConf.USE_WMAIN then
2485      main_prolog := "int wmain (int argc, wchar_t **argv)\n";
2486    elsif ccConf.USE_WINMAIN then
2487      main_prolog := "int WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, char *lpCmdLine, int nShowCmd)\n";
2488    else
2489      main_prolog := "int main (int argc, char **argv)\n";
2490    end if;
2491    main_prolog &:= "\n";
2492    main_prolog &:= "{\n";
2493    main_prolog &:= "int fail_value;\n";
2494    main_prolog &:= "catch_stack_pos = 0;\n";
2495    main_prolog &:= "max_catch_stack = 128;\n";
2496    if trace_function then
2497      main_prolog &:= "printf(\"-> main\\n\");\n";
2498      main_prolog &:= "fflush(stdout);\n";
2499    end if;
2500    if profile_function then
2501      main_prolog &:= "initProfile();\n";
2502      profiledFunctions @:= [objNumber(main_object)] main_object;
2503      main_prolog &:= "profile[";
2504      main_prolog &:= str(objNumber(main_object));
2505      main_prolog &:= "].count++;\n";
2506      main_prolog &:= "if (profile[";
2507      main_prolog &:= str(objNumber(main_object));
2508      main_prolog &:= "].depth == 0) {\n";
2509      main_prolog &:= "  profile[";
2510      main_prolog &:= str(objNumber(main_object));
2511      main_prolog &:= "].time -= timMicroSec();\n";
2512      main_prolog &:= "}\n";
2513      main_prolog &:= "profile[";
2514      main_prolog &:= str(objNumber(main_object));
2515      main_prolog &:= "].depth++;\n";
2516    end if;
2517    main_prolog &:= "catch_stack = (catch_type *)(malloc(max_catch_stack * sizeof(catch_type)));\n";
2518    main_prolog &:= "if ((fail_value = do_setjmp(catch_stack[catch_stack_pos])) == 0) {\n";
2519    main_prolog &:= "setupStack();\n";
2520    main_prolog &:= "setupRand();\n";
2521    main_prolog &:= "setupFiles();\n";
2522    if ccConf.USE_WINMAIN then
2523      main_prolog &:= "arg_v = getArgv(0, NULL, &arg_0, &programName, &programPath);\n";
2524    else
2525      main_prolog &:= "arg_v = getArgv(argc, argv, &arg_0, &programName, &programPath);\n";
2526    end if;
2527    main_prolog &:= "setupFloat();\n";
2528    main_prolog &:= "setupBig();\n";
2529    main_prolog &:= "init_values();\n";
2530    main_prolog &:= "setupSignalHandlers(1, " <& ord(trace_signal) <&  ", " <&
2531                                         ord(ccConf.OVERFLOW_SIGNAL <> "") <&
2532                                         ", 1, NULL);\n";
2533    main_prolog &:= "init_globals();\n";
2534    main_prolog &:= "{\n";
2535
2536    if ccConf.USE_WINMAIN then
2537      c_expr.expr &:= "typedef struct {\n";
2538      c_expr.expr &:= "    int dummy;\n";
2539      c_expr.expr &:= "  } HINSTANCE__;\n";
2540      c_expr.expr &:= "typedef HINSTANCE__* HINSTANCE;\n";
2541      c_expr.expr &:= "\n";
2542    end if;
2543    appendWithDiagnostic(main_prolog, c_expr);
2544    c_expr.expr &:= c_local_vars.temp_decls;
2545    appendWithDiagnostic(c_func_body.temp_decls, c_expr);
2546    c_expr.expr &:= c_local_vars.temp_assigns;
2547    appendWithDiagnostic(c_func_body.temp_assigns, c_expr);
2548    c_expr.expr &:= c_func_body.expr;
2549    appendWithDiagnostic(c_local_vars.temp_frees, c_expr);
2550    appendWithDiagnostic(c_func_body.temp_frees, c_expr);
2551    c_expr.expr &:= "}\n";
2552    c_expr.expr &:= global_init.temp_frees;
2553
2554    if profile_function then
2555      main_epilog &:= "profile[";
2556      main_epilog &:= str(objNumber(main_object));
2557      main_epilog &:= "].depth--;\n";
2558      main_epilog &:= "if (profile[";
2559      main_epilog &:= str(objNumber(main_object));
2560      main_epilog &:= "].depth == 0) {\n";
2561      main_epilog &:= "  profile[";
2562      main_epilog &:= str(objNumber(main_object));
2563      main_epilog &:= "].time += timMicroSec();\n";
2564      main_epilog &:= "}\n";
2565      main_epilog &:= "{\n";
2566      main_epilog &:= "  FILE *profile_file;\n";
2567      main_epilog &:= "  int index;\n";
2568      main_epilog &:= "  profile_file = fopen(\"profile_out\", \"wb\");\n";
2569      main_epilog &:= "  if (profile_file != NULL) {\n";
2570      main_epilog &:= "    qsort(profile, profile_size, sizeof(struct profileElement),\n";
2571      main_epilog &:= "          cmpProfileElement);\n";
2572      main_epilog &:= "    fprintf(profile_file, \"usecs\\tcalls\\tplace\\tname\\n\");\n";
2573      main_epilog &:= "    for (index = 0; index < profile_size; index++) {\n";
2574      main_epilog &:= "      if (profile[index].count != 0) {\n";
2575      main_epilog &:= "        if (profile[index].depth == 0) {\n";
2576      main_epilog &:= "          fprintf(profile_file, \"%ld\\t%ld\\t%s(%lu)\\t%s\\n\",\n";
2577      main_epilog &:= "                  (long) profile[index].time, (long) profile[index].count,\n";
2578      main_epilog &:= "                  profile[index].file, (long unsigned) profile[index].line,\n";
2579      main_epilog &:= "                  profile[index].name);\n";
2580      main_epilog &:= "        } else {\n";
2581      main_epilog &:= "          fprintf(profile_file, \"*%ld\\t%ld\\t%s(%lu)\\t%s\\n\",\n";
2582      main_epilog &:= "                  (long) (profile[index].time + timMicroSec()), (long) profile[index].count,\n";
2583      main_epilog &:= "                  profile[index].file, (long unsigned) profile[index].line,\n";
2584      main_epilog &:= "                  profile[index].name);\n";
2585      main_epilog &:= "        }\n";
2586      main_epilog &:= "      }\n";
2587      main_epilog &:= "    }\n";
2588      main_epilog &:= "    fclose(profile_file);\n";
2589      main_epilog &:= "  }\n";
2590      main_epilog &:= "}\n";
2591    end if;
2592    if trace_function then
2593      main_epilog &:= "printf(\"<- main\\n\");\n";
2594      main_epilog &:= "fflush(stdout);\n";
2595    end if;
2596    main_epilog &:= "return 0;\n";
2597    main_epilog &:= "} else {\n";
2598    main_epilog &:= "  printf(\"\\n*** Uncaught exception \");\n";
2599    main_epilog &:= "  if (fail_value >= 0 && fail_value < sizeof(exception_name) / sizeof(char *)) {\n";
2600    main_epilog &:= "    printf(\"%s\", exception_name[fail_value]);\n";
2601    main_epilog &:= "  } else {\n";
2602    main_epilog &:= "    printf(\"%d\", fail_value);\n";
2603    main_epilog &:= "  }\n";
2604    main_epilog &:= "  printf(\" raised\");\n";
2605    main_epilog &:= "  if (error_file != NULL) {\n";
2606    main_epilog &:= "    printf(\" at %s(%d)\", error_file, error_line);\n";
2607    main_epilog &:= "  }\n";
2608    main_epilog &:= "  printf(\"\\n\");\n";
2609    if databaseLibraryUsed then
2610      main_epilog &:= "  if (fail_value == 6 /*DATABASE_ERROR*/) {\n";
2611      main_epilog &:= "    striType message;\n";
2612      main_epilog &:= "    message = sqlErrMessage();\n";
2613      main_epilog &:= "    printf(\"\\nMessage from the DATABASE_ERROR exception:\\n\");\n";
2614      if consoleLibraryUsed then
2615        main_epilog &:= "    conWrite(message);\n";
2616      else
2617        main_epilog &:= "    ut8Write(&stdoutFileRecord, message);\n";
2618      end if;
2619      main_epilog &:= "    printf(\"\\n\");\n";
2620      main_epilog &:= "    strDestr(message);\n";
2621      main_epilog &:= "  }\n";
2622    end if;
2623    main_epilog &:= "  return 1;\n";
2624    main_epilog &:= "}\n";
2625    main_epilog &:= "}\n";
2626
2627    appendWithDiagnostic(main_epilog, c_expr);
2628    c_expr.expr &:= noDiagnosticLine;
2629    c_expr.expr &:= "\n";
2630    prototype_declared @:= [current_object] TRUE;
2631    count_declarations(c_expr);
2632  end func;
2633
2634
2635const proc: process_var_func_declaration (in reference: function,
2636    inout expr_type: c_expr) is func
2637
2638  local
2639    var expr_type: c_value is expr_type.value;
2640    var string: valueName is "";
2641  begin
2642    declare_type_if_necessary(getType(function), global_c_expr);
2643    create_name(function, objNumber(function), valueName);
2644    processFuncValue(valueName, getType(function), function, c_value);
2645    c_expr.expr &:= c_value.temp_decls;
2646    global_init.expr &:= diagnosticLine(function);
2647    global_init.expr &:= c_value.temp_assigns;
2648    c_expr.expr &:= type_name(getType(function));
2649    c_expr.expr &:= " o_";
2650    create_name(function, c_expr.expr);
2651    c_expr.expr &:= " = ";
2652    c_expr.expr &:= c_value.expr;
2653    c_expr.expr &:= ";\n\n";
2654    function_declared @:= [function] TRUE;
2655    function_var_declared @:= [function] TRUE;
2656  end func;
2657
2658
2659const proc: process_func_declaration (in reference: function,
2660    inout expr_type: c_expr) is func
2661
2662  begin
2663    if isVar(function) then
2664      process_var_func_declaration(function, c_expr);
2665    else
2666      process_const_func_declaration(function, c_expr);
2667    end if;
2668  end func;
2669
2670
2671const proc: process_prototype_declaration (in reference: current_object,
2672    inout expr_type: c_expr) is func
2673
2674  local
2675    var expr_type: c_param_list is expr_type.value;
2676    var type: current_type is void;
2677    var type: result_type is void;
2678    var ref_list: param_list is ref_list.EMPTY;
2679  begin
2680    current_type := getType(current_object);
2681    if isFunc(current_type) or isVarfunc(current_type) then
2682      result_type := resultType(current_type);
2683      param_list := formalParams(current_object);
2684      function_declared @:= [current_object] TRUE;
2685      declare_types_of_params(param_list, global_c_expr);
2686      c_expr.expr &:= "static ";
2687      c_expr.expr &:= type_name(result_type);
2688      if isVarfunc(current_type) then
2689        c_expr.expr &:= " *o_";
2690      else
2691        c_expr.expr &:= " o_";
2692      end if;
2693      create_name(current_object, c_expr.expr);
2694      c_expr.expr &:= " (";
2695      process_param_list_declaration(param_list, c_param_list);
2696      c_expr.expr &:= c_param_list.expr;
2697      c_expr.expr &:= ");\n\n";
2698    else
2699      c_expr.expr &:= "extern ";
2700      c_expr.expr &:= type_name(current_type);
2701      c_expr.expr &:= " o_";
2702      create_name(current_object, c_expr.expr);
2703      c_expr.expr &:= ";\n\n";
2704    end if;
2705  end func;
2706
2707
2708const proc: process_forward_declaration (in reference: fwd_ref,
2709    inout expr_type: c_expr) is func
2710
2711  local
2712    var reference: function is NIL;
2713  begin
2714    function := getValue(fwd_ref, reference);
2715    if function not in prototype_declared then
2716      process_prototype_declaration(function, c_expr);
2717      prototype_declared @:= [function] TRUE;
2718    end if;
2719  end func;
2720
2721
2722const proc: process_type_declaration (in reference: current_object,
2723    inout expr_type: c_expr) is func
2724
2725  local
2726    var type: aType is void;
2727  begin
2728    if isVar(current_object) then
2729      c_expr.expr &:= "typeType o_";
2730      create_name(current_object, c_expr.expr);
2731      c_expr.expr &:= ";\n\n";
2732      global_init.expr &:= diagnosticLine(current_object);
2733      global_init.expr &:= "o_";
2734      create_name(current_object, global_init.expr);
2735      global_init.expr &:= "=";
2736      global_init.expr &:= typeLiteral(getValue(current_object, type));
2737      global_init.expr &:= ";\n";
2738    else
2739      aType := getValue(current_object, type);
2740      declare_type_if_necessary(aType, c_expr);
2741    end if;
2742    count_declarations(c_expr);
2743  end func;
2744
2745
2746const proc: process_int_declaration (in reference: current_object,
2747    inout expr_type: c_expr) is func
2748
2749  begin
2750    if isVar(current_object) then
2751      c_expr.expr &:= "intType o_";
2752      create_name(current_object, c_expr.expr);
2753      c_expr.expr &:= "=";
2754      c_expr.expr &:= integerLiteral(getValue(current_object, integer));
2755      c_expr.expr &:= ";\n\n";
2756      count_declarations(c_expr);
2757    end if;
2758  end func;
2759
2760
2761const proc: process_bigint_declaration (in reference: current_object,
2762    inout expr_type: c_expr) is func
2763
2764  begin
2765    if isVar(current_object) then
2766      c_expr.expr &:= "bigIntType o_";
2767      create_name(current_object, c_expr.expr);
2768      c_expr.expr &:= ";\n\n";
2769      global_init.expr &:= diagnosticLine(current_object);
2770      global_init.expr &:= "o_";
2771      create_name(current_object, global_init.expr);
2772      global_init.expr &:= "=";
2773      process_big_create_call(getValue(current_object, bigInteger), global_init.expr);
2774      count_declarations(c_expr);
2775    end if;
2776  end func;
2777
2778
2779const proc: process_char_declaration (in reference: current_object,
2780    inout expr_type: c_expr) is func
2781
2782  begin
2783    if isVar(current_object) then
2784      c_expr.expr &:= "charType o_";
2785      create_name(current_object, c_expr.expr);
2786      c_expr.expr &:= "=";
2787      c_expr.expr &:= charLiteral(getValue(current_object, char));
2788      c_expr.expr &:= ";\n\n";
2789      count_declarations(c_expr);
2790    end if;
2791  end func;
2792
2793
2794const proc: process_stri_declaration (in reference: current_object,
2795    inout expr_type: c_expr) is func
2796
2797  begin
2798    if isVar(current_object) then
2799      c_expr.expr &:= "striType o_";
2800      create_name(current_object, c_expr.expr);
2801      c_expr.expr &:= ";\n\n";
2802      global_init.expr &:= diagnosticLine(current_object);
2803      global_init.expr &:= "o_";
2804      create_name(current_object, global_init.expr);
2805      global_init.expr &:= "=";
2806      process_str_create_call(getValue(current_object, string), global_init.expr);
2807      count_declarations(c_expr);
2808    end if;
2809  end func;
2810
2811
2812const proc: process_bstri_declaration (in reference: current_object,
2813    inout expr_type: c_expr) is func
2814
2815  begin
2816    if isVar(current_object) then
2817      c_expr.expr &:= "bstriType o_";
2818      create_name(current_object, c_expr.expr);
2819      c_expr.expr &:= ";\n\n";
2820      global_init.expr &:= diagnosticLine(current_object);
2821      global_init.expr &:= "o_";
2822      create_name(current_object, global_init.expr);
2823      global_init.expr &:= "=bstCreate(";
2824      global_init.expr &:= bstriLiteral(getValue(current_object, bstring));
2825      global_init.expr &:= ");\n";
2826      count_declarations(c_expr);
2827    end if;
2828  end func;
2829
2830
2831const proc: process_float_declaration (in reference: current_object,
2832    inout expr_type: c_expr) is func
2833
2834  begin
2835    if isVar(current_object) then
2836      c_expr.expr &:= "floatType o_";
2837      create_name(current_object, c_expr.expr);
2838      c_expr.expr &:= "=";
2839      c_expr.expr &:= floatLiteral(getValue(current_object, float));
2840      c_expr.expr &:= ";\n\n";
2841      count_declarations(c_expr);
2842    end if;
2843  end func;
2844
2845
2846const proc: action_address (in reference: function, inout expr_type: c_expr) is func
2847
2848  local
2849    var ACTION: current_action is action "PRC_NOOP";
2850    var string: action_name is "";
2851    var type: object_type is void;
2852  begin
2853    current_action := getValue(function, ACTION);
2854    action_name := str(current_action);
2855    if action_name = "ARR_CPY" then
2856      object_type := getType(formalParams(function)[1]);
2857      process_generic_cpy_declaration(object_type, global_c_expr);
2858      c_expr.expr &:= "&generic_cpy_";
2859      c_expr.expr &:= str(typeNumber(object_type));
2860    elsif action_name = "ARR_CREATE" then
2861      object_type := getType(formalParams(function)[1]);
2862      typeCategory @:= [object_type] ARRAYOBJECT;
2863      process_generic_create_declaration(object_type, global_c_expr);
2864      c_expr.expr &:= "&generic_create_";
2865      c_expr.expr &:= str(typeNumber(object_type));
2866    elsif action_name = "ARR_DESTR" then
2867      object_type := getType(formalParams(function)[1]);
2868      process_generic_destr_declaration(object_type, global_c_expr);
2869      c_expr.expr &:= "&generic_destr_";
2870      c_expr.expr &:= str(typeNumber(object_type));
2871    elsif action_name = "BIG_CMP" then
2872      c_expr.expr &:= "&bigCmpGeneric";
2873    elsif action_name = "BIG_CPY" then
2874      c_expr.expr &:= "&bigCpyGeneric";
2875    elsif action_name = "BIG_CREATE" then
2876      c_expr.expr &:= "&bigCreateGeneric";
2877    elsif action_name = "BIG_DESTR" then
2878      c_expr.expr &:= "&bigDestrGeneric";
2879    elsif action_name = "BIN_CMP" then
2880      c_expr.expr &:= "&uintCmpGeneric";
2881    elsif action_name = "BLN_CPY" then
2882      c_expr.expr &:= "&genericCpy";
2883    elsif action_name = "BLN_CREATE" then
2884      c_expr.expr &:= "&genericCreate";
2885    elsif action_name = "BST_CMP" then
2886      c_expr.expr &:= "&bstCmpGeneric";
2887    elsif action_name = "BST_CPY" then
2888      c_expr.expr &:= "&bstCpyGeneric";
2889    elsif action_name = "BST_CREATE" then
2890      c_expr.expr &:= "&bstCreateGeneric";
2891    elsif action_name = "BST_DESTR" then
2892      c_expr.expr &:= "&bstDestrGeneric";
2893    elsif action_name = "CHR_CMP" then
2894      c_expr.expr &:= "&chrCmpGeneric";
2895    elsif action_name = "CHR_CPY" then
2896      c_expr.expr &:= "&genericCpy";
2897    elsif action_name = "CHR_CREATE" then
2898      c_expr.expr &:= "&genericCreate";
2899    elsif action_name = "DRW_CMP" then
2900      c_expr.expr &:= "&ptrCmpGeneric";
2901    elsif action_name = "DRW_CPY" then
2902      c_expr.expr &:= "&drwCpyGeneric";
2903    elsif action_name = "DRW_CREATE" then
2904      c_expr.expr &:= "&drwCreateGeneric";
2905    elsif action_name = "DRW_DESTR" then
2906      c_expr.expr &:= "&drwDestrGeneric";
2907    elsif action_name = "ENU_CPY" then
2908      c_expr.expr &:= "&genericCpy";
2909    elsif action_name = "ENU_CREATE" then
2910      c_expr.expr &:= "&genericCreate";
2911    elsif action_name = "FIL_CPY" then
2912      c_expr.expr &:= "&filCpyGeneric";
2913    elsif action_name = "FIL_CREATE" then
2914      c_expr.expr &:= "&filCreateGeneric";
2915    elsif action_name = "FIL_DESTR" then
2916      c_expr.expr &:= "&filDestrGeneric";
2917    elsif action_name = "FLT_CMP" then
2918      c_expr.expr &:= "&fltCmpGeneric";
2919    elsif action_name = "FLT_CPY" then
2920      c_expr.expr &:= "&fltCpyGeneric";
2921    elsif action_name = "FLT_CREATE" then
2922      c_expr.expr &:= "&genericCreate";
2923    elsif action_name = "GEN_DESTR" then
2924      c_expr.expr &:= "&genericDestr";
2925    elsif action_name = "INT_CMP" then
2926      c_expr.expr &:= "&intCmpGeneric";
2927    elsif action_name = "INT_CPY" then
2928      c_expr.expr &:= "&genericCpy";
2929    elsif action_name = "INT_CREATE" then
2930      c_expr.expr &:= "&genericCreate";
2931    elsif action_name = "ITF_CMP" then
2932      c_expr.expr &:= "&ptrCmpGeneric";
2933    elsif action_name = "ITF_CPY" then
2934      object_type := getType(formalParams(function)[1]);
2935      process_generic_cpy_declaration(object_type, global_c_expr);
2936      c_expr.expr &:= "&generic_cpy_";
2937      c_expr.expr &:= str(typeNumber(object_type));
2938    elsif action_name = "ITF_CREATE" then
2939      c_expr.expr &:= "&itfCreateGeneric";
2940    elsif action_name = "ITF_DESTR" then
2941      object_type := getType(formalParams(function)[1]);
2942      process_generic_destr_declaration(object_type, global_c_expr);
2943      c_expr.expr &:= "&generic_destr_";
2944      c_expr.expr &:= str(typeNumber(object_type));
2945    elsif action_name = "PCS_CMP" then
2946      c_expr.expr &:= "&pcsCmpGeneric";
2947    elsif action_name = "PCS_CPY" then
2948      c_expr.expr &:= "&pcsCpyGeneric";
2949    elsif action_name = "PCS_CREATE" then
2950      c_expr.expr &:= "&pcsCreateGeneric";
2951    elsif action_name = "PCS_DESTR" then
2952      c_expr.expr &:= "&pcsDestrGeneric";
2953    elsif action_name = "PRC_NOOP" then
2954      c_expr.expr &:= "&prcNoop";
2955    elsif action_name = "REF_CMP" then
2956      c_expr.expr &:= "&ptrCmpGeneric";
2957    elsif action_name = "REF_CPY" then
2958      c_expr.expr &:= "&ptrCpyGeneric";
2959    elsif action_name = "REF_CREATE" then
2960      c_expr.expr &:= "&ptrCreateGeneric";
2961    elsif action_name = "RFL_CMP" then
2962      c_expr.expr &:= "&rflCmpGeneric";
2963    elsif action_name = "RFL_CPY" then
2964      c_expr.expr &:= "&rflCpyGeneric";
2965    elsif action_name = "RFL_CREATE" then
2966      c_expr.expr &:= "&rflCreateGeneric";
2967    elsif action_name = "RFL_DESTR" then
2968      c_expr.expr &:= "&rflDestrGeneric";
2969    elsif action_name = "SCT_CPY" then
2970      object_type := getType(formalParams(function)[1]);
2971      process_generic_cpy_declaration(object_type, global_c_expr);
2972      c_expr.expr &:= "&generic_cpy_";
2973      c_expr.expr &:= str(typeNumber(object_type));
2974    elsif action_name = "SCT_CREATE" then
2975      object_type := getType(formalParams(function)[1]);
2976      typeCategory @:= [object_type] STRUCTOBJECT;
2977      process_generic_create_declaration(object_type, global_c_expr);
2978      c_expr.expr &:= "&generic_create_";
2979      c_expr.expr &:= str(typeNumber(object_type));
2980    elsif action_name = "SCT_DESTR" then
2981      object_type := getType(formalParams(function)[1]);
2982      process_generic_destr_declaration(object_type, global_c_expr);
2983      c_expr.expr &:= "&generic_destr_";
2984      c_expr.expr &:= str(typeNumber(object_type));
2985    elsif action_name = "SET_CMP" then
2986      c_expr.expr &:= "&setCmpGeneric";
2987    elsif action_name = "SET_CPY" then
2988      c_expr.expr &:= "&setCpyGeneric";
2989    elsif action_name = "SET_CREATE" then
2990      c_expr.expr &:= "&setCreateGeneric";
2991    elsif action_name = "SET_DESTR" then
2992      c_expr.expr &:= "&setDestrGeneric";
2993    elsif action_name = "SQL_CMP_DB" then
2994      c_expr.expr &:= "&ptrCmpGeneric";
2995    elsif action_name = "SQL_CPY_DB" then
2996      c_expr.expr &:= "&sqlCpyDbGeneric";
2997    elsif action_name = "SQL_CREATE_DB" then
2998      c_expr.expr &:= "&sqlCreateDbGeneric";
2999    elsif action_name = "SQL_DESTR_DB" then
3000      c_expr.expr &:= "&sqlDestrDbGeneric";
3001    elsif action_name = "SQL_CMP_STMT" then
3002      c_expr.expr &:= "&ptrCmpGeneric";
3003    elsif action_name = "SQL_CPY_STMT" then
3004      c_expr.expr &:= "&sqlCpyStmtGeneric";
3005    elsif action_name = "SQL_CREATE_STMT" then
3006      c_expr.expr &:= "&sqlCreateStmtGeneric";
3007    elsif action_name = "SQL_DESTR_STMT" then
3008      c_expr.expr &:= "&sqlDestrStmtGeneric";
3009    elsif action_name = "STR_CMP" then
3010      c_expr.expr &:= "&strCmpGeneric";
3011    elsif action_name = "STR_CPY" then
3012      c_expr.expr &:= "&strCpyGeneric";
3013    elsif action_name = "STR_CREATE" then
3014      c_expr.expr &:= "&strCreateGeneric";
3015    elsif action_name = "STR_DESTR" then
3016      c_expr.expr &:= "&strDestrGeneric";
3017    elsif action_name = "TYP_CMP" then
3018      c_expr.expr &:= "&typCmpGeneric";
3019    elsif action_name = "TYP_CPY" then
3020      c_expr.expr &:= "&ptrCpyGeneric";
3021    elsif action_name = "TYP_CREATE" then
3022      c_expr.expr &:= "&ptrCreateGeneric";
3023    elsif action_name = "TYP_DESTR" then
3024      c_expr.expr &:= "&genericDestr";
3025    else
3026      c_expr.expr &:= "NULL /* ACTOBJECT { ";
3027      c_expr.expr &:= action_name;
3028      c_expr.expr &:= " }*/";
3029    end if;
3030  end func;
3031
3032
3033const proc: block_address (in reference: function, inout expr_type: c_expr) is func
3034
3035  local
3036    var ref_list: formal_params is ref_list.EMPTY;
3037    var reference: formal_param is NIL;
3038    var type: object_type is void;
3039    var boolean: address_written is FALSE;
3040  begin
3041    formal_params := formalParams(function);
3042    if length(formal_params) = 3 and category(formal_params[2]) = SYMBOLOBJECT and
3043        str(formal_params[2]) = ":=" then
3044      formal_param := formal_params[1];
3045      object_type := getType(formal_param);
3046      process_generic_cpy_declaration(object_type, global_c_expr);
3047      c_expr.expr &:= "&generic_cpy_";
3048      c_expr.expr &:= str(typeNumber(object_type));
3049      address_written := TRUE;
3050    elsif length(formal_params) = 3 and category(formal_params[2]) = SYMBOLOBJECT and
3051        str(formal_params[2]) = "::=" then
3052      formal_param := formal_params[1];
3053      object_type := getType(formal_param);
3054      process_generic_create_declaration(object_type, global_c_expr);
3055      c_expr.expr &:= "&generic_create_";
3056      c_expr.expr &:= str(typeNumber(object_type));
3057      address_written := TRUE;
3058    elsif length(formal_params) = 2 and category(formal_params[2]) = SYMBOLOBJECT and
3059        str(formal_params[2]) = "destroy" then
3060      formal_param := formal_params[1];
3061      object_type := getType(formal_param);
3062      process_generic_destr_declaration(object_type, global_c_expr);
3063      c_expr.expr &:= "&generic_destr_";
3064      c_expr.expr &:= str(typeNumber(object_type));
3065      address_written := TRUE;
3066    elsif length(formal_params) = 3 and category(formal_params[3]) = SYMBOLOBJECT and
3067        str(formal_params[3]) = "compare" then
3068      formal_param := formal_params[1];
3069      object_type := getType(formal_param);
3070      process_generic_cmp_declaration(function, object_type, global_c_expr);
3071      c_expr.expr &:= "&generic_cmp_";
3072      c_expr.expr &:= str(typeNumber(object_type));
3073      address_written := TRUE;
3074    end if;
3075    if not address_written then
3076      c_expr.expr &:= "&o_";
3077      create_name(function, c_expr.expr);
3078    end if;
3079  end func;
3080
3081
3082const proc: object_address (in reference: curr_expr, inout expr_type: c_expr) is func
3083
3084  local
3085    var category: exprCategory is category.value;
3086  begin
3087    if curr_expr = NIL then
3088      c_expr.expr &:= "NULL";
3089    else
3090      exprCategory := category(curr_expr);
3091      if exprCategory = ACTOBJECT then
3092        action_address(curr_expr, c_expr);
3093      elsif exprCategory = BLOCKOBJECT then
3094        block_address(curr_expr, c_expr);
3095      else
3096        c_expr.expr &:= "/* ";
3097        c_expr.expr &:= str(exprCategory);
3098        c_expr.expr &:= " */";
3099        block
3100          c_expr.expr &:= "&(";
3101          process_expr(curr_expr, c_expr);
3102          c_expr.expr &:= ")";
3103        exception
3104          catch RANGE_ERROR:
3105            c_expr.expr &:= "/*RANGE_ERROR*/";
3106            writeln("] ");
3107            TRACE(curr_expr);
3108            writeln;
3109        end block;
3110      end if;
3111    end if;
3112  end func;
3113
3114
3115const proc: process_reference_declaration (in reference: current_object,
3116    inout expr_type: c_expr) is func
3117
3118  begin
3119    (* if isVar(current_object) then *)
3120      c_expr.expr &:= "/* ";
3121      c_expr.expr &:= type_name2(getType(current_object));
3122      c_expr.expr &:= " */ ";
3123      if useFunctype(current_object) then
3124        c_expr.expr &:= "intfunctype o_";
3125      else
3126        c_expr.expr &:= "objRefType o_";
3127      end if;
3128      create_name(current_object, c_expr.expr);
3129      c_expr.expr &:= "=";
3130      if useFunctype(current_object) then
3131        c_expr.expr &:= "(intfunctype)(";
3132      else
3133        c_expr.expr &:= "(objRefType)(";
3134      end if;
3135      object_address(getValue(current_object, reference), c_expr);
3136      c_expr.expr &:= ");\n\n";
3137      function_pointer_declared @:= [current_object] TRUE;
3138      count_declarations(c_expr);
3139    (* end if; *)
3140  end func;
3141
3142
3143const proc: process_ref_list_declaration (in reference: current_object,
3144    inout expr_type: c_expr) is func
3145
3146  local
3147    var ref_list: refListValue is ref_list.EMPTY;
3148    var integer: index is 0;
3149  begin
3150    refListValue := getValue(current_object, ref_list);
3151    for index range length(refListValue) downto 1 do
3152      c_expr.expr &:= "struct listStruct rec_";
3153      c_expr.expr &:= str(objNumber(current_object));
3154      c_expr.expr &:= "_";
3155      c_expr.expr &:= str(index);
3156      c_expr.expr &:= "={";
3157      if index = length(refListValue) then
3158        c_expr.expr &:= "NULL";
3159      else
3160        c_expr.expr &:= "&rec_";
3161        c_expr.expr &:= str(objNumber(current_object));
3162        c_expr.expr &:= "_";
3163        c_expr.expr &:= str(succ(index));
3164      end if;
3165      c_expr.expr &:= ", (objRefType) &(";
3166      process_expr(refListValue[index], c_expr);
3167      c_expr.expr &:= ")};\n";
3168    end for;
3169    c_expr.expr &:= "\n";
3170    c_expr.expr &:= type_name(getType(current_object));
3171    c_expr.expr &:= " o_";
3172    create_name(current_object, c_expr.expr);
3173    c_expr.expr &:= "=";
3174    if length(refListValue) = 0 then
3175      c_expr.expr &:= "NULL";
3176    else
3177      c_expr.expr &:= "&rec_";
3178      c_expr.expr &:= str(objNumber(current_object));
3179      c_expr.expr &:= "_1";
3180    end if;
3181    c_expr.expr &:= ";\n\n";
3182    count_declarations(c_expr);
3183  end func;
3184
3185
3186const proc: process_file_declaration (in reference: current_object,
3187    inout expr_type: c_expr) is func
3188
3189  begin
3190    c_expr.expr &:= "fileType o_";
3191    create_name(current_object, c_expr.expr);
3192    c_expr.expr &:= "=&";
3193    c_expr.expr &:= lower(literal(getValue(current_object, clib_file)));
3194    c_expr.expr &:= "FileRecord;\n\n";
3195    count_declarations(c_expr);
3196  end func;
3197
3198
3199const proc: process_socket_declaration (in reference: current_object,
3200    inout expr_type: c_expr) is func
3201
3202  begin
3203    c_expr.expr &:= "socketType o_";
3204    create_name(current_object, c_expr.expr);
3205    c_expr.expr &:= " = (socketType) -1;\n\n";
3206    count_declarations(c_expr);
3207  end func;
3208
3209
3210const proc: process_poll_declaration (in reference: current_object,
3211    inout expr_type: c_expr) is func
3212
3213  begin
3214    c_expr.expr &:= "pollType o_";
3215    create_name(current_object, c_expr.expr);
3216    c_expr.expr &:= ";\n\n";
3217    count_declarations(c_expr);
3218  end func;
3219
3220
3221const proc: process_array_declaration (in reference: current_object,
3222    inout expr_type: c_expr) is func
3223
3224  local
3225    var string: param_value is "";
3226  begin
3227    typeCategory @:= [getType(current_object)] ARRAYOBJECT;
3228    if isVar(current_object) then
3229      c_expr.expr &:= type_name(getType(current_object));
3230      c_expr.expr &:= " o_";
3231      create_name(current_object, c_expr.expr);
3232      c_expr.expr &:= ";\n\n";
3233      if current_object not in const_table then
3234        const_table @:= [current_object] length(const_table);
3235      end if;
3236      global_init.expr &:= diagnosticLine(current_object);
3237      global_init.expr &:= "o_";
3238      create_name(current_object, global_init.expr);
3239      global_init.expr &:= "=";
3240      param_value := "(";
3241      param_value &:= type_name(getType(current_object));
3242      param_value &:= ")(arr[";
3243      param_value &:= str(const_table[current_object]);
3244      param_value &:= "])";
3245      process_create_declaration(getType(current_object), global_c_expr);
3246      process_create_call(getType(current_object),
3247          param_value, global_init.expr);
3248      global_init.expr &:= ";\n";
3249      count_declarations(c_expr);
3250    end if;
3251  end func;
3252
3253
3254const proc: process_hash_declaration (in reference: current_object,
3255    inout expr_type: c_expr) is func
3256
3257  local
3258    var string: param_value is "";
3259  begin
3260    typeCategory @:= [getType(current_object)] HASHOBJECT;
3261    c_expr.expr &:= type_name(getType(current_object));
3262    c_expr.expr &:= " o_";
3263    create_name(current_object, c_expr.expr);
3264    c_expr.expr &:= ";\n\n";
3265    if current_object not in const_table then
3266      const_table @:= [current_object] length(const_table);
3267    end if;
3268    global_init.expr &:= diagnosticLine(current_object);
3269    global_init.expr &:= "o_";
3270    create_name(current_object, global_init.expr);
3271    global_init.expr &:= "=";
3272    param_value := "(";
3273    param_value &:= type_name(getType(current_object));
3274    param_value &:= ")(hsh[";
3275    param_value &:= str(const_table[current_object]);
3276    param_value &:= "])";
3277    if isVar(current_object) then
3278      process_create_declaration(getType(current_object), global_c_expr);
3279      process_create_call(getType(current_object),
3280          param_value, global_init.expr);
3281    else
3282      global_init.expr &:= param_value;
3283    end if;
3284    global_init.expr &:= ";\n";
3285    count_declarations(c_expr);
3286  end func;
3287
3288
3289const proc: process_set_declaration (in reference: current_object,
3290    inout expr_type: c_expr) is func
3291
3292  begin
3293    if isVar(current_object) then
3294      c_expr.expr &:= type_name(getType(current_object));
3295      c_expr.expr &:= " o_";
3296      create_name(current_object, c_expr.expr);
3297      c_expr.expr &:= ";\n\n";
3298      global_init.expr &:= diagnosticLine(current_object);
3299      global_init.expr &:= "o_";
3300      create_name(current_object, global_init.expr);
3301      global_init.expr &:= "=setCreate(";
3302      global_init.expr &:= bitsetLiteral(getValue(current_object, bitset));
3303      global_init.expr &:= ");\n";
3304      count_declarations(c_expr);
3305    end if;
3306  end func;
3307
3308
3309const proc: process_struct_declaration (in reference: current_object,
3310    inout expr_type: c_expr) is func
3311
3312  local
3313    var string: param_value is "";
3314    var string: init_expr is "";
3315  begin
3316    declare_type_if_necessary(getType(current_object), c_expr);
3317    c_expr.expr &:= type_name(getType(current_object));
3318    c_expr.expr &:= " o_";
3319    create_name(current_object, c_expr.expr);
3320    c_expr.expr &:= ";\n\n";
3321    if current_object not in const_table then
3322      const_table @:= [current_object] length(const_table);
3323    end if;
3324    init_expr &:= diagnosticLine(current_object);
3325    init_expr &:= "o_";
3326    create_name(current_object, init_expr);
3327    init_expr &:= "=";
3328    param_value := "(";
3329    param_value &:= type_name(getType(current_object));
3330    param_value &:= ")(sct[";
3331    param_value &:= str(const_table[current_object]);
3332    param_value &:= "])";
3333    if isVar(current_object) then
3334      process_create_declaration(getType(current_object), global_c_expr);
3335      process_create_call(getType(current_object),
3336          param_value, init_expr);
3337    else
3338      init_expr &:= param_value;
3339    end if;
3340    init_expr &:= ";\n";
3341    if current_object in globalInitalisations then
3342      globalInitalisations @:= [current_object] globalInitalisations[current_object] & init_expr;
3343    else
3344      globalInitalisations @:= [current_object] init_expr;
3345    end if;
3346    count_declarations(c_expr);
3347  end func;
3348
3349
3350const proc: process_interface_declaration (in reference: current_object,
3351    inout expr_type: c_expr) is func
3352
3353  local
3354    var reference: object_value is NIL;
3355    var category: valueCategory is category.value;
3356  begin
3357    c_expr.expr &:= type_name(getType(current_object));
3358    c_expr.expr &:= " o_";
3359    create_name(current_object, c_expr.expr);
3360    c_expr.expr &:= ";\n\n";
3361    object_value := interfaceToStruct(current_object);
3362    valueCategory := category(object_value);
3363    if current_object not in const_table then
3364      const_table @:= [current_object] length(const_table);
3365    end if;
3366    global_init.expr &:= diagnosticLine(current_object);
3367    global_init.expr &:= "o_";
3368    create_name(current_object, global_init.expr);
3369    global_init.expr &:= "=(";
3370    global_init.expr &:= type_name(getType(current_object));
3371    global_init.expr &:= ")(itfCreate(itf[";
3372    global_init.expr &:= str(const_table[current_object]);
3373    global_init.expr &:= "]));\n";
3374    count_declarations(c_expr);
3375  end func;
3376
3377
3378const proc: process_win_declaration (in reference: current_object,
3379    inout expr_type: c_expr) is func
3380
3381  begin
3382    if isVar(current_object) then
3383      c_expr.expr &:= "winType o_";
3384      create_name(current_object, c_expr.expr);
3385      c_expr.expr &:= ";\n\n";
3386      global_init.expr &:= diagnosticLine(current_object);
3387      global_init.expr &:= "o_";
3388      create_name(current_object, global_init.expr);
3389      global_init.expr &:= "=drwCreate(";
3390      global_init.expr &:= windowLiteral(getValue(current_object, PRIMITIVE_WINDOW));
3391      global_init.expr &:= ");\n";
3392      count_declarations(c_expr);
3393    end if;
3394  end func;
3395
3396
3397const proc: process_process_declaration (in reference: current_object,
3398    inout expr_type: c_expr) is func
3399
3400  begin
3401    if isVar(current_object) then
3402      c_expr.expr &:= "processType o_";
3403      create_name(current_object, c_expr.expr);
3404      c_expr.expr &:= "=NULL;\n\n";
3405      count_declarations(c_expr);
3406    end if;
3407  end func;
3408
3409
3410const proc: process_prog_declaration (in reference: current_object,
3411    inout expr_type: c_expr) is func
3412
3413  begin
3414    if isVar(current_object) then
3415      c_expr.expr &:= "progType o_";
3416      create_name(current_object, c_expr.expr);
3417      c_expr.expr &:= "=NULL;\n\n";
3418      count_declarations(c_expr);
3419    end if;
3420  end func;
3421
3422
3423const proc: process_enum_declaration (in reference: current_object,
3424    inout expr_type: c_expr) is func
3425
3426  begin
3427    if isVar(current_object) or not isFunc(getType(current_object)) then
3428      if getType(current_object) = voidtype then
3429        c_expr.expr &:= "/* do not declare void variable or constant o_";
3430        create_name2(current_object, c_expr.expr);
3431        c_expr.expr &:= " */\n\n";
3432      else
3433        if not isVar(current_object) then
3434          c_expr.expr &:= "const ";
3435        end if;
3436        declare_type_if_necessary(getType(current_object), c_expr);
3437        c_expr.expr &:= type_name(getType(current_object));
3438        c_expr.expr &:= " o_";
3439        create_name(current_object, c_expr.expr);
3440        c_expr.expr &:= "=";
3441        c_expr.expr &:= enum_value(getValue(current_object, reference));
3442        c_expr.expr &:= ";\n\n";
3443      end if;
3444    end if;
3445    count_declarations(c_expr);
3446  end func;
3447
3448
3449const proc: process_enum_literal_declaration (in reference: current_object,
3450    inout expr_type: c_expr) is func
3451
3452  local
3453    var type: enum_type is void;
3454  begin
3455    enum_type := getType(current_object);
3456    if enum_type = voidtype then
3457      c_expr.expr &:= "/* do not declare: void o_4_empty */\n\n";
3458    else
3459      if enum_type not in enum_literal then
3460        enum_literal @:= [enum_type] element_number_hash.EMPTY_HASH;
3461      end if;
3462      if current_object not in enum_literal[enum_type] then
3463        enum_literal[enum_type] @:= [current_object] length(enum_literal[enum_type]);
3464      end if;
3465      c_expr.expr &:= "const ";
3466      declare_type_if_necessary(enum_type, c_expr);
3467      c_expr.expr &:= type_name(enum_type);
3468      c_expr.expr &:= " o_";
3469      create_name(current_object, c_expr.expr);
3470      c_expr.expr &:= "=";
3471      c_expr.expr &:= enum_value(current_object);
3472      c_expr.expr &:= ";\n\n";
3473    end if;
3474    count_declarations(c_expr);
3475  end func;
3476
3477
3478const proc: print_parameter_list (in ref_list: formal_params,
3479    inout expr_type: c_expr) is func
3480
3481  local
3482    var reference: formal_param is NIL;
3483    var category: paramCategory is category.value;
3484    var boolean: first_element is TRUE;
3485    var type: param_type is void;
3486    var type: implementationType is void;
3487  begin
3488    for formal_param range formal_params do
3489      paramCategory := category(formal_param);
3490      if paramCategory <> SYMBOLOBJECT then
3491        if first_element then
3492          first_element := FALSE;
3493        else
3494          c_expr.expr &:= " printf(\", \");\n";
3495        end if;
3496        param_type := getType(formal_param);
3497        if param_type in implements then
3498          c_expr.expr &:= " /*# ";
3499          for implementationType range implements[param_type] do
3500            c_expr.expr &:= type_name2(implementationType);
3501            c_expr.expr &:= "  ";
3502          end for;
3503          c_expr.expr &:= " */ ";
3504        end if;
3505        c_expr.expr &:= "printf(";
3506        c_expr.expr &:= c_literal(str(paramCategory) & " ");
3507        c_expr.expr &:= "); ";
3508        if param_type in typeCategory then
3509          case typeCategory[param_type] of
3510            when {INTOBJECT}:
3511              c_expr.expr &:= "printf(\"intType \"); ";
3512              c_expr.expr &:= "printf(\"%ld\", ";
3513            when {FLOATOBJECT}:
3514              c_expr.expr &:= "printf(\"floatType \"); ";
3515              c_expr.expr &:= "printf(\"%f\", ";
3516            when {CHAROBJECT}:
3517              c_expr.expr &:= "printf(\"charType \"); ";
3518              c_expr.expr &:= "printf(\"%c\", ";
3519            when {STRIOBJECT}:
3520              c_expr.expr &:= "printf(\"striType \"); ";
3521              c_expr.expr &:= "filPrint(";
3522            when {TYPEOBJECT}:
3523              c_expr.expr &:= "printf(\"typeType \"); ";
3524              c_expr.expr &:= "printf(\"%X\", ";
3525            otherwise:
3526              c_expr.expr &:= "printf(\"";
3527              c_expr.expr &:= type_name(param_type);
3528              c_expr.expr &:= " \"); ";
3529              c_expr.expr &:= "printf(\"%X\", ";
3530          end case;
3531        else
3532          c_expr.expr &:= "printf(\"";
3533          c_expr.expr &:= type_name(param_type);
3534          c_expr.expr &:= " \"); ";
3535          c_expr.expr &:= "printf(\"%X\", ";
3536        end if;
3537        if isPointerParam(formal_param) then
3538          c_expr.expr &:= "(o_";
3539          create_name(formal_param, c_expr.expr);
3540          c_expr.expr &:= "?*o_";
3541          create_name(formal_param, c_expr.expr);
3542          c_expr.expr &:= ":0)";
3543        else
3544          c_expr.expr &:= "o_";
3545          create_name(formal_param, c_expr.expr);
3546        end if;
3547        c_expr.expr &:= ");";
3548      end if;
3549    end for;
3550  end func;
3551
3552
3553const proc: process_dynamic_parameter_list (in reference: function,
3554    in ref_list: actual_params, inout expr_type: c_expr) is func
3555
3556  local
3557    var ref_list: formal_params is ref_list.EMPTY;
3558    var reference: formal_param is NIL;
3559    var reference: actual_param is NIL;
3560    var category: formalCategory is category.value;
3561    var category: paramCategory is category.value;
3562    var boolean: first_element is TRUE;
3563    var integer: number is 0;
3564  begin
3565    formal_params := formalParams(function);
3566    for number range 1 to length(formal_params) do
3567      formal_param := formal_params[number];
3568      actual_param := actual_params[number];
3569      formalCategory := category(formal_param);
3570      paramCategory := category(actual_param);
3571      if paramCategory <> SYMBOLOBJECT and
3572          formalCategory <> SYMBOLOBJECT then
3573        if formalCategory = TYPEOBJECT then
3574          c_expr.expr &:= "/* attr t_";
3575          c_expr.expr &:= str(typeNumber(getValue(formal_param, type)));
3576          c_expr.expr &:= " ";
3577          c_expr.expr &:= str(getValue(formal_param, type));
3578          c_expr.expr &:= "*/ ";
3579        else
3580          if first_element then
3581            first_element := FALSE;
3582          else
3583            c_expr.expr &:= ", ";
3584          end if;
3585          if not isVar(actual_param) and isInOutParam(formal_param) then
3586            c_expr.expr &:= "/* SHOULD NOT HAPPEN &o_";
3587            create_name(actual_param, c_expr.expr);
3588            c_expr.expr &:= " */";
3589          elsif isPointerParam(actual_param) = isPointerParam(formal_param) then
3590            c_expr.expr &:= "o_";
3591            create_name(actual_param, c_expr.expr);
3592          elsif isPointerParam(actual_param) and not isPointerParam(formal_param) then
3593            c_expr.expr &:= "*o_";
3594            create_name(actual_param, c_expr.expr);
3595          else # if isVar(actual_param) or not isInOutParam(formal_param) then
3596            c_expr.expr &:= "&o_";
3597            create_name(actual_param, c_expr.expr);
3598          end if;
3599        end if;
3600      end if;
3601    end for;
3602  end func;
3603
3604
3605const proc: process_dynamic_function_call (in reference: function,
3606    in ref_list: actual_params, in reference: interface_object, inout expr_type: c_expr) is func
3607
3608  local
3609    var expr_type: resultExpr is expr_type.value;
3610  begin
3611    resultExpr.currentFile := file(interface_object);
3612    resultExpr.currentLine := line(interface_object);
3613    resultExpr.expr &:= "o_";
3614    create_name(function, resultExpr.expr);
3615    resultExpr.expr &:= "(";
3616    process_dynamic_parameter_list(function, actual_params, resultExpr);
3617    resultExpr.expr &:= ")";
3618    if function in return_ref_to_value then
3619      c_expr.expr &:= "/* copy ref_to_value */ ";
3620      process_create_declaration(resultType(getType(interface_object)), global_c_expr);
3621      process_create_call(resultType(getType(interface_object)),
3622          resultExpr.expr, c_expr.expr);
3623    else
3624      c_expr.expr &:= resultExpr.expr;
3625    end if;
3626    c_expr.temp_decls &:= resultExpr.temp_decls;
3627    c_expr.temp_assigns &:= resultExpr.temp_assigns;
3628    c_expr.temp_frees &:= resultExpr.temp_frees;
3629    c_expr.temp_to_null &:= resultExpr.temp_to_null;
3630  end func;
3631
3632
3633const proc: process_dynamic_action_call (in reference: function,
3634    in ref_list: actual_params, in reference: interface_object, inout expr_type: c_expr) is func
3635
3636  local
3637    var expr_type: c_action_expr is expr_type.value;
3638  begin
3639    # c_expr.expr &:= "/* ";
3640    # c_expr.expr &:= str(getValue(function, ACTION));
3641    # c_expr.expr &:= " */ ";
3642    c_action_expr.currentFile := file(interface_object);
3643    c_action_expr.currentLine := line(interface_object);
3644    c_action_expr.temp_num := c_expr.temp_num;
3645    process_action(function, actual_params, c_action_expr);
3646    c_expr.temp_num := c_action_expr.temp_num;
3647    c_expr.temp_decls &:= c_action_expr.temp_decls;
3648    c_expr.temp_assigns &:= c_action_expr.temp_assigns;
3649    c_expr.temp_frees &:= c_action_expr.temp_frees;
3650    c_expr.temp_to_null &:= c_action_expr.temp_to_null;
3651    if c_action_expr.result_expr <> "" then
3652      c_expr.expr &:= c_action_expr.result_expr;
3653    else
3654      if isVarfunc(getType(interface_object)) or
3655          getType(interface_object) = proctype then
3656        c_expr.expr &:= c_action_expr.expr;
3657      else
3658        c_expr.expr &:= "/* copy ref_to_value */ ";
3659        process_create_declaration(resultType(getType(interface_object)), global_c_expr);
3660        process_create_call(resultType(getType(interface_object)),
3661            c_action_expr.expr, c_expr.expr);
3662      end if;
3663    end if;
3664  end func;
3665
3666
3667const proc: process_dynamic_call (in reference: function,
3668    in ref_list: actual_params, in reference: interface_object,
3669    inout expr_type: c_expr) is func
3670
3671  local
3672    var category: objectCategory is category.value;
3673    var expr_type: resultExpr is expr_type.value;
3674  begin
3675    if function <> NIL then
3676      c_expr.expr &:= diagnosticLine(interface_object);
3677      objectCategory := category(function);
3678      if objectCategory = BLOCKOBJECT then
3679        if resultType(getType(interface_object)) <> voidtype then
3680          c_expr.expr &:= "return ";
3681        end if;
3682        if function in function_declared or resultVar(function) <> NIL then
3683          process_dynamic_function_call(function, actual_params, interface_object, c_expr);
3684        else
3685          process_inline(function, actual_params, c_expr);
3686        end if;
3687        c_expr.expr &:= ";\n";
3688      elsif objectCategory = ACTOBJECT then
3689        if resultType(getType(interface_object)) <> voidtype then
3690          c_expr.expr &:= "return ";
3691          if isVarfunc(getType(interface_object)) then
3692            c_expr.expr &:= "&(";
3693          end if;
3694        end if;
3695        process_dynamic_action_call(function, actual_params, interface_object, c_expr);
3696        if resultType(getType(interface_object)) <> voidtype then
3697          if isVarfunc(getType(interface_object)) then
3698            c_expr.expr &:= ")";
3699          end if;
3700          c_expr.expr &:= ";\n";
3701        end if;
3702      elsif objectCategory = INTOBJECT or
3703          objectCategory = BIGINTOBJECT or
3704          objectCategory = FLOATOBJECT or
3705          objectCategory = CHAROBJECT or
3706          objectCategory = STRIOBJECT or
3707          objectCategory = BSTRIOBJECT or
3708          objectCategory = ARRAYOBJECT or
3709          objectCategory = STRUCTOBJECT or
3710          objectCategory = SETOBJECT or
3711          objectCategory = WINOBJECT or
3712          objectCategory = PROCESSOBJECT or
3713          objectCategory = CONSTENUMOBJECT then
3714        c_expr.expr &:= "return ";
3715        getAnyParamToExpr(function, resultExpr);
3716        process_create_declaration(getType(function), global_c_expr);
3717        process_create_call(getType(function),
3718            resultExpr.expr, c_expr.expr);
3719        c_expr.expr &:= ";\n";
3720      else
3721        c_expr.expr &:= "/* ";
3722        c_expr.expr &:= str(objectCategory);
3723        c_expr.expr &:= " */\n";
3724      end if;
3725    else
3726      c_expr.expr &:= "/* NOT FOUND */\n";
3727      c_expr.expr &:= diagnosticLine(interface_object);
3728      c_expr.expr &:= "raiseError(ACTION_ERROR);\n";
3729    end if;
3730  end func;
3731
3732
3733const proc: process_dynamic_condition (in reference: current_object,
3734    inout ref_list: formal_params, in var integer: paramNum,
3735    inout expr_type: c_expr) is forward;
3736
3737
3738const proc: process_dynamic_param_implements (in reference: current_object,
3739    inout ref_list: formal_params, in var integer: paramNum,
3740    in type: param_type, inout expr_type: c_expr) is func
3741
3742  local
3743    var reference: formal_param is NIL;
3744    var type: implementationType is void;
3745    var bitset: usedCaseLabels is {};
3746  begin
3747    formal_param := formal_params[paramNum];
3748    c_expr.expr &:= diagnosticLine(current_object);
3749    c_expr.expr &:= "switch (((interfaceType) ";
3750    if isPointerParam(formal_param) then
3751      c_expr.expr &:= "*o_";
3752    else
3753      c_expr.expr &:= "o_";
3754    end if;
3755    create_name(formal_param, c_expr.expr);
3756    c_expr.expr &:= ")->type_num) {\n";
3757    for implementationType range implements[param_type] do
3758      if typeNumber(implementationType) not in usedCaseLabels then
3759        c_expr.expr &:= "case ";
3760        c_expr.expr &:= str(typeNumber(implementationType));
3761        c_expr.expr &:= "/*";
3762        c_expr.expr &:= str(implementationType);
3763        c_expr.expr &:= "*/";
3764        c_expr.expr &:= ":\n";
3765        setType(formal_params[paramNum], implementationType);
3766        process_dynamic_condition(current_object,
3767            formal_params, paramNum, c_expr);
3768        setType(formal_params[paramNum], param_type);
3769        c_expr.expr &:= diagnosticLine(current_object);
3770        c_expr.expr &:= "break;\n";
3771        incl(usedCaseLabels, typeNumber(implementationType));
3772      end if;
3773    end for;
3774    c_expr.expr &:= "default:\n";
3775    c_expr.expr &:= diagnosticLine(current_object);
3776    c_expr.expr &:= "raiseError(ACTION_ERROR);\n";
3777    (*
3778    c_expr.expr &:= diagnosticLine(current_object);
3779    c_expr.expr &:= "printf(\"type_num=%d\\n\", ";
3780    if isPointerParam(formal_param) then
3781      c_expr.expr &:= "((interfaceType) *o_";
3782    else
3783      c_expr.expr &:= "((interfaceType) o_";
3784    end if;
3785    create_name(formal_param, c_expr.expr);
3786    c_expr.expr &:= ")->type_num);\n";
3787    c_expr.expr &:= diagnosticLine(current_object);
3788    c_expr.expr &:= "printf(\"o_";
3789    create_name(current_object, c_expr.expr);
3790    c_expr.expr &:= "(\");\n";
3791    c_expr.expr &:= diagnosticLine(current_object);
3792    print_parameter_list(formal_params, c_expr);
3793    c_expr.expr &:= "printf(\")\\n\");\n";
3794    *)
3795    c_expr.expr &:= diagnosticLine(current_object);
3796    c_expr.expr &:= "break;\n";
3797    c_expr.expr &:= "}\n";
3798  end func;
3799
3800
3801const proc: process_dynamic_param_enumeration (in reference: current_object,
3802    inout ref_list: formal_params, in var integer: paramNum,
3803    in type: param_type, inout expr_type: c_expr) is func
3804
3805  local
3806    var reference: formal_param is NIL;
3807    var number_element_hash: enumsByIntValue is number_element_hash.value;
3808    var integer: intValueOfEnum is 0;
3809    var reference: enumLiteral is NIL;
3810    var reference: backupParam is NIL;
3811  begin
3812    formal_param := formal_params[paramNum];
3813    c_expr.expr &:= diagnosticLine(current_object);
3814    c_expr.expr &:= "switch (";
3815    if isPointerParam(formal_param) then
3816      c_expr.expr &:= "*o_";
3817      create_name(formal_param, c_expr.expr);
3818    else
3819      c_expr.expr &:= "o_";
3820      create_name(formal_param, c_expr.expr);
3821    end if;
3822    c_expr.expr &:= ") {\n";
3823    enumsByIntValue := flip(enum_literal[param_type]);
3824    # Sort by integer values to always produce the same C code
3825    for intValueOfEnum range sort(keys(enumsByIntValue)) do
3826      c_expr.expr &:= diagnosticLine(current_object);
3827      c_expr.expr &:= "case ";
3828      c_expr.expr &:= str(intValueOfEnum);
3829      c_expr.expr &:= ": {\n";
3830      # If the enums are correct there will only be one per integer value
3831      enumLiteral := enumsByIntValue[intValueOfEnum][1];
3832      backupParam := formal_params[paramNum];
3833      formal_params @:= [paramNum] enumLiteral;
3834      process_dynamic_condition(current_object,
3835          formal_params, paramNum, c_expr);
3836      formal_params @:= [paramNum] backupParam;
3837      c_expr.expr &:= diagnosticLine(current_object);
3838      c_expr.expr &:= "} break;\n";
3839    end for;
3840    c_expr.expr &:= diagnosticLine(current_object);
3841    c_expr.expr &:= "default: {\n";
3842    c_expr.expr &:= diagnosticLine(current_object);
3843    c_expr.expr &:= "raiseError(ACTION_ERROR);\n";
3844    (*
3845    c_expr.expr &:= "printf(\"literal_num=%d\\n\", ";
3846    if isPointerParam(formal_param) then
3847      c_expr.expr &:= "*o_";
3848      create_name(formal_param, c_expr.expr);
3849    else
3850      c_expr.expr &:= "o_";
3851      create_name(formal_param, c_expr.expr);
3852    end if;
3853    c_expr.expr &:= ");\n";
3854    c_expr.expr &:= "printf(\"o_";
3855    create_name(current_object, c_expr.expr);
3856    c_expr.expr &:= "(\");\n";
3857    print_parameter_list(formal_params, c_expr);
3858    c_expr.expr &:= "printf(\")\\n\");\n";
3859    *)
3860    c_expr.expr &:= "} break;\n";
3861    c_expr.expr &:= "}\n";
3862  end func;
3863
3864
3865const proc: process_dynamic_condition (in reference: current_object,
3866    inout ref_list: formal_params, in var integer: paramNum,
3867    inout expr_type: c_expr) is func
3868
3869  local
3870    var reference: formal_param is NIL;
3871    var category: paramCategory is category.value;
3872    var type: param_type is void;
3873    var ref_list: param_list is ref_list.EMPTY;
3874    var reference: matched_object is NIL;
3875  begin
3876    incr(paramNum);
3877    if paramNum <= length(formal_params) then
3878      formal_param := formal_params[paramNum];
3879      paramCategory := category(formal_param);
3880      if paramCategory <> SYMBOLOBJECT then
3881        param_type := getType(formal_param);
3882        if param_type in implements then
3883          process_dynamic_param_implements(current_object,
3884              formal_params, paramNum, param_type, c_expr);
3885        elsif param_type in enum_literal then
3886          process_dynamic_param_enumeration(current_object,
3887              formal_params, paramNum, param_type, c_expr);
3888        else
3889          process_dynamic_condition(current_object,
3890              formal_params, paramNum, c_expr);
3891        end if;
3892      else
3893        process_dynamic_condition(current_object,
3894            formal_params, paramNum, c_expr);
3895      end if;
3896    else
3897      param_list := formal_params;
3898      matched_object := match(prog, param_list);
3899      (*
3900      if matched_object = NIL then
3901        c_expr.expr &:= "printf(\"NOT FOUND:\\n\");\n";
3902        for formal_param range formal_params do
3903          paramCategory := category(formal_param);
3904          if paramCategory <> SYMBOLOBJECT then
3905            param_type := getType(formal_param);
3906            if param_type in implements then
3907              c_expr.expr &:= "printf(\"type_num=%d\\n\", ";
3908              if isPointerParam(formal_param) then
3909                c_expr.expr &:= "((interfaceType) *o_";
3910              else
3911                c_expr.expr &:= "((interfaceType) o_";
3912              end if;
3913              create_name(formal_param, c_expr.expr);
3914              c_expr.expr &:= ")->type_num);\n";
3915            elsif param_type in enum_literal then
3916              c_expr.expr &:= "printf(\"literal_num=%d\\n\", ";
3917              if isPointerParam(formal_param) then
3918                c_expr.expr &:= "*o_";
3919              else
3920                c_expr.expr &:= "o_";
3921              end if;
3922              create_name(formal_param, c_expr.expr);
3923              c_expr.expr &:= ");\n";
3924            else
3925              c_expr.expr &:= "printf(\"other param_type\\n\");\n";
3926            end if;
3927          else
3928            c_expr.expr &:= "printf(\"" <& striToUtf8(str(formal_param)) <& "\\n\");\n";
3929          end if;
3930        end for;
3931      end if;
3932      *)
3933      process_dynamic_call(matched_object, formal_params, current_object, c_expr);
3934    end if;
3935  end func;
3936
3937
3938const proc: process_dynamic_decision (in reference: current_object,
3939    inout expr_type: c_expr) is func
3940
3941  local
3942    var expr_type: c_param_list is expr_type.value;
3943    var expr_type: c_func_body is expr_type.value;
3944    var type: object_type is void;
3945    var type: result_type is void;
3946    var ref_list: param_list is ref_list.EMPTY;
3947  begin
3948    object_type := getType(current_object);
3949    if isFunc(object_type) or isVarfunc(object_type) then
3950      result_type := resultType(object_type);
3951      if result_type not in typeCategory or typeCategory[result_type] <> TYPEOBJECT then
3952        declare_types_of_params(param_list, global_c_expr);
3953        c_expr.expr &:= diagnosticLine(current_object);
3954        c_expr.expr &:= "/* DYNAMIC */ static ";
3955        c_expr.expr &:= type_name(result_type);
3956        if isVarfunc(object_type) then
3957          c_expr.expr &:= " *o_";
3958        else
3959          c_expr.expr &:= " o_";
3960        end if;
3961        create_name(current_object, c_expr.expr);
3962        param_list := formalParams(current_object);
3963        c_expr.expr &:= " (";
3964        process_param_list_declaration(param_list, c_param_list);
3965        c_expr.expr &:= c_param_list.expr;
3966        c_expr.expr &:= ")\n";
3967        c_expr.expr &:= diagnosticLine(current_object);
3968        c_expr.expr &:= "{\n";
3969        process_dynamic_condition(current_object,
3970            param_list, 0, c_func_body);
3971        appendWithDiagnostic(c_param_list.temp_decls, c_expr);
3972        appendWithDiagnostic(c_func_body.temp_decls, c_expr);
3973        c_expr.expr &:= c_param_list.temp_assigns;
3974        appendWithDiagnostic(c_func_body.temp_assigns, c_expr);
3975        c_expr.expr &:= c_func_body.expr;
3976        appendWithDiagnostic(c_param_list.temp_frees, c_expr);
3977        appendWithDiagnostic(c_func_body.temp_frees, c_expr);
3978        c_expr.expr &:= diagnosticLine(current_object);
3979        c_expr.expr &:= "}\n\n";
3980      end if;
3981    end if;
3982  end func;
3983
3984
3985const proc: process_dynamic_decisions (inout expr_type: c_expr) is func
3986
3987  local
3988    var reference: current_object is NIL;
3989  begin
3990    for current_object range dynamic_functions do
3991      process_dynamic_decision(current_object, c_expr);
3992    end for;
3993  end func;
3994
3995
3996const proc: process_dynamic_declaration (in reference: current_object,
3997    inout expr_type: c_expr) is func
3998
3999  local
4000    var expr_type: c_param_list is expr_type.value;
4001    var type: object_type is void;
4002    var type: result_type is void;
4003    var ref_list: param_list is ref_list.EMPTY;
4004  begin
4005    object_type := getType(current_object);
4006    if isFunc(object_type) or isVarfunc(object_type) then
4007      result_type := resultType(object_type);
4008      if result_type not in typeCategory or typeCategory[result_type] <> TYPEOBJECT then
4009        dynamic_functions &:= make_list(current_object);
4010        declare_types_of_params(param_list, global_c_expr);
4011        c_expr.expr &:= "/* DYNAMIC */ static ";
4012        c_expr.expr &:= type_name(result_type);
4013        if isVarfunc(object_type) then
4014          c_expr.expr &:= " *o_";
4015        else
4016          c_expr.expr &:= " o_";
4017        end if;
4018        create_name(current_object, c_expr.expr);
4019        param_list := formalParams(current_object);
4020        c_expr.expr &:= " (";
4021        process_param_list_declaration(param_list, c_param_list);
4022        c_expr.expr &:= c_param_list.expr;
4023        c_expr.expr &:= ");\n";
4024        prototype_declared @:= [current_object] TRUE;
4025      end if;
4026    end if;
4027  end func;
4028
4029
4030const proc: process_hashcode (in reference: current_object, inout expr_type: c_expr) is func
4031
4032  local
4033    var ref_list: param_list is ref_list.EMPTY;
4034    var reference: expression is NIL;
4035  begin
4036    param_list := make_list(current_object);
4037    param_list &:= make_list(syobject(prog, "hashCode"));
4038    expression := matchExpr(prog, param_list);
4039    # TRACE_REF(expression);
4040    setCategory(expression, CALLOBJECT);
4041    process_expr(expression, c_expr);
4042  end func;
4043
4044
4045const func reference: keyCreateObj (in type: hash_type) is func
4046
4047  result
4048    var reference: keyCreate is NIL;
4049  local
4050    var ref_list: param_list is ref_list.EMPTY;
4051  begin
4052    param_list := make_list(typeObject(hash_type));
4053    param_list &:= make_list(syobject(prog, "."));
4054    param_list &:= make_list(syobject(prog, "keyCreate"));
4055    keyCreate := match(prog, param_list);
4056    keyCreate := getValue(keyCreate, reference);
4057  end func;
4058
4059
4060const func reference: keyCompareObj (in type: hash_type) is func
4061
4062  result
4063    var reference: keyCompare is NIL;
4064  local
4065    var ref_list: param_list is ref_list.EMPTY;
4066  begin
4067    param_list := make_list(typeObject(hash_type));
4068    param_list &:= make_list(syobject(prog, "."));
4069    param_list &:= make_list(syobject(prog, "keyCompare"));
4070    keyCompare := match(prog, param_list);
4071    keyCompare := getValue(keyCompare, reference);
4072  end func;
4073
4074
4075const func reference: dataCreateObj (in type: hash_type) is func
4076
4077  result
4078    var reference: dataCreate is NIL;
4079  local
4080    var ref_list: param_list is ref_list.EMPTY;
4081  begin
4082    param_list := make_list(typeObject(hash_type));
4083    param_list &:= make_list(syobject(prog, "."));
4084    param_list &:= make_list(syobject(prog, "dataCreate"));
4085    dataCreate := match(prog, param_list);
4086    dataCreate := getValue(dataCreate, reference);
4087  end func;
4088
4089
4090const func reference: dataCopyObj (in type: hash_type) is func
4091
4092  result
4093    var reference: dataCopy is NIL;
4094  local
4095    var ref_list: param_list is ref_list.EMPTY;
4096  begin
4097    param_list := make_list(typeObject(hash_type));
4098    param_list &:= make_list(syobject(prog, "."));
4099    param_list &:= make_list(syobject(prog, "dataCopy"));
4100    dataCopy := match(prog, param_list);
4101    dataCopy := getValue(dataCopy, reference);
4102  end func;
4103
4104
4105const proc: process_arr_cpy_declaration (in reference: current_object) is func
4106
4107  local
4108    var ref_list: params is ref_list.EMPTY;
4109    var type: base_type is void;
4110    var type: object_type is void;
4111  begin
4112    params := formalParams(current_object);
4113    if length(params) >= 1 then
4114      object_type := getType(params[1]);
4115      copyFunction @:= [object_type] current_object;
4116      typeCategory @:= [object_type] ARRAYOBJECT;
4117      base_type := base_type(object_type);
4118      if base_type <> void then
4119        if object_type not in array_element then
4120          array_element @:= [object_type] base_type;
4121        end if;
4122        if base_type not in array_type then
4123          array_type @:= [base_type] object_type;
4124        end if;
4125      end if;
4126    end if;
4127  end func;
4128
4129
4130const proc: process_arr_create_declaration (in reference: current_object) is func
4131
4132  local
4133    var ref_list: params is ref_list.EMPTY;
4134    var type: base_type is void;
4135    var type: object_type is void;
4136  begin
4137    params := formalParams(current_object);
4138    if length(params) >= 1 then
4139      object_type := getType(params[1]);
4140      createFunction @:= [object_type] current_object;
4141      typeCategory @:= [object_type] ARRAYOBJECT;
4142      base_type := base_type(object_type);
4143      if base_type <> void then
4144        if object_type not in array_element then
4145          array_element @:= [object_type] base_type;
4146        end if;
4147        if base_type not in array_type then
4148          array_type @:= [base_type] object_type;
4149        end if;
4150      end if;
4151    end if;
4152  end func;
4153
4154
4155const proc: process_arr_destr_declaration (in reference: current_object) is func
4156
4157  local
4158    var ref_list: params is ref_list.EMPTY;
4159    var type: base_type is void;
4160    var type: object_type is void;
4161  begin
4162    params := formalParams(current_object);
4163    if length(params) >= 1 then
4164      object_type := getType(params[1]);
4165      destrFunction @:= [object_type] current_object;
4166      typeCategory @:= [object_type] ARRAYOBJECT;
4167      base_type := base_type(object_type);
4168      if base_type <> void then
4169        if object_type not in array_element then
4170          array_element @:= [object_type] base_type;
4171        end if;
4172        if base_type not in array_type then
4173          array_type @:= [base_type] object_type;
4174        end if;
4175      end if;
4176    end if;
4177  end func;
4178
4179
4180const proc: process_arr_gen_declaration (in reference: current_object,
4181    inout expr_type: c_expr) is func
4182
4183  local
4184    var ref_list: params is ref_list.EMPTY;
4185    var type: result_type is void;
4186    var type: object_type is void;
4187  begin
4188    params := formalParams(current_object);
4189    if length(params) >= 1 then
4190      object_type := getType(params[1]);
4191      result_type := resultType(getType(current_object));
4192      if object_type not in array_type then
4193        array_type @:= [object_type] result_type;
4194      end if;
4195      if result_type not in array_element then
4196        array_element @:= [result_type] object_type;
4197      end if;
4198      c_expr.expr &:= "/* ACTION ARR_GEN for type ";
4199      c_expr.expr &:= type_name2(result_type);
4200      c_expr.expr &:= " element is ";
4201      c_expr.expr &:= type_name2(object_type);
4202      c_expr.expr &:= " */\n\n";
4203    end if;
4204  end func;
4205
4206
4207const proc: process_arr_idx_declaration (in reference: current_object,
4208    inout expr_type: c_expr) is func
4209
4210  local
4211    var ref_list: params is ref_list.EMPTY;
4212    var type: result_type is void;
4213    var type: object_type is void;
4214  begin
4215    params := formalParams(current_object);
4216    if length(params) >= 1 then
4217      object_type := getType(params[1]);
4218      result_type := resultType(getType(current_object));
4219      if object_type not in array_element then
4220        array_element @:= [object_type] result_type;
4221      end if;
4222      if result_type not in array_type then
4223        array_type @:= [result_type] object_type;
4224      end if;
4225      c_expr.expr &:= "/* ACTION ARR_IDX for type ";
4226      c_expr.expr &:= type_name2(object_type);
4227      c_expr.expr &:= " element is ";
4228      c_expr.expr &:= type_name2(result_type);
4229      c_expr.expr &:= " */\n\n";
4230    end if;
4231  end func;
4232
4233
4234const proc: process_arr_times_declaration (in reference: current_object,
4235    inout expr_type: c_expr) is func
4236
4237  local
4238    var string: diagnosticLine is "";
4239    var ref_list: params is ref_list.EMPTY;
4240    var type: result_type is void;
4241    var type: object_type is void;
4242  begin
4243    diagnosticLine := diagnosticLine(current_object);
4244    params := formalParams(current_object);
4245    if length(params) >= 3 then
4246      object_type := getType(params[3]);
4247      result_type := resultType(getType(current_object));
4248      if object_type in typeCategory and
4249          typeCategory[object_type] in simpleValueType then
4250        c_expr.expr &:= "/* times_";
4251        c_expr.expr &:= str(typeNumber(result_type));
4252        c_expr.expr &:= " not defined because arrTimes() is used instead. */\n";
4253      else
4254        process_create_declaration(object_type, c_expr);
4255        c_expr.expr &:= diagnosticLine;
4256        # c_expr.expr &:= type_name(result_type);
4257        c_expr.expr &:= "static arrayType times_";
4258        c_expr.expr &:= str(typeNumber(result_type));
4259        c_expr.expr &:= " (intType n, const ";
4260        if useConstPrefix(object_type) then
4261          c_expr.expr &:= "const_";
4262        end if;
4263        c_expr.expr &:= type_name(object_type);
4264        c_expr.expr &:= " b)\n";
4265        c_expr.expr &:= diagnosticLine;
4266        prototype_declared @:= [current_object] TRUE;
4267        c_expr.expr &:= "{\n";
4268        c_expr.expr &:= diagnosticLine;
4269        c_expr.expr &:= "arrayType a;\n";
4270        c_expr.expr &:= diagnosticLine;
4271        c_expr.expr &:= "memSizeType i;\n";
4272        c_expr.expr &:= diagnosticLine;
4273        c_expr.expr &:= "a=arrMalloc(1, n);\n";
4274        c_expr.expr &:= diagnosticLine;
4275        c_expr.expr &:= "for (i = 0; i < (memSizeType)(n); i++) {\n";
4276        c_expr.expr &:= diagnosticLine;
4277        c_expr.expr &:= "a->arr[i]";
4278        c_expr.expr &:= select_value_from_rtlObjectStruct(object_type);
4279        c_expr.expr &:= "=";
4280        process_create_call(object_type, "b", c_expr.expr);
4281        c_expr.expr &:= ";\n";
4282        c_expr.expr &:= diagnosticLine;
4283        c_expr.expr &:= "}\n";
4284        c_expr.expr &:= diagnosticLine;
4285        c_expr.expr &:= "return a;\n";
4286        c_expr.expr &:= diagnosticLine;
4287        c_expr.expr &:= "}\n";
4288        c_expr.expr &:= noDiagnosticLine;
4289        c_expr.expr &:= "\n";
4290      end if;
4291    end if;
4292  end func;
4293
4294
4295const proc: defineParam1TypeCategory (in reference: current_object,
4296    in category: param1Category) is func
4297
4298  local
4299    var ref_list: params is ref_list.EMPTY;
4300    var type: param1Type is void;
4301  begin
4302    params := formalParams(current_object);
4303    if length(params) >= 1 then
4304      param1Type := getType(params[1]);
4305      typeCategory @:= [param1Type] param1Category;
4306    end if;
4307  end func;
4308
4309
4310const proc: addImplementationToInterface (in type: implementationType, in type: interfaceType) is func
4311
4312  begin
4313    if interfaceType in implements then
4314      implements[interfaceType] &:= implementationType;
4315    else
4316      implements @:= [interfaceType] [] (implementationType);
4317    end if;
4318    if implementationType in interfaceOfType then
4319      interfaceOfType[implementationType] &:= interfaceType;
4320    else
4321      interfaceOfType @:= [implementationType] [] (interfaceType);
4322    end if;
4323  end func;
4324
4325
4326const proc: process_itf_cpy2_declaration (in reference: current_object,
4327    inout expr_type: c_expr) is func
4328
4329  local
4330    var ref_list: params is ref_list.EMPTY;
4331    var type: interfaceType is void;
4332    var type: implementationType is void;
4333  begin
4334    params := formalParams(current_object);
4335    if length(params) >= 1 then
4336      interfaceType := getType(params[1]);
4337      implementationType := getType(params[3]);
4338      addImplementationToInterface(implementationType, interfaceType);
4339      c_expr.expr &:= "/* itf_cpy2: ";
4340      c_expr.expr &:= type_name2(interfaceType);
4341      c_expr.expr &:= " := ";
4342      c_expr.expr &:= type_name2(implementationType);
4343      c_expr.expr &:= " */\n";
4344    end if;
4345  end func;
4346
4347
4348const proc: process_itf_next_file_declaration (in reference: current_object) is func
4349
4350  local
4351    var type: object_type is void;
4352  begin
4353    object_type := getType(current_object);
4354    if isFunc(object_type) or isVarfunc(object_type) then
4355      fileInterfaceType := resultType(object_type);
4356    end if;
4357  end func;
4358
4359
4360const proc: process_hsh_cpy_declaration (in reference: current_object) is func
4361
4362  local
4363    var ref_list: params is ref_list.EMPTY;
4364    var type: hash_type is void;
4365  begin
4366    params := formalParams(current_object);
4367    if length(params) >= 1 then
4368      hash_type := getType(params[1]);
4369      copyFunction @:= [hash_type] current_object;
4370      typeCategory @:= [hash_type] HASHOBJECT;
4371    end if;
4372  end func;
4373
4374
4375const proc: process_hsh_create_declaration (in reference: current_object) is func
4376
4377  local
4378    var ref_list: params is ref_list.EMPTY;
4379    var type: object_type is void;
4380  begin
4381    params := formalParams(current_object);
4382    if length(params) >= 1 then
4383      object_type := getType(params[1]);
4384      createFunction @:= [object_type] current_object;
4385      typeCategory @:= [object_type] HASHOBJECT;
4386    end if;
4387  end func;
4388
4389
4390const proc: process_hsh_destr_declaration (in reference: current_object) is func
4391
4392  local
4393    var ref_list: params is ref_list.EMPTY;
4394    var type: object_type is void;
4395  begin
4396    params := formalParams(current_object);
4397    if length(params) >= 1 then
4398      object_type := getType(params[1]);
4399      destrFunction @:= [object_type] current_object;
4400      typeCategory @:= [object_type] HASHOBJECT;
4401    end if;
4402  end func;
4403
4404
4405const proc: addStructElem (in type: structType, in type: elemType, in reference: elementOfStruct) is func
4406
4407  local
4408    var integer: elementIndex is 0;
4409    var element_idx_hash: element_index is element_idx_hash.EMPTY_HASH;
4410  begin
4411    if structType in struct_element_idx then
4412      elementIndex := struct_size[structType];
4413      struct_element_idx[structType] @:= [elementOfStruct] elementIndex;
4414      struct_element_type[structType] &:= elemType;
4415      struct_element[structType] &:= elementOfStruct;
4416      struct_size @:= [structType] succ(elementIndex);
4417    else
4418      struct_size @:= [structType] 1;
4419      element_index @:= [elementOfStruct] 0;
4420      struct_element_idx @:= [structType] element_index;
4421      struct_element_type @:= [structType] [0] elemType;
4422      struct_element @:= [structType] [0] elementOfStruct;
4423    end if;
4424  end func;
4425
4426
4427const proc: process_sct_cpy_declaration (in reference: current_object) is func
4428
4429  local
4430    var ref_list: params is ref_list.EMPTY;
4431    var type: sct_type is void;
4432    var type: meta_type is void;
4433    var type: interfaceType is void;
4434    var integer: structIndex is 0;
4435  begin
4436    params := formalParams(current_object);
4437    if length(params) >= 1 then
4438      sct_type := getType(params[1]);
4439      copyFunction @:= [sct_type] current_object;
4440      typeCategory @:= [sct_type] STRUCTOBJECT;
4441      if isDerived(sct_type) then
4442        meta_type := meta(sct_type);
4443        if meta_type in struct_element_idx then
4444          for structIndex range 0 to pred(struct_size[meta_type]) do
4445            addStructElem(sct_type, struct_element_type[meta_type][structIndex],
4446                          struct_element[meta_type][structIndex]);
4447          end for;
4448        end if;
4449        if meta_type in interfaceOfType then
4450          for interfaceType range interfaceOfType[meta_type] do
4451            addImplementationToInterface(sct_type, interfaceType);
4452          end for;
4453        end if;
4454      end if;
4455    end if;
4456  end func;
4457
4458
4459const proc: process_sct_create_declaration (in reference: current_object) is func
4460
4461  local
4462    var ref_list: params is ref_list.EMPTY;
4463    var type: object_type is void;
4464  begin
4465    params := formalParams(current_object);
4466    object_type := getType(params[1]);
4467    createFunction @:= [object_type] current_object;
4468    typeCategory @:= [object_type] STRUCTOBJECT;
4469  end func;
4470
4471
4472const proc: process_sct_destr_declaration (in reference: current_object) is func
4473
4474  local
4475    var ref_list: params is ref_list.EMPTY;
4476    var type: object_type is void;
4477  begin
4478    params := formalParams(current_object);
4479    object_type := getType(params[1]);
4480    destrFunction @:= [object_type] current_object;
4481    typeCategory @:= [object_type] STRUCTOBJECT;
4482  end func;
4483
4484
4485const proc: process_sct_select_declaration (in reference: current_object,
4486    inout expr_type: c_expr) is func
4487
4488  local
4489    var ref_list: params is ref_list.EMPTY;
4490    var type: elemType is void;
4491    var type: structType is void;
4492    var reference: elementOfStruct is NIL;
4493  begin
4494    params := formalParams(current_object);
4495    if length(params) >= 3 and not isVar(params[1]) then
4496      structType := getType(params[1]);
4497      elementOfStruct := params[3];
4498      elemType := resultType(getType(current_object));
4499      addStructElem(structType, elemType, elementOfStruct);
4500      c_expr.expr &:= "/* struct element ";
4501      c_expr.expr &:= type_name2(elemType);
4502      c_expr.expr &:= " ** ";
4503      c_expr.expr &:= type_name2(structType);
4504      c_expr.expr &:= "->o_";
4505      create_name2(elementOfStruct, c_expr.expr);
4506      c_expr.expr &:= " = ";
4507      c_expr.expr &:= str(struct_element_idx[structType][elementOfStruct]);
4508      c_expr.expr &:= " */\n";
4509    end if;
4510  end func;
4511
4512
4513const proc: process_ref_select_declaration (in reference: current_object,
4514    inout expr_type: c_expr) is func
4515
4516  local
4517    var ref_list: params is ref_list.EMPTY;
4518    var type: elemType is void;
4519    var type: structType is void;
4520    var reference: elementOfStruct is NIL;
4521  begin
4522    params := formalParams(current_object);
4523    if length(params) >= 3 and not isVar(params[1]) then
4524      structType := getType(params[1]);
4525      elementOfStruct := params[3];
4526      elemType := resultType(getType(current_object));
4527      addStructElem(structType, elemType, elementOfStruct);
4528      c_expr.expr &:= "/* ref struct element ";
4529      c_expr.expr &:= type_name2(elemType);
4530      c_expr.expr &:= " ** ";
4531      c_expr.expr &:= type_name2(structType);
4532      c_expr.expr &:= "->o_";
4533      create_name2(elementOfStruct, c_expr.expr);
4534      c_expr.expr &:= " = ";
4535      c_expr.expr &:= str(struct_element_idx[structType][elementOfStruct]);
4536      c_expr.expr &:= " */\n";
4537    end if;
4538  end func;
4539
4540
4541const proc: process_var_action_declaration (in reference: current_object,
4542    inout expr_type: c_expr) is func
4543
4544  local
4545    var expr_type: c_value is expr_type.value;
4546    var string: valueName is "";
4547  begin
4548    create_name(current_object, objNumber(current_object), valueName);
4549    processFuncValue(valueName, getType(current_object), current_object, c_value);
4550    c_expr.expr &:= c_value.temp_decls;
4551    global_init.expr &:= diagnosticLine(current_object);
4552    global_init.expr &:= c_value.temp_assigns;
4553    c_expr.expr &:= type_name(getType(current_object));
4554    c_expr.expr &:= " o_";
4555    create_name(current_object, c_expr.expr);
4556    c_expr.expr &:= " = ";
4557    c_expr.expr &:= c_value.expr;
4558    c_expr.expr &:= ";\n\n";
4559    function_declared @:= [current_object] TRUE;
4560  end func;
4561
4562
4563const proc: process_action_declaration (in reference: current_object,
4564    inout expr_type: c_expr) is func
4565
4566  local
4567    var ACTION: current_action is action "PRC_NOOP";
4568    var string: action_name is "";
4569  begin
4570    if isVar(current_object) then
4571      process_var_action_declaration(current_object, c_expr);
4572    else
4573      current_action := getValue(current_object, ACTION);
4574      action_name := str(current_action);
4575      if action_name = "PRC_DYNAMIC" then
4576        process_dynamic_declaration(current_object, c_expr);
4577        count_declarations(c_expr);
4578      elsif action_name = "ACT_CPY" then
4579        defineParam1TypeCategory(current_object, ACTOBJECT);
4580        count_declarations(c_expr);
4581      elsif action_name = "ARR_CPY" then
4582        process_arr_cpy_declaration(current_object);
4583        count_declarations(c_expr);
4584      elsif action_name = "ARR_CREATE" then
4585        process_arr_create_declaration(current_object);
4586        count_declarations(c_expr);
4587      elsif action_name = "ARR_DESTR" then
4588        process_arr_destr_declaration(current_object);
4589        count_declarations(c_expr);
4590      elsif action_name = "ARR_GEN" then
4591        process_arr_gen_declaration(current_object, c_expr);
4592        count_declarations(c_expr);
4593      elsif action_name = "ARR_IDX" then
4594        process_arr_idx_declaration(current_object, c_expr);
4595        count_declarations(c_expr);
4596      elsif action_name = "ARR_TIMES" then
4597        process_arr_times_declaration(current_object, c_expr);
4598        count_declarations(c_expr);
4599      elsif action_name = "BIG_CPY" or action_name = "BIG_CREATE" then
4600        defineParam1TypeCategory(current_object, BIGINTOBJECT);
4601        count_declarations(c_expr);
4602      elsif action_name = "BLN_CPY" then
4603        defineParam1TypeCategory(current_object, BOOLOBJECT);
4604        count_declarations(c_expr);
4605      elsif action_name = "BST_CPY" or action_name = "BST_CREATE" then
4606        defineParam1TypeCategory(current_object, BSTRIOBJECT);
4607        count_declarations(c_expr);
4608      elsif action_name = "DRW_CPY" or action_name = "DRW_CREATE" then
4609        defineParam1TypeCategory(current_object, WINOBJECT);
4610        count_declarations(c_expr);
4611      elsif action_name = "PCS_CPY" or action_name = "PCS_CREATE" then
4612        defineParam1TypeCategory(current_object, PROCESSOBJECT);
4613        count_declarations(c_expr);
4614      elsif action_name = "ENU_CPY" then
4615        defineParam1TypeCategory(current_object, ENUMOBJECT);
4616        count_declarations(c_expr);
4617      elsif action_name = "FIL_CPY" or action_name = "FIL_CREATE" then
4618        defineParam1TypeCategory(current_object, FILEOBJECT);
4619        count_declarations(c_expr);
4620      elsif action_name = "FLT_CPY" or action_name = "FLT_CREATE" then
4621        defineParam1TypeCategory(current_object, FLOATOBJECT);
4622        count_declarations(c_expr);
4623      elsif action_name = "HSH_CPY" then
4624        process_hsh_cpy_declaration(current_object);
4625        count_declarations(c_expr);
4626      elsif action_name = "HSH_CREATE" then
4627        process_hsh_create_declaration(current_object);
4628        count_declarations(c_expr);
4629      elsif action_name = "HSH_DESTR" then
4630        process_hsh_destr_declaration(current_object);
4631        count_declarations(c_expr);
4632      elsif action_name = "INT_CPY" or action_name = "INT_CREATE" then
4633        defineParam1TypeCategory(current_object, INTOBJECT);
4634        count_declarations(c_expr);
4635      elsif action_name = "ITF_CPY" then
4636        defineParam1TypeCategory(current_object, INTERFACEOBJECT);
4637        count_declarations(c_expr);
4638      elsif action_name = "ITF_CPY2" then
4639        process_itf_cpy2_declaration(current_object, c_expr);
4640        count_declarations(c_expr);
4641      elsif action_name = "POL_CPY" or action_name = "POL_CREATE" then
4642        defineParam1TypeCategory(current_object, POLLOBJECT);
4643        count_declarations(c_expr);
4644      elsif action_name = "POL_NEXT_FILE" then
4645        process_itf_next_file_declaration(current_object);
4646        count_declarations(c_expr);
4647      elsif action_name = "PRG_CPY" or action_name = "PRG_CREATE" then
4648        defineParam1TypeCategory(current_object, PROGOBJECT);
4649        count_declarations(c_expr);
4650      elsif action_name = "REF_CPY" or action_name = "REF_CREATE" then
4651        defineParam1TypeCategory(current_object, REFOBJECT);
4652        count_declarations(c_expr);
4653      elsif action_name = "REF_SELECT" then
4654        process_ref_select_declaration(current_object, c_expr);
4655        count_declarations(c_expr);
4656      elsif action_name = "RFL_CPY" or action_name = "RFL_CREATE" then
4657        defineParam1TypeCategory(current_object, REFLISTOBJECT);
4658        count_declarations(c_expr);
4659      elsif action_name = "SCT_CPY" then
4660        process_sct_cpy_declaration(current_object);
4661        count_declarations(c_expr);
4662      elsif action_name = "SCT_CREATE" then
4663        process_sct_create_declaration(current_object);
4664        count_declarations(c_expr);
4665      elsif action_name = "SCT_DESTR" then
4666        process_sct_destr_declaration(current_object);
4667        count_declarations(c_expr);
4668      elsif action_name = "SCT_SELECT" then
4669        process_sct_select_declaration(current_object, c_expr);
4670        count_declarations(c_expr);
4671      elsif action_name = "SET_CPY" or action_name = "SET_CREATE" then
4672        defineParam1TypeCategory(current_object, SETOBJECT);
4673        count_declarations(c_expr);
4674      elsif action_name = "SOC_CPY" or action_name = "SOC_CREATE" then
4675        defineParam1TypeCategory(current_object, SOCKETOBJECT);
4676        count_declarations(c_expr);
4677      elsif action_name = "SQL_CPY_DB" or action_name = "SQL_CREATE_DB" then
4678        defineParam1TypeCategory(current_object, DATABASEOBJECT);
4679        count_declarations(c_expr);
4680      elsif action_name = "SQL_CPY_STMT" or action_name = "SQL_CREATE_STMT" then
4681        defineParam1TypeCategory(current_object, SQLSTMTOBJECT);
4682        count_declarations(c_expr);
4683(*
4684      else
4685        c_expr.expr &:= "/* ACTION ";
4686        c_expr.expr &:= action_name;
4687        c_expr.expr &:= " */";
4688*)
4689      end if;
4690    end if;
4691  end func;
4692
4693
4694const proc: process_object_declaration (in reference: current_object,
4695    inout expr_type: c_expr) is func
4696
4697  local
4698    var category: objectCategory is category.value;
4699  begin
4700    objectCategory := category(current_object);
4701    if current_object = main_object then
4702      if category(current_object) = FORWARDOBJECT then
4703        process_library_initialisation(current_object, c_expr);
4704      else
4705        process_main_declaration(current_object, c_expr);
4706      end if;
4707    elsif objectCategory = BLOCKOBJECT then
4708      process_func_declaration(current_object, c_expr);
4709    elsif objectCategory = TYPEOBJECT then
4710      process_type_declaration(current_object, c_expr);
4711    elsif objectCategory = INTOBJECT then
4712      process_int_declaration(current_object, c_expr);
4713    elsif objectCategory = BIGINTOBJECT then
4714      process_bigint_declaration(current_object, c_expr);
4715    elsif objectCategory = CHAROBJECT then
4716      process_char_declaration(current_object, c_expr);
4717    elsif objectCategory = STRIOBJECT then
4718      process_stri_declaration(current_object, c_expr);
4719    elsif objectCategory = BSTRIOBJECT then
4720      process_bstri_declaration(current_object, c_expr);
4721    elsif objectCategory = FLOATOBJECT then
4722      process_float_declaration(current_object, c_expr);
4723    elsif objectCategory = REFOBJECT then
4724      process_reference_declaration(current_object, c_expr);
4725    elsif objectCategory = REFLISTOBJECT then
4726      process_ref_list_declaration(current_object, c_expr);
4727    elsif objectCategory = FILEOBJECT then
4728      process_file_declaration(current_object, c_expr);
4729    elsif objectCategory = SOCKETOBJECT then
4730      process_socket_declaration(current_object, c_expr);
4731    elsif objectCategory = POLLOBJECT then
4732      process_poll_declaration(current_object, c_expr);
4733    elsif objectCategory = ARRAYOBJECT then
4734      process_array_declaration(current_object, c_expr);
4735    elsif objectCategory = HASHOBJECT then
4736      process_hash_declaration(current_object, c_expr);
4737    elsif objectCategory = SETOBJECT then
4738      process_set_declaration(current_object, c_expr);
4739    elsif objectCategory = STRUCTOBJECT then
4740      process_struct_declaration(current_object, c_expr);
4741    elsif objectCategory = INTERFACEOBJECT then
4742      process_interface_declaration(current_object, c_expr);
4743    elsif objectCategory = WINOBJECT then
4744      process_win_declaration(current_object, c_expr);
4745    elsif objectCategory = PROCESSOBJECT then
4746      process_process_declaration(current_object, c_expr);
4747    elsif objectCategory = PROGOBJECT then
4748      process_prog_declaration(current_object, c_expr);
4749    elsif objectCategory = CONSTENUMOBJECT then
4750      process_enum_declaration(current_object, c_expr);
4751    elsif objectCategory = VARENUMOBJECT then
4752      process_enum_declaration(current_object, c_expr);
4753    elsif objectCategory = ENUMLITERALOBJECT then
4754      process_enum_literal_declaration(current_object, c_expr);
4755    elsif objectCategory = ACTOBJECT then
4756      process_action_declaration(current_object, c_expr);
4757    elsif objectCategory = FWDREFOBJECT then
4758      process_forward_declaration(current_object, c_expr);
4759    else
4760      c_expr.expr &:= "/* ";
4761      c_expr.expr &:= str(objectCategory);
4762      c_expr.expr &:= ": ";
4763      create_name2(current_object, c_expr.expr);
4764      c_expr.expr &:= " */\n";
4765    end if;
4766  end func;
4767
4768
4769const proc: replaceLocalsFromOutside (in reference: local_function,
4770    inout reference: current_expression, in ref_list: local_objects,
4771    inout ref_list: additional_act_params, inout ref_list: additional_form_params) is func
4772
4773  local
4774    var ref_list: params is ref_list.EMPTY;
4775    var integer: paramNum is 0;
4776    var reference: aParam is NIL;
4777    var category: paramCategory is category.value;
4778    var reference: formalRefParam is NIL;
4779  begin
4780    params := getValue(current_expression, ref_list);
4781    for paramNum range 2 to length(params) do
4782      aParam := params[paramNum];
4783      paramCategory := category(aParam);
4784      if paramCategory = MATCHOBJECT or paramCategory = CALLOBJECT then
4785        replaceLocalsFromOutside(local_function, aParam, local_objects,
4786            additional_act_params, additional_form_params);
4787      elsif paramCategory = LOCALVOBJECT or
4788            paramCategory = VALUEPARAMOBJECT or
4789            paramCategory = REFPARAMOBJECT or
4790            paramCategory = RESULTOBJECT then
4791        if aParam not in local_objects then
4792          if aParam in additional_act_params then
4793            formalRefParam := additional_form_params[pos(additional_act_params, aParam)];
4794          elsif local_function in params_added and
4795              aParam in params_added[local_function] then
4796            formalRefParam := params_added[local_function][aParam];
4797          else
4798            additional_act_params &:= make_list(aParam);
4799            formalRefParam := alloc(aParam);
4800            setCategory(formalRefParam, REFPARAMOBJECT);
4801            additional_form_params &:= make_list(formalRefParam);
4802          end if;
4803          params @:= [paramNum] formalRefParam;
4804        end if;
4805      end if;
4806    end for;
4807    setValue(current_expression, params);
4808  end func;
4809
4810
4811const proc: changeCallsOfLocalFunction (inout reference: current_expression,
4812    in reference: local_function, in ref_list: additional_params) is func
4813
4814  local
4815    var ref_list: params is ref_list.EMPTY;
4816    var integer: paramNum is 0;
4817    var reference: aParam is NIL;
4818    var category: paramCategory is category.value;
4819  begin
4820    params := getValue(current_expression, ref_list);
4821    for paramNum range 2 to length(params) do
4822      aParam := params[paramNum];
4823      paramCategory := category(aParam);
4824      if paramCategory = MATCHOBJECT or paramCategory = CALLOBJECT then
4825        changeCallsOfLocalFunction(aParam, local_function, additional_params);
4826      elsif aParam = local_function then
4827        aParam := alloc(aParam);
4828        setCategory(aParam, MATCHOBJECT);
4829        setValue(aParam, make_list(params[paramNum]) & additional_params);
4830        params @:= [paramNum] aParam;
4831        setValue(current_expression, params);
4832      end if;
4833    end for;
4834    if params[1] = local_function then
4835      params &:= additional_params;
4836      setValue(current_expression, params);
4837    end if;
4838  end func;
4839
4840
4841const proc: changeCallsFromSubFunctions (in reference: parent_function,
4842    in reference: local_function, in ref_list: additional_params) is func
4843
4844  local
4845    var reference: parent_body is NIL;
4846    var reference: obj is NIL;
4847  begin
4848    if parent_function <> local_function then
4849      parent_body := body(parent_function);
4850      changeCallsOfLocalFunction(parent_body, local_function, additional_params);
4851    end if;
4852    for obj range localConsts(parent_function) do
4853      if category(obj) = BLOCKOBJECT then
4854        changeCallsFromSubFunctions(obj, local_function, additional_params);
4855      end if;
4856    end for;
4857  end func;
4858
4859
4860const proc: adjustParamsToAdd (in reference: local_function,
4861    inout ref_list: additional_act_params, inout ref_list: additional_form_params) is func
4862
4863  local
4864    var integer: paramNum is 0;
4865    var reference: actParam is NIL;
4866    var reference: formParam is NIL;
4867  begin
4868    if length(additional_act_params) <> 0 then
4869      if local_function not in params_added then
4870        params_added @:= [local_function] act_to_form_param_hash.value;
4871      end if;
4872      paramNum := 1;
4873      while paramNum <= length(additional_act_params) do
4874        actParam := additional_act_params[paramNum];
4875        if actParam in params_added[local_function] then
4876          additional_act_params := additional_act_params[.. pred(paramNum)] &
4877                                   additional_act_params[succ(paramNum) ..];
4878          additional_form_params := additional_form_params[.. pred(paramNum)] &
4879                                    additional_form_params[succ(paramNum) ..];
4880        else
4881          incr(paramNum);
4882        end if;
4883      end while;
4884      for paramNum range 1 to length(additional_act_params) do
4885        actParam := additional_act_params[paramNum];
4886        formParam := additional_form_params[paramNum];
4887        if actParam not in params_added[local_function] then
4888          params_added[local_function] @:= [actParam] formParam;
4889        end if;
4890      end for;
4891    end if;
4892  end func;
4893
4894
4895const func boolean: fixLocalFunction (in reference: parent_function,
4896    in reference: local_function) is func
4897
4898  result
4899    var boolean: fix_done is FALSE;
4900  local
4901    var reference: body_expression is NIL;
4902    var category: bodyCategory is category.value;
4903    var ref_list: local_objects is ref_list.EMPTY;
4904    var ref_list: additional_act_params is ref_list.EMPTY;
4905    var ref_list: additional_form_params is ref_list.EMPTY;
4906  begin
4907    body_expression := body(local_function);
4908    bodyCategory := category(body_expression);
4909    if bodyCategory = MATCHOBJECT or bodyCategory = CALLOBJECT then
4910      local_objects := formalParams(local_function) & localVars(local_function) &
4911          make_list(resultVar(local_function));
4912      replaceLocalsFromOutside(local_function, body_expression, local_objects,
4913          additional_act_params, additional_form_params);
4914      adjustParamsToAdd(local_function, additional_act_params, additional_form_params);
4915      if length(additional_act_params) <> 0 then
4916        setFormalParams(local_function, formalParams(local_function) & additional_form_params);
4917        changeCallsOfLocalFunction(body_expression, local_function, additional_form_params);
4918        changeCallsFromSubFunctions(parent_function, local_function, additional_act_params);
4919        fix_done := TRUE;
4920      end if;
4921    end if;
4922  end func;
4923
4924
4925const proc: processLocalFunctions (in reference: current_object) is func
4926
4927  local
4928    var ref_list: objects is ref_list.EMPTY;
4929    var reference: obj is NIL;
4930    var boolean: fix_done is FALSE;
4931  begin
4932    objects := localConsts(current_object);
4933    repeat
4934      fix_done := FALSE;
4935      for obj range objects do
4936        if category(obj) = BLOCKOBJECT then
4937          processLocalFunctions(obj);
4938          if fixLocalFunction(current_object, obj) then
4939            fix_done := TRUE;
4940          end if;
4941        end if;
4942      end for;
4943    until not fix_done;
4944  end func;
4945
4946
4947const proc: addTypeCategoryForLocalVars (in reference: function) is func
4948
4949  local
4950    var ref_list: objects is ref_list.EMPTY;
4951    var reference: obj is NIL;
4952    var reference: object_value is NIL;
4953    var type: objectType is void;
4954    var category: valueCategory is category.value;
4955  begin
4956    objects := localVars(function);
4957    for obj range objects do
4958      object_value := getValue(obj, reference);
4959      valueCategory := category(object_value);
4960      objectType := getType(obj);
4961      if objectType = getType(object_value) and objectType not in typeCategory then
4962        typeCategory @:= [objectType] valueCategory;
4963      end if;
4964    end for;
4965  end func;
4966
4967
4968const proc: process_local_consts (in reference: function,
4969    inout expr_type: c_expr) is func
4970
4971  local
4972    var ref_list: objects is ref_list.EMPTY;
4973    var reference: obj is NIL;
4974  begin
4975    addTypeCategoryForLocalVars(function);
4976    processLocalFunctions(function);
4977    objects := localConsts(function);
4978    for obj range objects do
4979      if category(obj) <> FWDREFOBJECT then
4980        declare_type_if_necessary(getType(obj), global_c_expr);
4981      end if;
4982      process_object_declaration(obj, c_expr);
4983    end for;
4984  end func;
4985
4986
4987const proc: process_object (in reference: current_object) is func
4988
4989  local
4990    var expr_type: c_expr is expr_type.value;
4991  begin
4992    write_object_declaration := TRUE;
4993    process_object_declaration(current_object, c_expr);
4994    write(c_prog, global_c_expr.expr);
4995    if write_object_declaration then
4996      # writeln(c_prog, "/* " <& countDeclarations <& " */");
4997      write(c_prog, c_expr.expr);
4998(*
4999    else
5000      write(c_prog, "#ifdef WRITE_OBJECT_DECLARATION\n");
5001      write(c_prog, c_expr.expr);
5002      write(c_prog, "#endif\n");
5003*)
5004    end if;
5005    flush(c_prog);
5006    global_c_expr := expr_type.value;
5007  end func;
5008
5009
5010const proc: process_library_import_object (in reference: current_object) is func
5011
5012  local
5013    var expr_type: c_expr is expr_type.value;
5014  begin
5015    process_object_declaration(current_object, c_expr);
5016    global_c_expr := expr_type.value;
5017  end func;
5018
5019
5020const proc: write_file_head is func
5021
5022  begin
5023    writeln(c_prog, temp_marker);
5024    writeln(c_prog, "#include <stdlib.h>");
5025    writeln(c_prog, "#include <stdio.h>");
5026    writeln(c_prog, "#include <string.h>");
5027    writeln(c_prog, "#include <math.h>");
5028    writeln(c_prog, "#include <setjmp.h>");
5029    writeln(c_prog, "#include <signal.h>");
5030    writeln(c_prog, "typedef short int          int16Type;");
5031    writeln(c_prog, "typedef unsigned short int uint16Type;");
5032    writeln(c_prog, "typedef " <& ccConf.INT32TYPE <& " int32Type;");
5033    writeln(c_prog, "typedef " <& ccConf.UINT32TYPE <& " uint32Type;");
5034    writeln(c_prog, "typedef " <& ccConf.INT64TYPE <& " int64Type;");
5035    writeln(c_prog, "typedef " <& ccConf.UINT64TYPE <& " uint64Type;");
5036    if ccConf.INT128TYPE <> "" then
5037      writeln(c_prog, "typedef " <& ccConf.INT128TYPE <& " int128Type;");
5038      writeln(c_prog, "typedef " <& ccConf.UINT128TYPE <& " uint128Type;");
5039    end if;
5040    if ccConf.TWOS_COMPLEMENT_INTTYPE then
5041      writeln(c_prog, "#define INT32TYPE_MIN ((int32Type) -2147483648" <&
5042          ccConf.INT32TYPE_LITERAL_SUFFIX <& ")");
5043    else
5044      writeln(c_prog, "#define INT32TYPE_MIN             (-2147483647" <&
5045          ccConf.INT32TYPE_LITERAL_SUFFIX <& ")");
5046    end if;
5047    writeln(c_prog, "#define INT32TYPE_MAX               2147483647" <&
5048        ccConf.INT32TYPE_LITERAL_SUFFIX);
5049    if ccConf.INTTYPE_SIZE = 64 then
5050      writeln(c_prog, "#define INTTYPE_DECIMAL_SIZE 20");
5051      writeln(c_prog, "typedef int64Type intType;");
5052      writeln(c_prog, "typedef uint64Type uintType;");
5053      if ccConf.INT128TYPE <> "" then
5054        writeln(c_prog, "typedef int128Type doubleIntType;");
5055        writeln(c_prog, "typedef uint128Type doubleUintType;");
5056        writeln(c_prog, "#define inIntTypeRange(num) ((doubleIntType) (intType) (num) == (num))");
5057      end if;
5058    elsif ccConf.INTTYPE_SIZE = 32 then
5059      writeln(c_prog, "#define INTTYPE_DECIMAL_SIZE 11");
5060      writeln(c_prog, "typedef int32Type intType;");
5061      writeln(c_prog, "typedef uint32Type uintType;");
5062      writeln(c_prog, "typedef int64Type doubleIntType;");
5063      writeln(c_prog, "typedef uint64Type doubleUintType;");
5064      writeln(c_prog, "#define inIntTypeRange(num) ((doubleIntType) (intType) (num) == (num))");
5065    end if;
5066    writeln(c_prog, "typedef " <& ccConf.BOOLTYPE <& " boolType;");
5067    writeln(c_prog, "typedef int enumType;");
5068    if ccConf.FLOATTYPE_DOUBLE then
5069      writeln(c_prog, "typedef double floatType;");
5070    else
5071      writeln(c_prog, "typedef float floatType;");
5072    end if;
5073    writeln(c_prog, "typedef uint32Type charType;");
5074    writeln(c_prog, "typedef int32Type scharType;");
5075    writeln(c_prog, "typedef uint32Type strElemType;");
5076    writeln(c_prog, "typedef uintType bitSetType;");
5077    writeln(c_prog, "typedef uint" <& ccConf.POINTER_SIZE <& "Type memSizeType;");
5078    writeln(c_prog, "typedef FILE *cFileType;");
5079    writeln(c_prog, "typedef unsigned char *ustriType;");
5080    writeln(c_prog, "typedef const unsigned char *const_ustriType;");
5081    writeln(c_prog, "typedef struct striStruct {");
5082    writeln(c_prog, "  memSizeType size;");
5083    if ccConf.WITH_STRI_CAPACITY then
5084      writeln(c_prog, "  memSizeType capacity;");
5085    end if;
5086    if ccConf.ALLOW_STRITYPE_SLICES then
5087      writeln(c_prog, "  strElemType *mem;");
5088      writeln(c_prog, "  strElemType  mem1[1];");
5089    else
5090      writeln(c_prog, "  strElemType mem[1];");
5091    end if;
5092    writeln(c_prog, "} *striType;");
5093    writeln(c_prog, "typedef const struct striStruct  *const_striType;");
5094    writeln(c_prog, "#define SIZ_STRI(len) ((sizeof(struct striStruct) - sizeof(strElemType)) + (len) * sizeof(strElemType))");
5095    writeln(c_prog, "typedef struct bstriStruct {");
5096    writeln(c_prog, "  memSizeType size;");
5097    if ccConf.ALLOW_BSTRITYPE_SLICES then
5098      writeln(c_prog, "  unsigned char *mem;");
5099      writeln(c_prog, "  unsigned char  mem1[1];");
5100    else
5101      writeln(c_prog, "  unsigned char mem[1];");
5102    end if;
5103    writeln(c_prog, "} *bstriType;");
5104    writeln(c_prog, "typedef const struct bstriStruct  *const_bstriType;");
5105    writeln(c_prog, "typedef struct fileStruct {");
5106    writeln(c_prog, "  cFileType cFile;");
5107    writeln(c_prog, "  uintType usage_count;");
5108    writeln(c_prog, "} *fileType;");
5109    writeln(c_prog, "typedef const struct fileStruct  *const_fileType;");
5110    writeln(c_prog, "typedef struct setStruct {");
5111    writeln(c_prog, "  intType min_position;");
5112    writeln(c_prog, "  intType max_position;");
5113    writeln(c_prog, "  bitSetType bitset[1];");
5114    writeln(c_prog, "} *setType;");
5115    writeln(c_prog, "typedef const struct setStruct  *const_setType;");
5116    writeln(c_prog, "typedef struct {");
5117    writeln(c_prog, "  int dummy;");
5118    writeln(c_prog, "} bigIntRecord;");
5119    writeln(c_prog, "typedef bigIntRecord *bigIntType;");
5120    writeln(c_prog, "typedef const bigIntRecord *const_bigIntType;");
5121    writeln(c_prog, "typedef struct pollStruct {");
5122    writeln(c_prog, "  int dummy;");
5123    writeln(c_prog, "} *pollType;");
5124    writeln(c_prog, "typedef const struct pollStruct *const_pollType;");
5125    writeln(c_prog, "typedef struct winStruct {");
5126    writeln(c_prog, "  uintType usage_count;");
5127    writeln(c_prog, "} *winType;");
5128    writeln(c_prog, "typedef const struct winStruct *const_winType;");
5129    writeln(c_prog, "typedef struct processStruct {");
5130    writeln(c_prog, "  uintType usage_count;");
5131    writeln(c_prog, "  fileType stdIn;");
5132    writeln(c_prog, "  fileType stdOut;");
5133    writeln(c_prog, "  fileType stdErr;");
5134    writeln(c_prog, "} *processType;");
5135    writeln(c_prog, "typedef const struct processStruct *const_processType;");
5136    writeln(c_prog, "typedef struct databaseStruct {");
5137    writeln(c_prog, "  uintType usage_count;");
5138    writeln(c_prog, "} *databaseType;");
5139    writeln(c_prog, "typedef const struct databaseStruct *const_databaseType;");
5140    writeln(c_prog, "typedef struct sqlStmtStruct {");
5141    writeln(c_prog, "  uintType usage_count;");
5142    writeln(c_prog, "} *sqlStmtType;");
5143    writeln(c_prog, "typedef const struct sqlStmtStruct *const_sqlStmtType;");
5144    writeln(c_prog, "typedef struct progStruct {");
5145    writeln(c_prog, "  uintType usage_count;");
5146    writeln(c_prog, "} *progType;");
5147    writeln(c_prog, "typedef const struct progStruct *const_progType;");
5148    writeln(c_prog, "typedef struct typeStruct *typeType;");
5149    writeln(c_prog, "typedef const struct typeStruct *const_typeType;");
5150    writeln(c_prog, "typedef struct rtlArrayStruct *arrayType;");
5151    writeln(c_prog, "typedef const struct rtlArrayStruct *const_arrayType;");
5152    writeln(c_prog, "typedef struct rtlHashStruct *hashType;");
5153    writeln(c_prog, "typedef const struct rtlHashStruct *const_hashType;");
5154    writeln(c_prog, "typedef struct rtlStructStruct *structType;");
5155    writeln(c_prog, "typedef const struct rtlStructStruct *const_structType;");
5156    writeln(c_prog, "typedef struct rtlStructStruct *interfaceType;");
5157    writeln(c_prog, "typedef const struct rtlStructStruct *const_interfaceType;");
5158    writeln(c_prog, "typedef struct objectStruct *objRefType;");
5159    writeln(c_prog, "typedef const struct objectStruct *const_objRefType;");
5160    writeln(c_prog, "typedef struct listStruct *listType;");
5161    writeln(c_prog, "typedef const struct listStruct *const_listType;");
5162    writeln(c_prog, "typedef objRefType (*actType) (listType);");
5163    writeln(c_prog, "typedef int socketType;");
5164    writeln(c_prog, "typedef uint" <& ccConf.GENERIC_SIZE <& "Type genericType;");
5165    writeln(c_prog, "typedef union {");
5166    writeln(c_prog, "  genericType   genericValue;");
5167    writeln(c_prog, "  typeType      typeValue;");
5168    writeln(c_prog, "  boolType      boolValue;");
5169    writeln(c_prog, "  enumType      enumValue;");
5170    writeln(c_prog, "  intType       intValue;");
5171    writeln(c_prog, "  bigIntType    bigIntValue;");
5172    writeln(c_prog, "  floatType     floatValue;");
5173    writeln(c_prog, "  charType      charValue;");
5174    writeln(c_prog, "  striType      striValue;");
5175    writeln(c_prog, "  bstriType     bstriValue;");
5176    writeln(c_prog, "  fileType      fileValue;");
5177    writeln(c_prog, "  socketType    socketValue;");
5178    writeln(c_prog, "  pollType      pollValue;");
5179    writeln(c_prog, "  setType       setValue;");
5180    writeln(c_prog, "  winType       winValue;");
5181    writeln(c_prog, "  processType   processValue;");
5182    writeln(c_prog, "  progType      progValue;");
5183    writeln(c_prog, "  databaseType  databaseValue;");
5184    writeln(c_prog, "  sqlStmtType   sqlStmtValue;");
5185    writeln(c_prog, "  arrayType     arrayValue;");
5186    writeln(c_prog, "  hashType      hashValue;");
5187    writeln(c_prog, "  structType    structValue;");
5188    writeln(c_prog, "  interfaceType interfaceValue;");
5189    writeln(c_prog, "  objRefType    objRefValue;");
5190    writeln(c_prog, "  listType      listValue;");
5191    writeln(c_prog, "  actType       actValue;");
5192    writeln(c_prog, "} rtlValueUnion;");
5193    writeln(c_prog, "typedef union {");
5194    writeln(c_prog, "  genericType         genericValue;");
5195    writeln(c_prog, "  const_typeType      typeValue;");
5196    writeln(c_prog, "  boolType            boolValue;");
5197    writeln(c_prog, "  enumType            enumValue;");
5198    writeln(c_prog, "  intType             intValue;");
5199    writeln(c_prog, "  const_bigIntType    bigIntValue;");
5200    writeln(c_prog, "  floatType           floatValue;");
5201    writeln(c_prog, "  charType            charValue;");
5202    writeln(c_prog, "  const_striType      striValue;");
5203    writeln(c_prog, "  const_bstriType     bstriValue;");
5204    writeln(c_prog, "  fileType            fileValue;");
5205    writeln(c_prog, "  socketType          socketValue;");
5206    writeln(c_prog, "  const_pollType      pollValue;");
5207    writeln(c_prog, "  const_setType       setValue;");
5208    writeln(c_prog, "  const_winType       winValue;");
5209    writeln(c_prog, "  const_processType   processValue;");
5210    writeln(c_prog, "  const_progType      progValue;");
5211    writeln(c_prog, "  const_arrayType     arrayValue;");
5212    writeln(c_prog, "  const_hashType      hashValue;");
5213    writeln(c_prog, "  const_structType    structValue;");
5214    writeln(c_prog, "  const_interfaceType interfaceValue;");
5215    writeln(c_prog, "  const_objRefType    objRefValue;");
5216    writeln(c_prog, "  const_listType      listValue;");
5217    writeln(c_prog, "  actType             actValue;");
5218    writeln(c_prog, "} const_rtlValueUnion;");
5219    writeln(c_prog, "typedef struct rtlObjectStruct {");
5220    writeln(c_prog, "  rtlValueUnion value;");
5221    writeln(c_prog, "} rtlObjectType;");
5222    writeln(c_prog, "typedef const struct rtlObjectStruct const_rtlObjectType;");
5223    writeln(c_prog, "typedef intType (*intfunctype)();");
5224    writeln(c_prog, "typedef uint16Type categoryType;");
5225    writeln(c_prog, "struct objectStruct {");
5226    writeln(c_prog, "  typeType type_of;");
5227    writeln(c_prog, "  uint" <& ccConf.POINTER_SIZE <& "Type descriptor;");
5228    writeln(c_prog, "  rtlValueUnion value;");
5229    writeln(c_prog, "  categoryType objcategory;");
5230    writeln(c_prog, "};");
5231    writeln(c_prog, "struct typeStruct {");
5232    writeln(c_prog, "  objRefType match_obj;");
5233    writeln(c_prog, "  typeType meta;");
5234    writeln(c_prog, "  typeType func_type;");
5235    writeln(c_prog, "  typeType varfunc_type;");
5236    writeln(c_prog, "  typeType result_type;");
5237    writeln(c_prog, "  boolType is_varfunc_type;");
5238    writeln(c_prog, "  void *interfaces;");
5239    writeln(c_prog, "  void *name;");
5240    writeln(c_prog, "};");
5241    writeln(c_prog, "struct listStruct {");
5242    writeln(c_prog, "  listType next;");
5243    writeln(c_prog, "  objRefType obj;");
5244    writeln(c_prog, "};");
5245    writeln(c_prog, "struct rtlArrayStruct {");
5246    writeln(c_prog, "  intType min_position;");
5247    writeln(c_prog, "  intType max_position;");
5248    writeln(c_prog, "  rtlObjectType arr[1];");
5249    writeln(c_prog, "};");
5250    writeln(c_prog, "struct rtlStructStruct {");
5251    writeln(c_prog, "  memSizeType usage_count;");
5252    writeln(c_prog, "  uint32Type type_num;");
5253    writeln(c_prog, "  rtlObjectType stru[1];");
5254    writeln(c_prog, "};");
5255    writeln(c_prog, "typedef struct freeListElemStruct {");
5256    writeln(c_prog, "  struct freeListElemStruct *next;");
5257    writeln(c_prog, "} *freeListElemType;");
5258    writeln(c_prog, "typedef struct rtlHashElemStruct *hashElemType;");
5259    writeln(c_prog, "typedef const struct rtlHashElemStruct *const_hashElemType;");
5260    writeln(c_prog, "typedef struct rtlHashElemStruct *const hashElemType_const;");
5261    writeln(c_prog, "struct rtlHashElemStruct {");
5262    writeln(c_prog, "  hashElemType next_less;");
5263    writeln(c_prog, "  hashElemType next_greater;");
5264    writeln(c_prog, "  rtlObjectType key;");
5265    writeln(c_prog, "  rtlObjectType data;");
5266    writeln(c_prog, "};");
5267    writeln(c_prog, "struct rtlHashStruct {");
5268    writeln(c_prog, "  unsigned int bits;");
5269    writeln(c_prog, "  unsigned int mask;");
5270    writeln(c_prog, "  unsigned int table_size;");
5271    writeln(c_prog, "  memSizeType size;");
5272    writeln(c_prog, "  hashElemType table[1];");
5273    writeln(c_prog, "};");
5274    writeln(c_prog, "typedef struct hashElemListStruct {");
5275    writeln(c_prog, "  struct hashElemListStruct *next;");
5276    writeln(c_prog, "  hashElemType obj;");
5277    writeln(c_prog, "} *hashElemListType;");
5278    writeln(c_prog, "typedef union {");
5279    writeln(c_prog, "  uint32Type bits;");
5280    writeln(c_prog, "  float aFloat;");
5281    writeln(c_prog, "} float2BitsUnion;");
5282    writeln(c_prog, "typedef union {");
5283    writeln(c_prog, "  uint64Type bits;");
5284    writeln(c_prog, "  double aDouble;");
5285    writeln(c_prog, "} double2BitsUnion;");
5286    writeln(c_prog, "typedef intType (*compareType) (genericType, genericType);");
5287    writeln(c_prog, "typedef genericType (*createFuncType) (genericType);");
5288    writeln(c_prog, "typedef void (*destrFuncType) (genericType);");
5289    writeln(c_prog, "typedef void (*copyFuncType) (genericType *, genericType);");
5290    writeln(c_prog, "#define bitset_shift " <& log2(ccConf.INTTYPE_SIZE));
5291    writeln(c_prog, "#define bitset_mask  ((1 << bitset_shift) - 1)");
5292    if ccConf.RSHIFT_DOES_SIGN_EXTEND then
5293      writeln(c_prog, "#define bitset_pos(number) ((number)>>bitset_shift)");
5294    else
5295      writeln(c_prog, "#define bitset_pos(number) ((number)<0?~(~(number)>>bitset_shift):(number)>>bitset_shift)");
5296    end if;
5297    writeln(c_prog, "striType          arg_0;");
5298    writeln(c_prog, "striType          programName;");
5299    writeln(c_prog, "striType          programPath;");
5300    writeln(c_prog, "arrayType         arg_v;");
5301    if ccConf.ALLOW_STRITYPE_SLICES then
5302      writeln(c_prog, "extern struct striStruct str[];");
5303    else
5304      writeln(c_prog, "extern striType   str[];");
5305    end if;
5306    if ccConf.ALLOW_BSTRITYPE_SLICES then
5307      writeln(c_prog, "extern struct bstriStruct bst[];");
5308    else
5309      writeln(c_prog, "extern bstriType  bst[];");
5310    end if;
5311    writeln(c_prog, "extern setType          set[];");
5312    writeln(c_prog, "extern typeType         typ[];");
5313    writeln(c_prog, "extern double2BitsUnion nanValue[];");
5314    writeln(c_prog, "bigIntType             *big;");
5315    writeln(c_prog, "winType                *win;");
5316    writeln(c_prog, "arrayType              *arr;");
5317    writeln(c_prog, "structType             *sct;");
5318    writeln(c_prog, "hashType               *hsh;");
5319    writeln(c_prog, "interfaceType          *itf;");
5320    writeln(c_prog, "hashType               *caseLabels;");
5321    writeln(c_prog, "rtlValueUnion           flt2int;");
5322    writeln(c_prog, "extern memSizeType hs;");
5323    writeln(c_prog);
5324    writeln(c_prog, "static const intType fact[] = {");
5325    writeln(c_prog, "    1, 1, 2, 6, 24, 120, 720, 5040, 40320,");
5326    writeln(c_prog, "    362880, 3628800, 39916800, 479001600,");
5327    if ccConf.INTTYPE_SIZE = 64 then
5328      writeln(c_prog, "    6227020800, 87178291200, 1307674368000, 20922789888000,");
5329      writeln(c_prog, "    355687428096000, 6402373705728000, 121645100408832000,");
5330      writeln(c_prog, "    2432902008176640000");
5331    end if;
5332    writeln(c_prog, "  };");
5333    if ccConf.FLOAT_ZERO_DIV_ERROR then
5334      writeln(c_prog, "extern const rtlValueUnion f_const[];");
5335      writeln(c_prog, "#define NOT_A_NUMBER      f_const[0].floatValue");
5336      writeln(c_prog, "#define POSITIVE_INFINITY f_const[1].floatValue");
5337      writeln(c_prog, "#define NEGATIVE_INFINITY f_const[2].floatValue");
5338    else
5339      writeln(c_prog, "#define NOT_A_NUMBER      ( 0.0 / 0.0)");
5340      writeln(c_prog, "#define POSITIVE_INFINITY ( 1.0 / 0.0)");
5341      writeln(c_prog, "#define NEGATIVE_INFINITY (-1.0 / 0.0)");
5342    end if;
5343    writeln(c_prog, "extern const floatType negativeZero;");
5344    writeln(c_prog, "extern struct fileStruct nullFileRecord;");
5345    writeln(c_prog, "extern struct fileStruct stdinFileRecord;");
5346    writeln(c_prog, "extern struct fileStruct stdoutFileRecord;");
5347    writeln(c_prog, "extern struct fileStruct stderrFileRecord;");
5348    writeln(c_prog, "typedef int errInfoType;");
5349    writeln(c_prog, "#define OKAY_NO_ERROR   0");
5350    writeln(c_prog, "#define MEMORY_ERROR    1");
5351    writeln(c_prog, "#define NUMERIC_ERROR   2");
5352    writeln(c_prog, "#define OVERFLOW_ERROR  3");
5353    writeln(c_prog, "#define RANGE_ERROR     4");
5354    writeln(c_prog, "#define INDEX_ERROR     5");
5355    writeln(c_prog, "#define FILE_ERROR      6");
5356    writeln(c_prog, "#define DATABSE_ERROR   7");
5357    writeln(c_prog, "#define ACTION_ERROR    8");
5358    writeln(c_prog, "#define CREATE_ERROR    9");
5359    writeln(c_prog, "#define DESTROY_ERROR  10");
5360    writeln(c_prog, "#define COPY_ERROR     11");
5361    writeln(c_prog, "#define IN_ERROR       12");
5362    writeln(c_prog, "static const char *exception_name[] = {");
5363    writeln(c_prog, "    \"OKAY_NO_ERROR\",");
5364    writeln(c_prog, "    \"MEMORY_ERROR\",");
5365    writeln(c_prog, "    \"NUMERIC_ERROR\",");
5366    writeln(c_prog, "    \"OVERFLOW_ERROR\",");
5367    writeln(c_prog, "    \"RANGE_ERROR\",");
5368    writeln(c_prog, "    \"INDEX_ERROR\",");
5369    writeln(c_prog, "    \"FILE_ERROR\",");
5370    writeln(c_prog, "    \"DATABASE_ERROR\",");
5371    writeln(c_prog, "    \"ACTION_ERROR\",");
5372    writeln(c_prog, "    \"CREATE_ERROR\",");
5373    writeln(c_prog, "    \"DESTROY_ERROR\",");
5374    writeln(c_prog, "    \"COPY_ERROR\",");
5375    writeln(c_prog, "    \"IN_ERROR\",");
5376    writeln(c_prog, "  };");
5377    writeln(c_prog, ccConf.MACRO_DEFS);
5378    writeln(c_prog, "#define ovfChk(x) unlikely(x)");
5379    writeln(c_prog, "#define divChk(x) unlikely(x)");
5380    writeln(c_prog, "#define numChk(x) unlikely(x)");
5381    writeln(c_prog, "#define idxChk(x) unlikely(x)");
5382    writeln(c_prog, "#define rngChk(x) unlikely(x)");
5383    writeln(c_prog, "#define push_stack(stack,elem) \\");
5384    writeln(c_prog, "{\\");
5385    writeln(c_prog, "  hashElemListType new_head = (hashElemListType)(malloc(sizeof(struct hashElemListStruct)));\\");
5386    writeln(c_prog, "  if (new_head == NULL) {\\");
5387    writeln(c_prog, "    raiseError(MEMORY_ERROR);\\");
5388    writeln(c_prog, "  } else {\\");
5389    writeln(c_prog, "    new_head->next = stack;\\");
5390    writeln(c_prog, "    new_head->obj = elem;\\");
5391    writeln(c_prog, "    stack = new_head;\\");
5392    writeln(c_prog, "  }\\");
5393    writeln(c_prog, "}");
5394    writeln(c_prog, "#define pop_stack(stack,elem) \\");
5395    writeln(c_prog, "{\\");
5396    writeln(c_prog, "  hashElemListType old_head = stack;\\");
5397    writeln(c_prog, "  if (old_head == NULL) {\\");
5398    writeln(c_prog, "    elem = NULL;\\");
5399    writeln(c_prog, "  } else {\\");
5400    writeln(c_prog, "    stack = old_head->next;\\");
5401    writeln(c_prog, "    elem = old_head->obj;\\");
5402    writeln(c_prog, "    free(old_head);\\");
5403    writeln(c_prog, "  }\\");
5404    writeln(c_prog, "}");
5405    if ccConf.HAS_SIGSETJMP then
5406      writeln(c_prog, "#define do_setjmp(jump_buf) sigsetjmp(jump_buf, 1)");
5407      writeln(c_prog, "typedef sigjmp_buf catch_type;");
5408    else
5409      writeln(c_prog, "#define do_setjmp(jump_buf) setjmp(jump_buf)");
5410      writeln(c_prog, "typedef jmp_buf catch_type;");
5411    end if;
5412    writeln(c_prog, "catch_type *catch_stack;");
5413    writeln(c_prog, "size_t catch_stack_pos;");
5414    writeln(c_prog, "size_t max_catch_stack;");
5415    writeln(c_prog, "const char *error_file = NULL;");
5416    writeln(c_prog, "int error_line = 0;");
5417    if profile_function then
5418      writeln(c_prog, "intType timMicroSec (void);");
5419      writeln(c_prog, "static unsigned int profile_size;");
5420      writeln(c_prog, "struct profileElement {");
5421      writeln(c_prog, "  intType time;");
5422      writeln(c_prog, "  intType count;");
5423      writeln(c_prog, "  intType depth;");
5424      writeln(c_prog, "  char *file;");
5425      writeln(c_prog, "  intType line;");
5426      writeln(c_prog, "  char *name;");
5427      writeln(c_prog, "};");
5428      writeln(c_prog, "static struct profileElement profile[];");
5429      writeln(c_prog, "static void initProfile (void);");
5430      writeln(c_prog, "static int cmpProfileElement (const void *elem1, const void *elem2)");
5431      writeln(c_prog, "{");
5432      writeln(c_prog, "  int signumValue;");
5433      writeln(c_prog, "  if (((struct profileElement *) elem1)->time <");
5434      writeln(c_prog, "      ((struct profileElement *) elem2)->time) {");
5435      writeln(c_prog, "    signumValue = 1;");
5436      writeln(c_prog, "  } else if (((struct profileElement *) elem1)->time >");
5437      writeln(c_prog, "             ((struct profileElement *) elem2)->time) {");
5438      writeln(c_prog, "    signumValue = -1;");
5439      writeln(c_prog, "  } else if (((struct profileElement *) elem1)->count <");
5440      writeln(c_prog, "             ((struct profileElement *) elem2)->count) {");
5441      writeln(c_prog, "    signumValue = 1;");
5442      writeln(c_prog, "  } else if (((struct profileElement *) elem1)->count >");
5443      writeln(c_prog, "             ((struct profileElement *) elem2)->count) {");
5444      writeln(c_prog, "    signumValue = -1;");
5445      writeln(c_prog, "  } else {");
5446      writeln(c_prog, "    signumValue = strcmp(((struct profileElement *) elem1)->name,");
5447      writeln(c_prog, "                         ((struct profileElement *) elem2)->name);");
5448      writeln(c_prog, "  }");
5449      writeln(c_prog, "  return signumValue;");
5450      writeln(c_prog, "}");
5451    end if;
5452  end func;
5453
5454
5455const proc: declareExtern (in string: prototype) is func
5456
5457  begin
5458    write(c_prog, "extern ");
5459    if declare_with_extern_c then
5460      write(c_prog, "\"C\" ");
5461    end if;
5462    writeln(c_prog, prototype);
5463  end func;
5464
5465
5466const proc: write_prototypes is func
5467
5468  begin
5469    act_prototypes(c_prog);
5470    arr_prototypes(c_prog);
5471    big_prototypes(c_prog);
5472    bin_prototypes(c_prog);
5473    bln_prototypes(c_prog);
5474    bst_prototypes(c_prog);
5475    chr_prototypes(c_prog);
5476    cmd_prototypes(c_prog);
5477    con_prototypes(c_prog);
5478    drw_prototypes(c_prog);
5479    fil_prototypes(c_prog);
5480    flt_prototypes(c_prog);
5481    gkb_prototypes(c_prog);
5482    hsh_prototypes(c_prog);
5483    int_prototypes(c_prog);
5484    itf_prototypes(c_prog);
5485    kbd_prototypes(c_prog);
5486    pcs_prototypes(c_prog);
5487    pol_prototypes(c_prog);
5488    prc_prototypes(c_prog);
5489    prg_prototypes(c_prog);
5490    ref_prototypes(c_prog);
5491    rfl_prototypes(c_prog);
5492    set_prototypes(c_prog);
5493    soc_prototypes(c_prog);
5494    sql_prototypes(c_prog);
5495    str_prototypes(c_prog);
5496    tim_prototypes(c_prog);
5497    typ_prototypes(c_prog);
5498    ut8_prototypes(c_prog);
5499    if ccConf.USE_WMAIN then
5500      declareExtern("arrayType   getArgv (const int, wchar_t *const *const, striType *, striType *, striType *);");
5501    else
5502      declareExtern("arrayType   getArgv (const int, char *const *const, striType *, striType *, striType *);");
5503    end if;
5504    declareExtern("intType     heapsize (void);");
5505    declareExtern("void        setupStack (void);");
5506    declareExtern("void        setupFiles (void);");
5507    declareExtern("void        setupRand (void);");
5508    declareExtern("void        setupFloat (void);");
5509    declareExtern("void        setupBig (void);");
5510    writeln(c_prog, "static void        prcNoop (void) {}");
5511    writeln(c_prog, "static void        init_values (void);");
5512    writeln(c_prog, "static void        init_globals (void);");
5513    declareExtern("void        initPollOperations (const createFuncType, const destrFuncType);");
5514    declareExtern("void        genericCpy (genericType *const, const genericType);");
5515    declareExtern("genericType genericCreate (genericType);");
5516    declareExtern("void        genericDestr (genericType);");
5517    declareExtern("intType     ptrCmp (const void *const, const void *const);");
5518    declareExtern("intType     ptrCmpGeneric (const genericType, const genericType);");
5519    declareExtern("void        ptrCpyGeneric (genericType *const, const genericType);");
5520    declareExtern("genericType ptrCreateGeneric (const genericType);");
5521    writeln(c_prog, "typedef void (*suspendInterprType) (int signalNum);");
5522    declareExtern("void        setupSignalHandlers (boolType, boolType, boolType, boolType, suspendInterprType);");
5523    declareExtern("void        triggerSigfpe (void);");
5524    declareExtern("void        rtlRaiseError (int, const char *, int) NORETURN;");
5525    writeln(c_prog, "#define raiseError(num) rtlRaiseError(num, __FILE__, __LINE__)");
5526    writeln(c_prog, "#define intRaiseError(num) (rtlRaiseError(num, __FILE__, __LINE__), 0)");
5527    writeln(c_prog, "#define bigRaiseError(num) (bigIntType)(rtlRaiseError(num, __FILE__, __LINE__), NULL)");
5528    writeln(c_prog, "#define strRaiseError(num) (striType)(rtlRaiseError(num, __FILE__, __LINE__), NULL)");
5529    writeln(c_prog, "#define refRaiseError(num) (objRefType)(rtlRaiseError(num, __FILE__, __LINE__), NULL)");
5530(*
5531    declareExtern("intType     enuValue (objRefType a)                         {printf(\"enuValue\\n\");}");
5532    declareExtern("intType     enuValue (objRefType);");
5533*)
5534    if trace_signal then
5535      writeln(c_prog, "#define filGetc(inFile) filGetcChkCtrlC(inFile)");
5536      writeln(c_prog, "#define filGets(inFile, length) filGetsChkCtrlC(inFile, length)");
5537      writeln(c_prog, "#define filHasNext(inFile) filHasNextChkCtrlC(inFile)");
5538      writeln(c_prog, "#define filLineRead(inFile, terminationChar) filLineReadChkCtrlC(inFile, terminationChar)");
5539      writeln(c_prog, "#define filWordRead(inFile, terminationChar) filWordReadChkCtrlC(inFile, terminationChar)");
5540    else
5541      writeln(c_prog, "#define filGetc(inFile) (unlikely((inFile)->cFile==NULL)?intRaiseError(FILE_ERROR):fgetc((inFile)->cFile))");
5542    end if;
5543  end func;
5544
5545
5546const proc: write_resize_catch_stack is func
5547
5548  begin
5549    writeln(c_prog);
5550    writeln(c_prog);
5551    writeln(c_prog, "static void resize_catch_stack (void)");
5552    writeln(c_prog);
5553    writeln(c_prog, "  {");
5554    writeln(c_prog, "    catch_type *resized_stack;");
5555    writeln(c_prog);
5556    writeln(c_prog, "    max_catch_stack += 128;");
5557    writeln(c_prog, "    resized_stack = (catch_type *)(realloc(catch_stack, max_catch_stack));");
5558    writeln(c_prog, "    if (resized_stack == NULL) {");
5559    writeln(c_prog, "      catch_stack_pos--;");
5560    writeln(c_prog, "      raiseError(MEMORY_ERROR);");
5561    writeln(c_prog, "    } else {");
5562    writeln(c_prog, "      catch_stack = resized_stack;");
5563    writeln(c_prog, "    }");
5564    writeln(c_prog, "  }");
5565    writeln(c_prog);
5566    writeln(c_prog);
5567  end func;
5568
5569
5570const proc: initPollOperations (inout expr_type: c_expr) is func
5571
5572  begin
5573    if fileInterfaceType <> void then
5574      c_expr.expr &:= "initPollOperations((createFuncType)(&itfCreate), ";
5575      process_destr_declaration(fileInterfaceType, global_c_expr);
5576      c_expr.expr &:= "(destrFuncType)(&destr_";
5577      c_expr.expr &:= str(typeNumber(fileInterfaceType));
5578      c_expr.expr &:= "));\n";
5579    end if;
5580  end func;
5581
5582
5583const func ref_list: determine_multiple_array_elements (in ref_list: array_list) is func
5584
5585  result
5586    var ref_list: elements_to_walk is ref_list.EMPTY;
5587  local
5588    var reference: element is NIL;
5589    var reference: previous_element is NIL;
5590    var reference: repeat_block_element is NIL;
5591    var integer: repeat_count is 0;
5592  begin
5593    for element range array_list do
5594      if previous_element <> NIL then
5595        if identical_values(previous_element, element) then
5596          if repeat_block_element = NIL then
5597            repeat_block_element := previous_element;
5598            repeat_count := 2;
5599          else
5600            incr(repeat_count);
5601          end if;
5602        else
5603          elements_to_walk &:= make_list(element);
5604          if repeat_block_element <> NIL then
5605            element_repeat_count @:= [repeat_block_element] repeat_count;
5606            repeat_block_element := NIL;
5607          end if;
5608        end if;
5609      else
5610        elements_to_walk &:= make_list(element);
5611      end if;
5612      previous_element := element;
5613    end for;
5614    if repeat_block_element <> NIL then
5615      element_repeat_count @:= [repeat_block_element] repeat_count;
5616    end if;
5617  end func;
5618
5619
5620const proc: walk_const_list (in ref_list: const_list, inout ref_list: sorted_list) is func
5621
5622  local
5623    var reference: current_object is NIL;
5624    var reference: struct_of_interface is NIL;
5625    var category: objectCategory is category.value;
5626    var ref_list: elements_to_walk is ref_list.EMPTY;
5627  begin
5628    for current_object range const_list do
5629      objectCategory := category(current_object);
5630      if objectCategory = BIGINTOBJECT then
5631        if getValue(current_object, bigInteger) not in bigint_const_table then
5632          bigint_const_table @:= [getValue(current_object, bigInteger)] length(bigint_const_table);
5633        end if;
5634      elsif objectCategory = STRIOBJECT then
5635        if getValue(current_object, string) not in stri_const_table then
5636          stri_const_table @:= [getValue(current_object, string)] length(stri_const_table);
5637        end if;
5638      elsif objectCategory = BSTRIOBJECT then
5639        if getValue(current_object, bstring) not in bstri_const_table then
5640          bstri_const_table @:= [getValue(current_object, bstring)] length(bstri_const_table);
5641        end if;
5642      elsif objectCategory = SETOBJECT then
5643        if getValue(current_object, bitset) not in set_const_table then
5644          set_const_table @:= [getValue(current_object, bitset)] length(set_const_table);
5645        end if;
5646      elsif objectCategory = WINOBJECT then
5647        if getValue(current_object, PRIMITIVE_WINDOW) not in win_const_table then
5648          win_const_table @:= [getValue(current_object, PRIMITIVE_WINDOW)] length(win_const_table);
5649        end if;
5650      elsif objectCategory = ARRAYOBJECT then
5651        if current_object not in const_table then
5652          const_table @:= [current_object] length(const_table);
5653        end if;
5654        elements_to_walk := determine_multiple_array_elements(arrayToList(current_object));
5655        walk_const_list(elements_to_walk, sorted_list);
5656        sorted_list &:= make_list(current_object);
5657      elsif objectCategory = STRUCTOBJECT then
5658        if current_object not in const_table then
5659          const_table @:= [current_object] length(const_table);
5660        end if;
5661        walk_const_list(structToList(current_object), sorted_list);
5662        sorted_list &:= make_list(current_object);
5663      elsif objectCategory = HASHOBJECT then
5664        if current_object not in const_table then
5665          const_table @:= [current_object] length(const_table);
5666        end if;
5667        walk_const_list(hashKeysToList(current_object), sorted_list);
5668        walk_const_list(hashDataToList(current_object), sorted_list);
5669        sorted_list &:= make_list(current_object);
5670      elsif objectCategory = INTERFACEOBJECT then
5671        if current_object not in const_table then
5672          const_table @:= [current_object] length(const_table);
5673        end if;
5674        struct_of_interface := interfaceToStruct(current_object);
5675        if struct_of_interface not in const_table then
5676          const_table @:= [struct_of_interface] length(const_table);
5677          walk_const_list(structToList(struct_of_interface), sorted_list);
5678          sorted_list &:= make_list(struct_of_interface);
5679        elsif const_table[struct_of_interface] >= const_table[current_object] then
5680          sorted_list &:= make_list(struct_of_interface);
5681        end if;
5682        sorted_list &:= make_list(current_object);
5683      elsif objectCategory = MATCHOBJECT or objectCategory = ACTOBJECT or
5684          objectCategory = BLOCKOBJECT then
5685        if current_object not in const_table then
5686          const_table @:= [current_object] length(const_table);
5687        end if;
5688        sorted_list &:= make_list(current_object);
5689      end if;
5690    end for;
5691  end func;
5692
5693
5694const proc: prepare_func_literal (in reference: current_object,
5695    inout expr_type: c_expr) is func
5696
5697  local
5698    var expr_type: c_value is expr_type.value;
5699    var string: valueName is "";
5700  begin
5701    create_name(current_object, objNumber(current_object), valueName);
5702    processFuncValue(valueName, getType(current_object), current_object, c_value);
5703    global_c_expr.expr &:= c_value.temp_decls;
5704    global_init.expr &:= diagnosticLine(current_object);
5705    global_init.expr &:= c_value.temp_assigns;
5706    function_declared @:= [current_object] TRUE;
5707  end func;
5708
5709
5710const proc: process_func_literal (in reference: current_object,
5711    inout expr_type: c_expr) is func
5712
5713  local
5714    var string: valueName is "";
5715  begin
5716    create_name(current_object, objNumber(current_object), valueName);
5717    c_expr.expr &:= "&funcvalue_";
5718    c_expr.expr &:= valueName;
5719  end func;
5720
5721
5722const proc: process_pollData_literal (in var pollData: aPollData,
5723    inout expr_type: c_expr) is func
5724
5725  begin
5726    c_expr.expr &:= "polEmpty()";
5727  end func;
5728
5729
5730const proc: init_const_value (in reference: current_object, inout expr_type: c_expr) is func
5731
5732  local
5733    var category: objectCategory is category.value;
5734  begin
5735    objectCategory := category(current_object);
5736    if objectCategory = INTOBJECT then
5737      c_expr.expr &:= ".value.intValue=";
5738      c_expr.expr &:= integerLiteral(getValue(current_object, integer));
5739    elsif objectCategory = BIGINTOBJECT then
5740      c_expr.expr &:= ".value.bigIntValue=";
5741      c_expr.expr &:= bigIntegerLiteral(getValue(current_object, bigInteger));
5742    elsif objectCategory = CHAROBJECT then
5743      c_expr.expr &:= ".value.charValue=";
5744      c_expr.expr &:= charLiteral(getValue(current_object, char));
5745    elsif objectCategory = STRIOBJECT then
5746      c_expr.expr &:= ".value.striValue=";
5747      c_expr.expr &:= stringLiteral(getValue(current_object, string));
5748    elsif objectCategory = BSTRIOBJECT then
5749      c_expr.expr &:= ".value.bstriValue=";
5750      c_expr.expr &:= bstriLiteral(getValue(current_object, bstring));
5751    elsif objectCategory = SETOBJECT then
5752      c_expr.expr &:= ".value.setValue=";
5753      c_expr.expr &:= bitsetLiteral(getValue(current_object, bitset));
5754    elsif objectCategory = FLOATOBJECT then
5755      c_expr.expr &:= ".value.floatValue=";
5756      c_expr.expr &:= floatLiteral(getValue(current_object, float));
5757    elsif objectCategory = REFOBJECT then
5758      c_expr.expr &:= ".value.objRefValue=";
5759      if getValue(current_object, reference) = NIL then
5760        c_expr.expr &:= "NULL";
5761      else
5762        c_expr.expr &:= "(objRefType)(&(";
5763        process_expr(getValue(current_object, reference), c_expr);
5764        c_expr.expr &:= "))";
5765      end if;
5766    elsif objectCategory = FILEOBJECT then
5767      c_expr.expr &:= ".value.fileValue=&";
5768      c_expr.expr &:= lower(literal(getValue(current_object, clib_file)));
5769      c_expr.expr &:= "FileRecord";
5770    elsif objectCategory = SOCKETOBJECT then
5771      c_expr.expr &:= ".value.intValue=";
5772      c_expr.expr &:= "-1";
5773    elsif objectCategory = POLLOBJECT then
5774      c_expr.expr &:= ".value.pollValue=";
5775      process_pollData_literal(getValue(current_object, pollData), c_expr);
5776    elsif objectCategory = WINOBJECT then
5777      c_expr.expr &:= ".value.winValue=drwCreate(";
5778      c_expr.expr &:= windowLiteral(getValue(current_object, PRIMITIVE_WINDOW));
5779      c_expr.expr &:= ")";
5780    elsif objectCategory = PROCESSOBJECT then
5781      c_expr.expr &:= ".value.processValue=";
5782      c_expr.expr &:= "NULL";
5783    elsif objectCategory = TYPEOBJECT then
5784      c_expr.expr &:= ".value.typeValue=";
5785      c_expr.expr &:= typeLiteral(getValue(current_object, type));
5786    elsif objectCategory = CONSTENUMOBJECT then
5787      c_expr.expr &:= select_value_from_rtlObjectStruct(
5788          getType(getValue(current_object, reference)));
5789      c_expr.expr &:= "=";
5790      c_expr.expr &:= enum_value(getValue(current_object, reference));
5791    elsif objectCategory = VARENUMOBJECT then
5792      c_expr.expr &:= select_value_from_rtlObjectStruct(
5793          getType(getValue(current_object, reference)));
5794      c_expr.expr &:= "=";
5795      c_expr.expr &:= enum_value(getValue(current_object, reference));
5796    elsif objectCategory = ARRAYOBJECT then
5797      c_expr.expr &:= ".value.arrayValue=";
5798      c_expr.expr &:= "arr[";
5799      c_expr.expr &:= str(const_table[current_object]);
5800      c_expr.expr &:= "]";
5801    elsif objectCategory = STRUCTOBJECT then
5802      c_expr.expr &:= ".value.structValue=";
5803      c_expr.expr &:= "sct[";
5804      c_expr.expr &:= str(const_table[current_object]);
5805      c_expr.expr &:= "]";
5806    elsif objectCategory = HASHOBJECT then
5807      c_expr.expr &:= ".value.hashValue=";
5808      c_expr.expr &:= "hsh[";
5809      c_expr.expr &:= str(const_table[current_object]);
5810      c_expr.expr &:= "]";
5811    elsif objectCategory = INTERFACEOBJECT then
5812      c_expr.expr &:= ".value.interfaceValue=itfCreate(itf[";
5813      c_expr.expr &:= str(const_table[current_object]);
5814      c_expr.expr &:= "])";
5815    elsif objectCategory = MATCHOBJECT or objectCategory = ACTOBJECT or
5816        objectCategory = BLOCKOBJECT then
5817      c_expr.expr &:= ".value.genericValue=";
5818      process_func_literal(current_object, c_expr);
5819    else
5820      c_expr.expr &:= "/* ";
5821      c_expr.expr &:= str(objectCategory);
5822      c_expr.expr &:= " */";
5823    end if;
5824  end func;
5825
5826
5827const func string: int32AsFourBytes (in integer: number) is func
5828  result
5829    var string: stri is "";
5830  begin
5831    if ccConf.LITTLE_ENDIAN_INTTYPE then
5832      stri := bytes(number, UNSIGNED, LE, 4);
5833    else
5834      stri := bytes(number, UNSIGNED, BE, 4);
5835    end if;
5836  end func;
5837
5838
5839const func string: int64AsEightBytes (in integer: number) is func
5840  result
5841    var string: stri is "";
5842  begin
5843    if ccConf.LITTLE_ENDIAN_INTTYPE then
5844      stri := bytes(number, UNSIGNED, LE, 8);
5845    else
5846      stri := bytes(number, UNSIGNED, BE, 8);
5847    end if;
5848  end func;
5849
5850
5851const func string: int64AsTwoInt32 (in bigInteger: number) is func
5852
5853  result
5854    var string: literals is "";
5855  begin
5856    if ccConf.LITTLE_ENDIAN_INTTYPE then
5857      literals := str( number        mod 16#100000000_) &
5858                  "," &
5859                  str((number >> 32) mod 16#100000000_) &
5860                  ",";
5861    else
5862      literals := str((number >> 32) mod 16#100000000_) &
5863                  "," &
5864                  str( number        mod 16#100000000_) &
5865                  ",";
5866    end if;
5867  end func;
5868
5869
5870const proc: init_bigint_constants is func
5871
5872  local
5873    var bigint_index_hash: bigint_index is bigint_index_hash.EMPTY_HASH;
5874    var integer: number is 0;
5875    var bstring: bstri is bstring.value;
5876  begin
5877    bigint_index := flip(bigint_const_table);
5878    for number range sort(keys(bigint_index)) do
5879      bstri := bStriLe(bigint_index[number][1], TRUE);
5880      if bstri not in bstri_const_table then
5881        bstri_const_table @:= [bstri] length(bstri_const_table);
5882      end if;
5883      bigint_bstri_table @:= [number] bstri_const_table[bstri];
5884    end for;
5885  end func;
5886
5887
5888const proc: assign_bigint_constants (inout expr_type: c_expr) is func
5889
5890  local
5891    var bigint_index_hash: bigint_index is bigint_index_hash.EMPTY_HASH;
5892    var bigInteger: big1 is bigInteger.value;
5893    var integer: number is 0;
5894  begin
5895    if length(bigint_const_table) = 0 then
5896      c_expr.expr &:= "big = NULL;\n";
5897    else
5898      c_expr.expr &:= "big = (bigIntType *)(malloc(";
5899      c_expr.expr &:= str(length(bigint_const_table));
5900      c_expr.expr &:= " * sizeof(bigIntType)));\n";
5901      bigint_index := flip(bigint_const_table);
5902      for number range sort(keys(bigint_index)) do
5903        big1 := bigint_index[number][1];
5904        c_expr.expr &:= "big[";
5905        c_expr.expr &:= str(number);
5906        c_expr.expr &:= "]=bigFromBStriLe(";
5907        if ccConf.ALLOW_BSTRITYPE_SLICES then
5908          c_expr.expr &:= "&";
5909        end if;
5910        c_expr.expr &:= "bst[";
5911        c_expr.expr &:= str(bigint_bstri_table[number]);
5912        c_expr.expr &:= "], 1);";
5913        if bitLength(big1) <= MAX_SHOWN_BIGINT_LITERAL_BITLENGTH then
5914          c_expr.expr &:= " /* ";
5915          c_expr.expr &:= str(big1);
5916          c_expr.expr &:= " */";
5917        end if;
5918        c_expr.expr &:= "\n";
5919      end for;
5920    end if;
5921  end func;
5922
5923
5924const proc: init_win_constants is func
5925
5926  local
5927    var win_index_hash: win_index is win_index_hash.EMPTY_HASH;
5928    var PRIMITIVE_WINDOW: win1 is PRIMITIVE_WINDOW.value;
5929    var integer: number is 0;
5930    var integer: line is 0;
5931    var integer: column is 0;
5932    var pixel: pix is pixel.value;
5933    var string: image is "";
5934    var bstring: bImage is bstring.value;
5935  begin
5936    win_index := flip(win_const_table);
5937    for number range sort(keys(win_index)) do
5938      win1 := win_index[number][1];
5939      if width(win1) <> 0 or height(win1) <> 0 then
5940        bImage := getImage(win1);
5941        if bImage not in bstri_const_table then
5942          bstri_const_table @:= [bImage] length(bstri_const_table);
5943        end if;
5944        win_bstri_table @:= [number] bstri_const_table[bImage];
5945      end if;
5946    end for;
5947  end func;
5948
5949
5950const proc: assign_win_constants (inout expr_type: c_expr) is func
5951
5952  local
5953    var win_index_hash: win_index is win_index_hash.EMPTY_HASH;
5954    var PRIMITIVE_WINDOW: win1 is PRIMITIVE_WINDOW.value;
5955    var integer: number is 0;
5956  begin
5957    if length(win_const_table) = 0 then
5958      c_expr.expr &:= "win = NULL;\n";
5959    else
5960      c_expr.expr &:= "win = (winType *)(malloc(";
5961      c_expr.expr &:= str(length(win_const_table));
5962      c_expr.expr &:= " * sizeof(winType)));\n";
5963      win_index := flip(win_const_table);
5964      for number range sort(keys(win_index)) do
5965        win1 := win_index[number][1];
5966        c_expr.expr &:= "win[";
5967        c_expr.expr &:= str(number);
5968        c_expr.expr &:= "]=";
5969        if width(win1) = 0 and height(win1) = 0 then
5970          c_expr.expr &:= "drwEmpty();\n";
5971        else
5972          c_expr.expr &:= "drwImage((int32Type *)((";
5973          if ccConf.ALLOW_BSTRITYPE_SLICES then
5974            c_expr.expr &:= "&";
5975          end if;
5976          c_expr.expr &:= "bst[";
5977          c_expr.expr &:= str(win_bstri_table[number]);
5978          c_expr.expr &:= "])->mem), ";
5979          c_expr.expr &:= str(width(win1));
5980          c_expr.expr &:= ", ";
5981          c_expr.expr &:= str(height(win1));
5982          c_expr.expr &:= ");\n";
5983        end if;
5984      end for;
5985    end if;
5986  end func;
5987
5988
5989const proc: write_striChars (in string: striChars, inout expr_type: c_expr) is func
5990  local
5991    var integer: countChars is 0;
5992    var char: ch is ' ';
5993  begin
5994    if length(striChars) <> 0 then
5995      c_expr.expr &:= "static strElemType striChars[";
5996      c_expr.expr &:= str(length(striChars));
5997      c_expr.expr &:= "]={\n";
5998      for ch range striChars do
5999        c_expr.expr &:= c_literal(ch);
6000        c_expr.expr &:= ",";
6001        incr(countChars);
6002        if countChars = 20 then
6003          c_expr.expr &:= "\n";
6004          countChars := 0;
6005        end if;
6006      end for;
6007      c_expr.expr &:= "};\n\n";
6008    end if;
6009  end func;
6010
6011
6012const proc: write_str_table (in stri_index_hash: stri_index,
6013    in array integer: stringPosition, inout expr_type: c_expr) is func
6014  local
6015    var integer: number is 0;
6016    var string: stri is "";
6017  begin
6018    c_expr.expr &:= "struct striStruct str[]={\n";
6019    if length(stri_const_table) > 0 then
6020      for number range 0 to pred(length(stri_const_table)) do
6021        stri := stri_index[number][1];
6022        c_expr.expr &:= "/* str[";
6023        c_expr.expr &:= str(number);
6024        c_expr.expr &:= "] */ {";
6025        c_expr.expr &:= str(length(stri));
6026        c_expr.expr &:= ",";
6027        if ccConf.WITH_STRI_CAPACITY then
6028          c_expr.expr &:= str(length(stri));
6029          c_expr.expr &:= ",";
6030        end if;
6031        if stri = "" then
6032          c_expr.expr &:= "NULL";
6033        else
6034          c_expr.expr &:= "&striChars[";
6035          c_expr.expr &:= str(pred(stringPosition[number]));
6036          c_expr.expr &:= "]";
6037        end if;
6038        c_expr.expr &:= "},";
6039        c_expr.expr &:= stringInComment(stri);
6040        c_expr.expr &:= "\n";
6041      end for;
6042    else
6043      c_expr.expr &:= "/* dummy */ {0,";
6044      if ccConf.WITH_STRI_CAPACITY then
6045        c_expr.expr &:= "0,";
6046      end if;
6047      c_expr.expr &:= "NULL}";
6048    end if;
6049    c_expr.expr &:= "};\n\n";
6050  end func;
6051
6052
6053const proc: init_string_constants_with_slices (in stri_index_hash: stri_index,
6054    inout expr_type: c_expr) is func
6055
6056  local
6057    var stringLengthHash: stringLengths is stringLengthHash.value;
6058    var lengthToStriNumHash: lengthToStriNum is lengthToStriNumHash.value;
6059    var array integer: lengthList is 0 times 0;
6060    var integer: lengthIndex is 0;
6061    var integer: length is 0;
6062    var array integer: stringPosition is 0 times 0;
6063    var integer: number is 0;
6064    var string: stri is "";
6065    var integer: combinedStriLength is 0;
6066    var string: striChars is "";
6067    var integer: striPos is 0;
6068    var integer: striIndex is 0;
6069    var boolean: found is FALSE;
6070  begin
6071    stringPosition := [0 .. pred(length(stri_const_table))] times 0;
6072    for number range 0 to pred(length(stri_const_table)) do
6073      stringLengths @:= [number] length(stri_index[number][1]);
6074    end for;
6075    lengthToStriNum := flip(stringLengths);
6076    lengthList := sort(keys(lengthToStriNum));
6077    for lengthIndex range maxIdx(lengthList) downto minIdx(lengthList) do
6078      length := lengthList[lengthIndex];
6079      if length in lengthToStriNum then
6080        for number range lengthToStriNum[length] do
6081          stri := stri_index[number][1];
6082          combinedStriLength +:= length(stri);
6083          striPos := pos(striChars, stri);
6084          if striPos = 0 then
6085            found := FALSE;
6086            if length(striChars) > length(stri) then
6087              striIndex := rpos(stri, striChars[length(striChars)]);
6088              while striIndex <> 0 and not found do
6089                if stri[.. striIndex] = striChars[succ(length(striChars) - striIndex) ..] then
6090                  stringPosition[number] := succ(length(striChars) - striIndex);
6091                  striChars &:= stri[succ(striIndex) ..];
6092                  found := TRUE;
6093                else
6094                  striIndex := rpos(stri, striChars[length(striChars)], pred(striIndex));
6095                end if;
6096              end while;
6097            end if;
6098            if not found then
6099              stringPosition[number] := succ(length(striChars));
6100              striChars &:= stri;
6101            end if;
6102          else
6103            stringPosition[number] := striPos;
6104          end if;
6105        end for;
6106      end if;
6107    end for;
6108    write_striChars(striChars, c_expr);
6109    write_str_table(stri_index, stringPosition, c_expr);
6110    if SHOW_STATISTIC then
6111      writeln(combinedStriLength <& " chars in all strings");
6112      writeln(length(striChars) <& " chars in string pool");
6113      writeln(combinedStriLength - length(striChars) <& " chars of string memory saved");
6114    end if;
6115  end func;
6116
6117
6118const proc: init_string_constants_no_slices (in stri_index_hash: stri_index,
6119    inout expr_type: c_expr) is func
6120
6121  local
6122    var integer: number is 0;
6123    var string: stri is "";
6124    var char: ch is ' ';
6125  begin
6126    for number range sort(keys(stri_index)) do
6127      stri := stri_index[number][1];
6128      c_expr.expr &:= "/* str[";
6129      c_expr.expr &:= str(number);
6130      c_expr.expr &:= "] */ static strElemType stri_";
6131      c_expr.expr &:= str(number);
6132      c_expr.expr &:= "[]={";
6133      if ccConf.POINTER_SIZE = 32 then
6134        c_expr.expr &:= str(length(stri));
6135        c_expr.expr &:= ",";
6136        if ccConf.WITH_STRI_CAPACITY then
6137          c_expr.expr &:= str(length(stri));
6138          c_expr.expr &:= ",";
6139        end if;
6140      elsif ccConf.POINTER_SIZE = 64 then
6141        c_expr.expr &:= int64AsTwoInt32(bigInteger(length(stri)));
6142        if ccConf.WITH_STRI_CAPACITY then
6143          c_expr.expr &:= int64AsTwoInt32(bigInteger(length(stri)));
6144        end if;
6145      end if;
6146      for ch range stri do
6147        c_expr.expr &:= c_literal(ch);
6148        c_expr.expr &:= ",";
6149      end for;
6150      c_expr.expr &:= "};\n";
6151    end for;
6152    c_expr.expr &:= "striType str[]={\n";
6153    if length(stri_const_table) > 0 then
6154      for number range sort(keys(stri_index)) do
6155        stri := stri_index[number][1];
6156        c_expr.expr &:= "(striType) stri_";
6157        c_expr.expr &:= str(number);
6158        c_expr.expr &:= ",";
6159        c_expr.expr &:= stringInComment(stri);
6160        c_expr.expr &:= "\n";
6161      end for;
6162    else
6163      c_expr.expr &:= "(striType) NULL";
6164    end if;
6165    c_expr.expr &:= "};\n\n";
6166  end func;
6167
6168
6169const proc: init_string_constants (inout expr_type: c_expr) is func
6170
6171  local
6172    var stri_index_hash: stri_index is stri_index_hash.EMPTY_HASH;
6173  begin
6174    stri_index := flip(stri_const_table);
6175    if ccConf.ALLOW_STRITYPE_SLICES then
6176      init_string_constants_with_slices(stri_index, c_expr);
6177    else
6178      init_string_constants_no_slices(stri_index, c_expr);
6179    end if;
6180  end func;
6181
6182
6183const proc: write_bstriChars (in string: bstriChars, inout expr_type: c_expr) is func
6184  local
6185    var char: ch is ' ';
6186    var integer: countChars is 0;
6187  begin
6188    if length(bstriChars) <> 0 then
6189      c_expr.expr &:= "static unsigned char bstriChars[/*";
6190      c_expr.expr &:= str(length(bstriChars));
6191      c_expr.expr &:= "*/]";
6192      countChars := 0;
6193      if ccConf.LIMITED_CSTRI_LITERAL_LEN then
6194        c_expr.expr &:= "={";
6195        c_expr.expr &:= "\n";
6196        for ch range bstriChars do
6197          c_expr.expr &:= c_literal(ch);
6198          c_expr.expr &:= ",";
6199          incr(countChars);
6200          if countChars = 20 then
6201            c_expr.expr &:= "\n";
6202            countChars := 0;
6203          end if;
6204        end for;
6205        c_expr.expr &:= "};\n\n";
6206      else
6207        if length(bstriChars) <> 0 then
6208          c_expr.expr &:= "=";
6209          for countChars range 1 to length(bstriChars) step 40 do
6210            c_expr.expr &:= "\n";
6211            c_expr.expr &:= c_literal(bstriChars[countChars len 40]);
6212          end for;
6213        end if;
6214        c_expr.expr &:= ";\n\n";
6215      end if;
6216    end if;
6217  end func;
6218
6219
6220const proc: write_bst_table (in bstri_index_hash: bstri_index,
6221    in array integer: stringPosition, inout expr_type: c_expr) is func
6222  local
6223    var integer: number is 0;
6224    var string: stri is "";
6225  begin
6226    c_expr.expr &:= "struct bstriStruct bst[]={\n";
6227    if length(bstri_const_table) > 0 then
6228      for number range 0 to pred(length(bstri_const_table)) do
6229        stri := str(bstri_index[number][1]);
6230        c_expr.expr &:= "/* bst[";
6231        c_expr.expr &:= str(number);
6232        c_expr.expr &:= "] */ {";
6233        c_expr.expr &:= str(length(stri));
6234        c_expr.expr &:= ",";
6235        if stri = "" then
6236          c_expr.expr &:= "NULL";
6237        else
6238          c_expr.expr &:= "&bstriChars[";
6239          c_expr.expr &:= str(pred(stringPosition[number]));
6240          c_expr.expr &:= "]";
6241        end if;
6242        c_expr.expr &:= "},";
6243        c_expr.expr &:= stringInComment(stri);
6244        c_expr.expr &:= "\n";
6245      end for;
6246    else
6247      c_expr.expr &:= "/* dummy */ {0,";
6248      c_expr.expr &:= "NULL}";
6249    end if;
6250    c_expr.expr &:= "};\n\n";
6251  end func;
6252
6253
6254const proc: init_bstri_constants_with_slices (in bstri_index_hash: bstri_index,
6255    inout expr_type: c_expr) is func
6256
6257  local
6258    var stringLengthHash: stringLengths is stringLengthHash.value;
6259    var lengthToStriNumHash: lengthToStriNum is lengthToStriNumHash.value;
6260    var array integer: lengthList is 0 times 0;
6261    var integer: lengthIndex is 0;
6262    var integer: length is 0;
6263    var array integer: stringPosition is 0 times 0;
6264    var integer: number is 0;
6265    var string: stri is "";
6266    var integer: combinedBStriLength is 0;
6267    var string: bstriChars is "";
6268    var integer: striPos is 0;
6269    var integer: striIndex is 0;
6270    var boolean: found is FALSE;
6271  begin
6272    stringPosition := [0 .. pred(length(bstri_const_table))] times 0;
6273    for number range 0 to pred(length(bstri_const_table)) do
6274      stringLengths @:= [number] length(bstri_index[number][1]);
6275    end for;
6276    lengthToStriNum := flip(stringLengths);
6277    lengthList := sort(keys(lengthToStriNum));
6278    for lengthIndex range maxIdx(lengthList) downto minIdx(lengthList) do
6279      length := lengthList[lengthIndex];
6280      if length in lengthToStriNum then
6281        for number range lengthToStriNum[length] do
6282          stri := str(bstri_index[number][1]);
6283          combinedBStriLength +:= length(stri);
6284          striPos := pos(bstriChars, stri);
6285          if striPos = 0 then
6286            found := FALSE;
6287            if length(bstriChars) > length(stri) then
6288              striIndex := rpos(stri, bstriChars[length(bstriChars)]);
6289              while striIndex <> 0 and not found do
6290                if stri[.. striIndex] = bstriChars[succ(length(bstriChars) - striIndex) ..] then
6291                  stringPosition[number] := succ(length(bstriChars) - striIndex);
6292                  bstriChars &:= stri[succ(striIndex) ..];
6293                  found := TRUE;
6294                else
6295                  striIndex := rpos(stri, bstriChars[length(bstriChars)], pred(striIndex));
6296                end if;
6297              end while;
6298            end if;
6299            if not found then
6300              stringPosition[number] := succ(length(bstriChars));
6301              bstriChars &:= stri;
6302            end if;
6303          else
6304            stringPosition[number] := striPos;
6305          end if;
6306        end for;
6307      end if;
6308    end for;
6309    write_bstriChars(bstriChars, c_expr);
6310    write_bst_table(bstri_index, stringPosition, c_expr);
6311    if SHOW_STATISTIC then
6312      writeln(combinedBStriLength <& " chars in all bstrings");
6313      writeln(length(bstriChars) <& " chars in bstring pool");
6314      writeln(combinedBStriLength - length(bstriChars) <& " chars of bstring memory saved");
6315    end if;
6316  end func;
6317
6318
6319const proc: init_bstri_constants_no_slices (in bstri_index_hash: bstri_index,
6320    inout expr_type: c_expr) is func
6321
6322  local
6323    var bstring: bstri is bstring.value;
6324    var integer: number is 0;
6325    var string: lengthAsChars is "";
6326    var string: stri is "";
6327    var integer: countChars is 0;
6328    var char: ch is ' ';
6329  begin
6330    for number range sort(keys(bstri_index)) do
6331      bstri := bstri_index[number][1];
6332      c_expr.expr &:= "/* bst[";
6333      c_expr.expr &:= str(number);
6334      c_expr.expr &:= "] */ static const unsigned char bstri_";
6335      c_expr.expr &:= str(number);
6336      if ccConf.POINTER_SIZE = 32 then
6337        lengthAsChars := int32AsFourBytes(length(bstri));
6338      elsif ccConf.POINTER_SIZE = 64 then
6339        lengthAsChars := int64AsEightBytes(length(bstri));
6340      end if;
6341      countChars := 0;
6342      if ccConf.LIMITED_CSTRI_LITERAL_LEN then
6343        c_expr.expr &:= "[]={";
6344        for ch range lengthAsChars do
6345          c_expr.expr &:= c_literal(ch);
6346          c_expr.expr &:= ",";
6347        end for;
6348        c_expr.expr &:= "\n";
6349        for ch range bstri do
6350          c_expr.expr &:= c_literal(ch);
6351          c_expr.expr &:= ",";
6352          incr(countChars);
6353          if countChars = 20 then
6354            c_expr.expr &:= "\n";
6355            countChars := 0;
6356          end if;
6357        end for;
6358        c_expr.expr &:= "};\n";
6359      else
6360        c_expr.expr &:= "[]=";
6361        c_expr.expr &:= c_literal(lengthAsChars);
6362        if length(bstri) <> 0 then
6363          stri := str(bstri);
6364          for countChars range 1 to length(stri) step 40 do
6365            c_expr.expr &:= "\n";
6366            c_expr.expr &:= c_literal(stri[countChars len 40]);
6367          end for;
6368        end if;
6369        c_expr.expr &:= ";\n";
6370      end if;
6371    end for;
6372    c_expr.expr &:= "bstriType bst[]={\n";
6373    if length(bstri_const_table) > 0 then
6374      for number range sort(keys(bstri_index)) do
6375        c_expr.expr &:= "(bstriType) bstri_";
6376        c_expr.expr &:= str(number);
6377        c_expr.expr &:= ",\n";
6378      end for;
6379    else
6380      c_expr.expr &:= "(bstriType) NULL";
6381    end if;
6382    c_expr.expr &:= "};\n\n";
6383  end func;
6384
6385
6386const proc: init_bstri_constants (inout expr_type: c_expr) is func
6387
6388  local
6389    var bstri_index_hash: bstri_index is bstri_index_hash.EMPTY_HASH;
6390  begin
6391    bstri_index := flip(bstri_const_table);
6392    if ccConf.ALLOW_BSTRITYPE_SLICES then
6393      init_bstri_constants_with_slices(bstri_index, c_expr);
6394    else
6395      init_bstri_constants_no_slices(bstri_index, c_expr);
6396    end if;
6397  end func;
6398
6399
6400const proc: init_set_constants (inout expr_type: c_expr) is func
6401
6402  local
6403    var set_index_hash: set_index is set_index_hash.EMPTY_HASH;
6404    var bitset: set1 is EMPTY_SET;
6405    var integer: min_position is 0;
6406    var integer: max_position is 0;
6407    var integer: number is 0;
6408    var integer: elem_num is 0;
6409    var integer: columnsFree is 0;
6410  begin
6411    set_index := flip(set_const_table);
6412    for number range sort(keys(set_index)) do
6413      set1 := set_index[number][1];
6414      c_expr.expr &:= "/* set[";
6415      c_expr.expr &:= str(number);
6416      c_expr.expr &:= "] */ static bitSetType set_";
6417      c_expr.expr &:= str(number);
6418      c_expr.expr &:= "[]={";
6419      if set1 = EMPTY_SET then
6420        c_expr.expr &:= "0,0,0,";
6421      else
6422        min_position := min(set1) mdiv ccConf.INTTYPE_SIZE;
6423        max_position := max(set1) mdiv ccConf.INTTYPE_SIZE;
6424        if min_position < 0 then
6425          c_expr.expr &:= "(bitSetType)";
6426        end if;
6427        c_expr.expr &:= str(min_position);
6428        c_expr.expr &:= ",";
6429        if max_position < 0 then
6430          c_expr.expr &:= "(bitSetType)";
6431        end if;
6432        c_expr.expr &:= str(max_position);
6433        c_expr.expr &:= ",";
6434        columnsFree := 4;
6435        for elem_num range min_position to max_position do
6436          if columnsFree = 0 then
6437            c_expr.expr &:= "\n";
6438            columnsFree := 6;
6439          end if;
6440          c_expr.expr &:= "0x";
6441          c_expr.expr &:= getBinary(set1, elem_num * ccConf.INTTYPE_SIZE) radix 16 lpad0 16;
6442          c_expr.expr &:= ",";
6443          decr(columnsFree);
6444        end for;
6445      end if;
6446      c_expr.expr &:= "};\n";
6447    end for;
6448    c_expr.expr &:= "setType set[]={\n";
6449    if length(set_const_table) > 0 then
6450      for number range sort(keys(set_index)) do
6451        c_expr.expr &:= "(setType) set_";
6452        c_expr.expr &:= str(number);
6453        c_expr.expr &:= ",\n";
6454      end for;
6455    else
6456      c_expr.expr &:= "(setType) NULL";
6457    end if;
6458    c_expr.expr &:= "};\n\n";
6459  end func;
6460
6461
6462const proc: init_type_constants (inout expr_type: c_expr) is func
6463
6464  local
6465    var type_index_hash: type_index is type_index_hash.EMPTY_HASH;
6466    var type: aType is void;
6467    var integer: number is 0;
6468  begin
6469    type_index := flip(type_const_table);
6470    for number range sort(keys(type_index)) do
6471      aType := type_index[number][1];
6472      c_expr.expr &:= "/* typ[";
6473      c_expr.expr &:= str(number);
6474      c_expr.expr &:= "] */ static struct typeStruct typ_";
6475      c_expr.expr &:= str(number);
6476      c_expr.expr &:= "={";
6477      c_expr.expr &:= "NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL";
6478      # c_expr.expr &:= c_literal(aType);
6479      c_expr.expr &:= "};\n";
6480    end for;
6481    c_expr.expr &:= "typeType typ[]={\n";
6482    if length(type_const_table) > 0 then
6483      for number range sort(keys(type_index)) do
6484        aType := type_index[number][1];
6485        c_expr.expr &:= "&typ_";
6486        c_expr.expr &:= str(number);
6487        c_expr.expr &:= ", /* ";
6488        c_expr.expr &:= type_name2(aType);
6489        c_expr.expr &:= " */\n";
6490      end for;
6491    else
6492      c_expr.expr &:= "(typeType) NULL";
6493    end if;
6494    c_expr.expr &:= "};\n\n";
6495  end func;
6496
6497
6498const proc: init_array_constants (in reference: const_object, inout expr_type: c_expr) is func
6499
6500  local
6501    var ref_list: array_list is ref_list.EMPTY;
6502    var integer: number is 0;
6503    var integer: elem_num is 0;
6504    var integer: elem_after_repeat_block is 0;
6505    var reference: element is NIL;
6506  begin
6507    number := const_table[const_object];
6508    array_list := arrayToList(const_object);
6509    c_expr.expr &:= "arr[";
6510    c_expr.expr &:= str(number);
6511    c_expr.expr &:= "]=arrMalloc(";
6512    c_expr.expr &:= str(arrayMinIdx(const_object));
6513    c_expr.expr &:= ", ";
6514    c_expr.expr &:= str(pred(arrayMinIdx(const_object) + length(array_list)));
6515    c_expr.expr &:= ");\n";
6516    elem_num := 0;
6517    elem_after_repeat_block := 0;
6518    for element range array_list do
6519      if element in element_repeat_count then
6520        c_expr.expr &:= "{\n";
6521        c_expr.expr &:= "int idx;\n";
6522        c_expr.expr &:= "for (idx=";
6523        c_expr.expr &:= str(elem_num);
6524        c_expr.expr &:= "; idx < ";
6525        c_expr.expr &:= str(elem_num + element_repeat_count[element]);
6526        c_expr.expr &:= "; idx++) {\n";
6527        c_expr.expr &:= "arr[";
6528        c_expr.expr &:= str(number);
6529        c_expr.expr &:= "]->arr[idx]";
6530        init_const_value(element, c_expr);
6531        c_expr.expr &:= ";\n";
6532        c_expr.expr &:= "}\n";
6533        c_expr.expr &:= "}\n";
6534        elem_after_repeat_block := elem_num + element_repeat_count[element];
6535      elsif elem_num >= elem_after_repeat_block then
6536        c_expr.expr &:= "arr[";
6537        c_expr.expr &:= str(number);
6538        c_expr.expr &:= "]->arr[";
6539        c_expr.expr &:= str(elem_num);
6540        c_expr.expr &:= "]";
6541        init_const_value(element, c_expr);
6542        c_expr.expr &:= ";\n";
6543      end if;
6544      incr(elem_num);
6545    end for;
6546  end func;
6547
6548
6549const proc: malloc_struct (in reference: const_object, inout expr_type: c_expr) is func
6550
6551  local
6552    var ref_list: struct_list is ref_list.EMPTY;
6553    var integer: number is 0;
6554    var integer: elem_num is 0;
6555    var reference: element is NIL;
6556  begin
6557    number := const_table[const_object];
6558    struct_list := structToList(const_object);
6559    c_expr.expr &:= "sct[";
6560    c_expr.expr &:= str(number);
6561    c_expr.expr &:= "]=(structType)(malloc(sizeof(struct rtlStructStruct) - sizeof(rtlObjectType)";
6562    if length(struct_list) <> 0 then
6563      c_expr.expr &:= " +\n  ";
6564      c_expr.expr &:= str(length(struct_list));
6565      c_expr.expr &:= " * sizeof(rtlObjectType)";
6566    end if;
6567    c_expr.expr &:= "));\n";
6568  end func;
6569
6570
6571const proc: init_struct_constants (in reference: const_object, inout expr_type: c_expr) is func
6572
6573  local
6574    var ref_list: struct_list is ref_list.EMPTY;
6575    var integer: number is 0;
6576    var integer: elem_num is 0;
6577    var reference: element is NIL;
6578  begin
6579    number := const_table[const_object];
6580    struct_list := structToList(const_object);
6581    c_expr.expr &:= "sct[";
6582    c_expr.expr &:= str(number);
6583    c_expr.expr &:= "]->usage_count=0;\n";
6584    c_expr.expr &:= "sct[";
6585    c_expr.expr &:= str(number);
6586    c_expr.expr &:= "]->type_num=";
6587    c_expr.expr &:= str(typeNumber(getType(const_object)));
6588    c_expr.expr &:= "/*";
6589    c_expr.expr &:= str(getType(const_object));
6590    c_expr.expr &:= "*/";
6591    c_expr.expr &:= ";\n";
6592    elem_num := 1;
6593    for element range struct_list do
6594      c_expr.expr &:= "sct[";
6595      c_expr.expr &:= str(number);
6596      c_expr.expr &:= "]->stru[";
6597      c_expr.expr &:= str(pred(elem_num));
6598      c_expr.expr &:= "]";
6599      init_const_value(element, c_expr);
6600      c_expr.expr &:= ";\n";
6601      incr(elem_num);
6602    end for;
6603    if const_object in globalInitalisations then
6604      c_expr.expr &:= globalInitalisations[const_object];
6605    end if;
6606  end func;
6607
6608
6609const proc: init_hash_constants (in reference: const_object, inout expr_type: c_expr) is func
6610
6611  local
6612    var ref_list: hash_key_list is ref_list.EMPTY;
6613    var ref_list: hash_data_list is ref_list.EMPTY;
6614    var integer: number is 0;
6615    var integer: elem_num is 0;
6616    var reference: key_element is NIL;
6617    var expr_type: hashcode_expr is expr_type.value;
6618  begin
6619    number := const_table[const_object];
6620    hash_key_list := hashKeysToList(const_object);
6621    hash_data_list := hashDataToList(const_object);
6622    c_expr.expr &:= "hsh[";
6623    c_expr.expr &:= str(number);
6624    c_expr.expr &:= "]=hshEmpty();\n";
6625    if length(hash_key_list) <> 0 then
6626      c_expr.expr &:= "{\n";
6627      c_expr.expr &:= "rtlObjectType hash_key;\n";
6628      c_expr.expr &:= "rtlObjectType hash_data;\n";
6629      elem_num := 1;
6630      for key_element range hash_key_list do
6631        c_expr.expr &:= "hash_key";
6632        init_const_value(key_element, c_expr);
6633        c_expr.expr &:= ";\n";
6634        c_expr.expr &:= "hash_data";
6635        init_const_value(hash_data_list[elem_num], c_expr);
6636        c_expr.expr &:= ";\n";
6637        hashcode_expr := expr_type.value;
6638        setVar(key_element, FALSE);
6639        process_hashcode(key_element, hashcode_expr);
6640        if hashcode_expr.temp_decls <> "" then
6641          c_expr.expr &:= "{\n";
6642          c_expr.expr &:= hashcode_expr.temp_decls;
6643          c_expr.expr &:= hashcode_expr.temp_assigns;
6644        end if;
6645        c_expr.expr &:= "hshIncl(hsh[";
6646        c_expr.expr &:= str(number);
6647        c_expr.expr &:= "], hash_key.value.genericValue, hash_data.value.genericValue, ";
6648        c_expr.expr &:= hashcode_expr.expr;
6649        c_expr.expr &:= ", (compareType)(";
6650        object_address(keyCompareObj(getType(const_object)), c_expr);
6651        c_expr.expr &:= "), (createFuncType)(";
6652        object_address(keyCreateObj(getType(const_object)), c_expr);
6653        c_expr.expr &:= "), (createFuncType)(";
6654        object_address(dataCreateObj(getType(const_object)), c_expr);
6655        c_expr.expr &:= "), (copyFuncType)(";
6656        object_address(dataCopyObj(getType(const_object)), c_expr);
6657        c_expr.expr &:= "));\n";
6658        if hashcode_expr.temp_decls <> "" then
6659          c_expr.expr &:= hashcode_expr.temp_frees;
6660          c_expr.expr &:= "}\n";
6661        end if;
6662        incr(elem_num);
6663      end for;
6664      c_expr.expr &:= "}\n";
6665    end if;
6666  end func;
6667
6668
6669const proc: init_interface_constants (in reference: const_object, inout expr_type: c_expr) is func
6670
6671  local
6672    var reference: struct_of_interface is NIL;
6673    var integer: number is 0;
6674  begin
6675    number := const_table[const_object];
6676    struct_of_interface := interfaceToStruct(const_object);
6677    c_expr.expr &:= "itf[";
6678    c_expr.expr &:= str(number);
6679    c_expr.expr &:= "]";
6680    if isVar(struct_of_interface) and struct_of_interface in globalInitalisations then
6681      c_expr.expr &:= "=o_";
6682      create_name(struct_of_interface, c_expr.expr);
6683    elsif category(struct_of_interface) = STRUCTOBJECT then
6684      c_expr.expr &:= "=sct[";
6685      c_expr.expr &:= str(const_table[struct_of_interface]);
6686      c_expr.expr &:= "]";
6687    else
6688      c_expr.expr &:= " /* = ";
6689      c_expr.expr &:= str(category(struct_of_interface));
6690      c_expr.expr &:= " */";
6691    end if;
6692    c_expr.expr &:= ";\n";
6693  end func;
6694
6695
6696const proc: init_nan_constants (inout expr_type: c_expr) is func
6697
6698  local
6699    var nan_index_hash: nan_index is nan_index_hash.EMPTY_HASH;
6700    var integer: number is 0;
6701    var bin64: bits is bin64(0);
6702  begin
6703    c_expr.expr &:= "double2BitsUnion nanValue[] = {\n";
6704    if length(nan_const_table) > 0 then
6705      nan_index := flip(nan_const_table);
6706      for number range sort(keys(nan_index)) do
6707        bits := nan_index[number][1];
6708        c_expr.expr &:= "{0x";
6709        c_expr.expr &:= bits radix 16 lpad0 16;
6710        c_expr.expr &:= "},\n";
6711      end for;
6712    else
6713      c_expr.expr &:= "{0}";
6714    end if;
6715    c_expr.expr &:= "};\n\n";
6716  end func;
6717
6718
6719const proc: initCaseLabelsOfWhen (in integer: numOfCaseStmt, in integer: numOfWhenPart,
6720    in reference: whenLabels, inout expr_type: c_expr) is func
6721
6722  local
6723    var ref_list: hash_key_list is ref_list.EMPTY;
6724    var reference: key_element is NIL;
6725    var expr_type: hashcode_expr is expr_type.value;
6726  begin
6727    hash_key_list := hashKeysToList(whenLabels);
6728    if length(hash_key_list) <> 0 then
6729      for key_element range hash_key_list do
6730        c_expr.expr &:= "hash_key";
6731        init_const_value(key_element, c_expr);
6732        c_expr.expr &:= ";\n";
6733        hashcode_expr := expr_type.value;
6734        setVar(key_element, FALSE);
6735        process_hashcode(key_element, hashcode_expr);
6736        if hashcode_expr.temp_decls <> "" then
6737          c_expr.expr &:= "{\n";
6738          c_expr.expr &:= hashcode_expr.temp_decls;
6739          c_expr.expr &:= hashcode_expr.temp_assigns;
6740        end if;
6741        c_expr.expr &:= "hshIncl(caseLabels[";
6742        c_expr.expr &:= str(numOfCaseStmt);
6743        c_expr.expr &:= "], hash_key.value.genericValue, ";
6744        c_expr.expr &:= str(numOfWhenPart);
6745        c_expr.expr &:= ", ";
6746        c_expr.expr &:= hashcode_expr.expr;
6747        c_expr.expr &:= ", (compareType)(";
6748        object_address(keyCompareObj(getType(whenLabels)), c_expr);
6749        c_expr.expr &:= "), (createFuncType)(";
6750        object_address(keyCreateObj(getType(whenLabels)), c_expr);
6751        c_expr.expr &:= "), (createFuncType)(&genericCreate), (copyFuncType)(&genericCpy));\n";
6752        if hashcode_expr.temp_decls <> "" then
6753          c_expr.expr &:= hashcode_expr.temp_frees;
6754          c_expr.expr &:= "}\n";
6755        end if;
6756      end for;
6757    end if;
6758  end func;
6759
6760
6761const proc: initCaseLabelsOfCase (in integer: numOfCaseStmt,
6762    in array reference: caseWhens, inout expr_type: c_expr) is func
6763
6764  local
6765    var integer: numOfWhenPart is 0;
6766    var reference: whenLabels is NIL;
6767  begin
6768    c_expr.expr &:= "caseLabels[";
6769    c_expr.expr &:= str(numOfCaseStmt);
6770    c_expr.expr &:= "]=hshEmpty();\n";
6771    for whenLabels key numOfWhenPart range caseWhens do
6772      initCaseLabelsOfWhen(numOfCaseStmt, numOfWhenPart, whenLabels, c_expr);
6773    end for;
6774  end func;
6775
6776
6777const proc: initCaseLabels (inout expr_type: c_expr) is func
6778
6779  local
6780    var integer: numOfCaseStmt is 0;
6781  begin
6782    c_expr.expr &:= "void initCaseLabelsOfSwitch () {\n";
6783    if length(case_table) <> 0 then
6784      c_expr.expr &:= "rtlObjectType hash_key;\n";
6785      c_expr.expr &:= "caseLabels = (hashType *)(malloc(";
6786      c_expr.expr &:= str(length(case_table));
6787      c_expr.expr &:= " * sizeof(hashType)));\n";
6788      for key numOfCaseStmt range case_table do
6789        initCaseLabelsOfCase(numOfCaseStmt, case_table[numOfCaseStmt], c_expr);
6790      end for;
6791    end if;
6792    c_expr.expr &:= "}\n\n";
6793  end func;
6794
6795
6796const proc: init_values (inout expr_type: c_expr) is func
6797
6798  local
6799    var const_index_hash: const_index is const_index_hash.EMPTY_HASH;
6800    var ref_list: sorted_list is ref_list.EMPTY;
6801    var reference: struct_of_interface is NIL;
6802    var reference: const_object is NIL;
6803    var integer: number is 0;
6804    var ref_list: elements_to_walk is ref_list.EMPTY;
6805  begin
6806    const_index := flip(const_table);
6807    for number range sort(keys(const_index)) do
6808      const_object := const_index[number][1];
6809      if category(const_object) = ARRAYOBJECT then
6810        elements_to_walk := determine_multiple_array_elements(arrayToList(const_object));
6811        walk_const_list(elements_to_walk, sorted_list);
6812        sorted_list &:= make_list(const_object);
6813      elsif category(const_object) = STRUCTOBJECT then
6814        walk_const_list(structToList(const_object), sorted_list);
6815        sorted_list &:= make_list(const_object);
6816      elsif category(const_object) = HASHOBJECT then
6817        walk_const_list(hashKeysToList(const_object), sorted_list);
6818        walk_const_list(hashDataToList(const_object), sorted_list);
6819        sorted_list &:= make_list(const_object);
6820      elsif category(const_object) = INTERFACEOBJECT then
6821        if const_object not in const_table then
6822          const_table @:= [const_object] length(const_table);
6823        end if;
6824        struct_of_interface := interfaceToStruct(const_object);
6825        if struct_of_interface not in const_table then
6826          const_table @:= [struct_of_interface] length(const_table);
6827          walk_const_list(structToList(struct_of_interface), sorted_list);
6828          sorted_list &:= make_list(struct_of_interface);
6829        elsif const_table[struct_of_interface] >= const_table[const_object] then
6830          sorted_list &:= make_list(struct_of_interface);
6831        end if;
6832        sorted_list &:= make_list(const_object);
6833      end if;
6834    end for;
6835    writeln("after walk_const_list");
6836
6837    for const_object range sorted_list do
6838      # writeln(str(category(const_object)) <& ": " <& create_name(const_object));
6839      if category(const_object) = MATCHOBJECT or category(const_object) = ACTOBJECT or
6840          category(const_object) = BLOCKOBJECT then
6841        prepare_func_literal(const_object, c_expr);
6842      end if;
6843    end for;
6844
6845    init_bigint_constants;
6846    init_win_constants;
6847    init_string_constants(c_expr);
6848    init_bstri_constants(c_expr);
6849    init_set_constants(c_expr);
6850    init_type_constants(c_expr);
6851
6852    c_expr.expr &:= "static void init_values (void)\n";
6853    c_expr.expr &:= "{\n";
6854    initPollOperations(c_expr);
6855    assign_bigint_constants(c_expr);
6856    assign_win_constants(c_expr);
6857    c_expr.expr &:= "arr = (arrayType *)(malloc(";
6858    c_expr.expr &:= str(length(const_table));
6859    c_expr.expr &:= " * sizeof(arrayType)));\n";
6860    c_expr.expr &:= "sct = (structType *)(arr);\n";
6861    c_expr.expr &:= "hsh = (hashType *)(arr);\n";
6862    c_expr.expr &:= "itf = (interfaceType *)(arr);\n";
6863    for const_object range sorted_list do
6864      if category(const_object) = STRUCTOBJECT then
6865        malloc_struct(const_object, c_expr);
6866      end if;
6867    end for;
6868    for const_object range sorted_list do
6869      if category(const_object) = ARRAYOBJECT then
6870        init_array_constants(const_object, c_expr);
6871      elsif category(const_object) = STRUCTOBJECT then
6872        init_struct_constants(const_object, c_expr);
6873      elsif category(const_object) = HASHOBJECT then
6874        init_hash_constants(const_object, c_expr);
6875      elsif category(const_object) = INTERFACEOBJECT then
6876        init_interface_constants(const_object, c_expr);
6877      elsif category(const_object) <> MATCHOBJECT and
6878            category(const_object) <> ACTOBJECT then
6879        number := const_table[const_object];
6880        c_expr.expr &:= "/* const ";
6881        c_expr.expr &:= str(category(const_object));
6882        c_expr.expr &:= " [";
6883        c_expr.expr &:= str(number);
6884        c_expr.expr &:= "] */\n";
6885      end if;
6886    end for;
6887    c_expr.expr &:= "initCaseLabelsOfSwitch();\n";
6888    c_expr.expr &:= "}\n\n";
6889    init_nan_constants(c_expr);
6890  end func;
6891
6892
6893const proc: declare_rtlRaiseError (inout expr_type: c_expr) is func
6894
6895  begin
6896    c_expr.expr &:= "void rtlRaiseError (int fail_value, const char *file_name, int line_number)\n";
6897    c_expr.expr &:= "{\n";
6898    if trace_exception then
6899      c_expr.expr &:= "  int ch;\n";
6900      c_expr.expr &:= "  if (catch_stack_pos == 0) {\n";
6901      c_expr.expr &:= "    printf(\"\\n*** Uncaught exception \");\n";
6902      c_expr.expr &:= "  } else {\n";
6903      c_expr.expr &:= "    printf(\"\\n*** Caught exception \");\n";
6904      c_expr.expr &:= "  }\n";
6905      c_expr.expr &:= "  if (fail_value >= 0 && fail_value < sizeof(exception_name) / sizeof(char *)) {\n";
6906      c_expr.expr &:= "    printf(\"%s\", exception_name[fail_value]);\n";
6907      c_expr.expr &:= "  } else {\n";
6908      c_expr.expr &:= "    printf(\"%d\", fail_value);\n";
6909      c_expr.expr &:= "  }\n";
6910      c_expr.expr &:= "  printf(\" raised at %s(%d)\\n\", file_name, line_number);\n";
6911      c_expr.expr &:= "  printf(\"\\n*** The following commands are possible:\\n\"\n";
6912      c_expr.expr &:= "         \"  RETURN  Continue\\n\"\n";
6913      c_expr.expr &:= "         \"  *       Terminate\\n\"\n";
6914      c_expr.expr &:= "         \"  /       Trigger SIGFPE\\n\");\n";
6915      c_expr.expr &:= "  ch = fgetc(stdin);\n";
6916      c_expr.expr &:= "  if (ch == (int) '*') {\n";
6917      c_expr.expr &:= "    exit(1);\n";
6918      c_expr.expr &:= "  } else if (ch == (int) '/') {\n";
6919      c_expr.expr &:= "    triggerSigfpe();\n";
6920      c_expr.expr &:= "  }\n";
6921    end if;
6922    c_expr.expr &:= "  error_file = file_name;\n";
6923    c_expr.expr &:= "  error_line = line_number;\n";
6924    if signal_exception then
6925      c_expr.expr &:= "  if (catch_stack_pos == 0) {\n";
6926      c_expr.expr &:= "    printf(\"\\n*** Uncaught exception \");\n";
6927      c_expr.expr &:= "    if (fail_value >= 0 && fail_value < sizeof(exception_name) / sizeof(char *)) {\n";
6928      c_expr.expr &:= "      printf(\"%s\", exception_name[fail_value]);\n";
6929      c_expr.expr &:= "    } else {\n";
6930      c_expr.expr &:= "      printf(\"%d\", fail_value);\n";
6931      c_expr.expr &:= "    }\n";
6932      c_expr.expr &:= "    printf(\" raised at %s(%d)\\n\", file_name, line_number);\n";
6933      c_expr.expr &:= "    triggerSigfpe();\n";
6934      c_expr.expr &:= "  }\n";
6935    end if;
6936    if ccConf.HAS_SIGSETJMP then
6937      c_expr.expr &:= "  siglongjmp(catch_stack[catch_stack_pos], fail_value);\n";
6938    else
6939      c_expr.expr &:= "  longjmp(catch_stack[catch_stack_pos], fail_value);\n";
6940    end if;
6941    c_expr.expr &:= "}\n";
6942    c_expr.expr &:= "\n";
6943  end func;
6944
6945
6946const proc: declare_raise_error2 (inout expr_type: c_expr) is func
6947
6948  begin
6949    if compilerLibraryUsed then
6950      writeln(c_prog, "extern boolType interpreter_exception;");
6951      declareExtern("void interprRaiseError (int, const char *, int);");
6952    end if;
6953    c_expr.expr &:= "void raise_error2 (int fail_value, const char *file_name, int line_number)\n";
6954    c_expr.expr &:= "{\n";
6955    if compilerLibraryUsed then
6956      c_expr.expr &:= "  if (interpreter_exception) {\n";
6957      if trace_exception then
6958        c_expr.expr &:= "    int ch;\n";
6959        c_expr.expr &:= "    if (fail_value >= 0 && fail_value < sizeof(exception_name) / sizeof(char *)) {\n";
6960        c_expr.expr &:= "      printf(\"*** Exception %s\", exception_name[fail_value]);\n";
6961        c_expr.expr &:= "    } else {\n";
6962        c_expr.expr &:= "      printf(\"*** Exception %d\", fail_value);\n";
6963        c_expr.expr &:= "    }\n";
6964        c_expr.expr &:= "    printf(\" raised at %s(%d)\\n\", file_name, line_number);\n";
6965        c_expr.expr &:= "    printf(\"\\n*** The following commands are possible:\\n\"\n";
6966        c_expr.expr &:= "           \"  RETURN  Continue\\n\"\n";
6967        c_expr.expr &:= "           \"  *       Terminate\\n\"\n";
6968        c_expr.expr &:= "           \"  /       Trigger SIGFPE\\n\");\n";
6969        c_expr.expr &:= "    ch = fgetc(stdin);\n";
6970        c_expr.expr &:= "    if (ch == (int) '*') {\n";
6971        c_expr.expr &:= "      exit(1);\n";
6972        c_expr.expr &:= "    } else if (ch == (int) '/') {\n";
6973        c_expr.expr &:= "      triggerSigfpe();\n";
6974        c_expr.expr &:= "    }\n";
6975      end if;
6976      c_expr.expr &:= "    interprRaiseError(fail_value, file_name, line_number);\n";
6977      c_expr.expr &:= "  } else {\n";
6978      c_expr.expr &:= "    rtlRaiseError(fail_value, file_name, line_number);\n";
6979      c_expr.expr &:= "  }\n";
6980    else
6981      c_expr.expr &:= "  rtlRaiseError(fail_value, file_name, line_number);\n";
6982    end if;
6983    c_expr.expr &:= "}\n";
6984    c_expr.expr &:= "\n";
6985  end func;
6986
6987
6988const proc: init_globals (inout expr_type: c_expr) is func
6989
6990  begin
6991    c_expr.expr &:= "static void init_globals (void)\n";
6992    c_expr.expr &:= "{\n";
6993    c_expr.expr &:= global_init.temp_decls;
6994    c_expr.expr &:= global_init.temp_assigns;
6995    c_expr.expr &:= global_init.expr;
6996    c_expr.expr &:= "}\n\n";
6997  end func;
6998
6999
7000const proc: process_global_declarations (in program: prog) is func
7001
7002  local
7003    var expr_type: c_expr is expr_type.value;
7004    var type: int_type is void;
7005    var integer: numObjects is 0;
7006    var integer: index is 0;
7007  begin
7008    if not compDataLibraryUsed then
7009      declareExtern("intType heapsize (void) {return 0;}");
7010      declareExtern("typeType refType (objRefType a) {printf(\"refType\\n\"); return NULL;}");
7011      declareExtern("typeType typValue (objRefType a) {printf(\"typValue\\n\"); return NULL;}");
7012      writeln(c_prog);
7013    end if;
7014    if compDataLibraryUsed and not compilerLibraryUsed then
7015      declareExtern("striType get_file_name (unsigned int a) {return " <& stringLiteral("") <& ";}");
7016      declareExtern("const unsigned char *get_file_name_ustri (unsigned int a) {return (unsigned char *) \"?\";}");
7017      declareExtern("void *get_param_list (const_listType a, int *b) {printf(\"get_param_list\\n\"); return NULL;}");
7018      writeln(c_prog);
7019    end if;
7020    declare_rtlRaiseError(c_expr);
7021    declare_raise_error2(c_expr);
7022    process_dynamic_decisions(c_expr);
7023    declare_missing_create_declarations(c_expr);
7024    declare_missing_destr_declarations(c_expr);
7025    initCaseLabels(c_expr);
7026    init_values(c_expr);
7027    init_globals(c_expr);
7028    if profile_function then
7029      int_type := getValue(sysVar(prog, "integer"), type);
7030      numObjects := objNumber(alloc(TRUE, int_type, 0));
7031      writeln(c_prog, "static unsigned int profile_size = " <& numObjects <& ";");
7032      writeln(c_prog, "static struct profileElement profile[" <& numObjects <& "];");
7033      writeln(c_prog);
7034      writeln(c_prog, "static void initProfile (void)");
7035      writeln(c_prog, "{");
7036      writeln(c_prog, "  memSizeType index;");
7037      writeln(c_prog, "  memset(profile, 0, " <& numObjects <& " * sizeof(struct profileElement));");
7038      writeln(c_prog, "  for (index = 0; index < " <& numObjects <& "; index++) {");
7039      writeln(c_prog, "    profile[index].file = \"\";");
7040      writeln(c_prog, "    profile[index].name = \"\";");
7041      writeln(c_prog, "  }");
7042      for index range 1 to pred(numObjects) do
7043        if index in profiledFunctions then
7044          write(c_prog, "  profile[" <& index <& "].file = " <&
7045                c_literal(striToUtf8(file(profiledFunctions[index]))) <& ";");
7046          write(c_prog, " profile[" <& index <& "].line = " <&
7047                line(profiledFunctions[index]) <& ";");
7048          writeln(c_prog, " profile[" <& index <& "].name = " <&
7049                  c_literal(striToUtf8(str(profiledFunctions[index]))) <& ";");
7050        end if;
7051      end for;
7052      writeln(c_prog, "}");
7053      writeln(c_prog);
7054    end if;
7055    write(c_prog, global_c_expr.expr);
7056    write(c_prog, c_expr.expr);
7057    count_declarations(c_expr);
7058  end func;
7059
7060
7061const proc: init_systypes (in program: prog) is func
7062
7063  local
7064    var reference: type_ref is NIL;
7065    var reference: ref_to_empty is NIL;
7066    var type: type_type is void;
7067    var type: int_type is void;
7068    var type: float_type is void;
7069    var type: bigint_type is void;
7070    var type: char_type is void;
7071    var type: stri_type is void;
7072  begin
7073    type_ref := sysVar(prog, "type");
7074    if type_ref <> NIL then
7075      type_type := getValue(type_ref, type);
7076      typeCategory @:= [type_type] TYPEOBJECT;
7077    end if;
7078    type_ref := sysVar(prog, "proc");
7079    if type_ref <> NIL then
7080      proctype := getValue(type_ref, type);
7081    end if;
7082    type_ref := sysVar(prog, "integer");
7083    if type_ref <> NIL then
7084      int_type := getValue(type_ref, type);
7085      typeCategory @:= [int_type] INTOBJECT;
7086    end if;
7087    type_ref := sysVar(prog, "bigInteger");
7088    if type_ref <> NIL then
7089      bigint_type := getValue(type_ref, type);
7090      typeCategory @:= [bigint_type] BIGINTOBJECT;
7091    end if;
7092    type_ref := sysVar(prog, "float");
7093    if type_ref <> NIL then
7094      float_type := getValue(type_ref, type);
7095      typeCategory @:= [float_type] FLOATOBJECT;
7096    end if;
7097    type_ref := sysVar(prog, "char");
7098    if type_ref <> NIL then
7099      char_type := getValue(type_ref, type);
7100      typeCategory @:= [char_type] CHAROBJECT;
7101    end if;
7102    type_ref := sysVar(prog, "string");
7103    if type_ref <> NIL then
7104      stri_type := getValue(type_ref, type);
7105      typeCategory @:= [stri_type] STRIOBJECT;
7106    end if;
7107    ref_to_empty := sysVar(prog, "empty");
7108    if ref_to_empty <> NIL then
7109      voidtype := getType(ref_to_empty);
7110      typeCategory @:= [voidtype] VOIDOBJECT;
7111    end if;
7112  end func;
7113
7114
7115const func string: temp_name (in string: source) is func
7116  result
7117    var string: tempName is "";
7118  begin
7119    if rpos(source, "/") = 0 then
7120      tempName := "tmp_" & source;
7121    else
7122      tempName := source[.. rpos(source, "/")] &
7123          "tmp_" & source[succ(rpos(source, "/")) ..];
7124    end if;
7125  end func;
7126
7127
7128const proc: pass_1 (in string: source, inout program: prog,
7129    inout boolean: okay) is func
7130
7131  begin
7132    if source <> "" then
7133      writeln("Compiling the program ...");
7134      if "-g" in compiler_option then
7135        source_debug_info := compiler_option["-g"] <> "-debug_c";
7136      end if;
7137      if "-t" in compiler_option then
7138        if pos(compiler_option["-t"], 'e') <> 0 then
7139          trace_exception := TRUE;
7140        end if;
7141        if pos(compiler_option["-t"], 'f') <> 0 then
7142          trace_function := TRUE;
7143        end if;
7144        if pos(compiler_option["-t"], 's') <> 0 then
7145          trace_signal := TRUE;
7146        end if;
7147      end if;
7148      if "-p" in compiler_option then
7149        profile_function := TRUE;
7150      end if;
7151      if "-e" in compiler_option then
7152        signal_exception := TRUE;
7153      end if;
7154      if "-o" in compiler_option and compiler_option["-o"] in {"c0", "c1", "c2", "c3"} then
7155        evaluate_const_expr := integer(compiler_option["-o"][2 ..]);
7156      end if;
7157      setOptimizationSettings(evaluate_const_expr);
7158      if "-s" in compiler_option then
7159        if pos(compiler_option["-s"], 'd') <> 0 then
7160          integer_division_check := FALSE;
7161        end if;
7162        if pos(compiler_option["-s"], 'i') <> 0 then
7163          string_index_check := FALSE;
7164          bstring_index_check := FALSE;
7165          array_index_check := FALSE;
7166          ref_list_index_check := FALSE;
7167        end if;
7168        if pos(compiler_option["-s"], 'o') <> 0 then
7169          integer_overflow_check := FALSE;
7170        end if;
7171        if pos(compiler_option["-s"], 'r') <> 0 then
7172          function_range_check := FALSE;
7173          conversion_range_check := FALSE;
7174        end if;
7175      end if;
7176      setIntegerDivisionCheck(integer_division_check);
7177      setIntegerOverflowCheck(integer_overflow_check);
7178      if "-c" in compiler_option then
7179        generate_c_plus_plus := compiler_option["-c"] = "++";
7180        declare_with_extern_c := generate_c_plus_plus;
7181      end if;
7182      if "-f" in compiler_option then
7183        case compiler_option["-f"] of
7184          when {"lto"}:
7185            if ccConf.CC_OPT_LINK_TIME_OPTIMIZATION <> "" then
7186              enable_link_time_optimization := TRUE;
7187            end if;
7188          otherwise:
7189            writeln("*** Ignore unsupported option: -f" <& compiler_option["-f"]);
7190        end case;
7191      end if;
7192      block
7193        prog := parseFile(source, parseOptions.value, libraryDirs);
7194      exception
7195        otherwise:
7196          prog := program.EMPTY;
7197      end block;
7198      if prog = program.EMPTY then
7199        writeln("*** File " <& literal(source) <& " not found or a memory error occurred.");
7200        okay := FALSE;
7201      elsif errorCount(prog) <> 0 then
7202        write(errorCount(prog) <& " error");
7203        if errorCount(prog) > 1 then
7204          write("s");
7205        end if;
7206        writeln(" found");
7207        okay := FALSE;
7208      end if;
7209    else
7210      okay := FALSE;
7211    end if;
7212  end func;
7213
7214
7215const proc: pass_2 (in string: source, in program: prog,
7216    inout boolean: okay) is func
7217
7218  local
7219    var string: temporaryFileName is "";
7220    var ref_list: globalObjects is ref_list.EMPTY;
7221    var reference: obj is NIL;
7222  begin
7223    if okay then
7224      main_object := sysVar(prog, "main");
7225      if main_object <> NIL then
7226        compileLibrary := category(main_object) = FORWARDOBJECT;
7227        temporaryFileName := temp_name(source);
7228        if generate_c_plus_plus then
7229          temporaryFileName &:= ".cpp";
7230        else
7231          temporaryFileName &:= ".c";
7232        end if;
7233        # The temporary tmp_*.c file is marked with a temp_marker.
7234        # The temp_marker is checked, before the file is overwritten.
7235        c_prog := open(temporaryFileName, "r");
7236        if c_prog <> STD_NULL then
7237          if getln(c_prog) <> temp_marker then
7238            write("*** The file ");
7239            write(literal(temporaryFileName));
7240            writeln(" was not created by the compiler.");
7241            write("*** Remove the file ");
7242            write(literal(temporaryFileName));
7243            writeln(" manually and restart the compiler.");
7244            okay := FALSE;
7245          end if;
7246          close(c_prog);
7247        end if;
7248        if okay then
7249          c_prog := open(temporaryFileName, "w");
7250          if c_prog <> STD_NULL then
7251            writeln("Generating code ...");
7252            init_systypes(prog);
7253            write_file_head;
7254            write_prototypes;
7255            write_resize_catch_stack;
7256            globalObjects := globalObjects(prog);
7257            if compileLibrary then
7258              writeln("Compile library");
7259              for obj range globalObjects do
7260                if endsWith(path(prog), file(obj)) then
7261                  process_object(obj);
7262                else
7263                  process_library_import_object(obj);
7264                end if;
7265              end for;
7266            else
7267              for obj range globalObjects do
7268                process_object(obj);
7269              end for;
7270            end if;
7271            process_global_declarations(prog);
7272            close(c_prog);
7273            writeln(countDeclarations  <& " declarations processed");
7274            writeln(countOptimizations <& " optimizations done");
7275            if countEvaluations <> 0 then
7276              writeln(countEvaluations   <& " evaluations done");
7277            end if;
7278            if countRangeChecks <> 0 then
7279              writeln(countRangeChecks   <& " range checks inserted");
7280            end if;
7281            if countNoRangeChecks <> 0 then
7282              writeln(countNoRangeChecks <& " range checks suppressed");
7283            end if;
7284            if countIndexChecks <> 0 then
7285              writeln(countIndexChecks   <& " index checks inserted");
7286            end if;
7287            if countNoIndexChecks <> 0 then
7288              writeln(countNoIndexChecks <& " index checks suppressed");
7289            end if;
7290            if countOverflowChecks <> 0 then
7291              writeln(countOverflowChecks   <& " overflow checks inserted");
7292            end if;
7293          else
7294            write("*** Cannot open temp file ");
7295            write(literal(temporaryFileName));
7296            writeln(".");
7297            okay := FALSE;
7298          end if;
7299        end if;
7300      else
7301        writeln("*** main not found.");
7302        okay := FALSE;
7303      end if;
7304    end if;
7305  end func;
7306
7307
7308const proc: importEnvironment (in string: fileName) is func
7309  local
7310    var iniDataType: iniData is iniDataType.value;
7311    var string: aKey is "";
7312    var string: aValue is "";
7313  begin
7314    iniData := readIniFile(fileName);
7315    if "" in iniData then
7316      for aValue key aKey range iniData[""] do
7317        # writeln(aKey <& "=" <& aValue);
7318        setenv(aKey, aValue);
7319      end for;
7320    else
7321      writeln("*** C compiler environment file " <& literal(fileName) <& " not found.");
7322    end if;
7323  end func;
7324
7325
7326const proc: appendLibrary (inout array string: options, in string: libraryToAppend) is func
7327  local
7328    var string: existingOption is "";
7329    var boolean: found is FALSE;
7330  begin
7331    if libraryToAppend <> "" then
7332      for existingOption range options until found do
7333        found := existingOption = libraryToAppend;
7334      end for;
7335      if not found then
7336        options &:= libraryToAppend;
7337      end if;
7338    end if;
7339  end func;
7340
7341
7342const proc: appendLibrary (inout array string: options, in array string: librariesToAppend) is func
7343  local
7344    var string: libraryToAppend is "";
7345  begin
7346    for libraryToAppend range librariesToAppend do
7347      appendLibrary(options, libraryToAppend);
7348    end for;
7349  end func;
7350
7351
7352const proc: logProgram (in string: command, in array string: parameters,
7353    in string: errorFile) is func
7354
7355  begin
7356    write(toShellPath(command) <& " " <& shellParameters(parameters));
7357    case ccConf.CC_ERROR_FILEDES of
7358      when {1}:
7359        write(" " <& ccConf.REDIRECT_FILEDES_1 <& toShellPath(errorFile));
7360        write(" " <& ccConf.REDIRECT_FILEDES_2 <& ccConf.NULL_DEVICE);
7361      when {2}:
7362        write(" " <& ccConf.REDIRECT_FILEDES_2 <& toShellPath(errorFile));
7363        write(" " <& ccConf.REDIRECT_FILEDES_1 <& ccConf.NULL_DEVICE);
7364    end case;
7365    writeln;
7366    flush(OUT);
7367  end func;
7368
7369
7370const proc: execProgramScript (in string: command, in array string: parameters,
7371    in string: errorFile) is func
7372
7373  local
7374    var array string: redirection is 0 times "";
7375  begin
7376    logProgram(command, parameters, errorFile);
7377    case ccConf.CC_ERROR_FILEDES of
7378      when {1}:
7379        redirection &:= ccConf.REDIRECT_FILEDES_1 & toShellPath(errorFile);
7380        redirection &:= ccConf.REDIRECT_FILEDES_2 & ccConf.NULL_DEVICE;
7381      when {2}:
7382        redirection &:= ccConf.REDIRECT_FILEDES_2 & toShellPath(errorFile);
7383        redirection &:= ccConf.REDIRECT_FILEDES_1 & ccConf.NULL_DEVICE;
7384    end case;
7385    if length(redirection) = 0 then
7386      # An CC_ERROR_FILEDES of zero means: Do not redirect.
7387      cmd_sh(command, shellParameters(parameters));
7388    else
7389      cmd_sh(command, shellParameters(parameters) <& " " <& join(redirection, " "));
7390    end if
7391  end func;
7392
7393
7394const proc: execProgram (in string: command, in array string: parameters,
7395    in string: errorFile) is func
7396
7397  local
7398    var file: childStdout is STD_NULL;
7399    var file: childStderr is STD_NULL;
7400    var process: aProcess is process.value;
7401  begin
7402    logProgram(command, parameters, errorFile);
7403    case ccConf.CC_ERROR_FILEDES of
7404      when {1}:
7405        childStdout := open(errorFile, "w");
7406        if childStdout = STD_NULL then
7407          writeln("*** Could not open " <& errorFile);
7408        end if;
7409      when {2}:
7410        childStderr := open(errorFile, "w");
7411        if childStderr = STD_NULL then
7412          writeln("*** Could not open " <& errorFile);
7413        end if;
7414    end case;
7415    aProcess := startProcess(commandPath(command), parameters, STD_IN, childStdout, childStderr);
7416    waitFor(aProcess);
7417    case ccConf.CC_ERROR_FILEDES of
7418      when {1}: close(childStdout);
7419      when {2}: close(childStderr);
7420    end case;
7421  end func;
7422
7423
7424const proc: pass_3 (in string: sourcePath, in string: sourceExtension, in program: prog,
7425    inout boolean: okay) is func
7426
7427  local
7428    var string: s7_lib_dir     is "";
7429    var string: seed7_lib      is "";
7430    var string: draw_lib       is "";
7431    var string: console_lib    is "";
7432    var string: database_lib   is "";
7433    var string: comp_data_lib  is "";
7434    var string: compiler_lib   is "";
7435    var string: special_lib    is "";
7436    var string: cwd            is "";
7437    var string: workDir        is "";
7438    var string: sourceFile     is "";
7439    var string: cSourceFile    is "";
7440    var string: cErrorFile     is "";
7441    var string: objectFile     is "";
7442    var string: linkErrFile    is "";
7443    var string: tempExeFile    is "";
7444    var string: linkedProgram  is "";
7445    var string: compile_cmd    is "";
7446    var array string: compileParams is 0 times "";
7447    var string: link_cmd       is "";
7448    var array string: linkParams is 0 times "";
7449  begin
7450    if okay then
7451      writeln("Calling the C compiler ...");
7452      if ccConf.CC_ENVIRONMENT_INI <> "" then
7453        importEnvironment(ccConf.CC_ENVIRONMENT_INI);
7454      end if;
7455      if "-b" in compiler_option then
7456        s7_lib_dir := convDosPath(compiler_option["-b"]);
7457      else
7458        s7_lib_dir := ccConf.S7_LIB_DIR;
7459      end if;
7460      seed7_lib     := s7_lib_dir & "/" & ccConf.SEED7_LIB;
7461      draw_lib      := s7_lib_dir & "/" & ccConf.DRAW_LIB;
7462      console_lib   := s7_lib_dir & "/" & ccConf.CONSOLE_LIB;
7463      database_lib  := s7_lib_dir & "/" & ccConf.DATABASE_LIB;
7464      comp_data_lib := s7_lib_dir & "/" & ccConf.COMP_DATA_LIB;
7465      compiler_lib  := s7_lib_dir & "/" & ccConf.COMPILER_LIB;
7466      special_lib   := s7_lib_dir & "/" & ccConf.SPECIAL_LIB;
7467      cwd := getcwd();
7468      if rpos(sourcePath, "/") = 0 then
7469        sourceFile := sourcePath;
7470      else
7471        if rpos(sourcePath, "/") = 1 then
7472          chdir("/");
7473        else
7474          chdir(sourcePath[.. pred(rpos(sourcePath, "/"))]);
7475        end if;
7476        workDir := sourcePath[.. rpos(sourcePath, "/")];
7477        sourceFile := sourcePath[succ(rpos(sourcePath, "/")) ..];
7478      end if;
7479      cSourceFile  := "tmp_" & sourceFile;
7480      if generate_c_plus_plus then
7481        cSourceFile  &:= ".cpp";
7482      else
7483        cSourceFile  &:= ".c";
7484      end if;
7485      cErrorFile     := "tmp_" & sourceFile & ".cerrs";
7486      objectFile     := "tmp_" & sourceFile & ccConf.OBJECT_FILE_EXTENSION;
7487      linkErrFile    := "tmp_" & sourceFile & ".lerrs";
7488      tempExeFile    := "tmp_" & sourceFile & ccConf.LINKED_PROGRAM_EXTENSION;
7489      if sourceExtension = "" and ccConf.LINKED_PROGRAM_EXTENSION = "" then
7490        linkedProgram :=         sourceFile & "_exe";
7491      else
7492        linkedProgram :=         sourceFile & ccConf.LINKED_PROGRAM_EXTENSION;
7493      end if;
7494      if fileType(objectFile) = FILE_REGULAR then
7495        removeFile(objectFile);
7496      end if;
7497      if generate_c_plus_plus then
7498        compile_cmd := ccConf.CPLUSPLUS_COMPILER;
7499      else
7500        compile_cmd := ccConf.C_COMPILER;
7501      end if;
7502      compileParams &:= ccConf.CC_OPT_NO_WARNINGS;
7503      if enable_link_time_optimization then
7504        compileParams &:= ccConf.CC_OPT_LINK_TIME_OPTIMIZATION;
7505      end if;
7506      if "-O" in compiler_option then
7507        case compiler_option["-O"] of
7508          when {"", "1"}:
7509            compileParams &:= ccConf.CC_OPT_OPTIMIZE_1;
7510          when {"2"}:
7511            compileParams &:= ccConf.CC_OPT_OPTIMIZE_2;
7512          when {"3"}:
7513            compileParams &:= ccConf.CC_OPT_OPTIMIZE_3;
7514          otherwise:
7515            writeln("*** Ignore unsupported option: -O" <& compiler_option["-O"]);
7516        end case;
7517      end if;
7518      if integer_overflow_check and ccConf.CC_OPT_TRAP_OVERFLOW <> "" then
7519        compileParams &:= ccConf.CC_OPT_TRAP_OVERFLOW;
7520      end if;
7521      if "-g" in compiler_option then
7522        compileParams &:= ccConf.CC_OPT_DEBUG_INFO;
7523        if compiler_option["-g"] <> "" and compiler_option["-g"] <> "-debug_c" then
7524          compileParams &:= compiler_option["-g"];
7525        end if;
7526      end if;
7527      if length(ccConf.CC_FLAGS) <> 0 then
7528        compileParams &:= ccConf.CC_FLAGS;
7529      end if;
7530      compileParams &:= "-c";
7531      compileParams &:= toOsPath(cSourceFile);
7532      if ccConf.CALL_C_COMPILER_FROM_SHELL then
7533        execProgramScript(compile_cmd, compileParams, cErrorFile);
7534      else
7535        execProgram(compile_cmd, compileParams, cErrorFile);
7536      end if;
7537      if fileType(cErrorFile) = FILE_REGULAR and
7538          fileSize(cErrorFile) = 0 then
7539        removeFile(cErrorFile);
7540      end if;
7541      if fileType(objectFile) <> FILE_REGULAR then
7542        if fileType(cErrorFile) = FILE_REGULAR then
7543          writeln("*** Errors in " <& literal(workDir & cSourceFile) <&
7544              " - see " <& literal(workDir & cErrorFile));
7545        elsif ccConf.CC_ERROR_FILEDES not in {1, 2} then
7546          writeln("*** Compilation terminated");
7547        else
7548          writeln("*** Compilation terminated without error messages");
7549        end if;
7550        okay := FALSE;
7551      elsif fileType(cErrorFile) = FILE_REGULAR then
7552        removeFile(cErrorFile);
7553      end if;
7554      if okay then
7555        if "-g" not in compiler_option then
7556          removeFile(cSourceFile);
7557        end if;
7558        if compilerLibraryUsed then
7559          drawLibraryUsed := TRUE;
7560          consoleLibraryUsed := TRUE;
7561          databaseLibraryUsed := TRUE;
7562        end if;
7563        if fileType(seed7_lib) <> FILE_REGULAR then
7564          writeln("*** Seed7 library " <& literal(seed7_lib) <& " missing");
7565          okay := FALSE;
7566        end if;
7567        if drawLibraryUsed and fileType(draw_lib) <> FILE_REGULAR then
7568          writeln("*** Draw library " <& literal(draw_lib) <& " missing");
7569          okay := FALSE;
7570        end if;
7571        if consoleLibraryUsed and fileType(console_lib) <> FILE_REGULAR then
7572          writeln("*** Console library " <& literal(console_lib) <& " missing");
7573          okay := FALSE;
7574        end if;
7575        if databaseLibraryUsed and fileType(database_lib) <> FILE_REGULAR then
7576          writeln("*** Database library " <& literal(database_lib) <& " missing");
7577          okay := FALSE;
7578        end if;
7579        if compilerLibraryUsed and fileType(compiler_lib) <> FILE_REGULAR then
7580          writeln("*** Compiler library " <& literal(compiler_lib) <& " missing");
7581          okay := FALSE;
7582        end if;
7583        if compDataLibraryUsed and fileType(comp_data_lib) <> FILE_REGULAR then
7584          writeln("*** Compiler data library " <& literal(comp_data_lib) <& " missing");
7585          okay := FALSE;
7586        end if;
7587        if ccConf.LINKER_OPT_SPECIAL_LIB <> "" and fileType(special_lib) <> FILE_REGULAR then
7588          writeln("*** Special library " <& literal(compiler_lib) <& " missing");
7589          okay := FALSE;
7590        end if;
7591        if okay and not compileLibrary then
7592          if fileType(linkedProgram) = FILE_REGULAR then
7593            block
7594              removeFile(linkedProgram);
7595            exception
7596              catch FILE_ERROR:
7597                writeln("*** Cannot remove old executable: " <&
7598                    literal(linkedProgram));
7599            end block;
7600          end if;
7601          if fileType(linkedProgram) = FILE_ABSENT then
7602            writeln("Calling the linker ...");
7603            if generate_c_plus_plus then
7604              link_cmd := ccConf.CPLUSPLUS_COMPILER;
7605            else
7606              link_cmd := ccConf.C_COMPILER;
7607            end if;
7608            if enable_link_time_optimization or ccConf.LINKER_OPT_LTO_MANDATORY then
7609              linkParams &:= ccConf.CC_OPT_LINK_TIME_OPTIMIZATION;
7610            end if;
7611            if "-g" in compiler_option then
7612              if ccConf.LINKER_OPT_DEBUG_INFO <> "" then
7613                linkParams &:= ccConf.LINKER_OPT_DEBUG_INFO;
7614              end if;
7615            else
7616              if ccConf.LINKER_OPT_NO_DEBUG_INFO <> "" then
7617                linkParams &:= ccConf.LINKER_OPT_NO_DEBUG_INFO;
7618              end if;
7619            end if;
7620            linkParams &:= ccConf.LINKER_FLAGS;
7621            if ccConf.LINKER_OPT_OUTPUT_FILE <> "" then
7622              if endsWith(ccConf.LINKER_OPT_OUTPUT_FILE, " ") then
7623                linkParams &:= rtrim(ccConf.LINKER_OPT_OUTPUT_FILE);
7624                linkParams &:= toOsPath(linkedProgram);
7625              else
7626                linkParams &:= ccConf.LINKER_OPT_OUTPUT_FILE &
7627                               toOsPath(linkedProgram);
7628              end if;
7629            end if;
7630            linkParams &:= toOsPath(objectFile);
7631            if compilerLibraryUsed then
7632              appendLibrary(linkParams, toOsPath(compiler_lib));
7633            end if;
7634            if compDataLibraryUsed then
7635              appendLibrary(linkParams, toOsPath(comp_data_lib));
7636            end if;
7637            if drawLibraryUsed then
7638              appendLibrary(linkParams, toOsPath(draw_lib));
7639            end if;
7640            if consoleLibraryUsed then
7641              appendLibrary(linkParams, toOsPath(console_lib));
7642            end if;
7643            if databaseLibraryUsed then
7644              appendLibrary(linkParams, toOsPath(database_lib));
7645            end if;
7646            appendLibrary(linkParams, toOsPath(seed7_lib));
7647            if ccConf.LINKER_OPT_SPECIAL_LIB <> "" then
7648              appendLibrary(linkParams, ccConf.LINKER_OPT_SPECIAL_LIB);
7649              appendLibrary(linkParams, toOsPath(special_lib));
7650            end if;
7651            appendLibrary(linkParams, ccConf.SYSTEM_LIBS);
7652            if bigintLibraryUsed then
7653              appendLibrary(linkParams, ccConf.SYSTEM_BIGINT_LIBS);
7654            end if;
7655            if consoleLibraryUsed then
7656              appendLibrary(linkParams, ccConf.SYSTEM_CONSOLE_LIBS);
7657            end if;
7658            if databaseLibraryUsed then
7659              appendLibrary(linkParams, ccConf.SYSTEM_DATABASE_LIBS);
7660            end if;
7661            if drawLibraryUsed then
7662              appendLibrary(linkParams, ccConf.SYSTEM_DRAW_LIBS);
7663            end if;
7664            if mathLibraryUsed then
7665              appendLibrary(linkParams, ccConf.SYSTEM_MATH_LIBS);
7666            end if;
7667            if ccConf.CALL_C_COMPILER_FROM_SHELL then
7668              execProgramScript(link_cmd, linkParams, linkErrFile);
7669            else
7670              execProgram(link_cmd, linkParams, linkErrFile);
7671            end if;
7672            if ccConf.LINKER_OPT_OUTPUT_FILE = "" and
7673                fileType(tempExeFile) = FILE_REGULAR then
7674              moveFile(tempExeFile, linkedProgram);
7675            end if;
7676            if fileType(linkedProgram) <> FILE_REGULAR then
7677              if fileType(linkErrFile) = FILE_REGULAR and
7678                  fileSize(linkErrFile) = 0 then
7679                removeFile(linkErrFile);
7680              end if;
7681              if fileType(linkErrFile) = FILE_REGULAR then
7682                writeln("*** Linker errors with " <& literal(workDir & objectFile) <&
7683                    " - see " <& literal(workDir & linkErrFile));
7684              elsif ccConf.CC_ERROR_FILEDES not in {1, 2} then
7685                writeln("*** Linking terminated");
7686              else
7687                writeln("*** Linking terminated without error messages");
7688              end if;
7689            elsif fileType(linkErrFile) = FILE_REGULAR then
7690              removeFile(linkErrFile);
7691            end if;
7692            if "-g" not in compiler_option then
7693              removeFile(objectFile);
7694            end if;
7695          end if;
7696        end if;
7697      end if;
7698      chdir(cwd);
7699    end if;
7700  end func;
7701
7702
7703const proc: writeHelp is func
7704  begin
7705    writeln("usage: s7c [options] source");
7706    writeln;
7707    writeln("Options:");
7708    writeln("  -?   Write Seed7 compiler usage.");
7709    writeln("  -O and -O2  Tell the C compiler to optimize.");
7710    writeln("  -b   Specify the directory of the Seed7 runtime libraries (e.g.: -b ../bin).");
7711    writeln("  -e   Generate code which sends a signal, if an uncaught exception occurs.");
7712    writeln("       This option allows debuggers to handle uncaught Seed7 exceptions.");
7713    writeln("  -flto Enable link time optimization.");
7714    writeln("  -g   Tell the C compiler to generate an executable with debug information.");
7715    writeln("       This way the debugger will refer to Seed7 source files and line numbers.");
7716    writeln("       To generate debug information which refers to the temporary C program");
7717    writeln("       the option -g-debug_c can be used.");
7718    writeln("  -l   Add a directory to the include library search path (e.g.: -l ../lib).");
7719    writeln("  -ocn Optimize constants with level n. E.g.: -oc3");
7720    writeln("       The level n is a digit between 0 and 3:");
7721    writeln("         0 Do no optimizations with constants.");
7722    writeln("         1 Use literals and named constants to simplify expressions (default).");
7723    writeln("         2 Evaluate constant parameter expressions to simplify expressions.");
7724    writeln("         3 Like -oc2 and additionally evaluate all constant expressions.");
7725    writeln("  -p   Activate simple function profiling.");
7726    writeln("  -sx  Suppress checks specified with x. E.g.: -sr or -sro");
7727    writeln("       The checks x are specified with letters from the following list:");
7728    writeln("         d Suppress the generation of checks for integer division by zero.");
7729    writeln("         i Suppress the generation of index checks (e.g. string, array).");
7730    writeln("         o Suppress the generation of integer overflow checks.");
7731    writeln("         r Suppress the generation of range checks.");
7732    writeln("  -tx  Set runtime trace level to x. Where x is a string consisting of:");
7733    writeln("         e Trace exceptions and handlers");
7734    writeln("         f Trace functions");
7735    writeln("         s Trace signals");
7736    writeln;
7737  end func;
7738
7739
7740const proc: main is func
7741
7742  local
7743    var integer: index is 0;
7744    var string: curr_arg is "";
7745    var string: source is "";
7746    var string: sourcePath is "";
7747    var string: sourceExtension is "";
7748    var boolean: okay is TRUE;
7749
7750  begin
7751    OUT := STD_UTF8_OUT;
7752    writeln("SEED7 COMPILER Version 3.1." <& ccConf.VERSION_REVISION_LEVEL <&
7753            " Copyright (c) 1990-2021 Thomas Mertes");
7754    if length(argv(PROGRAM)) = 0 then
7755      writeln("This is free software; see the source for copying conditions.  There is NO");
7756      writeln("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
7757      writeln("S7c is written in the Seed7 programming language");
7758      writeln("Homepage: http://seed7.sourceforge.net");
7759      writeln;
7760      writeln("usage: s7c [options] source");
7761      writeln;
7762      writeln("Use  s7c -?  to get more information about s7c.");
7763      writeln;
7764    else
7765      for index range 1 to length(argv(PROGRAM)) do
7766        curr_arg := argv(PROGRAM)[index];
7767        if length(curr_arg) >= 2 and curr_arg[1] = '-' then
7768          if curr_arg in {"-b"} and index < length(argv(PROGRAM)) then
7769            incr(index);
7770            compiler_option @:= [curr_arg] argv(PROGRAM)[index];
7771          elsif curr_arg in {"-l"} and index < length(argv(PROGRAM)) then
7772            incr(index);
7773            libraryDirs &:= convDosPath(argv(PROGRAM)[index]);
7774          elsif curr_arg[.. 2] in {"-?", "-b", "-c", "-e", "-f", "-g", "-o", "-p", "-s", "-t", "-O"} then
7775            if curr_arg[.. 2] in compiler_option then
7776              writeln("*** Option " <& curr_arg[.. 2] <&
7777                      " specified twice. Ignore option: " <& curr_arg);
7778            else
7779              compiler_option @:= [curr_arg[.. 2]] curr_arg[3 ..];
7780            end if;
7781          else
7782            writeln("*** Ignore unsupported option: " <& curr_arg);
7783          end if;
7784        elsif source = "" then
7785          source := convDosPath(curr_arg);
7786        else
7787          writeln("*** Ignore superfluous parameter: " <& curr_arg);
7788        end if;
7789      end for;
7790      if "-?" in compiler_option then
7791        writeHelp;
7792      elsif source = "" then
7793        writeln("*** Sourcefile missing");
7794      else
7795        writeln("Source: " <& source);
7796        pass_1(source, prog, okay);
7797        if okay then
7798          sourcePath := path(prog);
7799          if  endsWith(sourcePath, ".sd7") or
7800              endsWith(sourcePath, ".s7i") then
7801            sourceExtension := sourcePath[length(sourcePath) - 3 ..];
7802            sourcePath := sourcePath[.. length(sourcePath) - 4];
7803          end if;
7804        end if;
7805        pass_2(sourcePath, prog, okay);
7806        pass_3(sourcePath, sourceExtension, prog, okay);
7807      end if;
7808    end if;
7809  end func;
7810