1 /********************************************************************/
2 /*                                                                  */
3 /*  arr_rtl.c     Primitive actions for the array type.             */
4 /*  Copyright (C) 1989 - 2016, 2018, 2019  Thomas Mertes            */
5 /*                                                                  */
6 /*  This file is part of the Seed7 Runtime Library.                 */
7 /*                                                                  */
8 /*  The Seed7 Runtime Library is free software; you can             */
9 /*  redistribute it and/or modify it under the terms of the GNU     */
10 /*  Lesser General Public License as published by the Free Software */
11 /*  Foundation; either version 2.1 of the License, or (at your      */
12 /*  option) any later version.                                      */
13 /*                                                                  */
14 /*  The Seed7 Runtime Library is distributed in the hope that it    */
15 /*  will be useful, but WITHOUT ANY WARRANTY; without even the      */
16 /*  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR */
17 /*  PURPOSE.  See the GNU Lesser General Public License for more    */
18 /*  details.                                                        */
19 /*                                                                  */
20 /*  You should have received a copy of the GNU Lesser General       */
21 /*  Public License along with this program; if not, write to the    */
22 /*  Free Software Foundation, Inc., 51 Franklin Street,             */
23 /*  Fifth Floor, Boston, MA  02110-1301, USA.                       */
24 /*                                                                  */
25 /*  Module: Seed7 Runtime Library                                   */
26 /*  File: seed7/src/arr_rtl.c                                       */
27 /*  Changes: 1991 - 1994, 2005, 2006, 2013  Thomas Mertes           */
28 /*  Content: Primitive actions for the array type.                  */
29 /*                                                                  */
30 /*  The functions from this file should only be used in compiled    */
31 /*  Seed7 programs. The interpreter should not use functions of     */
32 /*  this file.                                                      */
33 /*                                                                  */
34 /*  The functions in this file use type declarations from the       */
35 /*  include file data_rtl.h instead of data.h. Therefore the types  */
36 /*  rtlArrayType and rtlObjectType are declared different than the  */
37 /*  types arrayType and objectType in the interpreter.              */
38 /*                                                                  */
39 /********************************************************************/
40 
41 #define LOG_FUNCTIONS 0
42 #define VERBOSE_EXCEPTIONS 0
43 
44 #include "version.h"
45 
46 #include "stdlib.h"
47 #include "stdio.h"
48 #include "string.h"
49 
50 #include "common.h"
51 #include "data_rtl.h"
52 #include "os_decls.h"
53 #include "heaputl.h"
54 #include "striutl.h"
55 #include "str_rtl.h"
56 #include "cmd_rtl.h"
57 #include "cmd_drv.h"
58 #include "rtl_err.h"
59 
60 #undef EXTERN
61 #define EXTERN
62 #include "arr_rtl.h"
63 
64 
65 #define QSORT_LIMIT 8
66 
67 
68 
69 #if ANY_LOG_ACTIVE
70 #ifdef USE_WMAIN
printArgv(const int argc,const wstriType * const argv)71 static void printArgv (const int argc, const wstriType *const argv)
72 #else
73 static void printArgv (const int argc, const cstriType *const argv)
74 #endif
75 
76   {
77     int pos;
78 
79   /* printArgv */
80     if (argv == NULL) {
81       printf("NULL");
82     } else {
83       printf("{");
84       for (pos = 0; pos <= argc; pos++) {
85         if (pos != 0) {
86           printf(", ");
87         } /* if */
88 #ifdef USE_WMAIN
89         printf("\"" FMT_S_OS "\"", argv[pos]);
90 #else
91         printf("\"%s\"", argv[pos]);
92 #endif
93       } /* for */
94       printf("}");
95     }
96   } /* printArgv */
97 #endif
98 
99 
100 
101 /**
102  *  Sort an array of 'rtlObjectType' elements with the quicksort algorithm.
103  *  In contrast to qsort() this function uses a different compare function.
104  *  The compare function of qsort() has two void pointers as parameters.
105  *  @param begin_sort Pointer to first element to be sorted.
106  *  @param end_sort Pointer to the last element to be sorted.
107  *  @param cmp_func Pointer to a compare function that gets two values as
108  *         'genericType' and compares them.
109  */
rtl_qsort_array(rtlObjectType * begin_sort,rtlObjectType * end_sort,compareType cmp_func)110 static void rtl_qsort_array (rtlObjectType *begin_sort, rtlObjectType *end_sort,
111     compareType cmp_func)
112 
113   {
114     genericType compare_elem;
115     genericType help_element;
116     rtlObjectType *middle_elem;
117     rtlObjectType *less_elem;
118     rtlObjectType *greater_elem;
119     intType cmp;
120 
121   /* rtl_qsort_array */
122     if (end_sort - begin_sort < QSORT_LIMIT) {
123       /* Use insertion sort */
124       for (middle_elem = begin_sort + 1; middle_elem <= end_sort; middle_elem++) {
125         compare_elem = middle_elem->value.genericValue;
126         less_elem = begin_sort - 1;
127         do {
128           less_elem++;
129           cmp = cmp_func(less_elem->value.genericValue, compare_elem);
130         } while (cmp < 0);
131         memmove(&less_elem[1], less_elem, (memSizeType)
132                 (middle_elem - less_elem) * sizeof(rtlObjectType));
133         less_elem->value.genericValue = compare_elem;
134       } /* for */
135     } else {
136       middle_elem = &begin_sort[((memSizeType)(end_sort - begin_sort)) >> 1];
137       compare_elem = middle_elem->value.genericValue;
138       middle_elem->value.genericValue = end_sort->value.genericValue;
139       end_sort->value.genericValue = compare_elem;
140       less_elem = begin_sort - 1;
141       greater_elem = end_sort;
142       do {
143         do {
144           less_elem++;
145           cmp = cmp_func(less_elem->value.genericValue, compare_elem);
146         } while (cmp < 0);
147         do {
148           greater_elem--;
149           cmp = cmp_func(greater_elem->value.genericValue, compare_elem);
150         } while (cmp > 0 && greater_elem != begin_sort);
151         help_element = less_elem->value.genericValue;
152         less_elem->value.genericValue = greater_elem->value.genericValue;
153         greater_elem->value.genericValue = help_element;
154       } while (greater_elem > less_elem);
155       greater_elem->value.genericValue = less_elem->value.genericValue;
156       less_elem->value.genericValue = compare_elem;
157       end_sort->value.genericValue = help_element;
158       rtl_qsort_array(begin_sort, less_elem - 1, cmp_func);
159       rtl_qsort_array(less_elem + 1, end_sort, cmp_func);
160     } /* if */
161   } /* rtl_qsort_array */
162 
163 
164 
165 /**
166  *  Get the name of the program without path and extension.
167  *  @param arg_0 Parameter argv[0] from the function main() as string.
168  *  @return the name of the program.
169  */
getProgramName(const const_striType arg_0)170 static striType getProgramName (const const_striType arg_0)
171 
172   {
173     memSizeType name_len;
174 #if defined LINKED_PROGRAM_EXTENSION || defined EXECUTABLE_FILE_EXTENSION
175     striType exeExtension;
176 #endif
177     intType lastSlashPos;
178     striType program_name;
179 
180   /* getProgramName */
181     logFunction(printf("getProgramName(\"%s\")",
182                        striAsUnquotedCStri(arg_0));
183                 fflush(stdout););
184     name_len = arg_0->size;
185 #if defined LINKED_PROGRAM_EXTENSION || defined EXECUTABLE_FILE_EXTENSION
186 #ifdef LINKED_PROGRAM_EXTENSION
187     exeExtension = CSTRI_LITERAL_TO_STRI(LINKED_PROGRAM_EXTENSION);
188 #else
189     exeExtension = CSTRI_LITERAL_TO_STRI(EXECUTABLE_FILE_EXTENSION);
190 #endif
191     if (name_len > exeExtension->size &&
192         memcmp(&arg_0->mem[arg_0->size - exeExtension->size],
193                exeExtension->mem, exeExtension->size * sizeof(strElemType)) == 0) {
194       name_len -= exeExtension->size;
195     } /* if */
196     FREE_STRI(exeExtension, exeExtension->size);
197 #endif
198     lastSlashPos = strRChPos(arg_0, (charType) '/');
199     name_len -= (memSizeType) lastSlashPos;
200     if (ALLOC_STRI_SIZE_OK(program_name, name_len)) {
201       program_name->size = name_len;
202       memcpy(program_name->mem, &arg_0->mem[lastSlashPos],
203              name_len * sizeof(strElemType));
204     } /* if */
205     logFunctionResult(printf("\"%s\"\n", striAsUnquotedCStri(program_name)););
206     return program_name;
207   } /* getProgramName */
208 
209 
210 
211 /**
212  *  Copy the arguments from argv to an array of strings.
213  *  @param argv Parameter from the function main().
214  */
copyArgv(const int argc,const os_striType * const argv)215 static rtlArrayType copyArgv (const int argc, const os_striType *const argv)
216 
217   {
218     memSizeType arg_c;
219     rtlArrayType arg_v;
220     memSizeType number;
221     errInfoType err_info = OKAY_NO_ERROR;
222     striType stri;
223 
224   /* copyArgv */
225     logFunction(printf("copyArgv(%d, ...)\n", argc););
226     if (unlikely(argc < 0)) {
227       logError(printf("copyArgv(%d, ...): Argc is negative.\n",
228                       argc););
229       raise_error(RANGE_ERROR);
230       arg_v = NULL;
231     } else {
232       arg_c = (memSizeType) (argc);
233       if (unlikely(!ALLOC_RTL_ARRAY(arg_v, arg_c))) {
234         raise_error(MEMORY_ERROR);
235       } else {
236         arg_v->min_position = 1;
237         arg_v->max_position = (intType) (arg_c);
238         for (number = 0; number < arg_c; number++) {
239           stri = os_stri_to_stri(argv[number], &err_info);
240           if (likely(stri != NULL)) {
241             arg_v->arr[number].value.striValue = stri;
242           } else {
243             while (number >= 1) {
244               number--;
245               stri = arg_v->arr[number].value.striValue;
246               FREE_STRI(stri, stri->size);
247             } /* while */
248             FREE_RTL_ARRAY(arg_v, arg_c);
249             logError(printf("copyArgv(%d, ...): "
250                             "os_stri_to_stri(\"" FMT_S_OS "\", *) failed:\n"
251                             "err_info=%d\n",
252                             argc, argv[number], err_info););
253             raise_error(err_info);
254             arg_v = NULL;
255             number = arg_c; /* leave for-loop */
256           } /* if */
257         } /* for */
258       } /* if */
259     } /* if */
260     logFunction(printf("copyArgv -->\n"););
261     return arg_v;
262   } /* copyArgv */
263 
264 
265 
266 /**
267  *  Get the Seed7 argument vector of a program.
268  *  The name of the program is not part of the Seed7 argument vector.
269  *  @param argc Parameter from the function main().
270  *  @param argv Parameter from the function main().
271  *  @param arg_0 NULL or address to which argv[0] is copied.
272  *  @param programName NULL or address to which the program name
273  *         (without path and extension) is copied.
274  *  @param exePath NULL or address to which the absolute path of the
275  *         executable is copied (symbolic links of the path are resolved).
276  *  @return an array with the argument vector.
277  */
278 #ifdef USE_WMAIN
getArgv(const int argc,const wstriType * const argv,striType * arg_0,striType * programName,striType * exePath)279 rtlArrayType getArgv (const int argc, const wstriType *const argv,
280     striType *arg_0, striType *programName, striType *exePath)
281 
282   {
283     errInfoType err_info = OKAY_NO_ERROR;
284     striType arg_0_temp;
285     rtlArrayType arg_v;
286 
287   /* getArgv */
288     logFunction(printf("getArgv(%d, ", argc);
289                 printArgv(argc, argv);
290                 printf(", %s", arg_0 != NULL ? "*" : "NULL");
291                 printf(", %s", programName != NULL ? "*" : "NULL");
292                 printf(", %s)\n", exePath != NULL ? "*" : "NULL"););
293 #if EMULATE_ROOT_CWD
294     initEmulatedCwd(&err_info);
295     if (unlikely(err_info != OKAY_NO_ERROR)) {
296       logError(printf("getArgv(%d, ...): initEmulatedCwd(*) failed:\n"
297                       "err_info=%d\n",
298                       argc, err_info););
299       raise_error(err_info);
300       arg_v = NULL;
301     } else
302 #endif
303     {
304       arg_0_temp = cp_from_os_path(argv[0], &err_info);
305       if (unlikely(arg_0_temp == NULL)) {
306         logError(printf("getArgv(%d, ...): "
307                         "cp_from_os_path(\"%ls\", *) failed:\n"
308                         "err_info=%d\n",
309                         argc, argv[0], err_info););
310       } else {
311         if (programName != NULL) {
312           *programName = getProgramName(arg_0_temp);
313           if (*programName == NULL) {
314             err_info = MEMORY_ERROR;
315           } /* if */
316         } /* if */
317         if (exePath != NULL) {
318           *exePath = getExecutablePath(arg_0_temp);
319           if (*exePath == NULL) {
320             err_info = MEMORY_ERROR;
321           } /* if */
322         } /* if */
323         if (arg_0 != NULL) {
324           *arg_0 = arg_0_temp;
325         } else {
326           FREE_STRI(arg_0_temp, arg_0_temp->size);
327         } /* if */
328       } /* if */
329       if (unlikely(err_info != OKAY_NO_ERROR)) {
330         raise_error(err_info);
331         arg_v = NULL;
332       } else {
333         arg_v = copyArgv(argc - 1, &argv[1]);
334       } /* if */
335     }
336     logFunction(printf("getArgv(%d, ", argc);
337                 printArgv(argc, argv);
338                 printf(", \"%s\"",
339                        striAsUnquotedCStri(arg_0 != NULL ? *arg_0 : NULL));
340                 printf(", \"%s\"",
341                        striAsUnquotedCStri(programName != NULL ? *programName : NULL));
342                 printf(", \"%s\") -->\n",
343                        striAsUnquotedCStri(exePath != NULL ? *exePath : NULL)));
344     return arg_v;
345   } /* getArgv */
346 
347 #elif defined OS_STRI_WCHAR
348 
349 
350 
getArgv(const int argc,const cstriType * const argv,striType * arg_0,striType * programName,striType * exePath)351 rtlArrayType getArgv (const int argc, const cstriType *const argv,
352     striType *arg_0, striType *programName, striType *exePath)
353 
354   {
355     int w_argc;
356     os_striType *w_argv;
357     errInfoType err_info = OKAY_NO_ERROR;
358     striType arg_0_temp;
359     rtlArrayType arg_v;
360 
361   /* getArgv */
362     logFunction(printf("getArgv(%d, ", argc);
363                 printArgv(argc, argv);
364                 printf(", %s", arg_0 != NULL ? "*" : "NULL");
365                 printf(", %s", programName != NULL ? "*" : "NULL");
366                 printf(", %s)\n", exePath != NULL ? "*" : "NULL"););
367 #if EMULATE_ROOT_CWD
368     initEmulatedCwd(&err_info);
369     if (unlikely(err_info != OKAY_NO_ERROR)) {
370       logError(printf("getArgv(%d, ...): initEmulatedCwd(*) failed:\n"
371                       "err_info=%d\n",
372                       argc, err_info););
373       raise_error(err_info);
374       arg_v = NULL;
375     } else
376 #endif
377     {
378       w_argv = getUtf16Argv(&w_argc);
379       if (unlikely(w_argv == NULL)) {
380         raise_error(MEMORY_ERROR);
381         arg_v = NULL;
382       } else {
383         arg_0_temp = cp_from_os_path(w_argv[0], &err_info);
384         if (unlikely(arg_0_temp == NULL)) {
385           logError(printf("getArgv(%d, ...): "
386                           "cp_from_os_path(\"" FMT_S_OS "\", *) failed:\n"
387                           "err_info=%d\n",
388                           argc, w_argv[0], err_info););
389         } else {
390           if (programName != NULL) {
391             *programName = getProgramName(arg_0_temp);
392             if (*programName == NULL) {
393               err_info = MEMORY_ERROR;
394             } /* if */
395           } /* if */
396           if (exePath != NULL) {
397             *exePath = getExecutablePath(arg_0_temp);
398             if (*exePath == NULL) {
399               err_info = MEMORY_ERROR;
400             } /* if */
401           } /* if */
402           if (arg_0 != NULL) {
403             *arg_0 = arg_0_temp;
404           } else {
405             FREE_STRI(arg_0_temp, arg_0_temp->size);
406           } /* if */
407         } /* if */
408         if (unlikely(err_info != OKAY_NO_ERROR)) {
409           raise_error(err_info);
410           arg_v = NULL;
411         } else {
412           arg_v = copyArgv(w_argc - 1, &w_argv[1]);
413         } /* if */
414         freeUtf16Argv(w_argv);
415       } /* if */
416     }
417     logFunction(printf("getArgv(%d, ", argc);
418                 printArgv(argc, argv);
419                 printf(", \"%s\"",
420                        striAsUnquotedCStri(arg_0 != NULL ? *arg_0 : NULL));
421                 printf(", \"%s\"",
422                        striAsUnquotedCStri(programName != NULL ? *programName : NULL));
423                 printf(", \"%s\") -->\n",
424                        striAsUnquotedCStri(exePath != NULL ? *exePath : NULL)));
425     return arg_v;
426   } /* getArgv */
427 
428 #else
429 
430 
431 
getArgv(const int argc,const cstriType * const argv,striType * arg_0,striType * programName,striType * exePath)432 rtlArrayType getArgv (const int argc, const cstriType *const argv,
433     striType *arg_0, striType *programName, striType *exePath)
434 
435   {
436     errInfoType err_info = OKAY_NO_ERROR;
437     striType arg_0_temp;
438     rtlArrayType arg_v;
439 
440   /* getArgv */
441     logFunction(printf("getArgv(%d, ", argc);
442                 printArgv(argc, argv);
443                 printf(", %s", arg_0 != NULL ? "*" : "NULL");
444                 printf(", %s", programName != NULL ? "*" : "NULL");
445                 printf(", %s)\n", exePath != NULL ? "*" : "NULL"););
446 #if EMULATE_ROOT_CWD
447     initEmulatedCwd(&err_info);
448     if (unlikely(err_info != OKAY_NO_ERROR)) {
449       logError(printf("getArgv(%d, ...): initEmulatedCwd(*) failed:\n"
450                       "err_info=%d\n",
451                       argc, err_info););
452       raise_error(err_info);
453       arg_v = NULL;
454     } else
455 #endif
456     {
457       arg_0_temp = cp_from_os_path(argv[0], &err_info);
458       if (unlikely(arg_0_temp == NULL)) {
459         logError(printf("getArgv(%d, ...): "
460                         "cp_from_os_path(\"%s\", *) failed:\n"
461                         "err_info=%d\n",
462                         argc, argv[0], err_info););
463       } else {
464         if (programName != NULL) {
465           *programName = getProgramName(arg_0_temp);
466           if (*programName == NULL) {
467             err_info = MEMORY_ERROR;
468           } /* if */
469         } /* if */
470         if (exePath != NULL) {
471           *exePath = getExecutablePath(arg_0_temp);
472           if (*exePath == NULL) {
473             err_info = MEMORY_ERROR;
474           } /* if */
475         } /* if */
476         if (arg_0 != NULL) {
477           *arg_0 = arg_0_temp;
478         } else {
479           FREE_STRI(arg_0_temp, arg_0_temp->size);
480         } /* if */
481       } /* if */
482       if (unlikely(err_info != OKAY_NO_ERROR)) {
483         raise_error(err_info);
484         arg_v = NULL;
485       } else {
486         arg_v = copyArgv(argc - 1, &argv[1]);
487       } /* if */
488     }
489     logFunction(printf("getArgv(%d, ", argc);
490                 printArgv(argc, argv);
491                 printf(", \"%s\"",
492                        striAsUnquotedCStri(arg_0 != NULL ? *arg_0 : NULL));
493                 printf(", \"%s\"",
494                        striAsUnquotedCStri(programName != NULL ? *programName : NULL));
495                 printf(", \"%s\") -->\n",
496                        striAsUnquotedCStri(exePath != NULL ? *exePath : NULL)));
497     return arg_v;
498   } /* getArgv */
499 
500 #endif
501 
502 
503 
504 #ifndef OS_STRI_WCHAR
505 /**
506  *  Examine all directories in the search path and look for fileName.
507  *  @return the path to the executable, or
508  *          NULL if it was not found.
509  */
examineSearchPath(const const_striType fileName)510 striType examineSearchPath (const const_striType fileName)
511 
512   {
513     rtlArrayType searchPath;
514     memSizeType searchPathSize;
515     memSizeType pos;
516     striType aPath;
517     striType result;
518 
519   /* examineSearchPath */
520     logFunction(printf("examineSearchPath\n"););
521     result = NULL;
522     searchPath = cmdGetSearchPath();
523     if (searchPath != NULL) {
524       searchPathSize = arraySize(searchPath);
525       for (pos = 0; result == NULL && pos < searchPathSize; pos++) {
526         aPath = searchPath->arr[pos].value.striValue;
527         if (aPath->size != 0 && aPath->mem[aPath->size - 1] != (charType) '/') {
528           strPush(&aPath, (charType) '/');
529         } /* if */
530         strAppend(&aPath, fileName);
531         if (cmdFileType(aPath) == FILE_REGULAR) {
532           result = aPath;
533         } else {
534           FREE_STRI(aPath, aPath->size);
535         } /* if */
536       } /* for */
537       for (; pos < searchPathSize; pos++) {
538         aPath = searchPath->arr[pos].value.striValue;
539         FREE_STRI(aPath, aPath->size);
540       } /* for */
541       FREE_RTL_ARRAY(searchPath, searchPathSize);
542     } /* if */
543     logFunction(printf("examineSearchPath --> \"%s\"\n",
544                        striAsUnquotedCStri(result)););
545     return result;
546   } /* examineSearchPath */
547 #endif
548 
549 
550 
freeRtlStriArray(rtlArrayType work_array,intType used_max_position)551 void freeRtlStriArray (rtlArrayType work_array, intType used_max_position)
552 
553   {
554     memSizeType position;
555 
556   /* freeRtlStriArray */
557     for (position = 0; position < (uintType) used_max_position; position++) {
558       FREE_STRI(work_array->arr[position].value.striValue,
559                 work_array->arr[position].value.striValue->size);
560     } /* for */
561     FREE_RTL_ARRAY(work_array, (uintType) work_array->max_position);
562   } /* freeRtlStriArray */
563 
564 
565 
566 /**
567  *  Fill an array of 'len' objects with the generic value 'element'.
568  *  This function uses loop unrolling inspired by Duff's device.
569  *  The use of indices relative to pos allows the C compiler
570  *  to do more optimizations.
571  *  @param dest Destination array with object values.
572  *  @param element Generic value to be filled into 'dest'.
573  *  @param len Specifies how often 'element' is filled into 'dest'.
574  */
memsetGeneric(register rtlObjectType * const dest,register const genericType element,memSizeType len)575 static void memsetGeneric (register rtlObjectType *const dest,
576     register const genericType element, memSizeType len)
577 
578   {
579     register memSizeType pos;
580 
581   /* memsetGeneric */
582     if (len != 0) {
583       pos = (len + 31) & ~(memSizeType) 31;
584       switch (len & 31) {
585         do {
586           case  0: dest[pos -  1].value.genericValue = element;
587           case 31: dest[pos -  2].value.genericValue = element;
588           case 30: dest[pos -  3].value.genericValue = element;
589           case 29: dest[pos -  4].value.genericValue = element;
590           case 28: dest[pos -  5].value.genericValue = element;
591           case 27: dest[pos -  6].value.genericValue = element;
592           case 26: dest[pos -  7].value.genericValue = element;
593           case 25: dest[pos -  8].value.genericValue = element;
594           case 24: dest[pos -  9].value.genericValue = element;
595           case 23: dest[pos - 10].value.genericValue = element;
596           case 22: dest[pos - 11].value.genericValue = element;
597           case 21: dest[pos - 12].value.genericValue = element;
598           case 20: dest[pos - 13].value.genericValue = element;
599           case 19: dest[pos - 14].value.genericValue = element;
600           case 18: dest[pos - 15].value.genericValue = element;
601           case 17: dest[pos - 16].value.genericValue = element;
602           case 16: dest[pos - 17].value.genericValue = element;
603           case 15: dest[pos - 18].value.genericValue = element;
604           case 14: dest[pos - 19].value.genericValue = element;
605           case 13: dest[pos - 20].value.genericValue = element;
606           case 12: dest[pos - 21].value.genericValue = element;
607           case 11: dest[pos - 22].value.genericValue = element;
608           case 10: dest[pos - 23].value.genericValue = element;
609           case  9: dest[pos - 24].value.genericValue = element;
610           case  8: dest[pos - 25].value.genericValue = element;
611           case  7: dest[pos - 26].value.genericValue = element;
612           case  6: dest[pos - 27].value.genericValue = element;
613           case  5: dest[pos - 28].value.genericValue = element;
614           case  4: dest[pos - 29].value.genericValue = element;
615           case  3: dest[pos - 30].value.genericValue = element;
616           case  2: dest[pos - 31].value.genericValue = element;
617           case  1: dest[pos - 32].value.genericValue = element;
618         } while ((pos -= 32) != 0);
619       } /* switch */
620     } /* if */
621   } /* memsetGeneric */
622 
623 
624 
625 /**
626  *  Append the array 'extension' to the array 'arr_variable'.
627  *  @exception MEMORY_ERROR Not enough memory for the concatenated
628  *             array.
629  */
arrAppend(rtlArrayType * const arr_variable,const rtlArrayType extension)630 void arrAppend (rtlArrayType *const arr_variable, const rtlArrayType extension)
631 
632   {
633     rtlArrayType arr_to;
634     memSizeType new_size;
635     memSizeType arr_to_size;
636     memSizeType extension_size;
637 
638   /* arrAppend */
639     logFunction(printf("arrAppend(arr1 (size=" FMT_U_MEM "), arr2 (size=" FMT_U_MEM "))\n",
640                        arraySize(*arr_variable), arraySize(extension)););
641     extension_size = arraySize(extension);
642     if (extension_size != 0) {
643       arr_to = *arr_variable;
644       arr_to_size = arraySize(arr_to);
645       if (unlikely(arr_to_size > MAX_RTL_ARR_LEN - extension_size ||
646                    arr_to->max_position > (intType) (MAX_MEM_INDEX - extension_size))) {
647         raise_error(MEMORY_ERROR);
648       } else {
649         new_size = arr_to_size + extension_size;
650         arr_to = REALLOC_RTL_ARRAY(arr_to, arr_to_size, new_size);
651         if (unlikely(arr_to == NULL)) {
652           raise_error(MEMORY_ERROR);
653         } else {
654           COUNT3_RTL_ARRAY(arr_to_size, new_size);
655           *arr_variable = arr_to;
656           arr_to->max_position = arrayMaxPos(arr_to->min_position, new_size);
657           memcpy(&arr_to->arr[arr_to_size], extension->arr,
658                  (size_t) (extension_size * sizeof(rtlObjectType)));
659           FREE_RTL_ARRAY(extension, extension_size);
660         } /* if */
661       } /* if */
662     } /* if */
663     logFunction(printf("arrAppend --> arr (size=" FMT_U_MEM ")\n",
664                        arraySize(*arr_variable)););
665   } /* arrAppend */
666 
667 
668 
arrArrlit2(intType start_position,rtlArrayType arr1)669 rtlArrayType arrArrlit2 (intType start_position, rtlArrayType arr1)
670 
671   {
672     memSizeType result_size;
673 
674   /* arrArrlit2 */
675     result_size = arraySize(arr1);
676     if (unlikely(start_position < MIN_MEM_INDEX ||
677                  start_position > MAX_MEM_INDEX ||
678                  (result_size != 0 &&
679                   start_position > (intType) (MAX_MEM_INDEX - result_size + 1)) ||
680                  (result_size == 0 && start_position == MIN_MEM_INDEX))) {
681       logError(printf("arrArrlit2(" FMT_D ", arr1 (size=" FMT_U_MEM ")): "
682                       "Minimum or maximum index out of range.\n",
683                       start_position, result_size););
684       raise_error(RANGE_ERROR);
685       arr1 = NULL;
686     } else {
687       arr1->min_position = start_position;
688       arr1->max_position = arrayMaxPos(start_position, result_size);
689     } /* if */
690     return arr1;
691   } /* arrArrlit2 */
692 
693 
694 
arrBaselit(const genericType element)695 rtlArrayType arrBaselit (const genericType element)
696 
697   {
698     memSizeType result_size;
699     rtlArrayType result;
700 
701   /* arrBaselit */
702     result_size = 1;
703     if (unlikely(!ALLOC_RTL_ARRAY(result, result_size))) {
704       raise_error(MEMORY_ERROR);
705     } else {
706       result->min_position = 1;
707       result->max_position = 1;
708       result->arr[0].value.genericValue = element;
709     } /* if */
710     return result;
711   } /* arrBaselit */
712 
713 
714 
arrBaselit2(intType start_position,const genericType element)715 rtlArrayType arrBaselit2 (intType start_position, const genericType element)
716 
717   {
718     memSizeType result_size;
719     rtlArrayType result;
720 
721   /* arrBaselit2 */
722     result_size = 1;
723     if (unlikely(!ALLOC_RTL_ARRAY(result, result_size))) {
724       raise_error(MEMORY_ERROR);
725     } else {
726       result->min_position = start_position;
727       result->max_position = start_position;
728       result->arr[0].value.genericValue = element;
729     } /* if */
730     return result;
731   } /* arrBaselit2 */
732 
733 
734 
735 /**
736  *  Concatenate two arrays.
737  *  @return the result of the concatenation.
738  *  @exception MEMORY_ERROR Not enough memory for the concatenated
739  *             array.
740  */
arrCat(rtlArrayType arr1,const rtlArrayType arr2)741 rtlArrayType arrCat (rtlArrayType arr1, const rtlArrayType arr2)
742 
743   {
744     memSizeType arr1_size;
745     memSizeType arr2_size;
746     memSizeType result_size;
747     rtlArrayType result;
748 
749   /* arrCat */
750     arr1_size = arraySize(arr1);
751     arr2_size = arraySize(arr2);
752     if (unlikely(arr1_size > MAX_RTL_ARR_LEN - arr2_size ||
753                  arr1->max_position > (intType) (MAX_MEM_INDEX - arr2_size))) {
754       raise_error(MEMORY_ERROR);
755       result = NULL;
756     } else {
757       result_size = arr1_size + arr2_size;
758       result = REALLOC_RTL_ARRAY(arr1, arr1_size, result_size);
759       if (unlikely(result == NULL)) {
760         raise_error(MEMORY_ERROR);
761       } else {
762         COUNT3_RTL_ARRAY(arr1_size, result_size);
763         result->max_position = arrayMaxPos(result->min_position, result_size);
764         memcpy(&result->arr[arr1_size], arr2->arr, arr2_size * sizeof(rtlObjectType));
765         FREE_RTL_ARRAY(arr2, arr2_size);
766       } /* if */
767     } /* if */
768     return result;
769   } /* arrCat */
770 
771 
772 
773 /**
774  *  Concatenate an array and an element.
775  *  @return the result of the concatenation.
776  *  @exception MEMORY_ERROR Not enough memory for the concatenated
777  *             array.
778  */
arrExtend(rtlArrayType arr1,const genericType element)779 rtlArrayType arrExtend (rtlArrayType arr1, const genericType element)
780 
781   {
782     memSizeType arr1_size;
783     memSizeType result_size;
784     rtlArrayType result;
785 
786   /* arrExtend */
787     arr1_size = arraySize(arr1);
788     if (unlikely(arr1_size > MAX_RTL_ARR_LEN - 1 ||
789                  arr1->max_position > (intType) (MAX_MEM_INDEX - 1))) {
790       raise_error(MEMORY_ERROR);
791       result = NULL;
792     } else {
793       result_size = arr1_size + 1;
794       result = REALLOC_RTL_ARRAY(arr1, arr1_size, result_size);
795       if (unlikely(result == NULL)) {
796         raise_error(MEMORY_ERROR);
797       } else {
798         COUNT3_RTL_ARRAY(arr1_size, result_size);
799         result->max_position++;
800         result->arr[arr1_size].value.genericValue = element;
801       } /* if */
802     } /* if */
803     return result;
804   } /* arrExtend */
805 
806 
807 
808 /**
809  *  Free the memory referred by 'oldArray'.
810  *  This function is used by the compiler to define array destructor
811  *  functions. It is asssumed that, before arrFree is called,
812  *  destructors have been called for all elements of 'oldArray'.
813  *  After arrFree is left 'oldArray' refers to not existing memory.
814  *  The memory where 'oldArray' is stored can be freed afterwards.
815  */
arrFree(rtlArrayType oldArray)816 void arrFree (rtlArrayType oldArray)
817 
818   {
819     memSizeType size;
820 
821   /* arrFree */
822     size = arraySize(oldArray);
823     FREE_RTL_ARRAY(oldArray, size);
824   } /* arrFree */
825 
826 
827 
828 /**
829  *  Generate an array from the concatenation of two elements.
830  *  @return the result of the concatenation.
831  *  @exception MEMORY_ERROR Not enough memory for the concatenated
832  *             array.
833  */
arrGen(const genericType element1,const genericType element2)834 rtlArrayType arrGen (const genericType element1, const genericType element2)
835 
836   {
837     memSizeType result_size;
838     rtlArrayType result;
839 
840   /* arrGen */
841     result_size = 2;
842     if (unlikely(!ALLOC_RTL_ARRAY(result, result_size))) {
843       raise_error(MEMORY_ERROR);
844     } else {
845       result->min_position = 1;
846       result->max_position = 2;
847       result->arr[0].value.genericValue = element1;
848       result->arr[1].value.genericValue = element2;
849     } /* if */
850     return result;
851   } /* arrGen */
852 
853 
854 
855 /**
856  *  Get a sub array ending at the position 'stop'.
857  *  @return the sub array ending at the stop position.
858  *  @exception INDEX_ERROR The stop position is less than pred(minIdx(arr1)).
859  *  @exception MEMORY_ERROR Not enough memory to represent the result.
860  */
arrHead(const const_rtlArrayType arr1,intType stop)861 rtlArrayType arrHead (const const_rtlArrayType arr1, intType stop)
862 
863   {
864     memSizeType arr1_size;
865     memSizeType result_size;
866     rtlArrayType result;
867 
868   /* arrHead */
869     arr1_size = arraySize(arr1);
870     if (stop >= arr1->min_position && arr1_size >= 1) {
871       if (stop > arr1->max_position) {
872         stop = arr1->max_position;
873       } /* if */
874       result_size = arraySize2(arr1->min_position, stop);
875       if (unlikely(!ALLOC_RTL_ARRAY(result, result_size))) {
876         raise_error(MEMORY_ERROR);
877       } else {
878         result->min_position = arr1->min_position;
879         result->max_position = stop;
880         memcpy(result->arr, arr1->arr,
881                (size_t) (result_size * sizeof(rtlObjectType)));
882       } /* if */
883     } else if (unlikely(stop < arr1->min_position - 1)) {
884       logError(printf("arrHead(arr1 (minIdx=" FMT_D "), " FMT_D "): "
885                       "Stop less than pred(minIdx(arr1)).\n",
886                       arr1->min_position, stop););
887       raise_error(INDEX_ERROR);
888       result = NULL;
889     } else if (unlikely(arr1->min_position == MIN_MEM_INDEX)) {
890       logError(printf("arrHead(arr1 (size=" FMT_U_MEM "), " FMT_D "): "
891                       "Cannot create empty array with minimum index.\n",
892                       arr1_size, stop););
893       raise_error(RANGE_ERROR);
894       result = NULL;
895     } else {
896       if (unlikely(!ALLOC_RTL_ARRAY(result, 0))) {
897         raise_error(MEMORY_ERROR);
898       } else {
899         result->min_position = arr1->min_position;
900         result->max_position = arr1->min_position - 1;
901       } /* if */
902     } /* if */
903     return result;
904   } /* arrHead */
905 
906 
907 
908 /**
909  *  Get a sub array ending at the position 'stop'.
910  *  ArrHeadTemp is used by the compiler if 'arr_temp' is a temporary
911  *  value that can be reused.
912  *  @return the sub array ending at the stop position.
913  *  @exception INDEX_ERROR The stop position is less than pred(minIdx(arr1)).
914  *  @exception MEMORY_ERROR Not enough memory to represent the result.
915  */
arrHeadTemp(rtlArrayType * arr_temp,intType stop)916 rtlArrayType arrHeadTemp (rtlArrayType *arr_temp, intType stop)
917 
918   {
919     rtlArrayType arr1;
920     memSizeType arr1_size;
921     memSizeType result_size;
922     rtlArrayType new_arr1;
923     rtlArrayType result;
924 
925   /* arrHeadTemp */
926     arr1 = *arr_temp;
927     arr1_size = arraySize(arr1);
928     if (stop >= arr1->min_position && arr1_size >= 1) {
929       if (stop >= arr1->max_position) {
930         result = arr1;
931         *arr_temp = NULL;
932       } else {
933         result_size = arraySize2(arr1->min_position, stop);
934         if (unlikely(!ALLOC_RTL_ARRAY(new_arr1, arr1_size - result_size))) {
935           raise_error(MEMORY_ERROR);
936           result = NULL;
937         } else {
938           new_arr1->min_position = stop + 1;
939           new_arr1->max_position = arr1->max_position;
940           memcpy(new_arr1->arr, &arr1->arr[result_size],
941                  (size_t) ((arr1_size - result_size) * sizeof(rtlObjectType)));
942           result = REALLOC_RTL_ARRAY(arr1, arr1_size, result_size);
943           if (unlikely(result == NULL)) {
944             FREE_RTL_ARRAY(new_arr1, arr1_size - result_size);
945             raise_error(MEMORY_ERROR);
946           } else {
947             COUNT3_RTL_ARRAY(arr1_size, result_size);
948             result->max_position = stop;
949             *arr_temp = new_arr1;
950           } /* if */
951         } /* if */
952       } /* if */
953     } else if (unlikely(stop < arr1->min_position - 1)) {
954       logError(printf("arrHeadTemp(arr1 (minIdx=" FMT_U_MEM "), " FMT_D "): "
955                       "Stop less than pred(minIdx(arr1)).\n",
956                       arr1->min_position, stop););
957       raise_error(INDEX_ERROR);
958       result = NULL;
959     } else if (unlikely(arr1->min_position == MIN_MEM_INDEX)) {
960       logError(printf("arrHeadTemp(arr1 (size=" FMT_U_MEM "), " FMT_D "): "
961                       "Cannot create empty array with minimum index.\n",
962                       arr1_size, stop););
963       raise_error(RANGE_ERROR);
964       result = NULL;
965     } else {
966       if (unlikely(!ALLOC_RTL_ARRAY(result, 0))) {
967         raise_error(MEMORY_ERROR);
968       } else {
969         result->min_position = arr1->min_position;
970         result->max_position = arr1->min_position - 1;
971       } /* if */
972     } /* if */
973     return result;
974   } /* arrHeadTemp */
975 
976 
977 
978 /**
979  *  Access one element from the array 'arr_temp'.
980  *  The compiler uses this function if the array is destroyed
981  *  after the indexing. To avoid problems the indexed element is
982  *  removed from the array.
983  *  @return the element with the specified 'position' from 'arr_temp'.
984  *  @exception INDEX_ERROR If 'position' is less than minIdx(arr) or
985  *                         greater than maxIdx(arr)
986  */
arrIdxTemp(rtlArrayType * arr_temp,intType position)987 genericType arrIdxTemp (rtlArrayType *arr_temp, intType position)
988 
989   {
990     rtlArrayType arr1;
991     memSizeType arr1_size;
992     rtlArrayType resized_arr1;
993     genericType result;
994 
995   /* arrIdxTemp */
996     arr1 = *arr_temp;
997     if (unlikely(position < arr1->min_position ||
998                  position > arr1->max_position)) {
999       logError(printf("arrIdxTemp(arr1, " FMT_D "): "
1000                       "Index out of range (" FMT_D " .. " FMT_D ").\n",
1001                       position, arr1->min_position, arr1->max_position););
1002       raise_error(INDEX_ERROR);
1003       result = 0;
1004     } else {
1005       arr1_size = arraySize(arr1);
1006       result = arr1->arr[position - arr1->min_position].value.genericValue;
1007       if (position != arr1->max_position) {
1008         arr1->arr[position - arr1->min_position].value.genericValue =
1009             arr1->arr[arr1_size - 1].value.genericValue;
1010       } /* if */
1011       resized_arr1 = REALLOC_RTL_ARRAY(arr1, arr1_size, arr1_size - 1);
1012       if (unlikely(resized_arr1 == NULL)) {
1013         raise_error(MEMORY_ERROR);
1014       } else {
1015         COUNT3_RTL_ARRAY(arr1_size, arr1_size - 1);
1016         resized_arr1->max_position--;
1017         *arr_temp = resized_arr1;
1018       } /* if */
1019     } /* if */
1020     return result;
1021   } /* arrIdxTemp */
1022 
1023 
1024 
1025 /**
1026  *  Insert 'element' at 'position' into 'arr_to'.
1027  *  @exception INDEX_ERROR If 'position' is less than minIdx(arr) or
1028  *                         greater than succ(maxIdx(arr))
1029  */
arrInsert(rtlArrayType * arr_to,intType position,genericType element)1030 void arrInsert (rtlArrayType *arr_to, intType position, genericType element)
1031 
1032   {
1033     rtlArrayType arr1;
1034     rtlArrayType resized_arr1;
1035     rtlObjectType *array_pointer;
1036     memSizeType arr1_size;
1037 
1038   /* arrInsert */
1039     arr1 = *arr_to;
1040     logFunction(printf("arrInsert(" FMT_U_MEM " (size=" FMT_U_MEM "), "
1041                        FMT_D ", " FMT_U "))\n",
1042                        arr1, arraySize(arr1), position, element););
1043     if (unlikely(position < arr1->min_position ||
1044                  position > arr1->max_position + 1)) {
1045       logError(printf("arrInsert(arr1, " FMT_D ", *): "
1046                       "Index out of range (" FMT_D " .. " FMT_D ").\n",
1047                       position, arr1->min_position, arr1->max_position + 1););
1048       raise_error(INDEX_ERROR);
1049     } else {
1050       arr1_size = arraySize(arr1);
1051       resized_arr1 = REALLOC_RTL_ARRAY(arr1, arr1_size, arr1_size + 1);
1052       if (unlikely(resized_arr1 == NULL)) {
1053         raise_error(MEMORY_ERROR);
1054       } else {
1055         arr1 = resized_arr1;
1056         COUNT3_RTL_ARRAY(arr1_size, arr1_size + 1);
1057         array_pointer = arr1->arr;
1058         memmove(&array_pointer[position - arr1->min_position + 1],
1059             &array_pointer[position - arr1->min_position],
1060             arraySize2(position, arr1->max_position) * sizeof(rtlObjectType));
1061         array_pointer[position - arr1->min_position].value.genericValue = element;
1062         arr1->max_position++;
1063         *arr_to = arr1;
1064       } /* if */
1065     } /* if */
1066   } /* arrInsert */
1067 
1068 
1069 
1070 /**
1071  *  Insert 'elements' at 'position' into 'arr1'.
1072  *  @exception INDEX_ERROR If 'position' is less than minIdx(arr1) or
1073  *                         greater than succ(maxIdx(arr1))
1074  */
arrInsertArray(rtlArrayType * arr_to,intType position,rtlArrayType elements)1075 void arrInsertArray (rtlArrayType *arr_to, intType position,
1076     rtlArrayType elements)
1077 
1078   {
1079     rtlArrayType arr1;
1080     rtlArrayType resized_arr1;
1081     rtlObjectType *array_pointer;
1082     memSizeType new_size;
1083     memSizeType arr1_size;
1084     memSizeType elements_size;
1085 
1086   /* arrInsertArray */
1087     logFunction(printf("arrInsertArray\n"););
1088     arr1 = *arr_to;
1089     if (unlikely(position < arr1->min_position ||
1090                  position > arr1->max_position + 1)) {
1091       logError(printf("arrInsert(arr1, " FMT_D ", *): "
1092                       "Index out of range (" FMT_D " .. " FMT_D ").\n",
1093                       position, arr1->min_position, arr1->max_position + 1););
1094       raise_error(INDEX_ERROR);
1095     } else {
1096       elements_size = arraySize(elements);
1097       if (elements_size != 0) {
1098         arr1_size = arraySize(arr1);
1099         if (unlikely(arr1_size > MAX_RTL_ARR_LEN - elements_size ||
1100                      arr1->max_position > (intType) (MAX_MEM_INDEX - elements_size))) {
1101           raise_error(MEMORY_ERROR);
1102         } else {
1103           new_size = arr1_size + elements_size;
1104           resized_arr1 = REALLOC_RTL_ARRAY(arr1, arr1_size, new_size);
1105           if (unlikely(resized_arr1 == NULL)) {
1106             raise_error(MEMORY_ERROR);
1107           } else {
1108             COUNT3_RTL_ARRAY(arr1_size, new_size);
1109             *arr_to = resized_arr1;
1110             array_pointer = resized_arr1->arr;
1111             memmove(&array_pointer[arrayIndex(resized_arr1, position) + elements_size],
1112                     &array_pointer[arrayIndex(resized_arr1, position)],
1113                     arraySize2(position, resized_arr1->max_position) * sizeof(rtlObjectType));
1114             /* It is possible that arr1 == elements holds. */
1115             /* In this case the new hole in arr1 must be   */
1116             /* considered.                                   */
1117             if (unlikely(arr1 == elements)) {
1118               memcpy(&array_pointer[arrayIndex(resized_arr1, position)],
1119                      array_pointer, arrayIndex(resized_arr1, position) * sizeof(rtlObjectType));
1120               memcpy(&array_pointer[2 * arrayIndex(resized_arr1, position)],
1121                      &array_pointer[arrayIndex(resized_arr1, position) + elements_size],
1122                      (elements_size - arrayIndex(resized_arr1, position)) * sizeof(rtlObjectType));
1123             } else {
1124               memcpy(&array_pointer[arrayIndex(resized_arr1, position)],
1125                      elements->arr, elements_size * sizeof(rtlObjectType));
1126             } /* if */
1127             resized_arr1->max_position = arrayMaxPos(resized_arr1->min_position, new_size);
1128             FREE_RTL_ARRAY(elements, elements_size);
1129           } /* if */
1130         } /* if */
1131       } /* if */
1132     } /* if */
1133     logFunction(printf("arrInsertArray -->\n"););
1134   } /* arrInsertArray */
1135 
1136 
1137 
1138 /**
1139  *  Allocate memory for an array with given min and max positions.
1140  *  The min and max positions of the created array are set.
1141  *  @return A reference to the memory suitable for the array.
1142  *  @exception MEMORY_ERROR The min or max index is not in the
1143  *             allowed range, or there is not enough memory to
1144  *             allocate the array.
1145  *  @exception RANGE_ERROR If min and max indicate that the array
1146  *             would have a negative number of elements.
1147  */
arrMalloc(intType minPosition,intType maxPosition)1148 rtlArrayType arrMalloc (intType minPosition, intType maxPosition)
1149 
1150   {
1151     memSizeType size;
1152     rtlArrayType result;
1153 
1154   /* arrMalloc */
1155     if (unlikely(minPosition < MIN_MEM_INDEX ||
1156                  maxPosition > MAX_MEM_INDEX ||
1157                  (minPosition == MIN_MEM_INDEX &&
1158                   maxPosition == MAX_MEM_INDEX))) {
1159       raise_error(MEMORY_ERROR);
1160       result = NULL;
1161     } else if (unlikely(minPosition > MIN_MEM_INDEX &&
1162                         minPosition - 1 > maxPosition)) {
1163       raise_error(RANGE_ERROR);
1164       result = NULL;
1165     } else {
1166       size = arraySize2(minPosition, maxPosition);
1167       if (unlikely(size > MAX_RTL_ARR_LEN ||
1168                    !ALLOC_RTL_ARRAY(result, (memSizeType) size))) {
1169         raise_error(MEMORY_ERROR);
1170         result = NULL;
1171       } else {
1172         result->min_position = minPosition;
1173         result->max_position = maxPosition;
1174       } /* if */
1175     } /* if */
1176     return result;
1177   } /* arrMalloc */
1178 
1179 
1180 
1181 /**
1182  *  Append the given 'element' to the array 'arr_variable'.
1183  *  @exception MEMORY_ERROR Not enough memory for the concatenated
1184  *             array.
1185  */
arrPush(rtlArrayType * const arr_variable,const genericType element)1186 void arrPush (rtlArrayType *const arr_variable, const genericType element)
1187 
1188   {
1189     rtlArrayType arr_to;
1190     memSizeType new_size;
1191     memSizeType arr_to_size;
1192 
1193   /* arrPush */
1194     arr_to = *arr_variable;
1195     arr_to_size = arraySize(arr_to);
1196     if (unlikely(arr_to_size > MAX_RTL_ARR_LEN - 1 ||
1197                  arr_to->max_position > (intType) (MAX_MEM_INDEX - 1))) {
1198       raise_error(MEMORY_ERROR);
1199     } else {
1200       new_size = arr_to_size + 1;
1201       arr_to = REALLOC_RTL_ARRAY(arr_to, arr_to_size, new_size);
1202       if (unlikely(arr_to == NULL)) {
1203         raise_error(MEMORY_ERROR);
1204       } else {
1205         COUNT3_RTL_ARRAY(arr_to_size, new_size);
1206         *arr_variable = arr_to;
1207         arr_to->max_position ++;
1208         arr_to->arr[arr_to_size].value.genericValue = element;
1209       } /* if */
1210     } /* if */
1211   } /* arrPush */
1212 
1213 
1214 
1215 /**
1216  *  Get a sub array from the position 'start' to the position 'stop'.
1217  *  @return the sub array from position 'start' to 'stop'.
1218  *  @exception INDEX_ERROR The start position is less than minIdx(arr1), or
1219  *                         the stop position is less than pred(start).
1220  *  @exception MEMORY_ERROR Not enough memory to represent the result.
1221  */
arrRange(const const_rtlArrayType arr1,intType start,intType stop)1222 rtlArrayType arrRange (const const_rtlArrayType arr1, intType start, intType stop)
1223 
1224   {
1225     memSizeType arr1_size;
1226     memSizeType result_size;
1227     memSizeType start_idx;
1228     rtlArrayType result;
1229 
1230   /* arrRange */
1231     arr1_size = arraySize(arr1);
1232     if (unlikely(start < arr1->min_position)) {
1233       raise_error(INDEX_ERROR);
1234       result = NULL;
1235     } else if (stop >= start && start <= arr1->max_position &&
1236         stop >= arr1->min_position && arr1_size >= 1) {
1237       if (stop > arr1->max_position) {
1238         stop = arr1->max_position;
1239       } /* if */
1240       result_size = arraySize2(start, stop);
1241       if (unlikely(!ALLOC_RTL_ARRAY(result, result_size))) {
1242         raise_error(MEMORY_ERROR);
1243       } else {
1244         result->min_position = arr1->min_position;
1245         result->max_position = arrayMaxPos(arr1->min_position, result_size);
1246         start_idx = arrayIndex(arr1, start);
1247         memcpy(result->arr, &arr1->arr[start_idx],
1248                (size_t) (result_size * sizeof(rtlObjectType)));
1249       } /* if */
1250     } else if (unlikely(stop < start - 1)) {
1251       raise_error(INDEX_ERROR);
1252       result = NULL;
1253     } else if (unlikely(arr1->min_position == MIN_MEM_INDEX)) {
1254       logError(printf("arrRange(arr1 (size=" FMT_U_MEM "), " FMT_D ", " FMT_D "): "
1255                       "Cannot create empty array with minimum index.\n",
1256                       arr1_size, start, stop););
1257       raise_error(RANGE_ERROR);
1258       result = NULL;
1259     } else {
1260       if (unlikely(!ALLOC_RTL_ARRAY(result, 0))) {
1261         raise_error(MEMORY_ERROR);
1262       } else {
1263         result->min_position = arr1->min_position;
1264         result->max_position = arr1->min_position - 1;
1265       } /* if */
1266     } /* if */
1267     return result;
1268   } /* arrRange */
1269 
1270 
1271 
1272 /**
1273  *  Get a sub array from the position 'start' to the position 'stop'.
1274  *  ArrRangeTemp is used by the compiler if 'arr_temp' is a temporary
1275  *  value that can be reused.
1276  *  @return the sub array from position 'start' to 'stop'.
1277  *  @exception INDEX_ERROR The start position is less than minIdx(arr1), or
1278  *                         the stop position is less than pred(start).
1279  *  @exception MEMORY_ERROR Not enough memory to represent the result.
1280  */
arrRangeTemp(rtlArrayType * arr_temp,intType start,intType stop)1281 rtlArrayType arrRangeTemp (rtlArrayType *arr_temp, intType start, intType stop)
1282 
1283   {
1284     rtlArrayType arr1;
1285     memSizeType arr1_size;
1286     memSizeType result_size;
1287     memSizeType start_idx;
1288     memSizeType stop_idx;
1289     rtlArrayType resized_arr1;
1290     rtlArrayType result;
1291 
1292   /* arrRangeTemp */
1293     arr1 = *arr_temp;
1294     arr1_size = arraySize(arr1);
1295     if (unlikely(start < arr1->min_position)) {
1296       raise_error(INDEX_ERROR);
1297       result = NULL;
1298     } else if (stop >= start && start <= arr1->max_position && arr1_size >= 1) {
1299       if (stop > arr1->max_position) {
1300         stop = arr1->max_position;
1301       } /* if */
1302       result_size = arraySize2(start, stop);
1303       if (result_size == arr1_size) {
1304         result = arr1;
1305         *arr_temp = NULL;
1306       } else {
1307         if (unlikely(!ALLOC_RTL_ARRAY(result, result_size))) {
1308           raise_error(MEMORY_ERROR);
1309         } else {
1310           result->min_position = arr1->min_position;
1311           result->max_position = arrayMaxPos(arr1->min_position, result_size);
1312           start_idx = arrayIndex(arr1, start);
1313           stop_idx = arrayIndex(arr1, stop);
1314           memcpy(result->arr, &arr1->arr[start_idx],
1315                  (size_t) (result_size * sizeof(rtlObjectType)));
1316           memmove(&arr1->arr[start_idx], &arr1->arr[stop_idx + 1],
1317                   (size_t) ((arr1_size - stop_idx - 1) * sizeof(rtlObjectType)));
1318           resized_arr1 = REALLOC_RTL_ARRAY(arr1, arr1_size, arr1_size - result_size);
1319           if (unlikely(resized_arr1 == NULL)) {
1320             memcpy(&arr1->arr[arr1_size - result_size], result->arr,
1321                    (size_t) (result_size * sizeof(rtlObjectType)));
1322             FREE_RTL_ARRAY(result, result_size);
1323             raise_error(MEMORY_ERROR);
1324             result = NULL;
1325           } else {
1326             COUNT3_RTL_ARRAY(arr1_size, arr1_size - result_size);
1327             resized_arr1->max_position = arrayMaxPos(resized_arr1->min_position,
1328                                                      arr1_size - result_size);
1329             *arr_temp = resized_arr1;
1330           } /* if */
1331         } /* if */
1332       } /* if */
1333     } else if (unlikely(stop < start - 1)) {
1334       raise_error(INDEX_ERROR);
1335       result = NULL;
1336     } else if (unlikely(arr1->min_position == MIN_MEM_INDEX)) {
1337       logError(printf("arrRangeTemp(arr1 (size=" FMT_U_MEM "), " FMT_D ", " FMT_D "): "
1338                       "Cannot create empty array with minimum index.\n",
1339                       arr1_size, start, stop););
1340       raise_error(RANGE_ERROR);
1341       result = NULL;
1342     } else {
1343       if (unlikely(!ALLOC_RTL_ARRAY(result, 0))) {
1344         raise_error(MEMORY_ERROR);
1345       } else {
1346         result->min_position = arr1->min_position;
1347         result->max_position = arr1->min_position - 1;
1348       } /* if */
1349     } /* if */
1350     return result;
1351   } /* arrRangeTemp */
1352 
1353 
1354 
1355 /**
1356  *  Reallocate memory for an array from 'oldSize' to 'newSize'.
1357  *  This function is used by the compiler if an array is copied
1358  *  and the sizes of source and destination array are different.
1359  *  @return A reference to the memory of the array with 'newSize'.
1360  *  @exception MEMORY_ERROR There is not enough memory to
1361  *             reallocate the array.
1362  */
arrRealloc(rtlArrayType arr,memSizeType oldSize,memSizeType newSize)1363 rtlArrayType arrRealloc (rtlArrayType arr, memSizeType oldSize, memSizeType newSize)
1364 
1365   {
1366     rtlArrayType resized_arr;
1367 
1368   /* arrRealloc */
1369     resized_arr = REALLOC_RTL_ARRAY(arr, oldSize, newSize);
1370     if (unlikely(resized_arr == NULL)) {
1371       if (oldSize >= newSize) {
1372         resized_arr = arr;
1373       } /* if */
1374       raise_error(MEMORY_ERROR);
1375     } else {
1376       COUNT3_RTL_ARRAY(oldSize, newSize);
1377     } /* if */
1378     return resized_arr;
1379   } /* arrRealloc */
1380 
1381 
1382 
1383 /**
1384  *  Remove the element with 'position' from 'arr_to' and return the removed element.
1385  *  @return the removed element.
1386  *  @exception INDEX_ERROR If 'position' is less than minIdx(arr) or
1387  *                         greater than maxIdx(arr)
1388  */
arrRemove(rtlArrayType * arr_to,intType position)1389 genericType arrRemove (rtlArrayType *arr_to, intType position)
1390 
1391   {
1392     rtlArrayType arr1;
1393     rtlArrayType resized_arr1;
1394     rtlObjectType *array_pointer;
1395     memSizeType arr1_size;
1396     genericType result;
1397 
1398   /* arrRemove */
1399     arr1 = *arr_to;
1400     logFunction(printf("arrRemove(" FMT_U_MEM " (size=" FMT_U_MEM "), " FMT_D "))\n",
1401                        arr1, arraySize(arr1), position););
1402     if (unlikely(position < arr1->min_position ||
1403                  position > arr1->max_position)) {
1404       logError(printf("arrRemove(arr1, " FMT_D "): "
1405                       "Index out of range (" FMT_D " .. " FMT_D ").\n",
1406                       position, arr1->min_position, arr1->max_position););
1407       raise_error(INDEX_ERROR);
1408       result = 0;
1409     } else {
1410       array_pointer = arr1->arr;
1411       result = array_pointer[position - arr1->min_position].value.genericValue;
1412       memmove(&array_pointer[position - arr1->min_position],
1413           &array_pointer[position - arr1->min_position + 1],
1414           (arraySize2(position, arr1->max_position) - 1) * sizeof(rtlObjectType));
1415       arr1_size = arraySize(arr1);
1416       resized_arr1 = REALLOC_RTL_ARRAY(arr1, arr1_size, arr1_size - 1);
1417       if (unlikely(resized_arr1 == NULL)) {
1418         /* A realloc, which shrinks memory, usually succeeds. */
1419         /* The probability that this code path is executed is */
1420         /* probably zero. The code below restores the old     */
1421         /* value of arr1.                                     */
1422         memmove(&array_pointer[position - arr1->min_position + 1],
1423             &array_pointer[position - arr1->min_position],
1424             (arraySize2(position, arr1->max_position) - 1) * sizeof(rtlObjectType));
1425         array_pointer[position - arr1->min_position].value.genericValue = result;
1426         raise_error(MEMORY_ERROR);
1427         result = 0;
1428       } else {
1429         arr1 = resized_arr1;
1430         COUNT3_RTL_ARRAY(arr1_size, arr1_size - 1);
1431         arr1->max_position--;
1432         *arr_to = arr1;
1433       } /* if */
1434     } /* if */
1435     return result;
1436   } /* arrRemove */
1437 
1438 
1439 
1440 /**
1441  *  Remove the sub-array with 'position' and 'length' from 'arr1'.
1442  *  @return the removed sub-array.
1443  *  @exception INDEX_ERROR If 'position' is less than arr_minidx(arr2) or
1444  *                         greater than arr_maxidx(arr2)
1445  */
arrRemoveArray(rtlArrayType * arr_to,intType position,intType length)1446 rtlArrayType arrRemoveArray (rtlArrayType *arr_to, intType position, intType length)
1447 
1448   {
1449     rtlArrayType arr1;
1450     rtlArrayType resized_arr1;
1451     rtlObjectType *array_pointer;
1452     memSizeType arr1_size;
1453     memSizeType result_size;
1454     rtlArrayType result;
1455 
1456   /* arrRemoveArray */
1457     arr1 = *arr_to;
1458     logFunction(printf("arrRemoveArray(" FMT_U_MEM " (size=" FMT_U_MEM "), "
1459                        FMT_D ", " FMT_D "))\n",
1460                        arr1, arraySize(arr1), position, length););
1461     if (unlikely(length < 0)) {
1462       logError(printf("arrRemoveArray(arr1, " FMT_D ", " FMT_D "): "
1463                       "Length is negative.\n", position, length););
1464       raise_error(RANGE_ERROR);
1465       result = NULL;
1466     } else if (unlikely(position < arr1->min_position ||
1467                         position > arr1->max_position)) {
1468       logError(printf("arrRemoveArray(arr1, " FMT_D "): "
1469                       "Index out of range (" FMT_D " .. " FMT_D ").\n",
1470                       position, arr1->min_position, arr1->max_position););
1471       raise_error(INDEX_ERROR);
1472       result = NULL;
1473     } else {
1474       arr1_size = arraySize(arr1);
1475       if ((uintType) length > MAX_RTL_ARR_LEN) {
1476         result_size = MAX_RTL_ARR_LEN;
1477       } else {
1478         result_size = (memSizeType) (uintType) (length);
1479       } /* if */
1480       if (result_size > arraySize2(position, arr1->max_position)) {
1481         result_size = arraySize2(position, arr1->max_position);
1482       } /* if */
1483       if (unlikely(!ALLOC_RTL_ARRAY(result, result_size))) {
1484         raise_error(MEMORY_ERROR);
1485         return NULL;
1486       } else {
1487         result->min_position = arr1->min_position;
1488         result->max_position = arrayMaxPos(arr1->min_position, result_size);
1489         array_pointer = arr1->arr;
1490         memcpy(result->arr, &array_pointer[arrayIndex(arr1, position)],
1491                result_size * sizeof(rtlObjectType));
1492         memmove(&array_pointer[arrayIndex(arr1, position)],
1493                 &array_pointer[arrayIndex(arr1, position) + result_size],
1494                 (arraySize2(position, arr1->max_position) - result_size) * sizeof(rtlObjectType));
1495         arr1_size = arraySize(arr1);
1496         resized_arr1 = REALLOC_RTL_ARRAY(arr1, arr1_size, arr1_size - result_size);
1497         if (unlikely(resized_arr1 == NULL)) {
1498           /* A realloc, which shrinks memory, usually succeeds. */
1499           /* The probability that this code path is executed is */
1500           /* probably zero. The code below restores the old     */
1501           /* value of arr1.                                     */
1502           memmove(&array_pointer[arrayIndex(arr1, position) + result_size],
1503                   &array_pointer[arrayIndex(arr1, position)],
1504                   (arraySize2(position, arr1->max_position) - result_size) * sizeof(rtlObjectType));
1505           memcpy(&array_pointer[arrayIndex(arr1, position)], result->arr,
1506                  result_size * sizeof(rtlObjectType));
1507           FREE_RTL_ARRAY(result, result_size);
1508           raise_error(MEMORY_ERROR);
1509           return NULL;
1510         } else {
1511           arr1 = resized_arr1;
1512           COUNT3_RTL_ARRAY(arr1_size, arr1_size - result_size);
1513           arr1->max_position = arrayMaxPos(arr1->min_position, arr1_size - result_size);
1514           *arr_to = arr1;
1515         } /* if */
1516       } /* if */
1517     } /* if */
1518     return result;
1519   } /* arrRemoveArray */
1520 
1521 
1522 
arrSort(rtlArrayType arr1,compareType cmp_func)1523 rtlArrayType arrSort (rtlArrayType arr1, compareType cmp_func)
1524 
1525   { /* arrSort */
1526     /* printf("arrSort(%lX, %ld, %ld)\n", arr1, arr1->min_position, arr1->max_position); */
1527     rtl_qsort_array(arr1->arr, &arr1->arr[arr1->max_position - arr1->min_position], cmp_func);
1528     return arr1;
1529   } /* arrSort */
1530 
1531 
1532 
1533 /**
1534  *  Get a sub array from the position 'start' with maximum length 'length'.
1535  *  @return the sub array from position 'start' with maximum length 'length'.
1536  *  @exception INDEX_ERROR The start position is less than minIdx(arr1), or
1537  *                         the length is negative.
1538  *  @exception MEMORY_ERROR Not enough memory to represent the result.
1539  */
arrSubarr(const const_rtlArrayType arr1,intType start,intType length)1540 rtlArrayType arrSubarr (const const_rtlArrayType arr1, intType start, intType length)
1541 
1542   {
1543     memSizeType arr1_size;
1544     memSizeType result_size;
1545     memSizeType start_idx;
1546     rtlArrayType result;
1547 
1548   /* arrSubarr */
1549     if (unlikely(start < arr1->min_position || length < 0)) {
1550       raise_error(INDEX_ERROR);
1551       result = NULL;
1552     } else {
1553       arr1_size = arraySize(arr1);
1554       if (length != 0 && start <= arr1->max_position && arr1_size >= 1) {
1555         if (length - 1 > arr1->max_position - start) {
1556           length = arr1->max_position - start + 1;
1557         } /* if */
1558         result_size = (memSizeType) (uintType) (length);
1559         if (unlikely(!ALLOC_RTL_ARRAY(result, result_size))) {
1560           raise_error(MEMORY_ERROR);
1561         } else {
1562           result->min_position = arr1->min_position;
1563           result->max_position = arrayMaxPos(arr1->min_position, result_size);
1564           start_idx = arrayIndex(arr1, start);
1565           memcpy(result->arr, &arr1->arr[start_idx],
1566                  (size_t) (result_size * sizeof(rtlObjectType)));
1567         } /* if */
1568       } else if (unlikely(arr1->min_position == MIN_MEM_INDEX)) {
1569         logError(printf("arrSubarr(arr1 (size=" FMT_U_MEM "), " FMT_D ", " FMT_D "): "
1570                         "Cannot create empty array with minimum index.\n",
1571                         arr1_size, start, length););
1572         raise_error(RANGE_ERROR);
1573         result = NULL;
1574       } else {
1575         if (unlikely(!ALLOC_RTL_ARRAY(result, 0))) {
1576           raise_error(MEMORY_ERROR);
1577         } else {
1578           result->min_position = arr1->min_position;
1579           result->max_position = arr1->min_position - 1;
1580         } /* if */
1581       } /* if */
1582     } /* if */
1583     return result;
1584   } /* arrSubarr */
1585 
1586 
1587 
1588 /**
1589  *  Get a sub array from the position 'start' with maximum length 'length'.
1590  *  ArrSubarrTemp is used by the compiler if 'arr_temp' is a temporary
1591  *  value that can be reused.
1592  *  @return the sub array from position 'start' with maximum length 'length'.
1593  *  @exception INDEX_ERROR The start position is less than minIdx(arr1), or
1594  *                         the length is negative.
1595  *  @exception MEMORY_ERROR Not enough memory to represent the result.
1596  */
arrSubarrTemp(rtlArrayType * arr_temp,intType start,intType length)1597 rtlArrayType arrSubarrTemp (rtlArrayType *arr_temp, intType start, intType length)
1598 
1599   {
1600     rtlArrayType arr1;
1601     memSizeType arr1_size;
1602     memSizeType result_size;
1603     memSizeType start_idx;
1604     memSizeType stop_idx;
1605     rtlArrayType resized_arr1;
1606     rtlArrayType result;
1607 
1608   /* arrSubarrTemp */
1609     arr1 = *arr_temp;
1610     if (unlikely(start < arr1->min_position || length < 0)) {
1611       raise_error(INDEX_ERROR);
1612       result = NULL;
1613     } else {
1614       arr1_size = arraySize(arr1);
1615       if (length >= 1 && start <= arr1->max_position && arr1_size >= 1) {
1616         if (length - 1 > arr1->max_position - start) {
1617           length = arr1->max_position - start + 1;
1618         } /* if */
1619         result_size = (memSizeType) (uintType) (length);
1620         if (result_size == arr1_size) {
1621           result = arr1;
1622           *arr_temp = NULL;
1623         } else {
1624           if (unlikely(!ALLOC_RTL_ARRAY(result, result_size))) {
1625             raise_error(MEMORY_ERROR);
1626           } else {
1627             result->min_position = arr1->min_position;
1628             result->max_position = arrayMaxPos(arr1->min_position, result_size);
1629             start_idx = arrayIndex(arr1, start);
1630             stop_idx = arrayIndex(arr1, start + length - 1);
1631             memcpy(result->arr, &arr1->arr[start_idx],
1632                    (size_t) (result_size * sizeof(rtlObjectType)));
1633             memmove(&arr1->arr[start_idx], &arr1->arr[stop_idx + 1],
1634                     (size_t) ((arr1_size - stop_idx - 1) * sizeof(rtlObjectType)));
1635             resized_arr1 = REALLOC_RTL_ARRAY(arr1, arr1_size, arr1_size - result_size);
1636             if (unlikely(resized_arr1 == NULL)) {
1637               memcpy(&arr1->arr[arr1_size - result_size], result->arr,
1638                      (size_t) (result_size * sizeof(rtlObjectType)));
1639               FREE_RTL_ARRAY(result, result_size);
1640               raise_error(MEMORY_ERROR);
1641               result = NULL;
1642             } else {
1643               COUNT3_RTL_ARRAY(arr1_size, arr1_size - result_size);
1644               resized_arr1->max_position = arrayMaxPos(resized_arr1->min_position,
1645                                                        arr1_size - result_size);
1646               *arr_temp = resized_arr1;
1647             } /* if */
1648           } /* if */
1649         } /* if */
1650       } else if (unlikely(arr1->min_position == MIN_MEM_INDEX)) {
1651         logError(printf("arrSubarrTemp(arr1 (size=" FMT_U_MEM "), " FMT_D ", " FMT_D "): "
1652                         "Cannot create empty array with minimum index.\n",
1653                         arr1_size, start, length););
1654         raise_error(RANGE_ERROR);
1655         result = NULL;
1656       } else {
1657         if (unlikely(!ALLOC_RTL_ARRAY(result, 0))) {
1658           raise_error(MEMORY_ERROR);
1659         } else {
1660           result->min_position = arr1->min_position;
1661           result->max_position = arr1->min_position - 1;
1662         } /* if */
1663       } /* if */
1664     } /* if */
1665     return result;
1666   } /* arrSubarrTemp */
1667 
1668 
1669 
1670 /**
1671  *  Get a sub array beginning at the position 'start'.
1672  *  @return the sub array beginning at the start position.
1673  *  @exception INDEX_ERROR The start position is less than minIdx(arr1).
1674  *  @exception MEMORY_ERROR Not enough memory to represent the result.
1675  */
arrTail(const const_rtlArrayType arr1,intType start)1676 rtlArrayType arrTail (const const_rtlArrayType arr1, intType start)
1677 
1678   {
1679     memSizeType arr1_size;
1680     memSizeType result_size;
1681     memSizeType start_idx;
1682     rtlArrayType result;
1683 
1684   /* arrTail */
1685     arr1_size = arraySize(arr1);
1686     if (unlikely(start < arr1->min_position)) {
1687       logError(printf("arrTail(arr1 (minIdx=" FMT_D "), " FMT_D "): "
1688                       "Start less than minIdx(arr1).\n",
1689                       arr1->min_position, start););
1690       raise_error(INDEX_ERROR);
1691       result = NULL;
1692     } else if (start <= arr1->max_position && arr1_size >= 1) {
1693       result_size = arraySize2(start, arr1->max_position);
1694       if (unlikely(!ALLOC_RTL_ARRAY(result, result_size))) {
1695         raise_error(MEMORY_ERROR);
1696       } else {
1697         result->min_position = arr1->min_position;
1698         result->max_position = arrayMaxPos(arr1->min_position, result_size);
1699         start_idx = arrayIndex(arr1, start);
1700         memcpy(result->arr, &arr1->arr[start_idx],
1701                (size_t) (result_size * sizeof(rtlObjectType)));
1702       } /* if */
1703     } else if (unlikely(arr1->min_position == MIN_MEM_INDEX)) {
1704       logError(printf("arrTail(arr1 (size=" FMT_U_MEM "), " FMT_D "): "
1705                       "Cannot create empty array with minimum index.\n",
1706                       arr1_size, start););
1707       raise_error(RANGE_ERROR);
1708       result = NULL;
1709     } else {
1710       if (unlikely(!ALLOC_RTL_ARRAY(result, 0))) {
1711         raise_error(MEMORY_ERROR);
1712       } else {
1713         result->min_position = arr1->min_position;
1714         result->max_position = arr1->min_position - 1;
1715       } /* if */
1716     } /* if */
1717     return result;
1718   } /* arrTail */
1719 
1720 
1721 
1722 /**
1723  *  Get a sub array beginning at the position 'start'.
1724  *  ArrTailTemp is used by the compiler if 'arr_temp' is a temporary
1725  *  value that can be reused.
1726  *  @return the sub array beginning at the start position.
1727  *  @exception INDEX_ERROR The start position is less than minIdx(arr1).
1728  *  @exception MEMORY_ERROR Not enough memory to represent the result.
1729  */
arrTailTemp(rtlArrayType * arr_temp,intType start)1730 rtlArrayType arrTailTemp (rtlArrayType *arr_temp, intType start)
1731 
1732   {
1733     rtlArrayType arr1;
1734     memSizeType arr1_size;
1735     memSizeType result_size;
1736     memSizeType start_idx;
1737     rtlArrayType resized_arr1;
1738     rtlArrayType result;
1739 
1740   /* arrTailTemp */
1741     arr1 = *arr_temp;
1742     arr1_size = arraySize(arr1);
1743     if (start <= arr1->min_position) {
1744       if (unlikely(start < arr1->min_position)) {
1745         logError(printf("arrTailTemp(arr1 (minIdx=" FMT_D "), " FMT_D "): "
1746                         "Start less than minIdx(arr1).\n",
1747                         arr1->min_position, start););
1748         raise_error(INDEX_ERROR);
1749         result = NULL;
1750       } else {
1751         result = arr1;
1752         *arr_temp = NULL;
1753       } /* if */
1754     } else if (start <= arr1->max_position && arr1_size >= 1) {
1755       result_size = arraySize2(start, arr1->max_position);
1756       if (unlikely(!ALLOC_RTL_ARRAY(result, result_size))) {
1757         raise_error(MEMORY_ERROR);
1758       } else {
1759         result->min_position = arr1->min_position;
1760         result->max_position = arrayMaxPos(arr1->min_position, result_size);
1761         start_idx = arrayIndex(arr1, start);
1762         memcpy(result->arr, &arr1->arr[start_idx],
1763                (size_t) (result_size * sizeof(rtlObjectType)));
1764         resized_arr1 = REALLOC_RTL_ARRAY(arr1, arr1_size, arr1_size - result_size);
1765         if (unlikely(resized_arr1 == NULL)) {
1766           FREE_RTL_ARRAY(result, result_size);
1767           raise_error(MEMORY_ERROR);
1768           result = NULL;
1769         } else {
1770           COUNT3_RTL_ARRAY(arr1_size, arr1_size - result_size);
1771           resized_arr1->max_position = start - 1;
1772           *arr_temp = resized_arr1;
1773         } /* if */
1774       } /* if */
1775     } else if (unlikely(arr1->min_position == MIN_MEM_INDEX)) {
1776       logError(printf("arrTailTemp(arr1 (size=" FMT_U_MEM "), " FMT_D "): "
1777                       "Cannot create empty array with minimum index.\n",
1778                       arr1_size, start););
1779       raise_error(RANGE_ERROR);
1780       result = NULL;
1781     } else {
1782       if (unlikely(!ALLOC_RTL_ARRAY(result, 0))) {
1783         raise_error(MEMORY_ERROR);
1784       } else {
1785         result->min_position = arr1->min_position;
1786         result->max_position = arr1->min_position - 1;
1787       } /* if */
1788     } /* if */
1789     return result;
1790   } /* arrTailTemp */
1791 
1792 
1793 
1794 /**
1795  *  Create array with given 'min' and 'max' positions and 'element'.
1796  *  The 'min' and 'max' positions of the created array are set and
1797  *  the array is filled with 'element' values.
1798  *  @return The new created array.
1799  *  @exception MEMORY_ERROR The min or max index is not in the
1800  *             allowed range, or there is not enough memory to
1801  *             allocate the array.
1802  *  @exception RANGE_ERROR If min and max indicate that the array
1803  *             would have a negative number of elements.
1804  */
arrTimes(intType minPosition,intType maxPosition,const genericType element)1805 rtlArrayType arrTimes (intType minPosition, intType maxPosition,
1806     const genericType element)
1807 
1808   {
1809     memSizeType size;
1810     rtlArrayType result;
1811 
1812   /* arrTimes */
1813     result = arrMalloc(minPosition, maxPosition);
1814     if (result != NULL) {
1815       size = arraySize2(minPosition, maxPosition);
1816       memsetGeneric(result->arr, element, size);
1817     } /* if */
1818     return result;
1819   } /* arrTimes */
1820