"Fossies" - the Fresh Open Source Software Archive

Member "seed7/lib/comp/str_act.s7i" (6 Jan 2021, 133107 Bytes) of package /linux/misc/seed7_05_20210223.tgz:


As a special service "Fossies" has tried to format the requested text file into HTML format (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "str_act.s7i": 05_20201208_vs_05_20210106.

    1 
    2 (********************************************************************)
    3 (*                                                                  *)
    4 (*  str_act.s7i   Generate code for actions of the type string.     *)
    5 (*  Copyright (C) 1990 - 1994, 2004 - 2017  Thomas Mertes           *)
    6 (*                                                                  *)
    7 (*  This file is part of the Seed7 compiler.                        *)
    8 (*                                                                  *)
    9 (*  This program is free software; you can redistribute it and/or   *)
   10 (*  modify it under the terms of the GNU General Public License as  *)
   11 (*  published by the Free Software Foundation; either version 2 of  *)
   12 (*  the License, or (at your option) any later version.             *)
   13 (*                                                                  *)
   14 (*  This program is distributed in the hope that it will be useful, *)
   15 (*  but WITHOUT ANY WARRANTY; without even the implied warranty of  *)
   16 (*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   *)
   17 (*  GNU General Public License for more details.                    *)
   18 (*                                                                  *)
   19 (*  You should have received a copy of the GNU General Public       *)
   20 (*  License along with this program; if not, write to the           *)
   21 (*  Free Software Foundation, Inc., 51 Franklin Street,             *)
   22 (*  Fifth Floor, Boston, MA  02110-1301, USA.                       *)
   23 (*                                                                  *)
   24 (********************************************************************)
   25 
   26 
   27 const ACTION: STR_APPEND      is action "STR_APPEND";
   28 const ACTION: STR_CAT         is action "STR_CAT";
   29 const ACTION: STR_CHIPOS      is action "STR_CHIPOS";
   30 const ACTION: STR_CHPOS       is action "STR_CHPOS";
   31 const ACTION: STR_CHSPLIT     is action "STR_CHSPLIT";
   32 const ACTION: STR_CLIT        is action "STR_CLIT";
   33 const ACTION: STR_CMP         is action "STR_CMP";
   34 const ACTION: STR_CPY         is action "STR_CPY";
   35 const ACTION: STR_ELEMCPY     is action "STR_ELEMCPY";
   36 const ACTION: STR_EQ          is action "STR_EQ";
   37 const ACTION: STR_FOR         is action "STR_FOR";
   38 const ACTION: STR_FOR_KEY     is action "STR_FOR_KEY";
   39 const ACTION: STR_FOR_VAR_KEY is action "STR_FOR_VAR_KEY";
   40 const ACTION: STR_GE          is action "STR_GE";
   41 const ACTION: STR_GT          is action "STR_GT";
   42 const ACTION: STR_HASHCODE    is action "STR_HASHCODE";
   43 const ACTION: STR_HEAD        is action "STR_HEAD";
   44 const ACTION: STR_IDX         is action "STR_IDX";
   45 const ACTION: STR_IPOS        is action "STR_IPOS";
   46 const ACTION: STR_LE          is action "STR_LE";
   47 const ACTION: STR_LIT         is action "STR_LIT";
   48 const ACTION: STR_LNG         is action "STR_LNG";
   49 const ACTION: STR_LOW         is action "STR_LOW";
   50 const ACTION: STR_LPAD        is action "STR_LPAD";
   51 const ACTION: STR_LPAD0       is action "STR_LPAD0";
   52 const ACTION: STR_LT          is action "STR_LT";
   53 const ACTION: STR_LTRIM       is action "STR_LTRIM";
   54 const ACTION: STR_MULT        is action "STR_MULT";
   55 const ACTION: STR_NE          is action "STR_NE";
   56 const ACTION: STR_POS         is action "STR_POS";
   57 const ACTION: STR_POSCPY      is action "STR_POSCPY";
   58 const ACTION: STR_PUSH        is action "STR_PUSH";
   59 const ACTION: STR_RANGE       is action "STR_RANGE";
   60 const ACTION: STR_RCHIPOS     is action "STR_RCHIPOS";
   61 const ACTION: STR_RCHPOS      is action "STR_RCHPOS";
   62 const ACTION: STR_REPL        is action "STR_REPL";
   63 const ACTION: STR_RIPOS       is action "STR_RIPOS";
   64 const ACTION: STR_RPAD        is action "STR_RPAD";
   65 const ACTION: STR_RPOS        is action "STR_RPOS";
   66 const ACTION: STR_RTRIM       is action "STR_RTRIM";
   67 const ACTION: STR_SPLIT       is action "STR_SPLIT";
   68 const ACTION: STR_STR         is action "STR_STR";
   69 const ACTION: STR_SUBSTR      is action "STR_SUBSTR";
   70 const ACTION: STR_TAIL        is action "STR_TAIL";
   71 const ACTION: STR_TOUTF8      is action "STR_TOUTF8";
   72 const ACTION: STR_TRIM        is action "STR_TRIM";
   73 const ACTION: STR_UP          is action "STR_UP";
   74 const ACTION: STR_UTF8TOSTRI  is action "STR_UTF8TOSTRI";
   75 const ACTION: STR_VALUE       is action "STR_VALUE";
   76 
   77 
   78 const proc: str_prototypes (inout file: c_prog) is func
   79 
   80   begin
   81     declareExtern(c_prog, "void        strAppend (striType *const, const_striType);");
   82     declareExtern(c_prog, "void        strAppendN (striType *const, const const_striType[], memSizeType);");
   83     declareExtern(c_prog, "void        strAppendTemp (striType *const, const striType);");
   84     declareExtern(c_prog, "striType    strChChRepl (const const_striType, const charType, const charType);");
   85     declareExtern(c_prog, "intType     strChIPos (const const_striType, const charType, const intType);");
   86     declareExtern(c_prog, "striType    strChMult (const charType, const intType);");
   87     declareExtern(c_prog, "intType     strChPos (const const_striType, const charType);");
   88     declareExtern(c_prog, "striType    strChRepl (const const_striType, const charType, const const_striType);");
   89     declareExtern(c_prog, "arrayType   strChSplit (const const_striType, const charType);");
   90     declareExtern(c_prog, "intType     strCmpGeneric (const genericType, const genericType);");
   91     declareExtern(c_prog, "intType     strCompare (const const_striType, const const_striType);");
   92     declareExtern(c_prog, "striType    strConcat (const const_striType, const const_striType);");
   93     declareExtern(c_prog, "striType    strConcatN (const const_striType[], memSizeType);");
   94     declareExtern(c_prog, "striType    strConcatTemp (striType, const const_striType);");
   95     declareExtern(c_prog, "striType    strCLit (const const_striType);");
   96     declareExtern(c_prog, "void        strCopy (striType *const, const const_striType);");
   97     declareExtern(c_prog, "void        strCpyGeneric (genericType *const, const genericType);");
   98     declareExtern(c_prog, "striType    strCreate (const const_striType);");
   99     declareExtern(c_prog, "genericType strCreateGeneric (const genericType);");
  100     declareExtern(c_prog, "void        strDestr (const const_striType);");
  101     declareExtern(c_prog, "void        strDestrGeneric (const genericType);");
  102     declareExtern(c_prog, "striType    strEmpty(void);");
  103     declareExtern(c_prog, "boolType    strGe (const const_striType, const const_striType);");
  104     declareExtern(c_prog, "boolType    strGt (const const_striType, const const_striType);");
  105     declareExtern(c_prog, "intType     strHashCode (const const_striType);");
  106     declareExtern(c_prog, "striType    strHead (const_striType, intType);");
  107     declareExtern(c_prog, "void        strHeadSlice (const const_striType, const intType, striType);");
  108     declareExtern(c_prog, "striType    strHeadTemp (const striType, const intType);");
  109     declareExtern(c_prog, "intType     strIPos (const const_striType, const const_striType, const intType);");
  110     declareExtern(c_prog, "boolType    strLe (const const_striType, const const_striType);");
  111     declareExtern(c_prog, "striType    strLit (const const_striType);");
  112     declareExtern(c_prog, "striType    strLow (const const_striType);");
  113     declareExtern(c_prog, "striType    strLowTemp (const striType);");
  114     declareExtern(c_prog, "striType    strLpad (const const_striType, const intType);");
  115     declareExtern(c_prog, "striType    strLpadTemp (const striType, const intType);");
  116     declareExtern(c_prog, "striType    strLpad0 (const const_striType, const intType);");
  117     declareExtern(c_prog, "striType    strLpad0Temp (const striType, const intType);");
  118     declareExtern(c_prog, "boolType    strLt (const const_striType, const const_striType);");
  119     declareExtern(c_prog, "striType    strLtrim (const const_striType);");
  120     declareExtern(c_prog, "striType    strMult (const const_striType, const intType);");
  121     declareExtern(c_prog, "intType     strPos (const const_striType, const const_striType);");
  122     declareExtern(c_prog, "void        strPush (striType *const, const charType);");
  123     declareExtern(c_prog, "striType    strRange (const_striType, intType, intType);");
  124     declareExtern(c_prog, "void        strRangeSlice (const const_striType, intType, intType, striType);");
  125     declareExtern(c_prog, "intType     strRChIPos (const const_striType, const charType, const intType);");
  126     declareExtern(c_prog, "intType     strRChPos (const const_striType, const charType);");
  127     declareExtern(c_prog, "striType    strRepl (const const_striType, const const_striType, const const_striType);");
  128     declareExtern(c_prog, "intType     strRIPos (const const_striType, const const_striType, const intType);");
  129     declareExtern(c_prog, "striType    strRpad (const const_striType, const intType);");
  130     declareExtern(c_prog, "intType     strRPos (const const_striType, const const_striType);");
  131     declareExtern(c_prog, "striType    strRtrim (const const_striType);");
  132     declareExtern(c_prog, "arrayType   strSplit (const const_striType, const const_striType);");
  133     declareExtern(c_prog, "striType    strSubstr (const_striType, intType, intType);");
  134     declareExtern(c_prog, "void        strSubstrSlice (const const_striType, intType, intType, striType);");
  135     declareExtern(c_prog, "striType    strTail (const_striType, intType);");
  136     declareExtern(c_prog, "void        strTailSlice (const const_striType, intType, striType);");
  137     declareExtern(c_prog, "striType    strTailTemp (const striType, intType);");
  138     declareExtern(c_prog, "striType    strToUtf8 (const const_striType);");
  139     declareExtern(c_prog, "striType    strTrim (const const_striType);");
  140     declareExtern(c_prog, "striType    strUp (const const_striType);");
  141     declareExtern(c_prog, "striType    strUpTemp (const striType);");
  142     declareExtern(c_prog, "striType    strUtf8ToStri (const const_striType);");
  143     declareExtern(c_prog, "striType    strValue (const const_objRefType);");
  144     declareExtern(c_prog, "const_striType strValueRef (const const_objRefType);");
  145     declareExtern(c_prog, "striType    strZero (const intType);");
  146   end func;
  147 
  148 
  149 const func array reference: getConcatNParamList (in ref_list: params) is func
  150   result
  151     var array reference: concatNParamList is 0 times NIL;
  152   local
  153     var reference: leftParam is NIL;
  154     var boolean: concatFound is FALSE;
  155     var ref_list: subExprParams is ref_list.EMPTY;
  156   begin
  157     leftParam := params[1];
  158     concatNParamList := [] (params[3]);
  159     repeat
  160       concatFound := FALSE;
  161       if category(leftParam) = CALLOBJECT then
  162         subExprParams := getValue(leftParam, ref_list);
  163         if category(subExprParams[1]) = ACTOBJECT then
  164           if str(getValue(subExprParams[1], ACTION)) = "STR_CAT" then
  165             leftParam := subExprParams[2];
  166             concatNParamList := [] (subExprParams[4]) & concatNParamList;
  167             concatFound := TRUE;
  168           end if;
  169         end if;
  170       end if;
  171     until not concatFound;
  172     concatNParamList := [] (leftParam) & concatNParamList;
  173   end func;
  174 
  175 
  176 const func array reference: getAppendExtensions (in reference: extension) is func
  177   result
  178     var array reference: appendNParamList is 0 times NIL;
  179   local
  180     var ref_list: params is ref_list.EMPTY;
  181   begin
  182     if category(extension) = CALLOBJECT then
  183       params := getValue(extension, ref_list);
  184       if category(params[1]) = ACTOBJECT and
  185           str(getValue(params[1], ACTION)) = "STR_CAT" then
  186         appendNParamList := getConcatNParamList(params[2 ..]);
  187       else
  188         appendNParamList := [] (extension);
  189       end if;
  190     else
  191       appendNParamList := [] (extension);
  192     end if;
  193   end func;
  194 
  195 
  196 const proc: concatConstants (inout array reference: concatNParamList) is func
  197   local
  198     var integer: index is 1;
  199     var reference: evaluatedParam is NIL;
  200     var string: paramValue is "";
  201   begin
  202     while index <= length(concatNParamList) do
  203       if getConstant(concatNParamList[index], STRIOBJECT, evaluatedParam) then
  204         paramValue := getValue(evaluatedParam, string);
  205         if paramValue = "" then
  206           # Empty strings are removed.
  207           incr(countOptimizations);
  208           ignore(remove(concatNParamList, index));
  209         elsif succ(index) <= length(concatNParamList) and
  210             getConstant(concatNParamList[succ(index)], STRIOBJECT, evaluatedParam) then
  211           # Two consecutive constant strings are concatenated at compile time.
  212           incr(countOptimizations);
  213           concatNParamList[index] := alloc(FALSE, getType(concatNParamList[index]),
  214               paramValue & getValue(evaluatedParam, string));
  215           ignore(remove(concatNParamList, succ(index)));
  216         else
  217           incr(index);
  218         end if;
  219       else
  220         incr(index);
  221       end if;
  222     end while;
  223   end func;
  224 
  225 
  226 const proc: process_const_inline_str_push (in reference: param1, in char: ch,
  227     inout expr_type: c_expr) is func
  228 
  229   local
  230     var expr_type: statement is expr_type.value;
  231     var string: stri_name is "";
  232   begin
  233     if isNormalVariable(param1) then
  234       stri_name := normalVariable(param1, statement);
  235     else
  236       incr(statement.temp_num);
  237       stri_name := "tmp_" & str(statement.temp_num);
  238       statement.temp_decls &:= "striType *";
  239       statement.temp_decls &:= stri_name;
  240       statement.temp_decls &:= ";\n";
  241       statement.expr &:= stri_name;
  242       statement.expr &:= "=&(";
  243       process_expr(param1, statement);
  244       statement.expr &:= ");\n";
  245       stri_name := "*" & stri_name;
  246     end if;
  247     statement.expr &:= "if ((";
  248     statement.expr &:= stri_name;
  249     statement.expr &:= ")->size == (";
  250     statement.expr &:= stri_name;
  251     statement.expr &:= ")->capacity) {\n";
  252     statement.expr &:= "strPush(&(";
  253     statement.expr &:= stri_name;
  254     statement.expr &:= "), ";
  255     statement.expr &:= charLiteral(ch);
  256     statement.expr &:= ");\n";
  257     statement.expr &:= "} else {\n";
  258     statement.expr &:= "(";
  259     statement.expr &:= stri_name;
  260     statement.expr &:= ")->mem[(";
  261     statement.expr &:= stri_name;
  262     statement.expr &:= ")->size]=";
  263     statement.expr &:= charLiteral(ch);
  264     statement.expr &:= ";\n";
  265     statement.expr &:= "(";
  266     statement.expr &:= stri_name;
  267     statement.expr &:= ")->size++;\n";
  268     statement.expr &:= "}\n";
  269     doLocalDeclsOfStatement(statement, c_expr);
  270   end func;
  271 
  272 
  273 const proc: process_const_str_push (in reference: param1, in char: ch,
  274     inout expr_type: c_expr) is func
  275 
  276   begin
  277     if inlineFunctions and ccConf.WITH_STRI_CAPACITY then
  278       process_const_inline_str_push(param1, ch, c_expr);
  279     else
  280       c_expr.expr &:= "strPush(&(";
  281       process_expr(param1, c_expr);
  282       c_expr.expr &:= "), ";
  283       c_expr.expr &:= charLiteral(ch);
  284       c_expr.expr &:= ");\n";
  285     end if;
  286   end func;
  287 
  288 
  289 const proc: process_const_str_append (in reference: param1, in string: stri,
  290     inout expr_type: c_expr) is func
  291 
  292   begin
  293     setDiagnosticLine(c_expr);
  294     if stri = "" then
  295       incr(countOptimizations);
  296       c_expr.expr &:= "/* Append empty string */\n";
  297     elsif length(stri) = 1 then
  298       incr(countOptimizations);
  299       process_const_str_push(param1, stri[1], c_expr);
  300     else
  301       c_expr.expr &:= "strAppend(&(";
  302       process_expr(param1, c_expr);
  303       c_expr.expr &:= "), ";
  304       c_expr.expr &:= stringLiteral(stri);
  305       c_expr.expr &:= ");\n";
  306     end if;
  307   end func;
  308 
  309 
  310 (**
  311  *  Produces code for the string append operator.
  312  *  If two or more strings are appended the function
  313  *  strAppendN is used. This avoids copying and allocation operations.
  314  *)
  315 const proc: optimize_str_append (in reference: dest, in reference: extension,
  316     inout expr_type: c_expr) is func
  317 
  318   local
  319     var expr_type: statement is expr_type.value;
  320     var array reference: appendExtensions is 0 times NIL;
  321     var string: concatNParamName is "";
  322     var integer: index is 1;
  323     var reference: evaluatedParam is NIL;
  324     var expr_type: c_extension is expr_type.value;
  325   begin
  326     appendExtensions := getAppendExtensions(extension);
  327     concatConstants(appendExtensions);
  328     if length(appendExtensions) >= 2 then
  329       incr(countOptimizations);
  330       incr(statement.temp_num);
  331       concatNParamName := "tmp_" & str(statement.temp_num);
  332       statement.temp_decls &:= "const_striType ";
  333       statement.temp_decls &:= concatNParamName;
  334       statement.temp_decls &:= "[";
  335       statement.temp_decls &:= str(length(appendExtensions));
  336       statement.temp_decls &:= "];\n";
  337       for key index range appendExtensions do
  338         statement.expr &:= concatNParamName;
  339         statement.expr &:= "[";
  340         statement.expr &:= str(pred(index));
  341         statement.expr &:= "] = ";
  342         getAnyParamToExpr(appendExtensions[index], statement);
  343         statement.expr &:= ";\n";
  344       end for;
  345       statement.expr &:= "strAppendN(&(";
  346       process_expr(dest, statement);
  347       statement.expr &:= "), ";
  348       statement.expr &:= concatNParamName;
  349       statement.expr &:= ", ";
  350       statement.expr &:= str(length(appendExtensions));
  351       statement.expr &:= ");\n";
  352     elsif length(appendExtensions) = 1 then
  353       if getConstant(appendExtensions[1], STRIOBJECT, evaluatedParam) then
  354         process_const_str_append(dest, getValue(evaluatedParam, string), c_expr);
  355       else
  356         if isActionExpression(appendExtensions[1], "CHR_STR") then
  357           incr(countOptimizations);
  358           statement.expr &:= "strPush(&(";
  359           process_expr(dest, statement);
  360           statement.expr &:= "), ";
  361           process_expr(getActionParameter(appendExtensions[1], 1), statement);
  362         else
  363           prepareAnyParamTemporarys(appendExtensions[1], c_extension, statement);
  364           if c_extension.result_expr <> "" then
  365             statement.expr := "strAppendTemp(&(";
  366             process_expr(dest, statement);
  367             statement.expr &:= "), ";
  368             statement.expr &:= c_extension.result_expr;
  369           else
  370             statement.expr := "strAppend(&(";
  371             process_expr(dest, statement);
  372             statement.expr &:= "), ";
  373             statement.expr &:= c_extension.expr;
  374           end if;
  375         end if;
  376         statement.expr &:= ");\n";
  377       end if;
  378     else
  379       incr(countOptimizations);
  380       statement.expr &:= "/* Append empty string */\n";
  381     end if;
  382     doLocalDeclsOfStatement(statement, c_expr);
  383   end func;
  384 
  385 
  386 const proc: process_str_append (in reference: param1, in reference: param3,
  387     inout expr_type: c_expr) is func
  388 
  389   local
  390     var reference: evaluatedParam is NIL;
  391     var expr_type: c_param1 is expr_type.value;
  392     var expr_type: c_param3 is expr_type.value;
  393   begin
  394     if evaluate_const_expr >= 1 then
  395       optimize_str_append(param1, param3, c_expr);
  396     elsif getConstant(param3, STRIOBJECT, evaluatedParam) then
  397       process_const_str_append(param1, getValue(evaluatedParam, string), c_expr);
  398     else
  399       process_expr(param1, c_param1);
  400       c_param3.temp_num := c_param1.temp_num;
  401       if isActionExpression(param3, "CHR_STR") then
  402         incr(countOptimizations);
  403         process_expr(getActionParameter(param3, 1), c_param3);
  404       else
  405         process_expr(param3, c_param3);
  406       end if;
  407       if has_temp_values(c_param3) then
  408         c_expr.expr &:= "{\n";
  409         appendWithDiagnostic(c_param1.temp_decls, c_expr);
  410         appendWithDiagnostic(c_param3.temp_decls, c_expr);
  411         appendWithDiagnostic(c_param1.temp_assigns, c_expr);
  412         appendWithDiagnostic(c_param3.temp_assigns, c_expr);
  413       end if;
  414       setDiagnosticLine(c_expr);
  415       if isActionExpression(param3, "CHR_STR") then
  416         c_expr.expr &:= "strPush(&(";
  417         c_expr.expr &:= c_param1.expr;
  418         c_expr.expr &:= "), ";
  419         c_expr.expr &:= c_param3.expr;
  420       elsif c_param3.expr <> "" then
  421         c_expr.expr &:= "strAppend(&(";
  422         c_expr.expr &:= c_param1.expr;
  423         c_expr.expr &:= "), ";
  424         c_expr.expr &:= c_param3.expr;
  425       else
  426         c_expr.expr &:= "strAppendTemp(&(";
  427         c_expr.expr &:= c_param1.expr;
  428         c_expr.expr &:= "), ";
  429         c_expr.expr &:= c_param3.result_expr;
  430       end if;
  431       c_expr.expr &:= ");\n";
  432       if has_temp_values(c_param3) then
  433         appendWithDiagnostic(c_param1.temp_frees, c_expr);
  434         appendWithDiagnostic(c_param3.temp_frees, c_expr);
  435         c_expr.expr &:= "}\n";
  436       end if;
  437     end if;
  438   end func;
  439 
  440 
  441 const proc: process (STR_APPEND, in reference: function,
  442     in ref_list: params, inout expr_type: c_expr) is func
  443 
  444   begin
  445     process_str_append(params[1], params[3], c_expr);
  446   end func;
  447 
  448 
  449 (**
  450  *  Produces code for the string concatenation.
  451  *  If three or more strings are concatenated the function
  452  *  strConcatN is used. This saves copying and allocation operations.
  453  *  If the first parameter is a temporary value the concatenation
  454  *  is done with strConcatTemp. The strConcatTemp function returns
  455  *  the first parameter as result of the concatenation. That way the
  456  *  temporary of the first parameter must not be freed.
  457  *)
  458 const proc: optimize_str_cat (in ref_list: params, inout expr_type: c_expr) is func
  459 
  460   local
  461     var array reference: concatNParamList is 0 times NIL;
  462     var string: concatNParamName is "";
  463     var integer: index is 1;
  464     var reference: evaluatedParam is NIL;
  465     var expr_type: c_param1 is expr_type.value;
  466   begin
  467     concatNParamList := getConcatNParamList(params);
  468     concatConstants(concatNParamList);
  469     if length(concatNParamList) >= 3 then
  470       incr(countOptimizations);
  471       prepare_stri_result(c_expr);
  472       incr(c_expr.temp_num);
  473       concatNParamName := "tmp_" & str(c_expr.temp_num);
  474       c_expr.temp_decls &:= "const_striType ";
  475       c_expr.temp_decls &:= concatNParamName;
  476       c_expr.temp_decls &:= "[";
  477       c_expr.temp_decls &:= str(length(concatNParamList));
  478       c_expr.temp_decls &:= "];\n";
  479       c_expr.result_expr := "(";
  480       for key index range concatNParamList do
  481         if getConstant(concatNParamList[index], STRIOBJECT, evaluatedParam) then
  482           c_expr.temp_assigns &:= concatNParamName;
  483           c_expr.temp_assigns &:= "[";
  484           c_expr.temp_assigns &:= str(pred(index));
  485           c_expr.temp_assigns &:= "] = ";
  486           c_expr.temp_assigns &:= stringLiteral(getValue(evaluatedParam, string));
  487           c_expr.temp_assigns &:= ";\n";
  488         else
  489           c_expr.result_expr &:= concatNParamName;
  490           c_expr.result_expr &:= "[";
  491           c_expr.result_expr &:= str(pred(index));
  492           c_expr.result_expr &:= "] = ";
  493           getAnyParamToResultExpr(concatNParamList[index], c_expr);
  494           c_expr.result_expr &:= ", ";
  495         end if;
  496       end for;
  497       c_expr.result_expr &:= "strConcatN(";
  498       c_expr.result_expr &:= concatNParamName;
  499       c_expr.result_expr &:= ", ";
  500       c_expr.result_expr &:= str(length(concatNParamList));
  501       c_expr.result_expr &:= "))";
  502     elsif length(concatNParamList) = 2 then
  503       prepare_stri_result(c_expr);
  504       prepareAnyParamTemporarys(concatNParamList[1], c_param1, c_expr);
  505       if c_param1.expr <> "" then
  506         c_expr.result_expr := "strConcat(";
  507         c_expr.result_expr &:= c_param1.expr;
  508       else
  509         c_expr.result_expr := "strConcatTemp(";
  510         c_expr.result_expr &:= c_param1.result_expr;
  511       end if;
  512       c_expr.result_expr &:= ", ";
  513       getAnyParamToResultExpr(concatNParamList[2], c_expr);
  514       c_expr.result_expr &:= ")";
  515     elsif length(concatNParamList) = 1 then
  516       incr(countOptimizations);
  517       process_expr(concatNParamList[1], c_expr);
  518     else
  519       incr(countOptimizations);
  520       if c_expr.demand >= ASSIGN_RESULT then
  521         c_expr.result_expr := "strEmpty()";
  522       else
  523         c_expr.expr &:= stringLiteral("");
  524       end if;
  525     end if;
  526   end func;
  527 
  528 
  529 const proc: process (STR_CAT, in reference: function,
  530     in ref_list: params, inout expr_type: c_expr) is func
  531 
  532   local
  533     var expr_type: c_param1 is expr_type.value;
  534   begin
  535     if evaluate_const_expr >= 1 then
  536       optimize_str_cat(params, c_expr);
  537     else
  538       prepare_stri_result(c_expr);
  539       prepareAnyParamTemporarys(params[1], c_param1, c_expr);
  540       if c_param1.result_expr <> "" then
  541         c_expr.result_expr := "strConcatTemp(";
  542         c_expr.result_expr &:= c_param1.result_expr;
  543       else
  544         c_expr.result_expr := "strConcat(";
  545         c_expr.result_expr &:= c_param1.expr;
  546       end if;
  547       c_expr.result_expr &:= ", ";
  548       getAnyParamToResultExpr(params[3], c_expr);
  549       c_expr.result_expr &:= ")";
  550     end if;
  551   end func;
  552 
  553 
  554 const proc: process (STR_CHIPOS, in reference: function,
  555     in ref_list: params, inout expr_type: c_expr) is func
  556 
  557   begin
  558     c_expr.expr &:= "strChIPos(";
  559     getAnyParamToExpr(params[1], c_expr);
  560     c_expr.expr &:= ", ";
  561     process_expr(params[2], c_expr);
  562     c_expr.expr &:= ", ";
  563     process_expr(params[3], c_expr);
  564     c_expr.expr &:= ")";
  565   end func;
  566 
  567 
  568 const proc: process_const_str_chpos (in string: mainStri, in reference: searched,
  569     inout expr_type: c_expr) is func
  570 
  571   local
  572     var reference: evaluatedParam is NIL;
  573   begin
  574     if getConstant(searched, CHAROBJECT, evaluatedParam) then
  575       incr(countOptimizations);
  576       c_expr.expr &:= "/* pos(";
  577       c_expr.expr &:= replace(literal(mainStri), "*/", "*\\/");
  578       c_expr.expr &:= ",";
  579       c_expr.expr &:= literal(getValue(evaluatedParam, char));
  580       c_expr.expr &:= ") */ ";
  581       c_expr.expr &:= integerLiteral(pos(mainStri, getValue(evaluatedParam, char)));
  582     elsif length(mainStri) = 0 then
  583       incr(countOptimizations);
  584       c_expr.expr &:= "/* pos(\"\", *) */ ";
  585       c_expr.expr &:= integerLiteral(0);
  586     elsif length(mainStri) = 1 then
  587       incr(countOptimizations);
  588       c_expr.expr &:= "/* pos(";
  589       c_expr.expr &:= literal(mainStri);
  590       c_expr.expr &:= ", *) */ ";
  591       c_expr.expr &:= charLiteral(mainStri[1]);
  592       c_expr.expr &:= "==(";
  593       getAnyParamToExpr(searched, c_expr);
  594       c_expr.expr &:= ")?";
  595       c_expr.expr &:= integerLiteral(1);
  596       c_expr.expr &:= ":";
  597       c_expr.expr &:= integerLiteral(0);
  598     else
  599       c_expr.expr &:= "strChPos(";
  600       c_expr.expr &:= stringLiteral(mainStri);
  601       c_expr.expr &:= ", ";
  602       getAnyParamToExpr(searched, c_expr);
  603       c_expr.expr &:= ")";
  604     end if;
  605   end func;
  606 
  607 
  608 const proc: process (STR_CHPOS, in reference: function,
  609     in ref_list: params, inout expr_type: c_expr) is func
  610 
  611   local
  612     var reference: evaluatedParam is NIL;
  613   begin
  614     if getConstant(params[1], STRIOBJECT, evaluatedParam) then
  615       process_const_str_chpos(getValue(evaluatedParam, string), params[2], c_expr);
  616     else
  617       c_expr.expr &:= "strChPos(";
  618       getAnyParamToExpr(params[1], c_expr);
  619       c_expr.expr &:= ", ";
  620       process_expr(params[2], c_expr);
  621       c_expr.expr &:= ")";
  622     end if;
  623   end func;
  624 
  625 
  626 const proc: process (STR_CHSPLIT, in reference: function,
  627     in ref_list: params, inout expr_type: c_expr) is func
  628 
  629   begin
  630     prepare_typed_result(array_type[getExprResultType(params[1])], c_expr);
  631     c_expr.result_expr := "strChSplit(";
  632     getAnyParamToResultExpr(params[1], c_expr);
  633     c_expr.result_expr &:= ", ";
  634     getStdParamToResultExpr(params[2], c_expr);
  635     c_expr.result_expr &:= ")";
  636   end func;
  637 
  638 
  639 const proc: process (STR_CLIT, in reference: function,
  640     in ref_list: params, inout expr_type: c_expr) is func
  641 
  642   begin
  643     prepare_stri_result(c_expr);
  644     c_expr.result_expr := "strCLit(";
  645     getAnyParamToResultExpr(params[1], c_expr);
  646     c_expr.result_expr &:= ")";
  647   end func;
  648 
  649 
  650 const proc: process (STR_CMP, in reference: function,
  651     in ref_list: params, inout expr_type: c_expr) is func
  652 
  653   begin
  654     c_expr.expr &:= "strCompare(";
  655     getAnyParamToExpr(params[1], c_expr);
  656     c_expr.expr &:= ", ";
  657     getAnyParamToExpr(params[2], c_expr);
  658     c_expr.expr &:= ")";
  659   end func;
  660 
  661 
  662 const proc: process (STR_CPY, in reference: function,
  663     in ref_list: params, inout expr_type: c_expr) is func
  664 
  665   local
  666     var expr_type: statement is expr_type.value;
  667     var expr_type: c_param1 is expr_type.value;
  668     var expr_type: c_param3 is expr_type.value;
  669   begin
  670     if isActionExpression(params[3], "STR_CAT") and
  671         getActionParameter(params[3], 1) = params[1] then
  672       process_str_append(params[1], getActionParameter(params[3], 3), c_expr);
  673     else
  674       statement.temp_num := c_expr.temp_num;
  675       prepareAnyParamTemporarys(params[1], c_param1, statement);
  676       if isActionExpression(params[3], "STR_HEAD") and
  677           getActionParameter(params[3], 1) = params[1] then
  678         statement.expr &:= c_param1.expr;
  679         statement.expr &:= "=strHeadTemp(";
  680         statement.expr &:= c_param1.expr;
  681         statement.expr &:= ", ";
  682         process_expr(getActionParameter(params[3], 4), statement);
  683         statement.expr &:= ");\n";
  684       elsif isActionExpression(params[3], "STR_TAIL") and
  685           getActionParameter(params[3], 1) = params[1] then
  686         statement.expr &:= c_param1.expr;
  687         statement.expr &:= "=strTailTemp(";
  688         statement.expr &:= c_param1.expr;
  689         statement.expr &:= ", ";
  690         process_expr(getActionParameter(params[3], 3), statement);
  691         statement.expr &:= ");\n";
  692       elsif isActionExpression(params[3], "STR_LOW") and
  693           getActionParameter(params[3], 1) = params[1] then
  694         statement.expr &:= c_param1.expr;
  695         statement.expr &:= "=strLowTemp(";
  696         statement.expr &:= c_param1.expr;
  697         statement.expr &:= ");\n";
  698       elsif isActionExpression(params[3], "STR_UP") and
  699           getActionParameter(params[3], 1) = params[1] then
  700         statement.expr &:= c_param1.expr;
  701         statement.expr &:= "=strUpTemp(";
  702         statement.expr &:= c_param1.expr;
  703         statement.expr &:= ");\n";
  704       else
  705         c_param3.demand := ASSIGN_RESULT;
  706         prepareAnyParamTemporarys(params[3], c_param3, statement);
  707         if c_param3.result_expr <> "" then
  708           if isNormalVariable(params[1]) then
  709             statement.temp_decls &:= "striType old_stri=";
  710             statement.temp_decls &:= c_param1.expr;
  711             statement.temp_decls &:= ";\n";
  712             statement.expr &:= c_param1.expr;
  713             statement.expr &:= "=";
  714           else
  715             statement.temp_decls &:= "striType *stri_ptr=&(";
  716             statement.temp_decls &:= c_param1.expr;
  717             statement.temp_decls &:= ");\n";
  718             statement.expr &:= "striType old_stri=*stri_ptr;\n";
  719             statement.expr &:= "*stri_ptr=";
  720           end if;
  721           statement.expr &:= c_param3.result_expr;
  722           statement.expr &:= ";\n";
  723           statement.expr &:= "strDestr(old_stri);\n";
  724         else
  725           statement.expr &:= "strCopy(&(";
  726           statement.expr &:= c_param1.expr;
  727           statement.expr &:= "), ";
  728           statement.expr &:= c_param3.expr;
  729           statement.expr &:= ");\n";
  730         end if;
  731       end if;
  732       doLocalDeclsOfStatement(statement, c_expr);
  733     end if;
  734   end func;
  735 
  736 
  737 const proc: process_const_str_elemcpy (in reference: destStri,
  738     in integer: position, in char: aChar, inout expr_type: c_expr) is func
  739 
  740   local
  741     var expr_type: c_destStri is expr_type.value;
  742   begin
  743     incr(countOptimizations);
  744     if position < 1 then
  745       c_expr.expr &:= "/* 'string @:= [n] char' with n < 1 */\n";
  746       warning(DOES_RAISE, "INDEX_ERROR", c_expr);
  747       c_expr.expr &:= raiseError("INDEX_ERROR");
  748       c_expr.expr &:= "\n";
  749     else
  750       process_expr(destStri, c_destStri);
  751       if c_destStri.temp_num <> 0 or string_index_check then
  752         c_expr.expr &:= "{\n";
  753       end if;
  754       if c_destStri.temp_num <> 0 then
  755         appendWithDiagnostic(c_destStri.temp_decls, c_expr);
  756         appendWithDiagnostic(c_destStri.temp_assigns, c_expr);
  757       end if;
  758       if string_index_check then
  759         incr(countIndexChecks);
  760         c_expr.expr &:= "striType destStri=";
  761         c_expr.expr &:= c_destStri.expr;
  762         c_expr.expr &:= ";\n";
  763         c_expr.expr &:= "if (idxChk(destStri->size<=";
  764         c_expr.expr &:= integerLiteral(pred(position));
  765         c_expr.expr &:= ")) {\n";
  766         c_expr.expr &:= "  ";
  767         c_expr.expr &:= raiseError("INDEX_ERROR");
  768         c_expr.expr &:= "\n";
  769         c_expr.expr &:= "} else {\n";
  770         setDiagnosticLine(c_expr);
  771         c_expr.expr &:= "  destStri->mem[";
  772         c_expr.expr &:= integerLiteral(pred(position));
  773         c_expr.expr &:= "] = (strElemType)(";
  774         c_expr.expr &:= c_literal(aChar);
  775         c_expr.expr &:= ");\n";
  776         c_expr.expr &:= "}\n";
  777       else
  778         incr(countNoIndexChecks);
  779         setDiagnosticLine(c_expr);
  780         c_expr.expr &:= "(";
  781         c_expr.expr &:= c_destStri.expr;
  782         c_expr.expr &:= ")->mem[";
  783         c_expr.expr &:= integerLiteral(pred(position));
  784         c_expr.expr &:= "] = (strElemType)(";
  785         c_expr.expr &:= c_literal(aChar);
  786         c_expr.expr &:= ");\n";
  787       end if;
  788       if c_destStri.temp_num <> 0 then
  789         appendWithDiagnostic(c_destStri.temp_frees, c_expr);
  790       end if;
  791       if c_destStri.temp_num <> 0 or string_index_check then
  792         c_expr.expr &:= "}\n";
  793       end if;
  794     end if;
  795   end func;
  796 
  797 
  798 const proc: process_const_str_elemcpy (in reference: destStri,
  799     in integer: position, in reference: aChar, inout expr_type: c_expr) is func
  800 
  801   local
  802     var expr_type: c_destStri is expr_type.value;
  803     var expr_type: c_aChar is expr_type.value;
  804   begin
  805     incr(countOptimizations);
  806     if position < 1 then
  807       c_expr.expr &:= "/* 'string @:= [n] char' with n < 1 */\n";
  808       warning(DOES_RAISE, "INDEX_ERROR", c_expr);
  809       c_expr.expr &:= raiseError("INDEX_ERROR");
  810       c_expr.expr &:= "\n";
  811     else
  812       process_expr(destStri, c_destStri);
  813       c_aChar.temp_num := c_destStri.temp_num;
  814       process_expr(aChar, c_aChar);
  815       if c_aChar.temp_num <> 0 or string_index_check then
  816         c_expr.expr &:= "{\n";
  817       end if;
  818       if c_aChar.temp_num <> 0 then
  819         appendWithDiagnostic(c_destStri.temp_decls, c_expr);
  820         appendWithDiagnostic(c_aChar.temp_decls, c_expr);
  821         appendWithDiagnostic(c_destStri.temp_assigns, c_expr);
  822         appendWithDiagnostic(c_aChar.temp_assigns, c_expr);
  823       end if;
  824       if string_index_check then
  825         incr(countIndexChecks);
  826         c_expr.expr &:= "striType destStri=";
  827         c_expr.expr &:= c_destStri.expr;
  828         c_expr.expr &:= ";\n";
  829         c_expr.expr &:= "if (idxChk(destStri->size<=";
  830         c_expr.expr &:= integerLiteral(pred(position));
  831         c_expr.expr &:= ")) {\n";
  832         c_expr.expr &:= "  ";
  833         c_expr.expr &:= raiseError("INDEX_ERROR");
  834         c_expr.expr &:= "\n";
  835         c_expr.expr &:= "} else {\n";
  836         setDiagnosticLine(c_expr);
  837         c_expr.expr &:= "  destStri->mem[";
  838         c_expr.expr &:= integerLiteral(pred(position));
  839         c_expr.expr &:= "] = (strElemType)(";
  840         c_expr.expr &:= c_aChar.expr;
  841         c_expr.expr &:= ");\n";
  842         c_expr.expr &:= "}\n";
  843       else
  844         incr(countNoIndexChecks);
  845         setDiagnosticLine(c_expr);
  846         c_expr.expr &:= "(";
  847         c_expr.expr &:= c_destStri.expr;
  848         c_expr.expr &:= ")->mem[";
  849         c_expr.expr &:= integerLiteral(pred(position));
  850         c_expr.expr &:= "] = (strElemType)(";
  851         c_expr.expr &:= c_aChar.expr;
  852         c_expr.expr &:= ");\n";
  853       end if;
  854       if c_aChar.temp_num <> 0 then
  855         appendWithDiagnostic(c_destStri.temp_frees, c_expr);
  856         appendWithDiagnostic(c_aChar.temp_frees, c_expr);
  857       end if;
  858       if c_aChar.temp_num <> 0 or string_index_check then
  859         c_expr.expr &:= "}\n";
  860       end if;
  861     end if;
  862   end func;
  863 
  864 
  865 const proc: process_const_str_elemcpy (in reference: destStri,
  866     in reference: position, in char: aChar, inout expr_type: c_expr) is func
  867 
  868   local
  869     var reference: evaluatedParam is NIL;
  870     var expr_type: c_destStri is expr_type.value;
  871     var expr_type: c_position is expr_type.value;
  872   begin
  873     if getConstant(position, INTOBJECT, evaluatedParam) then
  874       process_const_str_elemcpy(destStri, getValue(evaluatedParam, integer), aChar, c_expr);
  875     else
  876       incr(countOptimizations);
  877       process_expr(destStri, c_destStri);
  878       c_position.temp_num := c_destStri.temp_num;
  879       process_expr(position, c_position);
  880       if c_position.temp_num <> 0 or string_index_check then
  881         c_expr.expr &:= "{\n";
  882       end if;
  883       if c_position.temp_num <> 0 then
  884         appendWithDiagnostic(c_destStri.temp_decls, c_expr);
  885         appendWithDiagnostic(c_position.temp_decls, c_expr);
  886         appendWithDiagnostic(c_destStri.temp_assigns, c_expr);
  887         appendWithDiagnostic(c_position.temp_assigns, c_expr);
  888       end if;
  889       if string_index_check then
  890         incr(countIndexChecks);
  891         c_expr.expr &:= "striType destStri=";
  892         c_expr.expr &:= c_destStri.expr;
  893         c_expr.expr &:= ";\n";
  894         if ccConf.TWOS_COMPLEMENT_INTTYPE then
  895           c_expr.expr &:= "uintType position=(uintType)(";
  896           c_expr.expr &:= c_position.expr;
  897           c_expr.expr &:= ")-1;\n";
  898           c_expr.expr &:= "if (idxChk(";
  899           c_expr.expr &:= "position>=destStri->size)) {\n";
  900         else
  901           c_expr.expr &:= "intType position=";
  902           c_expr.expr &:= c_position.expr;
  903           c_expr.expr &:= ";\n";
  904           c_expr.expr &:= "if (idxChk(";
  905           c_expr.expr &:= "position<=0 || ";
  906           c_expr.expr &:= "position>destStri->size)) {\n";
  907         end if;
  908         c_expr.expr &:= "  ";
  909         c_expr.expr &:= raiseError("INDEX_ERROR");
  910         c_expr.expr &:= "\n";
  911         c_expr.expr &:= "} else {\n";
  912         setDiagnosticLine(c_expr);
  913         if ccConf.TWOS_COMPLEMENT_INTTYPE then
  914           c_expr.expr &:= "  destStri->mem[position] = (strElemType)(";
  915         else
  916           c_expr.expr &:= "  destStri->mem[position-1] = (strElemType)(";
  917         end if;
  918         c_expr.expr &:= c_literal(aChar);
  919         c_expr.expr &:= ");\n";
  920         c_expr.expr &:= "}\n";
  921       else
  922         incr(countNoIndexChecks);
  923         setDiagnosticLine(c_expr);
  924         c_expr.expr &:= "(";
  925         c_expr.expr &:= c_destStri.expr;
  926         c_expr.expr &:= ")->mem[(";
  927         c_expr.expr &:= c_position.expr;
  928         c_expr.expr &:= ")-1] = (strElemType)(";
  929         c_expr.expr &:= c_literal(aChar);
  930         c_expr.expr &:= ");\n";
  931       end if;
  932       if c_position.temp_num <> 0 then
  933         appendWithDiagnostic(c_destStri.temp_frees, c_expr);
  934         appendWithDiagnostic(c_position.temp_frees, c_expr);
  935       end if;
  936       if c_position.temp_num <> 0 or string_index_check then
  937         c_expr.expr &:= "}\n";
  938       end if;
  939     end if;
  940   end func;
  941 
  942 
  943 const proc: process (STR_ELEMCPY, in reference: function,
  944     in ref_list: params, inout expr_type: c_expr) is func
  945 
  946   local
  947     var reference: evaluatedParam is NIL;
  948     var expr_type: c_destStri is expr_type.value;
  949     var expr_type: c_position is expr_type.value;
  950     var expr_type: c_aChar is expr_type.value;
  951   begin
  952     if getConstant(params[6], CHAROBJECT, evaluatedParam) then
  953       process_const_str_elemcpy(params[1], params[4], getValue(evaluatedParam, char), c_expr);
  954     elsif getConstant(params[4], INTOBJECT, evaluatedParam) then
  955       process_const_str_elemcpy(params[1], getValue(evaluatedParam, integer), params[6], c_expr);
  956     else
  957       process_expr(params[1], c_destStri);
  958       c_position.temp_num := c_destStri.temp_num;
  959       process_expr(params[4], c_position);
  960       c_aChar.temp_num := c_position.temp_num;
  961       process_expr(params[6], c_aChar);
  962       if c_aChar.temp_num <> 0 or string_index_check then
  963         c_expr.expr &:= "{\n";
  964       end if;
  965       if c_aChar.temp_num <> 0 then
  966         appendWithDiagnostic(c_destStri.temp_decls, c_expr);
  967         appendWithDiagnostic(c_position.temp_decls, c_expr);
  968         appendWithDiagnostic(c_aChar.temp_decls, c_expr);
  969         appendWithDiagnostic(c_destStri.temp_assigns, c_expr);
  970         appendWithDiagnostic(c_position.temp_assigns, c_expr);
  971         appendWithDiagnostic(c_aChar.temp_assigns, c_expr);
  972       end if;
  973       if string_index_check then
  974         incr(countIndexChecks);
  975         c_expr.expr &:= "striType destStri=";
  976         c_expr.expr &:= c_destStri.expr;
  977         c_expr.expr &:= ";\n";
  978         if ccConf.TWOS_COMPLEMENT_INTTYPE then
  979           c_expr.expr &:= "uintType position=(uintType)(";
  980           c_expr.expr &:= c_position.expr;
  981           c_expr.expr &:= ")-1;\n";
  982           c_expr.expr &:= "if (idxChk(";
  983           c_expr.expr &:= "position>=destStri->size)) {\n";
  984         else
  985           c_expr.expr &:= "intType position=";
  986           c_expr.expr &:= c_position.expr;
  987           c_expr.expr &:= ";\n";
  988           c_expr.expr &:= "if (idxChk(";
  989           c_expr.expr &:= "position<=0 || ";
  990           c_expr.expr &:= "position>destStri->size)) {\n";
  991         end if;
  992         c_expr.expr &:= "  ";
  993         c_expr.expr &:= raiseError("INDEX_ERROR");
  994         c_expr.expr &:= "\n";
  995         c_expr.expr &:= "} else {\n";
  996         setDiagnosticLine(c_expr);
  997         if ccConf.TWOS_COMPLEMENT_INTTYPE then
  998           c_expr.expr &:= "  destStri->mem[position] = (strElemType)(";
  999         else
 1000           c_expr.expr &:= "  destStri->mem[position-1] = (strElemType)(";
 1001         end if;
 1002         c_expr.expr &:= c_aChar.expr;
 1003         c_expr.expr &:= ");\n";
 1004         c_expr.expr &:= "}\n";
 1005       else
 1006         incr(countNoIndexChecks);
 1007         setDiagnosticLine(c_expr);
 1008         c_expr.expr &:= "(";
 1009         c_expr.expr &:= c_destStri.expr;
 1010         c_expr.expr &:= ")->mem[(";
 1011         c_expr.expr &:= c_position.expr;
 1012         c_expr.expr &:= ")-1] = (strElemType)(";
 1013         c_expr.expr &:= c_aChar.expr;
 1014         c_expr.expr &:= ");\n";
 1015       end if;
 1016       if c_aChar.temp_num <> 0 then
 1017         appendWithDiagnostic(c_destStri.temp_frees, c_expr);
 1018         appendWithDiagnostic(c_position.temp_frees, c_expr);
 1019         appendWithDiagnostic(c_aChar.temp_frees, c_expr);
 1020       end if;
 1021       if c_aChar.temp_num <> 0 or string_index_check then
 1022         c_expr.expr &:= "}\n";
 1023       end if;
 1024     end if;
 1025   end func;
 1026 
 1027 
 1028 const proc: process_const_str_eq (in reference: param1, in string: stri_b,
 1029     inout expr_type: c_expr) is func
 1030 
 1031   local
 1032     var reference: evaluatedParam is NIL;
 1033     var string: stri_a_name is "";
 1034   begin
 1035     incr(countOptimizations);
 1036     if getConstant(param1, STRIOBJECT, evaluatedParam) then
 1037       c_expr.expr &:= "/* ";
 1038       c_expr.expr &:= replace(literal(getValue(evaluatedParam, string)), "*/", "*\\/");
 1039       c_expr.expr &:= " == ";
 1040       c_expr.expr &:= replace(literal(stri_b), "*/", "*\\/");
 1041       c_expr.expr &:= " */ ";
 1042       if getValue(evaluatedParam, string) = stri_b then
 1043         c_expr.expr &:= "1";
 1044       else
 1045         c_expr.expr &:= "0";
 1046       end if;
 1047     elsif stri_b = "" then
 1048       c_expr.expr &:= "((";
 1049       getAnyParamToExpr(param1, c_expr);
 1050       c_expr.expr &:= ")->size==0 /* \"\" */)";
 1051     else
 1052       c_expr.expr &:= "(";
 1053       stri_a_name := getParameterAsVariable("const_striType", "tmp_", param1, c_expr);
 1054       if length(stri_b) = 1 then
 1055         (* Formula used: (a->size==1&&a->mem[0]==b->mem[0]) *)
 1056         c_expr.expr &:= stri_a_name;
 1057         c_expr.expr &:= "->size==1&&";
 1058         c_expr.expr &:= stri_a_name;
 1059         c_expr.expr &:= "->mem[0]==(strElemType)(";
 1060         c_expr.expr &:= c_literal(stri_b[1]);
 1061         c_expr.expr &:= ") /* ";
 1062         c_expr.expr &:= literal(stri_b);
 1063         c_expr.expr &:= " */)";
 1064       else
 1065         (* Formula used: (a->size==b->size&&memcmp(a->mem,b->mem,
 1066                          b->size*sizeof(strElemType))==0) *)
 1067         c_expr.expr &:= stri_a_name;
 1068         c_expr.expr &:= "->size==";
 1069         c_expr.expr &:= str(length(stri_b));
 1070         c_expr.expr &:= "&&memcmp(";
 1071         c_expr.expr &:= stri_a_name;
 1072         c_expr.expr &:= "->mem,(";
 1073         c_expr.expr &:= stringLiteral(stri_b);
 1074         c_expr.expr &:= ")->mem,";
 1075         c_expr.expr &:= str(length(stri_b));
 1076         c_expr.expr &:= "*sizeof(strElemType))==0)";
 1077       end if;
 1078     end if;
 1079   end func;
 1080 
 1081 
 1082 const proc: process (STR_EQ, in reference: function,
 1083     in ref_list: params, inout expr_type: c_expr) is func
 1084 
 1085   local
 1086     var reference: evaluatedParam is NIL;
 1087     var string: stri_a_name is "";
 1088     var string: stri_b_name is "";
 1089   begin
 1090     if getConstant(params[3], STRIOBJECT, evaluatedParam) then
 1091       process_const_str_eq(params[1], getValue(evaluatedParam, string), c_expr);
 1092     elsif getConstant(params[1], STRIOBJECT, evaluatedParam) then
 1093       process_const_str_eq(params[3], getValue(evaluatedParam, string), c_expr);
 1094     else
 1095       c_expr.expr &:= "(";
 1096       stri_a_name := getParameterAsVariable("const_striType", "tmp_a_", params[1], c_expr);
 1097       stri_b_name := getParameterAsVariable("const_striType", "tmp_b_", params[3], c_expr);
 1098       (* Formula used: (a->size==b->size&&memcmp(a->mem,b->mem,
 1099                        a->size*sizeof(strElemType))==0) *)
 1100       c_expr.expr &:= stri_a_name;
 1101       c_expr.expr &:= "->size==";
 1102       c_expr.expr &:= stri_b_name;
 1103       c_expr.expr &:= "->size&&memcmp(";
 1104       c_expr.expr &:= stri_a_name;
 1105       c_expr.expr &:= "->mem,";
 1106       c_expr.expr &:= stri_b_name;
 1107       c_expr.expr &:= "->mem,";
 1108       c_expr.expr &:= stri_a_name;
 1109       c_expr.expr &:= "->size*sizeof(strElemType))==0)";
 1110     end if;
 1111   end func;
 1112 
 1113 
 1114 const proc: process (STR_FOR, in reference: function,
 1115     in ref_list: params, inout expr_type: c_expr) is func
 1116 
 1117   local
 1118     var string: size_name is "";
 1119     var string: index_name is "";
 1120     var string: stri_name is "";
 1121     var expr_type: statement is expr_type.value;
 1122   begin
 1123     size_name := defineTempVariable("memSizeType", "size_", statement);
 1124     index_name := defineTempVariable("memSizeType", "index_", statement);
 1125     statement.expr &:= "for (";
 1126     stri_name := getParameterAsVariable("const_striType", "stri_", params[4], statement);
 1127     statement.expr &:= size_name;
 1128     statement.expr &:= "=";
 1129     statement.expr &:= stri_name;
 1130     statement.expr &:= "->size,";
 1131     statement.expr &:= index_name;
 1132     statement.expr &:= "=0; ";
 1133     statement.expr &:= index_name;
 1134     statement.expr &:= "<";
 1135     statement.expr &:= size_name;
 1136     statement.expr &:= "; (";
 1137     statement.expr &:= index_name;
 1138     statement.expr &:= ")++) {\n";
 1139     process_expr(params[2], statement);
 1140     statement.expr &:= "=";
 1141     statement.expr &:= stri_name;
 1142     statement.expr &:= "->mem[";
 1143     statement.expr &:= index_name;
 1144     statement.expr &:= "];\n";
 1145     process_call_by_name_expr(params[6], statement);
 1146     statement.expr &:= "}\n";
 1147     doLocalDeclsOfStatement(statement, c_expr);
 1148   end func;
 1149 
 1150 
 1151 const proc: process (STR_FOR_KEY, in reference: function,
 1152     in ref_list: params, inout expr_type: c_expr) is func
 1153 
 1154   local
 1155     var string: size_name is "";
 1156     var string: index_name is "";
 1157     var string: stri_name is "";
 1158     var expr_type: statement is expr_type.value;
 1159   begin
 1160     size_name := defineTempVariable("memSizeType", "size_", statement);
 1161     index_name := defineTempVariable("memSizeType", "index_", statement);
 1162     statement.expr &:= "for (";
 1163     stri_name := getParameterAsVariable("const_striType", "stri_", params[5], statement);
 1164     statement.expr &:= size_name;
 1165     statement.expr &:= "=";
 1166     statement.expr &:= stri_name;
 1167     statement.expr &:= "->size,";
 1168     statement.expr &:= index_name;
 1169     statement.expr &:= "=0; ";
 1170     statement.expr &:= index_name;
 1171     statement.expr &:= "<";
 1172     statement.expr &:= size_name;
 1173     statement.expr &:= "; (";
 1174     statement.expr &:= index_name;
 1175     statement.expr &:= ")++) {\n";
 1176     process_expr(params[3], statement);
 1177     statement.expr &:= "= (intType)(";
 1178     statement.expr &:= index_name;
 1179     statement.expr &:= " + 1);\n";
 1180     process_call_by_name_expr(params[7], statement);
 1181     statement.expr &:= "}\n";
 1182     doLocalDeclsOfStatement(statement, c_expr);
 1183   end func;
 1184 
 1185 
 1186 const proc: process (STR_FOR_VAR_KEY, in reference: function,
 1187     in ref_list: params, inout expr_type: c_expr) is func
 1188 
 1189   local
 1190     var string: size_name is "";
 1191     var string: index_name is "";
 1192     var string: stri_name is "";
 1193     var expr_type: statement is expr_type.value;
 1194   begin
 1195     size_name := defineTempVariable("memSizeType", "size_", statement);
 1196     index_name := defineTempVariable("memSizeType", "index_", statement);
 1197     statement.expr &:= "for (";
 1198     stri_name := getParameterAsVariable("const_striType", "stri_", params[6], statement);
 1199     statement.expr &:= size_name;
 1200     statement.expr &:= "=";
 1201     statement.expr &:= stri_name;
 1202     statement.expr &:= "->size,";
 1203     statement.expr &:= index_name;
 1204     statement.expr &:= "=0; ";
 1205     statement.expr &:= index_name;
 1206     statement.expr &:= "<";
 1207     statement.expr &:= size_name;
 1208     statement.expr &:= "; (";
 1209     statement.expr &:= index_name;
 1210     statement.expr &:= ")++) {\n";
 1211     process_expr(params[2], statement);
 1212     statement.expr &:= "=";
 1213     statement.expr &:= stri_name;
 1214     statement.expr &:= "->mem[";
 1215     statement.expr &:= index_name;
 1216     statement.expr &:= "];\n";
 1217     process_expr(params[4], statement);
 1218     statement.expr &:= "= (intType)(";
 1219     statement.expr &:= index_name;
 1220     statement.expr &:= " + 1);\n";
 1221     process_call_by_name_expr(params[8], statement);
 1222     statement.expr &:= "}\n";
 1223     doLocalDeclsOfStatement(statement, c_expr);
 1224   end func;
 1225 
 1226 
 1227 const proc: process_const_str_le (in string: stri1, in reference: stri2,
 1228     inout expr_type: c_expr) is forward;
 1229 
 1230 
 1231 const proc: process_const_str_ge (in string: stri1, in reference: stri2,
 1232     inout expr_type: c_expr) is func
 1233 
 1234   local
 1235     var string: stri2_name is "";
 1236   begin
 1237     if stri1 = "" then
 1238       c_expr.expr &:= "(";
 1239       getAnyParamToExpr(stri2, c_expr);
 1240       c_expr.expr &:= ")->size==0";
 1241     elsif length(stri1) = 1 then
 1242       c_expr.expr &:= "(";
 1243       stri2_name := getParameterAsVariable("const_striType", "stri2_", stri2, c_expr);
 1244       c_expr.expr &:= stri2_name;
 1245       c_expr.expr &:= "->size==0||";
 1246       c_expr.expr &:= stri2_name;
 1247       c_expr.expr &:= "->size==1&&";
 1248       c_expr.expr &:= stri2_name;
 1249       c_expr.expr &:= "->mem[0]<=(strElemType)(";
 1250       c_expr.expr &:= c_literal(stri1[1]);
 1251       c_expr.expr &:= ") /* ";
 1252       c_expr.expr &:= literal(stri1);
 1253       c_expr.expr &:= " */||";
 1254       c_expr.expr &:= stri2_name;
 1255       c_expr.expr &:= "->mem[0]<(strElemType)(";
 1256       c_expr.expr &:= c_literal(stri1[1]);
 1257       c_expr.expr &:= ") /* ";
 1258       c_expr.expr &:= literal(stri1);
 1259       c_expr.expr &:= " */)";
 1260     else
 1261       c_expr.expr &:= "strGe(";
 1262       c_expr.expr &:= stringLiteral(stri1);
 1263       c_expr.expr &:= ", ";
 1264       getAnyParamToExpr(stri2, c_expr);
 1265       c_expr.expr &:= ")";
 1266     end if;
 1267   end func;
 1268 
 1269 
 1270 const proc: process (STR_GE, in reference: function,
 1271     in ref_list: params, inout expr_type: c_expr) is func
 1272 
 1273   local
 1274     var reference: evaluatedParam is NIL;
 1275   begin
 1276     if getConstant(params[1], STRIOBJECT, evaluatedParam) then
 1277       process_const_str_ge(getValue(evaluatedParam, string), params[3], c_expr);
 1278     elsif getConstant(params[3], STRIOBJECT, evaluatedParam) then
 1279       process_const_str_le(getValue(evaluatedParam, string), params[1], c_expr);
 1280     else
 1281       c_expr.expr &:= "strGe(";
 1282       getAnyParamToExpr(params[1], c_expr);
 1283       c_expr.expr &:= ", ";
 1284       getAnyParamToExpr(params[3], c_expr);
 1285       c_expr.expr &:= ")";
 1286     end if;
 1287   end func;
 1288 
 1289 
 1290 const proc: process_const_str_lt (in string: stri1, in reference: stri2,
 1291     inout expr_type: c_expr) is forward;
 1292 
 1293 
 1294 const proc: process_const_str_gt (in string: stri1, in reference: stri2,
 1295     inout expr_type: c_expr) is func
 1296 
 1297   local
 1298     var string: stri2_name is "";
 1299   begin
 1300     if stri1 = "" then
 1301       c_expr.expr &:= "0";
 1302     elsif length(stri1) = 1 then
 1303       c_expr.expr &:= "(";
 1304       stri2_name := getParameterAsVariable("const_striType", "stri2_", stri2, c_expr);
 1305       c_expr.expr &:= stri2_name;
 1306       c_expr.expr &:= "->size==0||";
 1307       c_expr.expr &:= stri2_name;
 1308       c_expr.expr &:= "->mem[0]<(strElemType)(";
 1309       c_expr.expr &:= c_literal(stri1[1]);
 1310       c_expr.expr &:= ") /* ";
 1311       c_expr.expr &:= literal(stri1);
 1312       c_expr.expr &:= " */)";
 1313     else
 1314       c_expr.expr &:= "strGt(";
 1315       c_expr.expr &:= stringLiteral(stri1);
 1316       c_expr.expr &:= ", ";
 1317       getAnyParamToExpr(stri2, c_expr);
 1318       c_expr.expr &:= ")";
 1319     end if;
 1320   end func;
 1321 
 1322 
 1323 const proc: process (STR_GT, in reference: function,
 1324     in ref_list: params, inout expr_type: c_expr) is func
 1325 
 1326   local
 1327     var reference: evaluatedParam is NIL;
 1328   begin
 1329     if getConstant(params[1], STRIOBJECT, evaluatedParam) then
 1330       process_const_str_gt(getValue(evaluatedParam, string), params[3], c_expr);
 1331     elsif getConstant(params[3], STRIOBJECT, evaluatedParam) then
 1332       process_const_str_lt(getValue(evaluatedParam, string), params[1], c_expr);
 1333     else
 1334       c_expr.expr &:= "strGt(";
 1335       getAnyParamToExpr(params[1], c_expr);
 1336       c_expr.expr &:= ", ";
 1337       getAnyParamToExpr(params[3], c_expr);
 1338       c_expr.expr &:= ")";
 1339     end if;
 1340   end func;
 1341 
 1342 
 1343 const proc: process (STR_HASHCODE, in reference: function,
 1344     in ref_list: params, inout expr_type: c_expr) is func
 1345 
 1346   local
 1347     var reference: evaluatedParam is NIL;
 1348     var string: stri_name is "";
 1349   begin
 1350     if getConstant(params[1], STRIOBJECT, evaluatedParam) then
 1351       incr(countOptimizations);
 1352       c_expr.expr &:= integerLiteral(hashCode(getValue(evaluatedParam, string)));
 1353     elsif inlineFunctions then
 1354       c_expr.expr &:= "(";
 1355       stri_name := getParameterAsVariable("const_striType", "tmp_", params[1], c_expr);
 1356       c_expr.expr &:= stri_name;
 1357       c_expr.expr &:= "->size==0 ? 0 : (";
 1358       c_expr.expr &:= stri_name;
 1359       c_expr.expr &:= "->mem[0]<<5 ^ ";
 1360       c_expr.expr &:= stri_name;
 1361       c_expr.expr &:= "->mem[";
 1362       c_expr.expr &:= stri_name;
 1363       c_expr.expr &:= "->size>>1]<<3 ^ ";
 1364       c_expr.expr &:= stri_name;
 1365       c_expr.expr &:= "->mem[";
 1366       c_expr.expr &:= stri_name;
 1367       c_expr.expr &:= "->size-1]<<1 ^ ";
 1368       c_expr.expr &:= stri_name;
 1369       c_expr.expr &:= "->size))";
 1370     else
 1371       c_expr.expr &:= "strHashCode(";
 1372       getAnyParamToExpr(params[1], c_expr);
 1373       c_expr.expr &:= ")";
 1374     end if;
 1375   end func;
 1376 
 1377 
 1378 const proc: process_const_str_head (in string: stri, in reference: length,
 1379     inout expr_type: c_expr) is func
 1380 
 1381   local
 1382     var reference: evaluatedParam is NIL;
 1383     var integer: length_value is 0;
 1384     var string: length_name is "";
 1385     var string: slice_name is "";
 1386   begin
 1387     if getConstant(length, INTOBJECT, evaluatedParam) then
 1388       incr(countOptimizations);
 1389       length_value := getValue(evaluatedParam, integer);
 1390       if length_value < 0 then
 1391         warning(DOES_RAISE, "INDEX_ERROR", c_expr);
 1392         c_expr.expr &:= intRaiseError("INDEX_ERROR");
 1393       else
 1394         c_expr.expr &:= stringLiteral(stri[.. length_value]);
 1395       end if;
 1396     elsif stri = "" then
 1397       incr(countOptimizations);
 1398       c_expr.expr &:= "/* \"\"[ .. n] */ (";
 1399       if string_index_check then
 1400         incr(countIndexChecks);
 1401         c_expr.expr &:= "idxChk(";
 1402         process_expr(length, c_expr);
 1403         c_expr.expr &:= "<0)?";
 1404         c_expr.expr &:= intRaiseError("INDEX_ERROR");
 1405         c_expr.expr &:= ":";
 1406       else
 1407         incr(countNoIndexChecks);
 1408       end if;
 1409       c_expr.expr &:= stringLiteral("");
 1410       c_expr.expr &:= ")";
 1411     elsif length(stri) = 1 then
 1412       incr(countOptimizations);
 1413       c_expr.expr &:= "(";
 1414       length_name := getParameterAsVariable("intType", "length_", length, c_expr);
 1415       if string_index_check then
 1416         incr(countIndexChecks);
 1417         c_expr.expr &:= "idxChk(";
 1418         c_expr.expr &:= length_name;
 1419         c_expr.expr &:= "<0)?";
 1420         c_expr.expr &:= intRaiseError("INDEX_ERROR");
 1421         c_expr.expr &:= ":";
 1422       else
 1423         incr(countNoIndexChecks);
 1424       end if;
 1425       c_expr.expr &:= length_name;
 1426       c_expr.expr &:= ">=1?";
 1427       c_expr.expr &:= stringLiteral(stri);
 1428       c_expr.expr &:= ":";
 1429       c_expr.expr &:= stringLiteral("");
 1430       c_expr.expr &:= ")";
 1431     elsif ccConf.ALLOW_STRITYPE_SLICES and c_expr.demand < REQUIRE_RESULT then
 1432       incr(c_expr.temp_num);
 1433       slice_name := "slice_" & str(c_expr.temp_num);
 1434       c_expr.temp_decls &:= "struct striStruct ";
 1435       c_expr.temp_decls &:= slice_name;
 1436       c_expr.temp_decls &:= ";\n";
 1437       c_expr.expr &:= "(strHeadSlice(";
 1438       c_expr.expr &:= stringLiteral(stri);
 1439       c_expr.expr &:= ", ";
 1440       process_expr(length, c_expr);
 1441       c_expr.expr &:= ", &";
 1442       c_expr.expr &:= slice_name;
 1443       c_expr.expr &:= "), &";
 1444       c_expr.expr &:= slice_name;
 1445       c_expr.expr &:= ")";
 1446     else
 1447       prepare_stri_result(c_expr);
 1448       c_expr.result_expr := "strHead(";
 1449       c_expr.result_expr &:= stringLiteral(stri);
 1450       c_expr.result_expr &:= ", ";
 1451       getStdParamToResultExpr(length, c_expr);
 1452       c_expr.result_expr &:= ")";
 1453     end if;
 1454   end func;
 1455 
 1456 
 1457 const proc: process_const_str_head1 (in reference: param1,
 1458     inout expr_type: c_expr) is func
 1459 
 1460   local
 1461     var string: temp_name is "";
 1462     var string: stri1_name is "";
 1463     var expr_type: c_param1 is expr_type.value;
 1464   begin
 1465     if c_expr.demand < REQUIRE_RESULT then
 1466       incr(countOptimizations);
 1467       c_expr.expr &:= "(";
 1468       temp_name := getParameterAsVariable("const_striType", "tmp_", param1, c_expr);
 1469       incr(c_expr.temp_num);
 1470       stri1_name := "stri1_" & str(c_expr.temp_num);
 1471       c_expr.temp_decls &:= "struct striStruct ";
 1472       c_expr.temp_decls &:= stri1_name;
 1473       c_expr.temp_decls &:= ";\n";
 1474       c_expr.expr &:= temp_name;
 1475       c_expr.expr &:= "->size>=1?chrStrMacro(";
 1476       c_expr.expr &:= temp_name;
 1477       c_expr.expr &:= "->mem[0],";
 1478       c_expr.expr &:= stri1_name;
 1479       c_expr.expr &:= "):";
 1480       c_expr.expr &:= stringLiteral("");
 1481       c_expr.expr &:= ")";
 1482     else
 1483       prepareAnyParamTemporarys(param1, c_param1, c_expr);
 1484       prepare_stri_result(c_expr);
 1485       if c_param1.result_expr <> "" then
 1486         c_expr.result_expr := "strHeadTemp(";
 1487         c_expr.result_expr &:= c_param1.result_expr;
 1488       else
 1489         c_expr.result_expr := "strHead(";
 1490         c_expr.result_expr &:= c_param1.expr;
 1491       end if;
 1492       c_expr.result_expr &:= ", 1)";
 1493     end if;
 1494   end func;
 1495 
 1496 
 1497 const proc: process_str_head (in reference: param1, in reference: length,
 1498     inout expr_type: c_expr) is func
 1499 
 1500   local
 1501     var reference: evaluatedParam is NIL;
 1502     var expr_type: c_param1 is expr_type.value;
 1503     var string: slice_name is "";
 1504   begin
 1505     if getConstant(param1, STRIOBJECT, evaluatedParam) then
 1506       process_const_str_head(getValue(evaluatedParam, string), length, c_expr);
 1507     elsif getConstant(length, INTOBJECT, evaluatedParam) and
 1508         getValue(evaluatedParam, integer) = 1 then
 1509       process_const_str_head1(param1, c_expr);
 1510     else
 1511       prepareAnyParamTemporarys(param1, c_param1, c_expr);
 1512       if c_param1.result_expr <> "" then
 1513         prepare_stri_result(c_expr);
 1514         c_expr.result_expr := "strHeadTemp(";
 1515         c_expr.result_expr &:= c_param1.result_expr;
 1516         c_expr.result_expr &:= ", ";
 1517         getStdParamToResultExpr(length, c_expr);
 1518         c_expr.result_expr &:= ")";
 1519       elsif ccConf.ALLOW_STRITYPE_SLICES and c_expr.demand < REQUIRE_RESULT then
 1520         incr(c_expr.temp_num);
 1521         slice_name := "slice_" & str(c_expr.temp_num);
 1522         c_expr.temp_decls &:= "struct striStruct ";
 1523         c_expr.temp_decls &:= slice_name;
 1524         c_expr.temp_decls &:= ";\n";
 1525         c_expr.expr &:= "(strHeadSlice(";
 1526         c_expr.expr &:= c_param1.expr;
 1527         c_expr.expr &:= ", ";
 1528         process_expr(length, c_expr);
 1529         c_expr.expr &:= ", &";
 1530         c_expr.expr &:= slice_name;
 1531         c_expr.expr &:= "), &";
 1532         c_expr.expr &:= slice_name;
 1533         c_expr.expr &:= ")";
 1534       else
 1535         prepare_stri_result(c_expr);
 1536         c_expr.result_expr := "strHead(";
 1537         c_expr.result_expr &:= c_param1.expr;
 1538         c_expr.result_expr &:= ", ";
 1539         getStdParamToResultExpr(length, c_expr);
 1540         c_expr.result_expr &:= ")";
 1541       end if;
 1542     end if;
 1543   end func;
 1544 
 1545 
 1546 const proc: process (STR_HEAD, in reference: function,
 1547     in ref_list: params, inout expr_type: c_expr) is func
 1548 
 1549   begin
 1550     process_str_head(params[1], params[4], c_expr);
 1551   end func;
 1552 
 1553 
 1554 const proc: process_const_str_idx (in string: stri,
 1555     in reference: index, inout expr_type: c_expr) is func
 1556 
 1557   local
 1558     var reference: evaluatedParam is NIL;
 1559     var integer: index_value is 0;
 1560     var string: index_name is "";
 1561   begin
 1562     incr(countOptimizations);
 1563     if getConstant(index, INTOBJECT, evaluatedParam) then
 1564       index_value := getValue(evaluatedParam, integer);
 1565       if index_value < 1 or index_value > length(stri) then
 1566         warning(DOES_RAISE, "INDEX_ERROR", c_expr);
 1567         c_expr.expr &:= intRaiseError("INDEX_ERROR");
 1568       else
 1569         c_expr.expr &:= charLiteral(stri[index_value]);
 1570       end if;
 1571     else
 1572       c_expr.expr &:= "(";
 1573       c_expr.expr &:= stringLiteral(stri);
 1574       c_expr.expr &:= ")->mem[";
 1575       if string_index_check then
 1576         incr(countIndexChecks);
 1577         incr(c_expr.temp_num);
 1578         index_name := "idx_" & str(c_expr.temp_num);
 1579         if ccConf.TWOS_COMPLEMENT_INTTYPE then
 1580           c_expr.temp_decls &:= "uintType ";
 1581         else
 1582           c_expr.temp_decls &:= "intType ";
 1583         end if;
 1584         c_expr.temp_decls &:= index_name;
 1585         c_expr.temp_decls &:= ";\n";
 1586         c_expr.expr &:= "(";
 1587         c_expr.expr &:= index_name;
 1588         c_expr.expr &:= "=";
 1589         if ccConf.TWOS_COMPLEMENT_INTTYPE then
 1590           c_expr.expr &:= "(uintType)(";
 1591           process_expr(index, c_expr);
 1592           c_expr.expr &:= ")-1, idxChk(";
 1593           c_expr.expr &:= index_name;
 1594           c_expr.expr &:= ">=";
 1595         else
 1596           process_expr(index, c_expr);
 1597           c_expr.expr &:= ", idxChk(";
 1598           c_expr.expr &:= index_name;
 1599           c_expr.expr &:= "<=0 || ";
 1600           c_expr.expr &:= index_name;
 1601           c_expr.expr &:= ">";
 1602         end if;
 1603         c_expr.expr &:= str(length(stri));
 1604         c_expr.expr &:= ") ? ";
 1605         c_expr.expr &:= intRaiseError("INDEX_ERROR");
 1606         c_expr.expr &:= " : ";
 1607         c_expr.expr &:= index_name;
 1608         if ccConf.TWOS_COMPLEMENT_INTTYPE then
 1609           c_expr.expr &:= ")";
 1610         else
 1611           c_expr.expr &:= "-1)";
 1612         end if;
 1613       else
 1614         incr(countNoIndexChecks);
 1615         c_expr.expr &:= "(";
 1616         process_expr(index, c_expr);
 1617         c_expr.expr &:= ")-1";
 1618       end if;
 1619       c_expr.expr &:= "]";
 1620     end if;
 1621   end func;
 1622 
 1623 
 1624 const proc: process_const_str_idx (in reference: param1,
 1625     in integer: index, inout expr_type: c_expr) is func
 1626 
 1627   local
 1628     var string: stri_name is "";
 1629   begin
 1630     incr(countOptimizations);
 1631     if index < 1 then
 1632       warning(DOES_RAISE, "INDEX_ERROR", c_expr);
 1633       c_expr.expr &:= intRaiseError("INDEX_ERROR");
 1634     elsif string_index_check then
 1635       incr(countIndexChecks);
 1636       c_expr.expr &:= "(";
 1637       stri_name := getParameterAsVariable("const_striType", "tmp_", param1, c_expr);
 1638       c_expr.expr &:= stri_name;
 1639       c_expr.expr &:= "->mem[(idxChk(";
 1640       c_expr.expr &:= stri_name;
 1641       c_expr.expr &:= "->size<";
 1642       c_expr.expr &:= integerLiteral(index);
 1643       c_expr.expr &:= ") ? ";
 1644       c_expr.expr &:= intRaiseError("INDEX_ERROR");
 1645       c_expr.expr &:= " : ";
 1646       c_expr.expr &:= integerLiteral(pred(index));
 1647       c_expr.expr &:= ")])";
 1648     else
 1649       incr(countNoIndexChecks);
 1650       c_expr.expr &:= "(";
 1651       getAnyParamToExpr(param1, c_expr);
 1652       c_expr.expr &:= ")->mem[";
 1653       c_expr.expr &:= integerLiteral(pred(index));
 1654       c_expr.expr &:= "]";
 1655     end if;
 1656   end func;
 1657 
 1658 
 1659 const proc: process (STR_IDX, in reference: function,
 1660     in ref_list: params, inout expr_type: c_expr) is func
 1661 
 1662   local
 1663     var reference: evaluatedParam is NIL;
 1664     var string: stri_name is "";
 1665     var string: index_name is "";
 1666   begin
 1667     if getConstant(params[1], STRIOBJECT, evaluatedParam) then
 1668       process_const_str_idx(getValue(evaluatedParam, string), params[3], c_expr);
 1669     elsif getConstant(params[3], INTOBJECT, evaluatedParam) then
 1670       process_const_str_idx(params[1], getValue(evaluatedParam, integer), c_expr);
 1671     elsif string_index_check then
 1672       incr(countIndexChecks);
 1673       incr(c_expr.temp_num);
 1674       index_name := "idx_" & str(c_expr.temp_num);
 1675       if ccConf.TWOS_COMPLEMENT_INTTYPE then
 1676         c_expr.temp_decls &:= "uintType ";
 1677       else
 1678         c_expr.temp_decls &:= "intType ";
 1679       end if;
 1680       c_expr.temp_decls &:= index_name;
 1681       c_expr.temp_decls &:= ";\n";
 1682       c_expr.expr &:= "(";
 1683       stri_name := getParameterAsVariable("const_striType", "tmp_", params[1], c_expr);
 1684       c_expr.expr &:= stri_name;
 1685       c_expr.expr &:= "->mem[(";
 1686       c_expr.expr &:= index_name;
 1687       c_expr.expr &:= "=";
 1688       if ccConf.TWOS_COMPLEMENT_INTTYPE then
 1689         c_expr.expr &:= "(uintType)(";
 1690         process_expr(params[3], c_expr);
 1691         c_expr.expr &:= ")-1, idxChk(";
 1692         c_expr.expr &:= index_name;
 1693         c_expr.expr &:= ">=";
 1694       else
 1695         process_expr(params[3], c_expr);
 1696         c_expr.expr &:= ", idxChk(";
 1697         c_expr.expr &:= index_name;
 1698         c_expr.expr &:= "<=0 || ";
 1699         c_expr.expr &:= index_name;
 1700         c_expr.expr &:= ">";
 1701       end if;
 1702       c_expr.expr &:= stri_name;
 1703       c_expr.expr &:= "->size) ? ";
 1704       c_expr.expr &:= intRaiseError("INDEX_ERROR");
 1705       c_expr.expr &:= " : ";
 1706       c_expr.expr &:= index_name;
 1707       if ccConf.TWOS_COMPLEMENT_INTTYPE then
 1708         c_expr.expr &:= ")])";
 1709       else
 1710         c_expr.expr &:= "-1)])";
 1711       end if;
 1712     else
 1713       incr(countNoIndexChecks);
 1714       c_expr.expr &:= "(";
 1715       getAnyParamToExpr(params[1], c_expr);
 1716       c_expr.expr &:= ")->mem[(";
 1717       process_expr(params[3], c_expr);
 1718       c_expr.expr &:= ")-1]";
 1719     end if;
 1720   end func;
 1721 
 1722 
 1723 const proc: process (STR_IPOS, in reference: function,
 1724     in ref_list: params, inout expr_type: c_expr) is func
 1725 
 1726   local
 1727     var reference: evaluatedParam is NIL;
 1728   begin
 1729     if getConstant(params[2], STRIOBJECT, evaluatedParam) and
 1730         length(getValue(evaluatedParam, string)) = 1 then
 1731       incr(countOptimizations);
 1732       c_expr.expr &:= "strChIPos(";
 1733       getAnyParamToExpr(params[1], c_expr);
 1734       c_expr.expr &:= ", ";
 1735       c_expr.expr &:= charLiteral(getValue(evaluatedParam, string)[1]);
 1736       c_expr.expr &:= ", ";
 1737       process_expr(params[3], c_expr);
 1738       c_expr.expr &:= ")";
 1739     else
 1740       c_expr.expr &:= "strIPos(";
 1741       getAnyParamToExpr(params[1], c_expr);
 1742       c_expr.expr &:= ", ";
 1743       getAnyParamToExpr(params[2], c_expr);
 1744       c_expr.expr &:= ", ";
 1745       process_expr(params[3], c_expr);
 1746       c_expr.expr &:= ")";
 1747     end if;
 1748   end func;
 1749 
 1750 
 1751 const proc: process_const_str_le (in string: stri1, in reference: stri2,
 1752     inout expr_type: c_expr) is func
 1753 
 1754   local
 1755     var string: stri2_name is "";
 1756   begin
 1757     if stri1 = "" then
 1758       c_expr.expr &:= "1";
 1759     elsif length(stri1) = 1 then
 1760       c_expr.expr &:= "(";
 1761       stri2_name := getParameterAsVariable("const_striType", "stri2_", stri2, c_expr);
 1762       c_expr.expr &:= stri2_name;
 1763       c_expr.expr &:= "->size>=1&&";
 1764       c_expr.expr &:= stri2_name;
 1765       c_expr.expr &:= "->mem[0]>=(strElemType)(";
 1766       c_expr.expr &:= c_literal(stri1[1]);
 1767       c_expr.expr &:= ") /* ";
 1768       c_expr.expr &:= literal(stri1);
 1769       c_expr.expr &:= " */)";
 1770     else
 1771       c_expr.expr &:= "strLe(";
 1772       c_expr.expr &:= stringLiteral(stri1);
 1773       c_expr.expr &:= ", ";
 1774       getAnyParamToExpr(stri2, c_expr);
 1775       c_expr.expr &:= ")";
 1776     end if;
 1777   end func;
 1778 
 1779 
 1780 const proc: process (STR_LE, in reference: function,
 1781     in ref_list: params, inout expr_type: c_expr) is func
 1782 
 1783   local
 1784     var reference: evaluatedParam is NIL;
 1785   begin
 1786     if getConstant(params[1], STRIOBJECT, evaluatedParam) then
 1787       process_const_str_le(getValue(evaluatedParam, string), params[3], c_expr);
 1788     elsif getConstant(params[3], STRIOBJECT, evaluatedParam) then
 1789       process_const_str_ge(getValue(evaluatedParam, string), params[1], c_expr);
 1790     else
 1791       c_expr.expr &:= "strLe(";
 1792       getAnyParamToExpr(params[1], c_expr);
 1793       c_expr.expr &:= ", ";
 1794       getAnyParamToExpr(params[3], c_expr);
 1795       c_expr.expr &:= ")";
 1796     end if;
 1797   end func;
 1798 
 1799 
 1800 const proc: process (STR_LIT, in reference: function,
 1801     in ref_list: params, inout expr_type: c_expr) is func
 1802 
 1803   begin
 1804     prepare_stri_result(c_expr);
 1805     c_expr.result_expr := "strLit(";
 1806     getAnyParamToResultExpr(params[1], c_expr);
 1807     c_expr.result_expr &:= ")";
 1808   end func;
 1809 
 1810 
 1811 const func integer: sumLengthOfConstants (inout array reference: concatNParamList) is func
 1812   result
 1813     var integer: lengthOfConstants is 0;
 1814   local
 1815     var integer: index is 1;
 1816     var reference: evaluatedParam is NIL;
 1817     var string: paramValue is "";
 1818   begin
 1819     while index <= length(concatNParamList) do
 1820       if getConstant(concatNParamList[index], STRIOBJECT, evaluatedParam) then
 1821         lengthOfConstants +:= length(getValue(evaluatedParam, string));
 1822         ignore(remove(concatNParamList, index));
 1823       else
 1824         incr(index);
 1825       end if;
 1826     end while;
 1827   end func;
 1828 
 1829 
 1830 const proc: optimize_str_lng (in reference: lengthParam,
 1831     inout expr_type: c_expr) is forward;
 1832 
 1833 
 1834 const proc: optimize_str_lng (STR_CAT, in ref_list: params,
 1835     inout expr_type: c_expr) is func
 1836 
 1837   local
 1838     var array reference: concatNParamList is 0 times NIL;
 1839     var integer: lengthOfConstants is 0;
 1840     var reference: striObj is NIL;
 1841   begin
 1842     concatNParamList := getConcatNParamList(params);
 1843     lengthOfConstants := sumLengthOfConstants(concatNParamList);
 1844     for striObj range concatNParamList do
 1845       optimize_str_lng(striObj, c_expr);
 1846       c_expr.expr &:= " + ";
 1847     end for;
 1848     c_expr.expr &:= str(lengthOfConstants);
 1849   end func;
 1850 
 1851 
 1852 const proc: optimize_str_lng (in reference: lengthParam,
 1853     inout expr_type: c_expr) is func
 1854 
 1855   local
 1856     var reference: evaluatedParam is NIL;
 1857     var string: stri is "";
 1858     var ref_list: params is ref_list.value;
 1859   begin
 1860     if getConstant(lengthParam, STRIOBJECT, evaluatedParam) then
 1861       incr(countOptimizations);
 1862       stri := getValue(evaluatedParam, string);
 1863       c_expr.expr &:= str(length(stri));
 1864       c_expr.expr &:= " /* length(";
 1865       c_expr.expr &:= replace(literal(stri), "*/", "*\\/");
 1866       c_expr.expr &:= ") */";
 1867     elsif isActionExpression(lengthParam, "STR_CAT") then
 1868       params := getValue(lengthParam, ref_list)[2 ..];
 1869       optimize_str_lng(STR_CAT, params, c_expr);
 1870     else
 1871       c_expr.expr &:= "(";
 1872       getAnyParamToExpr(lengthParam, c_expr);
 1873       c_expr.expr &:= ")->size";
 1874     end if;
 1875   end func;
 1876 
 1877 
 1878 const proc: process (STR_LNG, in reference: function,
 1879     in ref_list: params, inout expr_type: c_expr) is func
 1880 
 1881   begin
 1882     if evaluate_const_expr >= 1 then
 1883       c_expr.expr &:= "(intType)(";
 1884       optimize_str_lng(params[1], c_expr);
 1885       c_expr.expr &:= ")";
 1886     else
 1887       c_expr.expr &:= "(intType)((";
 1888       getAnyParamToExpr(params[1], c_expr);
 1889       c_expr.expr &:= ")->size)";
 1890     end if;
 1891   end func;
 1892 
 1893 
 1894 (**
 1895  *  Produces code to return a string converted to lower case.
 1896  *  If the parameter is a temporary value the conversion is done
 1897  *  with strLowTemp. The strLowTemp function returns the parameter as
 1898  *  result of the conversion. That way the temporary of the parameter
 1899  *  must not be freed.
 1900  *)
 1901 const proc: process (STR_LOW, in reference: function,
 1902     in ref_list: params, inout expr_type: c_expr) is func
 1903 
 1904   local
 1905     var expr_type: c_param1 is expr_type.value;
 1906   begin
 1907     prepare_stri_result(c_expr);
 1908     prepareAnyParamTemporarys(params[1], c_param1, c_expr);
 1909     if c_param1.result_expr <> "" then
 1910       c_expr.result_expr := "strLowTemp(";
 1911       c_expr.result_expr &:= c_param1.result_expr;
 1912     else
 1913       c_expr.result_expr := "strLow(";
 1914       c_expr.result_expr &:= c_param1.expr;
 1915     end if;
 1916     c_expr.result_expr &:= ")";
 1917   end func;
 1918 
 1919 
 1920 (**
 1921  *  Produces code for the lpad operator.
 1922  *  If the first parameter is a temporary value the operation
 1923  *  is done with strLpadTemp. The strLpadTemp function returns
 1924  *  the first parameter as result of the operation. That way the
 1925  *  temporary of the first parameter must not be freed.
 1926  *)
 1927 const proc: process (STR_LPAD, in reference: function,
 1928     in ref_list: params, inout expr_type: c_expr) is func
 1929 
 1930   local
 1931     var expr_type: c_param1 is expr_type.value;
 1932   begin
 1933     prepare_stri_result(c_expr);
 1934     prepareAnyParamTemporarys(params[1], c_param1, c_expr);
 1935     if c_param1.result_expr <> "" then
 1936       c_expr.result_expr := "strLpadTemp(";
 1937       c_expr.result_expr &:= c_param1.result_expr;
 1938     else
 1939       c_expr.result_expr := "strLpad(";
 1940       c_expr.result_expr &:= c_param1.expr;
 1941     end if;
 1942     c_expr.result_expr &:= ", ";
 1943     getStdParamToResultExpr(params[3], c_expr);
 1944     c_expr.result_expr &:= ")";
 1945   end func;
 1946 
 1947 
 1948 (**
 1949  *  Produces code for the lpad0 operator.
 1950  *  If the first parameter is a temporary value the operation
 1951  *  is done with strLpad0Temp. The strLpad0Temp function returns
 1952  *  the first parameter as result of the operation. That way the
 1953  *  temporary of the first parameter must not be freed.
 1954  *)
 1955 const proc: process (STR_LPAD0, in reference: function,
 1956     in ref_list: params, inout expr_type: c_expr) is func
 1957 
 1958   local
 1959     var expr_type: c_param1 is expr_type.value;
 1960   begin
 1961     prepare_stri_result(c_expr);
 1962     prepareAnyParamTemporarys(params[1], c_param1, c_expr);
 1963     if c_param1.result_expr <> "" then
 1964       c_expr.result_expr := "strLpad0Temp(";
 1965       c_expr.result_expr &:= c_param1.result_expr;
 1966     else
 1967       c_expr.result_expr := "strLpad0(";
 1968       c_expr.result_expr &:= c_param1.expr;
 1969     end if;
 1970     c_expr.result_expr &:= ", ";
 1971     getStdParamToResultExpr(params[3], c_expr);
 1972     c_expr.result_expr &:= ")";
 1973   end func;
 1974 
 1975 
 1976 const proc: process_const_str_lt (in string: stri1, in reference: stri2,
 1977     inout expr_type: c_expr) is func
 1978 
 1979   local
 1980     var string: stri2_name is "";
 1981   begin
 1982     if stri1 = "" then
 1983       c_expr.expr &:= "(";
 1984       getAnyParamToExpr(stri2, c_expr);
 1985       c_expr.expr &:= ")->size!=0";
 1986     elsif length(stri1) = 1 then
 1987       c_expr.expr &:= "(";
 1988       stri2_name := getParameterAsVariable("const_striType", "stri2_", stri2, c_expr);
 1989       c_expr.expr &:= stri2_name;
 1990       c_expr.expr &:= "->size>1&&";
 1991       c_expr.expr &:= stri2_name;
 1992       c_expr.expr &:= "->mem[0]>=(strElemType)(";
 1993       c_expr.expr &:= c_literal(stri1[1]);
 1994       c_expr.expr &:= ") /* ";
 1995       c_expr.expr &:= literal(stri1);
 1996       c_expr.expr &:= " */)||";
 1997       c_expr.expr &:= stri2_name;
 1998       c_expr.expr &:= "->size==1&&";
 1999       c_expr.expr &:= stri2_name;
 2000       c_expr.expr &:= "->mem[0]>(strElemType)(";
 2001       c_expr.expr &:= c_literal(stri1[1]);
 2002       c_expr.expr &:= ") /* ";
 2003       c_expr.expr &:= literal(stri1);
 2004       c_expr.expr &:= " */";
 2005     else
 2006       c_expr.expr &:= "strLt(";
 2007       c_expr.expr &:= stringLiteral(stri1);
 2008       c_expr.expr &:= ", ";
 2009       getAnyParamToExpr(stri2, c_expr);
 2010       c_expr.expr &:= ")";
 2011     end if;
 2012   end func;
 2013 
 2014 
 2015 const proc: process (STR_LT, in reference: function,
 2016     in ref_list: params, inout expr_type: c_expr) is func
 2017 
 2018   local
 2019     var reference: evaluatedParam is NIL;
 2020   begin
 2021     if getConstant(params[1], STRIOBJECT, evaluatedParam) then
 2022       process_const_str_lt(getValue(evaluatedParam, string), params[3], c_expr);
 2023     elsif getConstant(params[3], STRIOBJECT, evaluatedParam) then
 2024       process_const_str_gt(getValue(evaluatedParam, string), params[1], c_expr);
 2025     else
 2026       c_expr.expr &:= "strLt(";
 2027       getAnyParamToExpr(params[1], c_expr);
 2028       c_expr.expr &:= ", ";
 2029       getAnyParamToExpr(params[3], c_expr);
 2030       c_expr.expr &:= ")";
 2031     end if;
 2032   end func;
 2033 
 2034 
 2035 const proc: process (STR_LTRIM, in reference: function,
 2036     in ref_list: params, inout expr_type: c_expr) is func
 2037 
 2038   begin
 2039     prepare_stri_result(c_expr);
 2040     c_expr.result_expr := "strLtrim(";
 2041     getAnyParamToResultExpr(params[1], c_expr);
 2042     c_expr.result_expr &:= ")";
 2043   end func;
 2044 
 2045 
 2046 const proc: process_const_str_mult (in string: stri, in reference: factor,
 2047     inout expr_type: c_expr) is func
 2048 
 2049   local
 2050     var char: ch is ' ';
 2051   begin
 2052     if stri = "" then
 2053       incr(countOptimizations);
 2054       if function_range_check then
 2055         incr(countRangeChecks);
 2056         c_expr.expr &:= "(rngChk((";
 2057         process_expr(factor, c_expr);
 2058         c_expr.expr &:= ")<0)?";
 2059         c_expr.expr &:= strRaiseError("RANGE_ERROR");
 2060         c_expr.expr &:= ":";
 2061         c_expr.expr &:= stringLiteral("");
 2062         c_expr.expr &:= ")";
 2063       else
 2064         incr(countNoRangeChecks);
 2065         c_expr.expr &:= stringLiteral("");
 2066       end if;
 2067     else
 2068       prepare_stri_result(c_expr);
 2069       if length(stri) = 1 then
 2070         incr(countOptimizations);
 2071         ch := stri[1];
 2072         if ch = '\0;' then
 2073           c_expr.result_expr := "strZero(";
 2074         else
 2075           c_expr.result_expr := "strChMult(";
 2076           c_expr.result_expr &:= charLiteral(ch);
 2077           c_expr.result_expr &:= ", ";
 2078         end if;
 2079       else
 2080         c_expr.result_expr := "strMult(";
 2081         c_expr.result_expr &:= stringLiteral(stri);
 2082         c_expr.result_expr &:= ", ";
 2083       end if;
 2084       getStdParamToResultExpr(factor, c_expr);
 2085       c_expr.result_expr &:= ")";
 2086     end if;
 2087   end func;
 2088 
 2089 
 2090 const proc: process_const_str_mult (in reference: stri, in integer: factor,
 2091     inout expr_type: c_expr) is func
 2092 
 2093   local
 2094     var expr_type: c_stri is expr_type.value;
 2095   begin
 2096     if factor < 0 then
 2097       incr(countOptimizations);
 2098       warning(DOES_RAISE, "RANGE_ERROR", c_expr);
 2099       c_expr.expr &:= strRaiseError("RANGE_ERROR");
 2100     elsif factor = 0 then
 2101       incr(countOptimizations);
 2102       c_expr.expr &:= stringLiteral("");
 2103     elsif factor = 1 then
 2104       incr(countOptimizations);
 2105       process_expr(stri, c_expr);
 2106     else
 2107       prepare_stri_result(c_expr);
 2108       c_expr.result_expr := "strMult(";
 2109       getAnyParamToResultExpr(stri, c_expr);
 2110       c_expr.result_expr &:= ", ";
 2111       c_expr.result_expr &:= integerLiteral(factor);
 2112       c_expr.result_expr &:= ")";
 2113     end if;
 2114   end func;
 2115 
 2116 
 2117 const proc: process (STR_MULT, in reference: function,
 2118     in ref_list: params, inout expr_type: c_expr) is func
 2119 
 2120   local
 2121     var reference: evaluatedParam is NIL;
 2122   begin
 2123     if getConstant(params[1], STRIOBJECT, evaluatedParam) then
 2124       process_const_str_mult(getValue(evaluatedParam, string), params[3], c_expr);
 2125     elsif getConstant(params[3], INTOBJECT, evaluatedParam) then
 2126       process_const_str_mult(params[1], getValue(evaluatedParam, integer), c_expr);
 2127     elsif isActionExpression(params[1], "CHR_STR") then
 2128       incr(countOptimizations);
 2129       prepare_stri_result(c_expr);
 2130       c_expr.result_expr := "strChMult(";
 2131       getAnyParamToResultExpr(getActionParameter(params[1], 1), c_expr);
 2132       c_expr.result_expr &:= ", ";
 2133       getStdParamToResultExpr(params[3], c_expr);
 2134       c_expr.result_expr &:= ")";
 2135     else
 2136       prepare_stri_result(c_expr);
 2137       c_expr.result_expr := "strMult(";
 2138       getAnyParamToResultExpr(params[1], c_expr);
 2139       c_expr.result_expr &:= ", ";
 2140       getStdParamToResultExpr(params[3], c_expr);
 2141       c_expr.result_expr &:= ")";
 2142     end if;
 2143   end func;
 2144 
 2145 
 2146 const proc: process_const_str_ne (in reference: param1, in string: stri_b,
 2147     inout expr_type: c_expr) is func
 2148 
 2149   local
 2150     var reference: evaluatedParam is NIL;
 2151     var string: stri_a_name is "";
 2152   begin
 2153     incr(countOptimizations);
 2154     if getConstant(param1, STRIOBJECT, evaluatedParam) then
 2155       c_expr.expr &:= "/* ";
 2156       c_expr.expr &:= replace(literal(getValue(evaluatedParam, string)), "*/", "*\\/");
 2157       c_expr.expr &:= " != ";
 2158       c_expr.expr &:= replace(literal(stri_b), "*/", "*\\/");
 2159       c_expr.expr &:= " */ ";
 2160       if getValue(evaluatedParam, string) <> stri_b then
 2161         c_expr.expr &:= "1";
 2162       else
 2163         c_expr.expr &:= "0";
 2164       end if;
 2165     elsif stri_b = "" then
 2166       c_expr.expr &:= "((";
 2167       getAnyParamToExpr(param1, c_expr);
 2168       c_expr.expr &:= ")->size!=0 /* \"\" */)";
 2169     else
 2170       c_expr.expr &:= "(";
 2171       stri_a_name := getParameterAsVariable("const_striType", "tmp_", param1, c_expr);
 2172       if length(stri_b) = 1 then
 2173         (* Formula used: (a->size!=1||a->mem[0]!=b->mem[0]) *)
 2174         c_expr.expr &:= stri_a_name;
 2175         c_expr.expr &:= "->size!=1||";
 2176         c_expr.expr &:= stri_a_name;
 2177         c_expr.expr &:= "->mem[0]!=(strElemType)(";
 2178         c_expr.expr &:= c_literal(stri_b[1]);
 2179         c_expr.expr &:= ") /* ";
 2180         c_expr.expr &:= literal(stri_b);
 2181         c_expr.expr &:= " */)";
 2182       else
 2183         (* Formula used: (a->size!=b->size||memcmp(a->mem,b->mem,
 2184                          b->size*sizeof(strElemType))!=0) *)
 2185         c_expr.expr &:= stri_a_name;
 2186         c_expr.expr &:= "->size!=";
 2187         c_expr.expr &:= str(length(stri_b));
 2188         c_expr.expr &:= "||memcmp(";
 2189         c_expr.expr &:= stri_a_name;
 2190         c_expr.expr &:= "->mem,(";
 2191         c_expr.expr &:= stringLiteral(stri_b);
 2192         c_expr.expr &:= ")->mem,";
 2193         c_expr.expr &:= str(length(stri_b));
 2194         c_expr.expr &:= "*sizeof(strElemType))!=0)";
 2195       end if;
 2196     end if;
 2197   end func;
 2198 
 2199 
 2200 const proc: process (STR_NE, in reference: function,
 2201     in ref_list: params, inout expr_type: c_expr) is func
 2202 
 2203   local
 2204     var reference: evaluatedParam is NIL;
 2205     var string: stri_a_name is "";
 2206     var string: stri_b_name is "";
 2207   begin
 2208     if getConstant(params[3], STRIOBJECT, evaluatedParam) then
 2209       process_const_str_ne(params[1], getValue(evaluatedParam, string), c_expr);
 2210     elsif getConstant(params[1], STRIOBJECT, evaluatedParam) then
 2211       process_const_str_ne(params[3], getValue(evaluatedParam, string), c_expr);
 2212     else
 2213       c_expr.expr &:= "(";
 2214       stri_a_name := getParameterAsVariable("const_striType", "tmp_a_", params[1], c_expr);
 2215       stri_b_name := getParameterAsVariable("const_striType", "tmp_b_", params[3], c_expr);
 2216       (* Formula used: (a->size!=b->size||memcmp(a->mem,b->mem,
 2217                        a->size*sizeof(strElemType))!=0) *)
 2218       c_expr.expr &:= stri_a_name;
 2219       c_expr.expr &:= "->size!=";
 2220       c_expr.expr &:= stri_b_name;
 2221       c_expr.expr &:= "->size||memcmp(";
 2222       c_expr.expr &:= stri_a_name;
 2223       c_expr.expr &:= "->mem,";
 2224       c_expr.expr &:= stri_b_name;
 2225       c_expr.expr &:= "->mem,";
 2226       c_expr.expr &:= stri_a_name;
 2227       c_expr.expr &:= "->size*sizeof(strElemType))!=0)";
 2228     end if;
 2229   end func;
 2230 
 2231 
 2232 const proc: process_const_str_pos (in reference: mainStri, in string: searched,
 2233     inout expr_type: c_expr) is func
 2234 
 2235   local
 2236     var reference: evaluatedParam is NIL;
 2237   begin
 2238     if getConstant(mainStri, STRIOBJECT, evaluatedParam) then
 2239       incr(countOptimizations);
 2240       c_expr.expr &:= "/* pos(";
 2241       c_expr.expr &:= replace(literal(getValue(evaluatedParam, string)), "*/", "*\\/");
 2242       c_expr.expr &:= ",";
 2243       c_expr.expr &:= replace(literal(searched), "*/", "*\\/");
 2244       c_expr.expr &:= ") */ ";
 2245       c_expr.expr &:= integerLiteral(pos(getValue(evaluatedParam, string), searched));
 2246     elsif length(searched) = 0 then
 2247       incr(countOptimizations);
 2248       c_expr.expr &:= "/* pos(*, \"\") */ ";
 2249       c_expr.expr &:= integerLiteral(0);
 2250     elsif length(searched) = 1 then
 2251       incr(countOptimizations);
 2252       c_expr.expr &:= "strChPos(";
 2253       getAnyParamToExpr(mainStri, c_expr);
 2254       c_expr.expr &:= ", ";
 2255       c_expr.expr &:= charLiteral(searched[1]);
 2256       c_expr.expr &:= ")";
 2257     else
 2258       c_expr.expr &:= "strPos(";
 2259       getAnyParamToExpr(mainStri, c_expr);
 2260       c_expr.expr &:= ", ";
 2261       c_expr.expr &:= stringLiteral(searched);
 2262       c_expr.expr &:= ")";
 2263     end if;
 2264   end func;
 2265 
 2266 
 2267 const proc: process (STR_POS, in reference: function,
 2268     in ref_list: params, inout expr_type: c_expr) is func
 2269 
 2270   local
 2271     var reference: evaluatedParam is NIL;
 2272   begin
 2273     if getConstant(params[2], STRIOBJECT, evaluatedParam) then
 2274       process_const_str_pos(params[1], getValue(evaluatedParam, string), c_expr);
 2275     elsif getConstant(params[1], STRIOBJECT, evaluatedParam) and
 2276         length(getValue(evaluatedParam, string)) = 0 then
 2277       incr(countOptimizations);
 2278       c_expr.expr &:= "/* pos(\"\", *) */ ";
 2279       c_expr.expr &:= integerLiteral(0);
 2280     else
 2281       c_expr.expr &:= "strPos(";
 2282       getAnyParamToExpr(params[1], c_expr);
 2283       c_expr.expr &:= ", ";
 2284       getAnyParamToExpr(params[2], c_expr);
 2285       c_expr.expr &:= ")";
 2286     end if;
 2287   end func;
 2288 
 2289 
 2290 const proc: process_const_str_poscpy (in reference: destStri,
 2291     in integer: position, in string: aStri, inout expr_type: c_expr) is func
 2292   local
 2293     var expr_type: c_destStri is expr_type.value;
 2294   begin
 2295     incr(countOptimizations);
 2296     if position < 1 then
 2297       c_expr.expr &:= "/* 'string @:= [n] string' with n < 1 */\n";
 2298       warning(DOES_RAISE, "INDEX_ERROR", c_expr);
 2299       c_expr.expr &:= raiseError("INDEX_ERROR");
 2300       c_expr.expr &:= "\n";
 2301     else
 2302       incr(countOptimizations);
 2303       process_expr(destStri, c_destStri);
 2304       c_expr.expr &:= "{\n";
 2305       if c_destStri.temp_num <> 0 then
 2306         appendWithDiagnostic(c_destStri.temp_decls, c_expr);
 2307         appendWithDiagnostic(c_destStri.temp_assigns, c_expr);
 2308        end if;
 2309       if string_index_check then
 2310         incr(countIndexChecks);
 2311         c_expr.expr &:= "striType destStri=";
 2312         c_expr.expr &:= c_destStri.expr;
 2313         c_expr.expr &:= ";\n";
 2314         c_expr.expr &:= "if (idxChk(";
 2315         c_expr.expr &:= "destStri->size<";
 2316         c_expr.expr &:= integerLiteral(length(aStri));
 2317         c_expr.expr &:= " || (uintType)";
 2318         c_expr.expr &:= integerLiteral(pred(position));
 2319         c_expr.expr &:= ">destStri->size-";
 2320         c_expr.expr &:= integerLiteral(length(aStri));
 2321         c_expr.expr &:= ")) {\n";
 2322         c_expr.expr &:= "  ";
 2323         c_expr.expr &:= raiseError("INDEX_ERROR");
 2324         c_expr.expr &:= "\n";
 2325         c_expr.expr &:= "} else {\n";
 2326         setDiagnosticLine(c_expr);
 2327         c_expr.expr &:= "  memcpy(&destStri->mem[";
 2328         c_expr.expr &:= integerLiteral(pred(position));
 2329         c_expr.expr &:= "], (";
 2330         c_expr.expr &:= stringLiteral(aStri);
 2331         c_expr.expr &:= ")->mem, ";
 2332         c_expr.expr &:= integerLiteral(length(aStri));
 2333         c_expr.expr &:= "*sizeof(strElemType));\n";
 2334         c_expr.expr &:= "}\n";
 2335       else
 2336         incr(countNoIndexChecks);
 2337         setDiagnosticLine(c_expr);
 2338         c_expr.expr &:= "memcpy(&(";
 2339         c_expr.expr &:= c_destStri.expr;
 2340         c_expr.expr &:= ")->mem[";
 2341         c_expr.expr &:= integerLiteral(pred(position));
 2342         c_expr.expr &:= "], (";
 2343         c_expr.expr &:= stringLiteral(aStri);
 2344         c_expr.expr &:= ")->mem, ";
 2345         c_expr.expr &:= integerLiteral(length(aStri));
 2346         c_expr.expr &:= "*sizeof(strElemType));\n";
 2347       end if;
 2348       if c_destStri.temp_num <> 0 then
 2349         appendWithDiagnostic(c_destStri.temp_frees, c_expr);
 2350       end if;
 2351       c_expr.expr &:= "}\n";
 2352     end if;
 2353   end func;
 2354 
 2355 
 2356 const proc: process_const_str_poscpy (in reference: destStri,
 2357     in integer: position, in reference: aStri, inout expr_type: c_expr) is func
 2358 
 2359   local
 2360     var expr_type: c_destStri is expr_type.value;
 2361     var expr_type: c_aStri is expr_type.value;
 2362   begin
 2363     incr(countOptimizations);
 2364     if position < 1 then
 2365       c_expr.expr &:= "/* 'string @:= [n] string' with n < 1 */\n";
 2366       warning(DOES_RAISE, "INDEX_ERROR", c_expr);
 2367       c_expr.expr &:= raiseError("INDEX_ERROR");
 2368       c_expr.expr &:= "\n";
 2369     else
 2370       process_expr(destStri, c_destStri);
 2371       c_aStri.temp_num := c_destStri.temp_num;
 2372       getAnyParamToExpr(aStri, c_aStri);
 2373       c_expr.expr &:= "{\n";
 2374       if c_aStri.temp_num <> 0 then
 2375         appendWithDiagnostic(c_destStri.temp_decls, c_expr);
 2376         appendWithDiagnostic(c_aStri.temp_decls, c_expr);
 2377         appendWithDiagnostic(c_destStri.temp_assigns, c_expr);
 2378         appendWithDiagnostic(c_aStri.temp_assigns, c_expr);
 2379       end if;
 2380       if string_index_check then
 2381         incr(countIndexChecks);
 2382         c_expr.expr &:= "striType destStri=";
 2383         c_expr.expr &:= c_destStri.expr;
 2384         c_expr.expr &:= ";\n";
 2385         c_expr.expr &:= "striType aStri=";
 2386         c_expr.expr &:= c_aStri.expr;
 2387         c_expr.expr &:= ";\n";
 2388         c_expr.expr &:= "if (idxChk(destStri->size<aStri->size || (uintType)";
 2389         c_expr.expr &:= integerLiteral(pred(position));
 2390         c_expr.expr &:= ">destStri->size-aStri->size)) {\n";
 2391         c_expr.expr &:= "  ";
 2392         c_expr.expr &:= raiseError("INDEX_ERROR");
 2393         c_expr.expr &:= "\n";
 2394         c_expr.expr &:= "} else {\n";
 2395         setDiagnosticLine(c_expr);
 2396         c_expr.expr &:= "  memmove(&destStri->mem[";
 2397         c_expr.expr &:= integerLiteral(pred(position));
 2398         c_expr.expr &:= "], aStri->mem, aStri->size*sizeof(strElemType));\n";
 2399         c_expr.expr &:= "}\n";
 2400       else
 2401         incr(countNoIndexChecks);
 2402         c_expr.expr &:= "striType aStri=";
 2403         c_expr.expr &:= c_aStri.expr;
 2404         c_expr.expr &:= ";\n";
 2405         setDiagnosticLine(c_expr);
 2406         c_expr.expr &:= "memmove(&(";
 2407         c_expr.expr &:= c_destStri.expr;
 2408         c_expr.expr &:= ")->mem[";
 2409         c_expr.expr &:= integerLiteral(pred(position));
 2410         c_expr.expr &:= "], aStri->mem, aStri->size*sizeof(strElemType));\n";
 2411       end if;
 2412       if c_aStri.temp_num <> 0 then
 2413         appendWithDiagnostic(c_destStri.temp_frees, c_expr);
 2414         appendWithDiagnostic(c_aStri.temp_frees, c_expr);
 2415       end if;
 2416       c_expr.expr &:= "}\n";
 2417     end if;
 2418   end func;
 2419 
 2420 
 2421 const proc: process_const_str_poscpy (in reference: destStri,
 2422     in reference: position, in string: aStri, inout expr_type: c_expr) is func
 2423 
 2424   local
 2425     var reference: evaluatedParam is NIL;
 2426     var expr_type: c_destStri is expr_type.value;
 2427     var expr_type: c_position is expr_type.value;
 2428   begin
 2429     if getConstant(position, INTOBJECT, evaluatedParam) then
 2430       process_const_str_poscpy(destStri, getValue(evaluatedParam, integer), aStri, c_expr);
 2431     else
 2432       incr(countOptimizations);
 2433       process_expr(destStri, c_destStri);
 2434       c_position.temp_num := c_destStri.temp_num;
 2435       process_expr(position, c_position);
 2436       c_expr.expr &:= "{\n";
 2437       if c_position.temp_num <> 0 then
 2438         appendWithDiagnostic(c_destStri.temp_decls, c_expr);
 2439         appendWithDiagnostic(c_position.temp_decls, c_expr);
 2440         appendWithDiagnostic(c_destStri.temp_assigns, c_expr);
 2441         appendWithDiagnostic(c_position.temp_assigns, c_expr);
 2442       end if;
 2443       if string_index_check then
 2444         incr(countIndexChecks);
 2445         c_expr.expr &:= "striType destStri=";
 2446         c_expr.expr &:= c_destStri.expr;
 2447         c_expr.expr &:= ";\n";
 2448         c_expr.expr &:= "intType position=";
 2449         c_expr.expr &:= c_position.expr;
 2450         c_expr.expr &:= ";\n";
 2451         c_expr.expr &:= "if (idxChk(";
 2452         c_expr.expr &:= "position<=0 || ";
 2453         c_expr.expr &:= "destStri->size<";
 2454         c_expr.expr &:= integerLiteral(length(aStri));
 2455         c_expr.expr &:= " || (uintType)(position-1)>destStri->size-";
 2456         c_expr.expr &:= integerLiteral(length(aStri));
 2457         c_expr.expr &:= ")) {\n";
 2458         c_expr.expr &:= "  ";
 2459         c_expr.expr &:= raiseError("INDEX_ERROR");
 2460         c_expr.expr &:= "\n";
 2461         c_expr.expr &:= "} else {\n";
 2462         setDiagnosticLine(c_expr);
 2463         c_expr.expr &:= "  memcpy(&destStri->mem[position-1], (";
 2464         c_expr.expr &:= stringLiteral(aStri);
 2465         c_expr.expr &:= ")->mem, ";
 2466         c_expr.expr &:= integerLiteral(length(aStri));
 2467         c_expr.expr &:= "*sizeof(strElemType));\n";
 2468         c_expr.expr &:= "}\n";
 2469       else
 2470         incr(countNoIndexChecks);
 2471         setDiagnosticLine(c_expr);
 2472         c_expr.expr &:= "memcpy(&(";
 2473         c_expr.expr &:= c_destStri.expr;
 2474         c_expr.expr &:= ")->mem[(";
 2475         c_expr.expr &:= c_position.expr;
 2476         c_expr.expr &:= ")-1], (";
 2477         c_expr.expr &:= stringLiteral(aStri);
 2478         c_expr.expr &:= ")->mem, ";
 2479         c_expr.expr &:= integerLiteral(length(aStri));
 2480         c_expr.expr &:= "*sizeof(strElemType));\n";
 2481       end if;
 2482       if c_position.temp_num <> 0 then
 2483         appendWithDiagnostic(c_destStri.temp_frees, c_expr);
 2484         appendWithDiagnostic(c_position.temp_frees, c_expr);
 2485       end if;
 2486       c_expr.expr &:= "}\n";
 2487     end if;
 2488   end func;
 2489 
 2490 
 2491 const proc: process (STR_POSCPY, in reference: function,
 2492     in ref_list: params, inout expr_type: c_expr) is func
 2493 
 2494   local
 2495     var reference: evaluatedParam is NIL;
 2496     var string: destStri is "";
 2497     var expr_type: c_destStri is expr_type.value;
 2498     var expr_type: c_position is expr_type.value;
 2499     var expr_type: c_aStri is expr_type.value;
 2500   begin
 2501     if getConstant(params[6], STRIOBJECT, evaluatedParam) then
 2502       destStri := getValue(evaluatedParam, string);
 2503       if length(destStri) = 1 then
 2504         process_const_str_elemcpy(params[1], params[4], destStri[1], c_expr);
 2505       else
 2506         process_const_str_poscpy(params[1], params[4], destStri, c_expr);
 2507       end if;
 2508     elsif getConstant(params[4], INTOBJECT, evaluatedParam) then
 2509       process_const_str_poscpy(params[1], getValue(evaluatedParam, integer), params[6], c_expr);
 2510     else
 2511       process_expr(params[1], c_destStri);
 2512       c_position.temp_num := c_destStri.temp_num;
 2513       process_expr(params[4], c_position);
 2514       c_aStri.temp_num := c_position.temp_num;
 2515       getAnyParamToExpr(params[6], c_aStri);
 2516       c_expr.expr &:= "{\n";
 2517       if c_aStri.temp_num <> 0 then
 2518         appendWithDiagnostic(c_destStri.temp_decls, c_expr);
 2519         appendWithDiagnostic(c_position.temp_decls, c_expr);
 2520         appendWithDiagnostic(c_aStri.temp_decls, c_expr);
 2521         appendWithDiagnostic(c_destStri.temp_assigns, c_expr);
 2522         appendWithDiagnostic(c_position.temp_assigns, c_expr);
 2523         appendWithDiagnostic(c_aStri.temp_assigns, c_expr);
 2524       end if;
 2525       if string_index_check then
 2526         incr(countIndexChecks);
 2527         c_expr.expr &:= "striType destStri=";
 2528         c_expr.expr &:= c_destStri.expr;
 2529         c_expr.expr &:= ";\n";
 2530         c_expr.expr &:= "striType aStri=";
 2531         c_expr.expr &:= c_aStri.expr;
 2532         c_expr.expr &:= ";\n";
 2533         c_expr.expr &:= "intType position=";
 2534         c_expr.expr &:= c_position.expr;
 2535         c_expr.expr &:= ";\n";
 2536         c_expr.expr &:= "if (idxChk(";
 2537         c_expr.expr &:= "position<=0 || ";
 2538         c_expr.expr &:= "destStri->size<aStri->size || (uintType)(position-1)>destStri->size-aStri->size)) {\n";
 2539         c_expr.expr &:= "  ";
 2540         c_expr.expr &:= raiseError("INDEX_ERROR");
 2541         c_expr.expr &:= "\n";
 2542         c_expr.expr &:= "} else {\n";
 2543         setDiagnosticLine(c_expr);
 2544         c_expr.expr &:= "  memmove(&destStri->mem[position-1], aStri->mem, aStri->size*sizeof(strElemType));\n";
 2545         c_expr.expr &:= "}\n";
 2546       else
 2547         incr(countNoIndexChecks);
 2548         c_expr.expr &:= "striType aStri=";
 2549         c_expr.expr &:= c_aStri.expr;
 2550         c_expr.expr &:= ";\n";
 2551         setDiagnosticLine(c_expr);
 2552         c_expr.expr &:= "memmove(&(";
 2553         c_expr.expr &:= c_destStri.expr;
 2554         c_expr.expr &:= ")->mem[(";
 2555         c_expr.expr &:= c_position.expr;
 2556         c_expr.expr &:= ")-1], aStri->mem, aStri->size*sizeof(strElemType));\n";
 2557       end if;
 2558       if c_aStri.temp_num <> 0 then
 2559         appendWithDiagnostic(c_destStri.temp_frees, c_expr);
 2560         appendWithDiagnostic(c_position.temp_frees, c_expr);
 2561         appendWithDiagnostic(c_aStri.temp_frees, c_expr);
 2562       end if;
 2563       c_expr.expr &:= "}\n";
 2564     end if;
 2565   end func;
 2566 
 2567 
 2568 const proc: process_inline_str_push (in ref_list: params,
 2569     inout expr_type: c_expr) is func
 2570 
 2571   local
 2572     var expr_type: statement is expr_type.value;
 2573     var string: stri_name is "";
 2574     var string: char_name is "";
 2575   begin
 2576     if isNormalVariable(params[1]) then
 2577       stri_name := normalVariable(params[1], statement);
 2578     else
 2579       incr(statement.temp_num);
 2580       stri_name := "tmp_" & str(statement.temp_num);
 2581       statement.temp_decls &:= "striType *";
 2582       statement.temp_decls &:= stri_name;
 2583       statement.temp_decls &:= ";\n";
 2584       statement.expr &:= stri_name;
 2585       statement.expr &:= "=&(";
 2586       process_expr(params[1], statement);
 2587       statement.expr &:= ");\n";
 2588       stri_name := "*" & stri_name;
 2589     end if;
 2590     if isNormalVariable(params[3]) then
 2591       char_name := normalVariable(params[3], statement);
 2592     else
 2593       incr(statement.temp_num);
 2594       char_name := "tmp_" & str(statement.temp_num);
 2595       statement.temp_decls &:= "charType ";
 2596       statement.temp_decls &:= char_name;
 2597       statement.temp_decls &:= ";\n";
 2598       statement.expr &:= char_name;
 2599       statement.expr &:= "=";
 2600       process_expr(params[3], statement);
 2601       statement.expr &:= ";\n";
 2602     end if;
 2603     statement.expr &:= "if ((";
 2604     statement.expr &:= stri_name;
 2605     statement.expr &:= ")->size == (";
 2606     statement.expr &:= stri_name;
 2607     statement.expr &:= ")->capacity) {\n";
 2608     statement.expr &:= "strPush(&(";
 2609     statement.expr &:= stri_name;
 2610     statement.expr &:= "), ";
 2611     statement.expr &:= char_name;
 2612     statement.expr &:= ");\n";
 2613     statement.expr &:= "} else {\n";
 2614     statement.expr &:= "(";
 2615     statement.expr &:= stri_name;
 2616     statement.expr &:= ")->mem[(";
 2617     statement.expr &:= stri_name;
 2618     statement.expr &:= ")->size]=";
 2619     statement.expr &:= char_name;
 2620     statement.expr &:= ";\n";
 2621     statement.expr &:= "(";
 2622     statement.expr &:= stri_name;
 2623     statement.expr &:= ")->size++;\n";
 2624     statement.expr &:= "}\n";
 2625     doLocalDeclsOfStatement(statement, c_expr);
 2626   end func;
 2627 
 2628 
 2629 const proc: process (STR_PUSH, in reference: function,
 2630     in ref_list: params, inout expr_type: c_expr) is func
 2631 
 2632   local
 2633     var reference: evaluatedParam is NIL;
 2634     var expr_type: statement is expr_type.value;
 2635   begin
 2636     if getConstant(params[3], CHAROBJECT, evaluatedParam) then
 2637       process_const_str_push(params[1], getValue(evaluatedParam, char), c_expr);
 2638     elsif inlineFunctions and ccConf.WITH_STRI_CAPACITY then
 2639       process_inline_str_push(params, c_expr);
 2640     else
 2641       statement.expr := "strPush(&(";
 2642       process_expr(params[1], statement);
 2643       statement.expr &:= "), ";
 2644       process_expr(params[3], statement);
 2645       statement.expr &:= ");\n";
 2646       doLocalDeclsOfStatement(statement, c_expr);
 2647     end if;
 2648   end func;
 2649 
 2650 
 2651 const proc: process_inline_str_range (in ref_list: params, in string: slice_name,
 2652     inout expr_type: c_expr) is func
 2653 
 2654   local
 2655     var reference: evaluatedParam is NIL;
 2656     var string: stri_name is "";
 2657     var string: start_name is "";
 2658     var string: stop_name is "";
 2659     var integer: start_value is 0;
 2660     var boolean: start_is_variable is TRUE;
 2661     var integer: stop_value is 0;
 2662     var boolean: stop_is_variable is TRUE;
 2663     var boolean: raisesIndexError is FALSE;
 2664   begin
 2665     stri_name := getParameterAsVariable("const_striType", "stri_", params[1], c_expr);
 2666     if getConstant(params[3], INTOBJECT, evaluatedParam) then
 2667       start_is_variable := FALSE;
 2668       start_value := getValue(evaluatedParam, integer);
 2669       if start_value < 1 then
 2670         warning(DOES_RAISE, "INDEX_ERROR", c_expr);
 2671         c_expr.expr &:= strRaiseError("INDEX_ERROR");
 2672         raisesIndexError := TRUE;
 2673       else
 2674         start_name := integerLiteral(start_value);
 2675       end if;
 2676     else
 2677       start_name := getTempVariable("intType", "start_", params[3], c_expr);
 2678       if string_index_check then
 2679         incr(countIndexChecks);
 2680         c_expr.expr &:= "idxChk(";
 2681         c_expr.expr &:= start_name;
 2682         c_expr.expr &:= "<1)?";
 2683         c_expr.expr &:= intRaiseError("INDEX_ERROR");
 2684         c_expr.expr &:= ":0, ";
 2685       else
 2686         incr(countNoIndexChecks);
 2687       end if;
 2688     end if;
 2689     if not raisesIndexError then
 2690       if getConstant(params[5], INTOBJECT, evaluatedParam) then
 2691         stop_is_variable := FALSE;
 2692         stop_value := getValue(evaluatedParam, integer);
 2693         if stop_value < 0 or
 2694             not start_is_variable and stop_value < pred(start_value) then
 2695           warning(DOES_RAISE, "INDEX_ERROR", c_expr);
 2696           c_expr.expr &:= strRaiseError("INDEX_ERROR");
 2697           raisesIndexError := TRUE;
 2698         else
 2699           stop_name := integerLiteral(stop_value);
 2700         end if;
 2701       else
 2702         stop_name := getParameterAsVariable("intType", "stop_", params[5], c_expr);
 2703       end if;
 2704       if not raisesIndexError then
 2705         (* Formula used: slice.capacity=0,
 2706                          stop>=start && (uintType)start <= stri->size ?
 2707                          (slice.mem = &stri->mem[start-1],
 2708                          (uintType)stop > stri->size ?
 2709                          slice.size = stri->size-(memSizeType)start+1 :
 2710                          (slice.size = (memSizeType)stop-(memSizeType)start+1))
 2711                          : idxChk(stop<start-1)?INDEX_ERROR
 2712                          : (slice.mem = NULL,slice.size = 0) *)
 2713         if ccConf.WITH_STRI_CAPACITY then
 2714           c_expr.expr &:= slice_name;
 2715           c_expr.expr &:= ".capacity=0, ";
 2716         end if;
 2717         c_expr.expr &:= stop_name;
 2718         c_expr.expr &:= ">=";
 2719         c_expr.expr &:= start_name;
 2720         c_expr.expr &:= " && (uintType)";
 2721         c_expr.expr &:= start_name;
 2722         c_expr.expr &:= "<=";
 2723         c_expr.expr &:= stri_name;
 2724         c_expr.expr &:= "->size ? (";
 2725         c_expr.expr &:= slice_name;
 2726         c_expr.expr &:= ".mem = &";
 2727         c_expr.expr &:= stri_name;
 2728         c_expr.expr &:= "->mem[";
 2729         c_expr.expr &:= start_name;
 2730         c_expr.expr &:= "-1], (uintType)";
 2731         c_expr.expr &:= stop_name;
 2732         c_expr.expr &:= " > ";
 2733         c_expr.expr &:= stri_name;
 2734         c_expr.expr &:= "->size ? ";
 2735         c_expr.expr &:= slice_name;
 2736         c_expr.expr &:= ".size = ";
 2737         c_expr.expr &:= stri_name;
 2738         c_expr.expr &:= "->size-(memSizeType)";
 2739         c_expr.expr &:= start_name;
 2740         c_expr.expr &:= "+1 : (";
 2741         c_expr.expr &:= slice_name;
 2742         c_expr.expr &:= ".size = (memSizeType)";
 2743         c_expr.expr &:= stop_name;
 2744         c_expr.expr &:= "-(memSizeType)";
 2745         c_expr.expr &:= start_name;
 2746         c_expr.expr &:= "+1))";
 2747         if stop_is_variable or start_is_variable then
 2748           if string_index_check then
 2749             incr(countIndexChecks);
 2750             c_expr.expr &:= " : idxChk(";
 2751             c_expr.expr &:= stop_name;
 2752             c_expr.expr &:= "<";
 2753             c_expr.expr &:= start_name;
 2754             c_expr.expr &:= "-1)?";
 2755             c_expr.expr &:= strRaiseError("INDEX_ERROR");
 2756           else
 2757             incr(countNoIndexChecks);
 2758           end if;
 2759         end if;
 2760         c_expr.expr &:= " : (";
 2761         c_expr.expr &:= slice_name;
 2762         c_expr.expr &:= ".mem = NULL,";
 2763         c_expr.expr &:= slice_name;
 2764         c_expr.expr &:= ".size = 0)";
 2765       end if;
 2766     end if;
 2767   end func;
 2768 
 2769 
 2770 const proc: process_str_range_of_empty_string (in ref_list: params,
 2771     inout expr_type: c_expr) is func
 2772 
 2773   local
 2774     var reference: evaluatedParam is NIL;
 2775     var string: start_name is "";
 2776     var string: stop_name is "";
 2777     var integer: start_value is 0;
 2778     var boolean: start_is_variable is TRUE;
 2779     var integer: stop_value is 0;
 2780     var boolean: stop_is_variable is TRUE;
 2781     var boolean: raisesIndexError is FALSE;
 2782   begin
 2783     incr(countOptimizations);
 2784     c_expr.expr &:= "/* \"\"[m .. n] */ (";
 2785     if getConstant(params[3], INTOBJECT, evaluatedParam) then
 2786       start_is_variable := FALSE;
 2787       start_value := getValue(evaluatedParam, integer);
 2788       if start_value < 1 then
 2789         warning(DOES_RAISE, "INDEX_ERROR", c_expr);
 2790         c_expr.expr &:= strRaiseError("INDEX_ERROR");
 2791         raisesIndexError := TRUE;
 2792       else
 2793         start_name := integerLiteral(start_value);
 2794       end if;
 2795     else
 2796       start_name := getTempVariable("intType", "start_", params[3], c_expr);
 2797     end if;
 2798     if not raisesIndexError then
 2799       if getConstant(params[5], INTOBJECT, evaluatedParam) then
 2800         stop_is_variable := FALSE;
 2801         stop_value := getValue(evaluatedParam, integer);
 2802         if stop_value < 0 or
 2803             not start_is_variable and stop_value < pred(start_value) then
 2804           warning(DOES_RAISE, "INDEX_ERROR", c_expr);
 2805           c_expr.expr &:= strRaiseError("INDEX_ERROR");
 2806           raisesIndexError := TRUE;
 2807         else
 2808           stop_name := integerLiteral(stop_value);
 2809         end if;
 2810       else
 2811         stop_name := getParameterAsVariable("intType", "stop_", params[5], c_expr);
 2812       end if;
 2813       if not raisesIndexError then
 2814         if start_is_variable or stop_is_variable then
 2815           if string_index_check then
 2816             incr(countIndexChecks);
 2817             c_expr.expr &:= "idxChk(";
 2818             if start_is_variable then
 2819               c_expr.expr &:= start_name;
 2820               c_expr.expr &:= "<1||";
 2821             end if;
 2822             c_expr.expr &:= stop_name;
 2823             c_expr.expr &:= "<";
 2824             c_expr.expr &:= start_name;
 2825             c_expr.expr &:= "-1)?";
 2826             c_expr.expr &:= strRaiseError("INDEX_ERROR");
 2827             c_expr.expr &:= ":";
 2828           else
 2829             incr(countNoIndexChecks);
 2830           end if;
 2831         end if;
 2832         c_expr.expr &:= stringLiteral("");
 2833       end if;
 2834     end if;
 2835     c_expr.expr &:= ")";
 2836   end func;
 2837 
 2838 
 2839 const proc: process (STR_RANGE, in reference: function,
 2840     in ref_list: params, inout expr_type: c_expr) is func
 2841 
 2842   local
 2843     var reference: evaluatedParam is NIL;
 2844     var string: start_name is "";
 2845     var string: slice_name is "";
 2846   begin
 2847     if getConstant(params[1], STRIOBJECT, evaluatedParam) and
 2848         getValue(evaluatedParam, string) = "" then
 2849       process_str_range_of_empty_string(params, c_expr);
 2850     elsif getConstant(params[3], INTOBJECT, evaluatedParam) and
 2851         getValue(evaluatedParam, integer) = 1 then
 2852       incr(countOptimizations);
 2853       process_str_head(params[1], params[5], c_expr);
 2854     elsif ccConf.ALLOW_STRITYPE_SLICES and c_expr.demand < REQUIRE_RESULT then
 2855       c_expr.expr &:= "(";
 2856       incr(c_expr.temp_num);
 2857       slice_name := "slice_" & str(c_expr.temp_num);
 2858       c_expr.temp_decls &:= "struct striStruct ";
 2859       c_expr.temp_decls &:= slice_name;
 2860       c_expr.temp_decls &:= ";\n";
 2861       if inlineFunctions then
 2862         process_inline_str_range(params, slice_name, c_expr);
 2863       else
 2864         c_expr.expr &:= "strRangeSlice(";
 2865         getAnyParamToExpr(params[1], c_expr);
 2866         c_expr.expr &:= ", ";
 2867         process_expr(params[3], c_expr);
 2868         c_expr.expr &:= ", ";
 2869         process_expr(params[5], c_expr);
 2870         c_expr.expr &:= ", &";
 2871         c_expr.expr &:= slice_name;
 2872         c_expr.expr &:= ")";
 2873       end if;
 2874       c_expr.expr &:= ", &";
 2875       c_expr.expr &:= slice_name;
 2876       c_expr.expr &:= ")";
 2877     else
 2878       prepare_stri_result(c_expr);
 2879       c_expr.result_expr := "strRange(";
 2880       getAnyParamToResultExpr(params[1], c_expr);
 2881       c_expr.result_expr &:= ", ";
 2882       getStdParamToResultExpr(params[3], c_expr);
 2883       c_expr.result_expr &:= ", ";
 2884       getStdParamToResultExpr(params[5], c_expr);
 2885       c_expr.result_expr &:= ")";
 2886     end if;
 2887   end func;
 2888 
 2889 
 2890 const proc: process (STR_RCHIPOS, in reference: function,
 2891     in ref_list: params, inout expr_type: c_expr) is func
 2892 
 2893   begin
 2894     c_expr.expr &:= "strRChIPos(";
 2895     getAnyParamToExpr(params[1], c_expr);
 2896     c_expr.expr &:= ", ";
 2897     process_expr(params[2], c_expr);
 2898     c_expr.expr &:= ", ";
 2899     process_expr(params[3], c_expr);
 2900     c_expr.expr &:= ")";
 2901   end func;
 2902 
 2903 
 2904 const proc: process_const_str_rchpos (in string: mainStri, in reference: param2,
 2905     inout expr_type: c_expr) is func
 2906 
 2907   local
 2908     var reference: evaluatedParam is NIL;
 2909   begin
 2910     if getConstant(param2, CHAROBJECT, evaluatedParam) then
 2911       incr(countOptimizations);
 2912       c_expr.expr &:= "/* rpos(";
 2913       c_expr.expr &:= replace(literal(mainStri), "*/", "*\\/");
 2914       c_expr.expr &:= ",";
 2915       c_expr.expr &:= literal(getValue(evaluatedParam, char));
 2916       c_expr.expr &:= ") */ ";
 2917       c_expr.expr &:= integerLiteral(rpos(mainStri, getValue(evaluatedParam, char)));
 2918     elsif length(mainStri) = 0 then
 2919       incr(countOptimizations);
 2920       c_expr.expr &:= "/* rpos(\"\", *) */ ";
 2921       c_expr.expr &:= integerLiteral(0);
 2922     elsif length(mainStri) = 1 then
 2923       incr(countOptimizations);
 2924       c_expr.expr &:= "/* rpos(";
 2925       c_expr.expr &:= literal(mainStri);
 2926       c_expr.expr &:= ", *) */ ";
 2927       c_expr.expr &:= charLiteral(mainStri[1]);
 2928       c_expr.expr &:= "==(";
 2929       getAnyParamToExpr(param2, c_expr);
 2930       c_expr.expr &:= ")?";
 2931       c_expr.expr &:= integerLiteral(1);
 2932       c_expr.expr &:= ":";
 2933       c_expr.expr &:= integerLiteral(0);
 2934     else
 2935       c_expr.expr &:= "strRChPos(";
 2936       c_expr.expr &:= stringLiteral(mainStri);
 2937       c_expr.expr &:= ", ";
 2938       getAnyParamToExpr(param2, c_expr);
 2939       c_expr.expr &:= ")";
 2940     end if;
 2941   end func;
 2942 
 2943 
 2944 const proc: process (STR_RCHPOS, in reference: function,
 2945     in ref_list: params, inout expr_type: c_expr) is func
 2946 
 2947   local
 2948     var reference: evaluatedParam is NIL;
 2949   begin
 2950     if getConstant(params[1], STRIOBJECT, evaluatedParam) then
 2951       process_const_str_rchpos(getValue(evaluatedParam, string), params[2], c_expr);
 2952     else
 2953       c_expr.expr &:= "strRChPos(";
 2954       getAnyParamToExpr(params[1], c_expr);
 2955       c_expr.expr &:= ", ";
 2956       process_expr(params[2], c_expr);
 2957       c_expr.expr &:= ")";
 2958     end if;
 2959   end func;
 2960 
 2961 
 2962 const proc: process_const_str_repl (in reference: param1,
 2963     in string: searched, in reference: param3, inout expr_type: c_expr) is func
 2964 
 2965   local
 2966     var expr_type: c_param1 is expr_type.value;
 2967     var reference: evaluatedParam is NIL;
 2968     var string: replacement is "";
 2969   begin
 2970     if searched = "" then
 2971       incr(countOptimizations);
 2972       prepareAnyParamTemporarys(param1, c_param1, c_expr);
 2973       if c_param1.result_expr <> "" then
 2974         prepare_stri_result(c_expr);
 2975         c_expr.result_expr := "/* strRepl(*, \"\", *) */ ";
 2976         c_expr.result_expr &:= c_param1.result_expr;
 2977       else
 2978         c_expr.expr &:= "/* strRepl(*, \"\", *) */ ";
 2979         c_expr.expr &:= c_param1.expr;
 2980       end if;
 2981     elsif getConstant(param3, STRIOBJECT, evaluatedParam) then
 2982       replacement := getValue(evaluatedParam, string);
 2983       if searched = replacement then
 2984         prepareAnyParamTemporarys(param1, c_param1, c_expr);
 2985         if c_param1.result_expr <> "" then
 2986           prepare_stri_result(c_expr);
 2987           c_expr.result_expr := "/* strRepl(*, ";
 2988           c_expr.result_expr &:= replace(literal(searched), "*/", "*\\/");
 2989           c_expr.result_expr &:= ", ";
 2990           c_expr.result_expr &:= replace(literal(replacement), "*/", "*\\/");
 2991           c_expr.result_expr &:= ") */ ";
 2992           c_expr.result_expr &:= c_param1.result_expr;
 2993         else
 2994           c_expr.expr &:= "/* strRepl(*, ";
 2995           c_expr.expr &:= replace(literal(searched), "*/", "*\\/");
 2996           c_expr.expr &:= ", ";
 2997           c_expr.expr &:= replace(literal(replacement), "*/", "*\\/");
 2998           c_expr.expr &:= ") */ ";
 2999           c_expr.expr &:= c_param1.expr;
 3000         end if;
 3001       elsif length(searched) = 1 then
 3002         if length(replacement) = 1 then
 3003           prepare_stri_result(c_expr);
 3004           c_expr.result_expr := "strChChRepl(";
 3005           getAnyParamToResultExpr(param1, c_expr);
 3006           c_expr.result_expr &:= ", ";
 3007           c_expr.result_expr &:= charLiteral(searched[1]);
 3008           c_expr.result_expr &:= ", ";
 3009           c_expr.result_expr &:= charLiteral(replacement[1]);
 3010           c_expr.result_expr &:= ")";
 3011         else
 3012           prepare_stri_result(c_expr);
 3013           c_expr.result_expr := "strChRepl(";
 3014           getAnyParamToResultExpr(param1, c_expr);
 3015           c_expr.result_expr &:= ", ";
 3016           c_expr.result_expr &:= charLiteral(searched[1]);
 3017           c_expr.result_expr &:= ", ";
 3018           c_expr.result_expr &:= stringLiteral(replacement);
 3019           c_expr.result_expr &:= ")";
 3020         end if;
 3021       else
 3022         prepare_stri_result(c_expr);
 3023         c_expr.result_expr := "strRepl(";
 3024         getAnyParamToResultExpr(param1, c_expr);
 3025         c_expr.result_expr &:= ", ";
 3026         c_expr.result_expr &:= stringLiteral(searched);
 3027         c_expr.result_expr &:= ", ";
 3028         c_expr.result_expr &:= stringLiteral(replacement);
 3029         c_expr.result_expr &:= ")";
 3030       end if;
 3031     elsif length(searched) = 1 then
 3032       incr(countOptimizations);
 3033       if isActionExpression(param3, "CHR_STR") then
 3034         prepare_stri_result(c_expr);
 3035         c_expr.result_expr := "strChChRepl(";
 3036         getAnyParamToResultExpr(param1, c_expr);
 3037         c_expr.result_expr &:= ", ";
 3038         c_expr.result_expr &:= charLiteral(searched[1]);
 3039         c_expr.result_expr &:= ", ";
 3040         getAnyParamToResultExpr(getActionParameter(param3, 1), c_expr);
 3041         c_expr.result_expr &:= ")";
 3042       else
 3043         prepare_stri_result(c_expr);
 3044         c_expr.result_expr := "strChRepl(";
 3045         getAnyParamToResultExpr(param1, c_expr);
 3046         c_expr.result_expr &:= ", ";
 3047         c_expr.result_expr &:= charLiteral(searched[1]);
 3048         c_expr.result_expr &:= ", ";
 3049         getAnyParamToResultExpr(param3, c_expr);
 3050         c_expr.result_expr &:= ")";
 3051       end if;
 3052     else
 3053       prepare_stri_result(c_expr);
 3054       c_expr.result_expr := "strRepl(";
 3055       getAnyParamToResultExpr(param1, c_expr);
 3056       c_expr.result_expr &:= ", ";
 3057       c_expr.result_expr &:= stringLiteral(searched);
 3058       c_expr.result_expr &:= ", ";
 3059       getAnyParamToResultExpr(param3, c_expr);
 3060       c_expr.result_expr &:= ")";
 3061     end if;
 3062   end func;
 3063 
 3064 
 3065 const proc: process (STR_REPL, in reference: function,
 3066     in ref_list: params, inout expr_type: c_expr) is func
 3067 
 3068   local
 3069     var reference: evaluatedParam is NIL;
 3070     var string: replacement is "";
 3071   begin
 3072     if getConstant(params[2], STRIOBJECT, evaluatedParam) then
 3073       process_const_str_repl(params[1], getValue(evaluatedParam, string), params[3], c_expr);
 3074     elsif isActionExpression(params[2], "CHR_STR") then
 3075       incr(countOptimizations);
 3076       prepare_stri_result(c_expr);
 3077       if getConstant(params[3], STRIOBJECT, evaluatedParam) then
 3078         replacement := getValue(evaluatedParam, string);
 3079         if length(replacement) = 1 then
 3080           c_expr.result_expr := "strChChRepl(";
 3081           getAnyParamToResultExpr(params[1], c_expr);
 3082           c_expr.result_expr &:= ", ";
 3083           getAnyParamToResultExpr(getActionParameter(params[2], 1), c_expr);
 3084           c_expr.result_expr &:= ", ";
 3085           c_expr.result_expr &:= charLiteral(replacement[1]);
 3086           c_expr.result_expr &:= ")";
 3087         else
 3088           c_expr.result_expr := "strChRepl(";
 3089           getAnyParamToResultExpr(params[1], c_expr);
 3090           c_expr.result_expr &:= ", ";
 3091           getAnyParamToResultExpr(getActionParameter(params[2], 1), c_expr);
 3092           c_expr.result_expr &:= ", ";
 3093           c_expr.result_expr &:= stringLiteral(replacement);
 3094           c_expr.result_expr &:= ")";
 3095         end if;
 3096       elsif isActionExpression(params[3], "CHR_STR") then
 3097         c_expr.result_expr := "strChChRepl(";
 3098         getAnyParamToResultExpr(params[1], c_expr);
 3099         c_expr.result_expr &:= ", ";
 3100         getAnyParamToResultExpr(getActionParameter(params[2], 1), c_expr);
 3101         c_expr.result_expr &:= ", ";
 3102         getAnyParamToResultExpr(getActionParameter(params[3], 1), c_expr);
 3103         c_expr.result_expr &:= ")";
 3104       else
 3105         c_expr.result_expr := "strChRepl(";
 3106         getAnyParamToResultExpr(params[1], c_expr);
 3107         c_expr.result_expr &:= ", ";
 3108         getAnyParamToResultExpr(getActionParameter(params[2], 1), c_expr);
 3109         c_expr.result_expr &:= ", ";
 3110         getAnyParamToResultExpr(params[3], c_expr);
 3111         c_expr.result_expr &:= ")";
 3112       end if;
 3113     else
 3114       prepare_stri_result(c_expr);
 3115       c_expr.result_expr := "strRepl(";
 3116       getAnyParamToResultExpr(params[1], c_expr);
 3117       c_expr.result_expr &:= ", ";
 3118       getAnyParamToResultExpr(params[2], c_expr);
 3119       c_expr.result_expr &:= ", ";
 3120       getAnyParamToResultExpr(params[3], c_expr);
 3121       c_expr.result_expr &:= ")";
 3122     end if;
 3123   end func;
 3124 
 3125 
 3126 const proc: process (STR_RIPOS, in reference: function,
 3127     in ref_list: params, inout expr_type: c_expr) is func
 3128 
 3129   local
 3130     var reference: evaluatedParam is NIL;
 3131   begin
 3132     if getConstant(params[2], STRIOBJECT, evaluatedParam) and
 3133         length(getValue(evaluatedParam, string)) = 1 then
 3134       incr(countOptimizations);
 3135       c_expr.expr &:= "strRChIPos(";
 3136       getAnyParamToExpr(params[1], c_expr);
 3137       c_expr.expr &:= ", ";
 3138       c_expr.expr &:= charLiteral(getValue(evaluatedParam, string)[1]);
 3139       c_expr.expr &:= ", ";
 3140       process_expr(params[3], c_expr);
 3141       c_expr.expr &:= ")";
 3142     else
 3143       c_expr.expr &:= "strRIPos(";
 3144       getAnyParamToExpr(params[1], c_expr);
 3145       c_expr.expr &:= ", ";
 3146       getAnyParamToExpr(params[2], c_expr);
 3147       c_expr.expr &:= ", ";
 3148       process_expr(params[3], c_expr);
 3149       c_expr.expr &:= ")";
 3150     end if;
 3151   end func;
 3152 
 3153 
 3154 const proc: process (STR_RPAD, in reference: function,
 3155     in ref_list: params, inout expr_type: c_expr) is func
 3156 
 3157   begin
 3158     prepare_stri_result(c_expr);
 3159     c_expr.result_expr := "strRpad(";
 3160     getAnyParamToResultExpr(params[1], c_expr);
 3161     c_expr.result_expr &:= ", ";
 3162     getStdParamToResultExpr(params[3], c_expr);
 3163     c_expr.result_expr &:= ")";
 3164   end func;
 3165 
 3166 
 3167 const proc: process_const_str_rpos (in reference: mainStri, in string: searched,
 3168     inout expr_type: c_expr) is func
 3169 
 3170   local
 3171     var reference: evaluatedParam is NIL;
 3172   begin
 3173     if getConstant(mainStri, STRIOBJECT, evaluatedParam) then
 3174       incr(countOptimizations);
 3175       c_expr.expr &:= "/* rpos(";
 3176       c_expr.expr &:= replace(literal(getValue(evaluatedParam, string)), "*/", "*\\/");
 3177       c_expr.expr &:= ",";
 3178       c_expr.expr &:= replace(literal(searched), "*/", "*\\/");
 3179       c_expr.expr &:= ") */ ";
 3180       c_expr.expr &:= integerLiteral(rpos(getValue(evaluatedParam, string), searched));
 3181     elsif length(searched) = 0 then
 3182       incr(countOptimizations);
 3183       c_expr.expr &:= "/* rpos(*, \"\") */ ";
 3184       c_expr.expr &:= integerLiteral(0);
 3185     elsif length(searched) = 1 then
 3186       incr(countOptimizations);
 3187       c_expr.expr &:= "strRChPos(";
 3188       getAnyParamToExpr(mainStri, c_expr);
 3189       c_expr.expr &:= ", ";
 3190       c_expr.expr &:= charLiteral(searched[1]);
 3191       c_expr.expr &:= ")";
 3192     else
 3193       c_expr.expr &:= "strRPos(";
 3194       getAnyParamToExpr(mainStri, c_expr);
 3195       c_expr.expr &:= ", ";
 3196       c_expr.expr &:= stringLiteral(searched);
 3197       c_expr.expr &:= ")";
 3198     end if;
 3199   end func;
 3200 
 3201 
 3202 const proc: process (STR_RPOS, in reference: function,
 3203     in ref_list: params, inout expr_type: c_expr) is func
 3204 
 3205   local
 3206     var reference: evaluatedParam is NIL;
 3207   begin
 3208     if getConstant(params[2], STRIOBJECT, evaluatedParam) then
 3209       process_const_str_rpos(params[1], getValue(evaluatedParam, string), c_expr);
 3210     elsif getConstant(params[1], STRIOBJECT, evaluatedParam) and
 3211         length(getValue(evaluatedParam, string)) = 0 then
 3212       incr(countOptimizations);
 3213       c_expr.expr &:= "/* rpos(\"\", *) */ ";
 3214       c_expr.expr &:= integerLiteral(0);
 3215     else
 3216       c_expr.expr &:= "strRPos(";
 3217       getAnyParamToExpr(params[1], c_expr);
 3218       c_expr.expr &:= ", ";
 3219       getAnyParamToExpr(params[2], c_expr);
 3220       c_expr.expr &:= ")";
 3221     end if;
 3222   end func;
 3223 
 3224 
 3225 const proc: process (STR_RTRIM, in reference: function,
 3226     in ref_list: params, inout expr_type: c_expr) is func
 3227 
 3228   begin
 3229     prepare_stri_result(c_expr);
 3230     c_expr.result_expr := "strRtrim(";
 3231     getAnyParamToResultExpr(params[1], c_expr);
 3232     c_expr.result_expr &:= ")";
 3233   end func;
 3234 
 3235 
 3236 const proc: process (STR_SPLIT, in reference: function,
 3237     in ref_list: params, inout expr_type: c_expr) is func
 3238 
 3239   local
 3240     var reference: evaluatedParam is NIL;
 3241   begin
 3242     prepare_typed_result(array_type[getExprResultType(params[1])], c_expr);
 3243     if getConstant(params[2], STRIOBJECT, evaluatedParam) and
 3244         length(getValue(evaluatedParam, string)) = 1 then
 3245       incr(countOptimizations);
 3246       c_expr.result_expr := "strChSplit(";
 3247       getAnyParamToResultExpr(params[1], c_expr);
 3248       c_expr.result_expr &:= ", ";
 3249       c_expr.result_expr &:= charLiteral(getValue(evaluatedParam, string)[1]);
 3250       c_expr.result_expr &:= ")";
 3251     else
 3252       c_expr.result_expr := "strSplit(";
 3253       getAnyParamToResultExpr(params[1], c_expr);
 3254       c_expr.result_expr &:= ", ";
 3255       getAnyParamToResultExpr(params[2], c_expr);
 3256       c_expr.result_expr &:= ")";
 3257     end if;
 3258   end func;
 3259 
 3260 
 3261 const proc: process (STR_STR, in reference: function,
 3262     in ref_list: params, inout expr_type: c_expr) is func
 3263 
 3264   begin
 3265     process_expr(params[1], c_expr);
 3266   end func;
 3267 
 3268 
 3269 const proc: process_str_substr1 (in reference: stri, in reference: index,
 3270     inout expr_type: c_expr) is func
 3271 
 3272   local
 3273     var string: stri_name is "";
 3274     var string: index_name is "";
 3275     var string: striStruct_name is "";
 3276   begin
 3277     if c_expr.demand < REQUIRE_RESULT then
 3278       incr(countOptimizations);
 3279       c_expr.expr &:= "(";
 3280       stri_name := getParameterAsVariable("const_striType", "tmp_", stri, c_expr);
 3281       incr(c_expr.temp_num);
 3282       index_name := getParameterAsVariable("intType", "idx_", index, c_expr);
 3283       incr(c_expr.temp_num);
 3284       striStruct_name := "stri_" & str(c_expr.temp_num);
 3285       c_expr.temp_decls &:= "struct striStruct ";
 3286       c_expr.temp_decls &:= striStruct_name;
 3287       c_expr.temp_decls &:= ";\n";
 3288       if string_index_check then
 3289         incr(countIndexChecks);
 3290         c_expr.expr &:= "idxChk(";
 3291         c_expr.expr &:= index_name;
 3292         c_expr.expr &:= "<1)?";
 3293         c_expr.expr &:= strRaiseError("INDEX_ERROR");
 3294         c_expr.expr &:= ":";
 3295       else
 3296         incr(countNoIndexChecks);
 3297       end if;
 3298       c_expr.expr &:= "(";
 3299       c_expr.expr &:= index_name;
 3300       c_expr.expr &:= ">";
 3301       c_expr.expr &:= stri_name;
 3302       c_expr.expr &:= "->size ? ";
 3303       c_expr.expr &:= stringLiteral("");
 3304       c_expr.expr &:= " : chrStrMacro(";
 3305       c_expr.expr &:= stri_name;
 3306       c_expr.expr &:= "->mem[";
 3307       c_expr.expr &:= index_name;
 3308       c_expr.expr &:= "-1],";
 3309       c_expr.expr &:= striStruct_name;
 3310       c_expr.expr &:= ")))";
 3311     else
 3312       prepare_stri_result(c_expr);
 3313       c_expr.result_expr := "strSubstr(";
 3314       getAnyParamToResultExpr(stri, c_expr);
 3315       c_expr.result_expr &:= ", ";
 3316       getStdParamToResultExpr(index, c_expr);
 3317       c_expr.result_expr &:= ", 1)";
 3318     end if;
 3319   end func;
 3320 
 3321 
 3322 const proc: process_inline_str_substr (in ref_list: params, in string: slice_name,
 3323     inout expr_type: c_expr) is func
 3324 
 3325   local
 3326     var reference: evaluatedParam is NIL;
 3327     var string: stri_name is "";
 3328     var string: start_name is "";
 3329     var string: length_name is "";
 3330     var integer: start_value is 0;
 3331     var boolean: start_is_variable is TRUE;
 3332     var integer: length_value is 0;
 3333     var boolean: length_is_variable is TRUE;
 3334     var boolean: raisesIndexError is FALSE;
 3335   begin
 3336     stri_name := getParameterAsVariable("const_striType", "stri_", params[1], c_expr);
 3337     if getConstant(params[3], INTOBJECT, evaluatedParam) then
 3338       start_is_variable := FALSE;
 3339       start_value := getValue(evaluatedParam, integer);
 3340       if start_value < 1 then
 3341         warning(DOES_RAISE, "INDEX_ERROR", c_expr);
 3342         c_expr.expr &:= strRaiseError("INDEX_ERROR");
 3343         raisesIndexError := TRUE;
 3344       else
 3345         start_name := integerLiteral(start_value);
 3346       end if;
 3347     else
 3348       start_name := getTempVariable("intType", "start_", params[3], c_expr);
 3349     end if;
 3350     if not raisesIndexError then
 3351       if getConstant(params[5], INTOBJECT, evaluatedParam) then
 3352         length_is_variable := FALSE;
 3353         length_value := getValue(evaluatedParam, integer);
 3354         if length_value < 0 then
 3355           warning(DOES_RAISE, "INDEX_ERROR", c_expr);
 3356           c_expr.expr &:= strRaiseError("INDEX_ERROR");
 3357           raisesIndexError := TRUE;
 3358         else
 3359           length_name := integerLiteral(length_value);
 3360         end if;
 3361       else
 3362         length_name := getParameterAsVariable("intType", "length_", params[5], c_expr);
 3363       end if;
 3364       if not raisesIndexError then
 3365         if start_is_variable or length_is_variable then
 3366           if string_index_check then
 3367             incr(countIndexChecks);
 3368             c_expr.expr &:= "idxChk(";
 3369             if start_is_variable then
 3370               c_expr.expr &:= start_name;
 3371               c_expr.expr &:= "<1";
 3372             end if;
 3373             if start_is_variable and length_is_variable then
 3374               c_expr.expr &:= "||";
 3375             end if;
 3376             if length_is_variable then
 3377               c_expr.expr &:= length_name;
 3378               c_expr.expr &:= "<0";
 3379             end if;
 3380             c_expr.expr &:= ")?";
 3381             c_expr.expr &:= intRaiseError("INDEX_ERROR");
 3382             c_expr.expr &:= ":0, ";
 3383           else
 3384             incr(countNoIndexChecks);
 3385           end if;
 3386         end if;
 3387         if ccConf.WITH_STRI_CAPACITY then
 3388           c_expr.expr &:= slice_name;
 3389           c_expr.expr &:= ".capacity=0, ";
 3390         end if;
 3391         if not length_is_variable and length_value = 0 then
 3392           c_expr.expr &:= slice_name;
 3393           c_expr.expr &:= ".mem = NULL, ";
 3394           c_expr.expr &:= slice_name;
 3395           c_expr.expr &:= ".size = 0";
 3396         else
 3397           (* Formula used: slice.capacity=0,
 3398                            length!=1 &&
 3399                            (uintType)start<=stri->size ?
 3400                            (slice.mem = &stri->mem[start-1],
 3401                            (uintType)length > stri->size-(memSizeType)start+1 ?
 3402                            slice.size = stri->size-(memSizeType)start+1 :
 3403                            (slice.size = (memSizeType)length)) :
 3404                            (slice.mem = NULL, slice.size = 0) *)
 3405           if length_is_variable then
 3406             c_expr.expr &:= length_name;
 3407             c_expr.expr &:= "!=0 && ";
 3408           end if;
 3409           c_expr.expr &:= "(uintType)";
 3410           c_expr.expr &:= start_name;
 3411           c_expr.expr &:= "<=";
 3412           c_expr.expr &:= stri_name;
 3413           c_expr.expr &:= "->size ? (";
 3414           c_expr.expr &:= slice_name;
 3415           c_expr.expr &:= ".mem = &";
 3416           c_expr.expr &:= stri_name;
 3417           c_expr.expr &:= "->mem[";
 3418           c_expr.expr &:= start_name;
 3419           c_expr.expr &:= "-1], (uintType)";
 3420           c_expr.expr &:= length_name;
 3421           c_expr.expr &:= ">";
 3422           c_expr.expr &:= stri_name;
 3423           c_expr.expr &:= "->size-(memSizeType)";
 3424           c_expr.expr &:= start_name;
 3425           c_expr.expr &:= "+1 ? ";
 3426           c_expr.expr &:= slice_name;
 3427           c_expr.expr &:= ".size = ";
 3428           c_expr.expr &:= stri_name;
 3429           c_expr.expr &:= "->size-(memSizeType)";
 3430           c_expr.expr &:= start_name;
 3431           c_expr.expr &:= "+1 : (";
 3432           c_expr.expr &:= slice_name;
 3433           c_expr.expr &:= ".size = (memSizeType)";
 3434           c_expr.expr &:= length_name;
 3435           c_expr.expr &:= ")) : (";
 3436           c_expr.expr &:= slice_name;
 3437           c_expr.expr &:= ".mem = NULL, ";
 3438           c_expr.expr &:= slice_name;
 3439           c_expr.expr &:= ".size = 0)";
 3440         end if;
 3441       end if;
 3442     end if;
 3443   end func;
 3444 
 3445 
 3446 const proc: process (STR_SUBSTR, in reference: function,
 3447     in ref_list: params, inout expr_type: c_expr) is func
 3448 
 3449   local
 3450     var reference: evaluatedParam is NIL;
 3451     var integer: length is 0;
 3452     var string: slice_name is "";
 3453   begin
 3454     if getConstant(params[1], STRIOBJECT, evaluatedParam) and
 3455         getValue(evaluatedParam, string) = "" then
 3456       incr(countOptimizations);
 3457       c_expr.expr &:= "/* \"\"[m len n] */ (";
 3458       if string_index_check then
 3459         incr(countIndexChecks);
 3460         c_expr.expr &:= "idxChk((";
 3461         process_expr(params[3], c_expr);
 3462         c_expr.expr &:= ")<1||(";
 3463         process_expr(params[5], c_expr);
 3464         c_expr.expr &:= ")<0)?";
 3465         c_expr.expr &:= strRaiseError("INDEX_ERROR");
 3466         c_expr.expr &:= ":";
 3467       else
 3468         incr(countNoIndexChecks);
 3469       end if;
 3470       c_expr.expr &:= stringLiteral("");
 3471       c_expr.expr &:= ")";
 3472     elsif getConstant(params[3], INTOBJECT, evaluatedParam) and
 3473         getValue(evaluatedParam, integer) = 1 then
 3474       incr(countOptimizations);
 3475       process_str_head(params[1], params[5], c_expr);
 3476     elsif getConstant(params[5], INTOBJECT, evaluatedParam) and
 3477         getValue(evaluatedParam, integer) <= 1 then
 3478       length := getValue(evaluatedParam, integer);
 3479       if length = 1 then
 3480         process_str_substr1(params[1], params[3], c_expr);
 3481       elsif length = 0 then
 3482         incr(countOptimizations);
 3483         c_expr.expr &:= "/* string[m len 0] */ (";
 3484         if string_index_check then
 3485           incr(countIndexChecks);
 3486           c_expr.expr &:= "idxChk((";
 3487           process_expr(params[3], c_expr);
 3488           c_expr.expr &:= ")<1)?";
 3489           c_expr.expr &:= strRaiseError("INDEX_ERROR");
 3490           c_expr.expr &:= ":";
 3491         else
 3492           incr(countNoIndexChecks);
 3493         end if;
 3494         c_expr.expr &:= stringLiteral("");
 3495         c_expr.expr &:= ")";
 3496       else
 3497         incr(countOptimizations);
 3498         warning(DOES_RAISE, "INDEX_ERROR", c_expr);
 3499         c_expr.expr &:= strRaiseError("INDEX_ERROR");
 3500       end if;
 3501     elsif ccConf.ALLOW_STRITYPE_SLICES and c_expr.demand < REQUIRE_RESULT then
 3502       c_expr.expr &:= "(";
 3503       incr(c_expr.temp_num);
 3504       slice_name := "slice_" & str(c_expr.temp_num);
 3505       c_expr.temp_decls &:= "struct striStruct ";
 3506       c_expr.temp_decls &:= slice_name;
 3507       c_expr.temp_decls &:= ";\n";
 3508       if inlineFunctions then
 3509         process_inline_str_substr(params, slice_name, c_expr);
 3510       else
 3511         c_expr.expr &:= "strSubstrSlice(";
 3512         getAnyParamToExpr(params[1], c_expr);
 3513         c_expr.expr &:= ", ";
 3514         process_expr(params[3], c_expr);
 3515         c_expr.expr &:= ", ";
 3516         process_expr(params[5], c_expr);
 3517         c_expr.expr &:= ", &";
 3518         c_expr.expr &:= slice_name;
 3519         c_expr.expr &:= ")";
 3520       end if;
 3521       c_expr.expr &:= ", &";
 3522       c_expr.expr &:= slice_name;
 3523       c_expr.expr &:= ")";
 3524     else
 3525       prepare_stri_result(c_expr);
 3526       c_expr.result_expr := "strSubstr(";
 3527       getAnyParamToResultExpr(params[1], c_expr);
 3528       c_expr.result_expr &:= ", ";
 3529       getStdParamToResultExpr(params[3], c_expr);
 3530       c_expr.result_expr &:= ", ";
 3531       getStdParamToResultExpr(params[5], c_expr);
 3532       c_expr.result_expr &:= ")";
 3533     end if;
 3534   end func;
 3535 
 3536 
 3537 const proc: process (STR_TAIL, in reference: function,
 3538     in ref_list: params, inout expr_type: c_expr) is func
 3539 
 3540   local
 3541     var reference: evaluatedParam is NIL;
 3542     var string: slice_name is "";
 3543   begin
 3544     if getConstant(params[1], STRIOBJECT, evaluatedParam) and
 3545         getValue(evaluatedParam, string) = "" then
 3546       incr(countOptimizations);
 3547       c_expr.expr &:= "/* \"\"[n .. ] */ (";
 3548       if string_index_check then
 3549         incr(countIndexChecks);
 3550         c_expr.expr &:= "idxChk((";
 3551         process_expr(params[3], c_expr);
 3552         c_expr.expr &:= ")<1)?";
 3553         c_expr.expr &:= strRaiseError("INDEX_ERROR");
 3554         c_expr.expr &:= ":";
 3555       else
 3556         incr(countNoIndexChecks);
 3557       end if;
 3558       c_expr.expr &:= stringLiteral("");
 3559       c_expr.expr &:= ")";
 3560     elsif ccConf.ALLOW_STRITYPE_SLICES and c_expr.demand < ASSIGN_RESULT then
 3561       incr(c_expr.temp_num);
 3562       slice_name := "slice_" & str(c_expr.temp_num);
 3563       c_expr.temp_decls &:= "struct striStruct ";
 3564       c_expr.temp_decls &:= slice_name;
 3565       c_expr.temp_decls &:= ";\n";
 3566       c_expr.expr &:= "(strTailSlice(";
 3567       getAnyParamToExpr(params[1], c_expr);
 3568       c_expr.expr &:= ", ";
 3569       process_expr(params[3], c_expr);
 3570       c_expr.expr &:= ", &";
 3571       c_expr.expr &:= slice_name;
 3572       c_expr.expr &:= "), &";
 3573       c_expr.expr &:= slice_name;
 3574       c_expr.expr &:= ")";
 3575     else
 3576       prepare_stri_result(c_expr);
 3577       c_expr.result_expr := "strTail(";
 3578       getAnyParamToResultExpr(params[1], c_expr);
 3579       c_expr.result_expr &:= ", ";
 3580       getStdParamToResultExpr(params[3], c_expr);
 3581       c_expr.result_expr &:= ")";
 3582     end if;
 3583   end func;
 3584 
 3585 
 3586 const proc: process (STR_TOUTF8, in reference: function,
 3587     in ref_list: params, inout expr_type: c_expr) is func
 3588 
 3589   begin
 3590     prepare_stri_result(c_expr);
 3591     c_expr.result_expr := "strToUtf8(";
 3592     getAnyParamToResultExpr(params[1], c_expr);
 3593     c_expr.result_expr &:= ")";
 3594   end func;
 3595 
 3596 
 3597 const proc: process (STR_TRIM, in reference: function,
 3598     in ref_list: params, inout expr_type: c_expr) is func
 3599 
 3600   begin
 3601     prepare_stri_result(c_expr);
 3602     c_expr.result_expr := "strTrim(";
 3603     getAnyParamToResultExpr(params[1], c_expr);
 3604     c_expr.result_expr &:= ")";
 3605   end func;
 3606 
 3607 
 3608 (**
 3609  *  Produces code to return a string converted to upper case.
 3610  *  If the parameter is a temporary value the conversion is done
 3611  *  with strUpTemp. The strUpTemp function returns the parameter as
 3612  *  result of the conversion. That way the temporary of the parameter
 3613  *  must not be freed.
 3614  *)
 3615 const proc: process (STR_UP, in reference: function,
 3616     in ref_list: params, inout expr_type: c_expr) is func
 3617 
 3618   local
 3619     var expr_type: c_param1 is expr_type.value;
 3620   begin
 3621     prepare_stri_result(c_expr);
 3622     prepareAnyParamTemporarys(params[1], c_param1, c_expr);
 3623     if c_param1.result_expr <> "" then
 3624       c_expr.result_expr := "strUpTemp(";
 3625       c_expr.result_expr &:= c_param1.result_expr;
 3626     else
 3627       c_expr.result_expr := "strUp(";
 3628       c_expr.result_expr &:= c_param1.expr;
 3629     end if;
 3630     c_expr.result_expr &:= ")";
 3631   end func;
 3632 
 3633 
 3634 const proc: process (STR_UTF8TOSTRI, in reference: function,
 3635     in ref_list: params, inout expr_type: c_expr) is func
 3636 
 3637   begin
 3638     prepare_stri_result(c_expr);
 3639     c_expr.result_expr := "strUtf8ToStri(";
 3640     getAnyParamToResultExpr(params[1], c_expr);
 3641     c_expr.result_expr &:= ")";
 3642   end func;
 3643 
 3644 
 3645 const proc: process (STR_VALUE, in reference: function,
 3646     in ref_list: params, inout expr_type: c_expr) is func
 3647 
 3648   begin
 3649     prepare_stri_result(c_expr);
 3650     c_expr.result_expr := "strValue(";
 3651     getStdParamToResultExpr(params[1], c_expr);
 3652     c_expr.result_expr &:= ")";
 3653   end func;