Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 80.0% 260 / 0 / 325
Functions: 80.0% 36 / 0 / 45
Branches: 73.5% 119 / 0 / 162

OMCompiler/SimulationRuntime/c/meta/meta_modelica_builtin.c
Line Branch Exec Source
1 /*
2 * This file belongs to the OpenModelica Run-Time System
3 *
4 * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC), c/o Linköpings
5 * universitet, Department of Computer and Information Science, SE-58183 Linköping, Sweden. All rights
6 * reserved.
7 *
8 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF THE BSD NEW LICENSE OR THE
9 * AGPL VERSION 3 LICENSE OR THE OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8. ANY
10 * USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES RECIPIENT'S
11 * ACCEPTANCE OF THE BSD NEW LICENSE OR THE OSMC PUBLIC LICENSE OR THE AGPL
12 * VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
13 *
14 * The OpenModelica software and the OSMC (Open Source Modelica Consortium) Public License
15 * (OSMC-PL) are obtained from OSMC, either from the above address, from the URLs:
16 * http://www.openmodelica.org or https://github.com/OpenModelica/ or
17 * http://www.ida.liu.se/projects/OpenModelica, and in the OpenModelica distribution. GNU
18 * AGPL version 3 is obtained from: https://www.gnu.org/licenses/licenses.html#GPL. The BSD NEW
19 * License is obtained from: http://www.opensource.org/licenses/BSD-3-Clause.
20 *
21 * This program is distributed WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY
23 * SET FORTH IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF
24 * OSMC-PL.
25 *
26 */
27
28 #include "meta_modelica_string.h"
29 #include "meta_modelica_builtin.h"
30 #include "meta_modelica.h"
31 #include <float.h>
32 #include <limits.h>
33 #include <assert.h>
34 #include <time.h>
35 #include <math.h>
36 #include <string.h>
37 #include <stdio.h>
38 #include <stdint.h>
39
40 #define GEN_META_MODELICA_BUILTIN_BOXPTR
41 #include "meta_modelica_builtin_boxptr.h"
42 #include "../util/omc_numbers.h"
43
44 19700780 metamodelica_string intString(modelica_integer i)
45 {
46 /* 64-bit integer: 1+log_10(2**63)+1 = 20 digits max */
47 char buffer[22];
48 void *res;
49
2/2
✓ Branch 0 taken 12163920 times.
✓ Branch 1 taken 7536860 times.
19700780 if (i>=0 && i<=9) /* Small integers are used so much it makes sense to cache them */
50 12163920 return mmc_strings_len1['0'+i];
51 snprintf(buffer, 22, "%" PRINT_MMC_SINT_T, i);
52 7536860 res = mmc_mk_scon(buffer);
53 MMC_CHECK_STRING(res);
54 7536860 return res;
55 }
56
57 /* String Character Conversion */
58
59 132682 modelica_integer nobox_stringCharInt(threadData_t *threadData,metamodelica_string chr)
60 {
61 unsigned char c;
62
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 132682 times.
132682 if (MMC_STRLEN(chr) != 1)
63 ✗ MMC_THROW_INTERNAL();
64 MMC_CHECK_STRING(chr);
65 132682 return (unsigned char) MMC_STRINGDATA(chr)[0];
66 }
67
68 ✗ metamodelica_string nobox_intStringChar(threadData_t *threadData,modelica_integer ix)
69 {
70 char chr[2];
71 ✗ if (ix < 1 || ix > 255)
72 ✗ MMC_THROW_INTERNAL();
73 ✗ chr[0] = (char) ix;
74 ✗ chr[1] = '\0';
75 ✗ return mmc_mk_scon(chr);
76 }
77
78 /* String Operations */
79
80 60906 modelica_integer nobox_stringInt(threadData_t *threadData,metamodelica_string s)
81 {
82 modelica_integer res;
83 60906 char *endptr,*str=MMC_STRINGDATA(s);
84 MMC_CHECK_STRING(s);
85 60906 errno = 0;
86 #if defined(_WIN64) || defined(__MINGW64__)
87 res = strtoll(str,&endptr,10);
88 #else
89 60906 res = strtol(str,&endptr,10);
90 #endif
91
3/4
✓ Branch 0 taken 60906 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11753 times.
✓ Branch 3 taken 49153 times.
60906 if (errno != 0 || str == endptr)
92 11753 MMC_THROW_INTERNAL();
93
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 49153 times.
49153 if (*endptr != '\0')
94 ✗ MMC_THROW_INTERNAL();
95 if (res > MODELICA_INT_MAX || res < MODELICA_INT_MIN)
96 MMC_THROW_INTERNAL();
97 49153 return res;
98 }
99
100 1525431 modelica_real nobox_stringReal(threadData_t *threadData,metamodelica_string s)
101 {
102 modelica_real res;
103 1525431 char *endptr,*str=MMC_STRINGDATA(s);
104 MMC_CHECK_STRING(s);
105 1525431 errno = 0;
106 1525431 res = om_strtod(str,&endptr);
107
5/8
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1525429 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1525431 times.
1525431 if ((errno != 0 && (res == 0 || res > DBL_MIN)) || str == endptr)
108 ✗ MMC_THROW_INTERNAL();
109
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1525431 times.
1525431 if (*endptr != '\0')
110 ✗ MMC_THROW_INTERNAL();
111 1525431 return res;
112 }
113
114 /******************** String HASH Functions ********************/
115 /*
116 * adrpo 2008-12-02
117 * http://www.cse.yorku.ca/~oz/hash.html
118 * hash functions which could be useful to replace System__hash:
119 */
120 /* A hash returned as a modelica_integer decides UnorderedSet/UnorderedMap
121 * bucket order, so it is accumulated fixed-width and reduced to 31 bits. */
122 #define MMC_HASH_MASK 0x7fffffff
123
124 /*** djb2 hash ***/
125 static inline uint32_t djb2_hash_continue(const unsigned char *str, uint32_t hash)
126 {
127 int c;
128
6/6
✓ Branch 0 taken 47490527 times.
✓ Branch 1 taken 40806406 times.
✓ Branch 2 taken 1490565629 times.
✓ Branch 3 taken 456180642 times.
✓ Branch 4 taken 79635776 times.
✓ Branch 5 taken 5488360 times.
2120167340 while (0 != (c = *str++)) hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
129 return hash;
130 }
131
132 static inline uint32_t djb2_hash(const unsigned char *str)
133 {
134 return djb2_hash_continue(str, 5381);
135 }
136
137 /* CodegenCFunctions bakes stringHashDjb2Mod's remainder into the generated
138 * string-switch `case` labels, so its recurrence must not change. */
139 static inline unsigned long djb2_hash_wide(const unsigned char *str)
140 {
141 unsigned long hash = 5381;
142 int c;
143
2/2
✓ Branch 0 taken 18988922 times.
✓ Branch 1 taken 2449459 times.
21438381 while (0 != (c = *str++)) hash = ((hash << 5) + hash) + c;
144 return hash;
145 }
146
147 /*** sdbm hash ***/
148 static inline uint32_t sdbm_hash(const unsigned char* str)
149 {
150 uint32_t hash = 0;
151 int c;
152 ✗ while (0 != (c = *str++)) hash = c + (hash << 6) + (hash << 16) - hash;
153 return hash;
154 }
155
156 /* adrpo: really bad hash :) */
157 ✗ modelica_integer stringHash(metamodelica_string_const s)
158 {
159 ✗ const char* str = MMC_STRINGDATA(s);
160 long res = 0, i=0;
161 ✗ while (0 != (str[i])) { res += str[i]; i++; }
162 ✗ return res;
163 }
164
165 /* adrpo: see the comment above about djb2 hash */
166 5488360 modelica_integer stringHashDjb2(metamodelica_string_const s)
167 {
168 5488360 const char* str = MMC_STRINGDATA(s);
169 5488360 return djb2_hash((const unsigned char*)str) & MMC_HASH_MASK;
170 }
171
172 /* adrpo: see the comment above about djb2 hash */
173 456180642 modelica_integer stringHashDjb2Continue(metamodelica_string_const s, modelica_integer hash)
174 {
175 456180642 const char* str = MMC_STRINGDATA(s);
176 456180642 return djb2_hash_continue((const unsigned char*)str, (uint32_t)hash) & MMC_HASH_MASK;
177 }
178
179 /* Same result as stringHashDjb2Continue(intString(i), hash), without building
180 * the string. Cannot live in MetaModelica: MMC_HASH_MASK is not a legal
181 * Integer literal where modelica_integer holds 31 bits. */
182 40806406 modelica_integer intHashDjb2Continue(modelica_integer i, modelica_integer hash)
183 {
184 unsigned char buf[24];
185 int n = sizeof(buf) - 1;
186
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 40806404 times.
40806406 mmc_uint_t v = i < 0 ? -(mmc_uint_t) i : (mmc_uint_t) i;
187
188 40806406 buf[n] = '\0';
189
2/2
✓ Branch 0 taken 6684119 times.
✓ Branch 1 taken 40806406 times.
47490525 do { buf[--n] = '0' + (unsigned char) (v % 10); v /= 10; } while (v);
190
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 40806404 times.
40806406 if (i < 0) buf[--n] = '-';
191
192 40806406 return djb2_hash_continue(buf + n, (uint32_t) hash) & MMC_HASH_MASK;
193 }
194
195 /* adrpo: see the comment above about djb2 hash */
196 2449459 modelica_integer stringHashDjb2Mod(metamodelica_string_const s, modelica_integer mod)
197 {
198 2449459 const char* str = MMC_STRINGDATA(s);
199 long res;
200
1/2
✓ Branch 0 taken 2449459 times.
✗ Branch 1 not taken.
2449459 if (mod == 0) {
201 ✗ MMC_THROW();
202 }
203 2449459 res = djb2_hash_wide((const unsigned char*)str) % (unsigned int) mod;
204 2449459 return res;
205 }
206
207 ✗ modelica_metatype boxptr_stringHashDjb2Mod(threadData_t *threadData,modelica_metatype v,modelica_metatype mod)
208 {
209 ✗ modelica_integer modunbox = mmc_unbox_integer(mod);
210 ✗ if (modunbox < 1) {
211 ✗ MMC_THROW_INTERNAL();
212 }
213 ✗ return mmc_mk_icon(stringHashDjb2Mod(v,modunbox));
214 }
215
216 /* adrpo: see the comment above about sdbm hash */
217 ✗ modelica_integer stringHashSdbm(metamodelica_string_const s)
218 {
219 ✗ const char* str = MMC_STRINGDATA(s);
220 ✗ return sdbm_hash((const unsigned char*)str) & MMC_HASH_MASK;
221 }
222
223 2003230 modelica_metatype boxptr_substring(threadData_t *threadData, metamodelica_string_const str, modelica_metatype boxstart, modelica_metatype boxstop)
224 {
225 unsigned header = 0, nwords;
226 2003230 long start = MMC_UNTAGFIXNUM(boxstart) - 1;
227 2003230 long stop = MMC_UNTAGFIXNUM(boxstop) - 1;
228 2003230 long totalLen = MMC_STRLEN(str), len = stop-start+1;
229 struct mmc_string *res;
230 char *tmp;
231 modelica_metatype p;
232 /* Bad indexes */
233
3/4
✓ Branch 0 taken 2003229 times.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 2003229 times.
2003230 if (start < 0 || start >= totalLen || stop < start || stop >= totalLen) {
234 1 MMC_THROW_INTERNAL();
235 }
236 2003229 header = MMC_STRINGHDR(len);
237 2003229 nwords = MMC_HDRSLOTS(header) + 1;
238 res = (struct mmc_string *) mmc_alloc_words_atomic(nwords);
239 2003229 res->header = header;
240 2003229 tmp = (char*) res->data;
241 2003229 memcpy(tmp, MMC_STRINGDATA(str) + start, len);
242 2003229 tmp[len] = '\0';
243 2003229 p = MMC_TAGPTR(res);
244 MMC_CHECK_STRING(p);
245 2003229 return p;
246 }
247
248 26844 metamodelica_string stringListStringChar(metamodelica_string s)
249 {
250 26844 const char *str = MMC_STRINGDATA(s);
251 26844 char chr[2] = {'\0', '\0'};
252 modelica_metatype res = NULL;
253 int i = 0;
254
255 MMC_CHECK_STRING(s);
256 res = mmc_mk_nil();
257
2/2
✓ Branch 0 taken 854842 times.
✓ Branch 1 taken 26844 times.
881686 for (i=MMC_STRLEN(s)-1; i>=0; i--) {
258 854842 chr[0] = str[i];
259 854842 res = mmc_mk_cons(mmc_mk_scon(chr), res);
260 }
261 26844 return res;
262 }
263
264 3924564 metamodelica_string stringAppendList(modelica_metatype lst)
265 {
266 /* fprintf(stderr, "stringAppendList(%s)\n", anyString(lst)); */
267 modelica_integer lstLen = 0, len = 0;
268 unsigned nbytes = 0, header = 0, nwords = 0;
269 modelica_metatype car = NULL, lstHead = NULL, lstTmp = NULL;
270 char *tmp = NULL;
271 struct mmc_string *res = NULL;
272 void *p = NULL;
273
274 lstLen = 0;
275 nbytes = 0;
276 lstHead = lst;
277 lstTmp = lst;
278
2/2
✓ Branch 0 taken 11405053 times.
✓ Branch 1 taken 3924564 times.
15329617 while (!listEmpty(lstTmp)) {
279 MMC_CHECK_STRING(MMC_CAR(lstTmp));
280 11405053 nbytes += MMC_STRLEN(MMC_CAR(lstTmp));
281 /* fprintf(stderr, "stringAppendList: Has success reading input %d: %s\n", lstLen, MMC_STRINGDATA(MMC_CAR(lst))); */
282 11405053 lstTmp = MMC_CDR(lstTmp);
283 11405053 lstLen++;
284 }
285
2/2
✓ Branch 0 taken 1664 times.
✓ Branch 1 taken 3922900 times.
3924564 if (nbytes == 0) return mmc_emptystring;
286
2/2
✓ Branch 0 taken 28339 times.
✓ Branch 1 taken 3894561 times.
3922900 if (lstLen == 1) return MMC_CAR(lstHead);
287
288 3894561 header = MMC_STRINGHDR(nbytes);
289 3894561 nwords = MMC_HDRSLOTS(header) + 1;
290 res = (struct mmc_string *) mmc_alloc_words_atomic(nwords);
291 3894561 res->header = header;
292 3894561 tmp = (char*) res->data;
293 nbytes = 0;
294 lstTmp = lstHead;
295
2/2
✓ Branch 0 taken 11375235 times.
✓ Branch 1 taken 3894561 times.
15269796 while (!listEmpty(lstTmp)) {
296 11375235 car = MMC_CAR(lstTmp);
297 11375235 len = MMC_STRLEN(car);
298 /* fprintf(stderr, "stringAppendList: %s %d %d\n", MMC_STRINGDATA(car), len, strlen(MMC_STRINGDATA(car))); */
299 /* Might be useful to check this when debugging. String literals are often done wrong :) */
300 MMC_DEBUG_ASSERT(len == strlen(MMC_STRINGDATA(car)));
301 11375235 memcpy(tmp+nbytes,MMC_STRINGDATA(car),len);
302 11375235 nbytes += len;
303 11375235 lstTmp = MMC_CDR(lstTmp);
304 }
305 3894561 tmp[nbytes] = '\0';
306 /* fprintf(stderr, "stringAppendList(%s)=>%s\n", anyString(lstHead), anyString(MMC_TAGPTR(res))); */
307 3894561 p = MMC_TAGPTR(res);
308 MMC_CHECK_STRING(p);
309 3894561 return p;
310 }
311
312 3269480 modelica_metatype stringDelimitList(modelica_metatype lst, metamodelica_string_const delimiter)
313 {
314 /* fprintf(stderr, "stringDelimitList(%s)\n", anyString(lst)); */
315 modelica_integer lstLen = 0, len = 0, lenDelimiter = 0;
316 unsigned nbytes = 0, header = 0, nwords = 0;
317 modelica_metatype car = NULL, lstHead = NULL, lstTmp = NULL;
318 char *tmp = 0, *delimiter_cstr = 0;
319 struct mmc_string *res = NULL;
320 void *p = NULL;
321
322 lstLen = 0;
323 nbytes = 0;
324 lstHead = lst;
325 lstTmp = lst;
326
2/2
✓ Branch 0 taken 3920975 times.
✓ Branch 1 taken 3269480 times.
7190455 while (!listEmpty(lstTmp)) {
327 MMC_CHECK_STRING(MMC_CAR(lstTmp));
328 3920975 nbytes += MMC_STRLEN(MMC_CAR(lstTmp));
329 /* fprintf(stderr, "stringDelimitList: Has success reading input %d: %s\n", lstLen, MMC_STRINGDATA(MMC_CAR(lst))); */
330 3920975 lstTmp = MMC_CDR(lstTmp);
331 3920975 lstLen++;
332 }
333
2/2
✓ Branch 0 taken 608061 times.
✓ Branch 1 taken 2661419 times.
3269480 if (nbytes == 0) return mmc_emptystring;
334
2/2
✓ Branch 0 taken 2098900 times.
✓ Branch 1 taken 562519 times.
2661419 if (lstLen == 1) return MMC_CAR(lstHead);
335 562519 lenDelimiter = MMC_STRLEN(delimiter);
336 562519 nbytes += (lstLen-1)*lenDelimiter;
337 562519 delimiter_cstr = MMC_STRINGDATA(delimiter);
338 MMC_DEBUG_ASSERT(lenDelimiter == strlen(delimiter_cstr));
339
340 562519 header = MMC_STRINGHDR(nbytes);
341 562519 nwords = MMC_HDRSLOTS(header) + 1;
342 res = (struct mmc_string *) mmc_alloc_words_atomic(nwords);
343 562519 res->header = header;
344 562519 tmp = (char*) res->data;
345 nbytes = 0;
346 lstTmp = lstHead;
347 { /* Unrolled first element (not delimiter in front) */
348 562519 car = MMC_CAR(lstTmp);
349 562519 len = MMC_STRLEN(car);
350 MMC_DEBUG_ASSERT(len == strlen(MMC_STRINGDATA(car)));
351 562519 memcpy(tmp+nbytes,MMC_STRINGDATA(car),len);
352 562519 nbytes += len;
353 562519 lstTmp = MMC_CDR(lstTmp);
354 }
355
2/2
✓ Branch 0 taken 1259556 times.
✓ Branch 1 taken 562519 times.
1822075 while (!listEmpty(lstTmp)) {
356 1259556 memcpy(tmp+nbytes,delimiter_cstr,lenDelimiter);
357 1259556 nbytes += lenDelimiter;
358 1259556 car = MMC_CAR(lstTmp);
359 1259556 len = MMC_STRLEN(car);
360 /* fprintf(stderr, "stringDelimitList: %s %d %d\n", MMC_STRINGDATA(car), len, strlen(MMC_STRINGDATA(car))); */
361 /* Might be useful to check this when debugging. String literals are often done wrong :) */
362 MMC_DEBUG_ASSERT(len == strlen(MMC_STRINGDATA(car)));
363 1259556 memcpy(tmp+nbytes,MMC_STRINGDATA(car),len);
364 1259556 nbytes += len;
365 1259556 lstTmp = MMC_CDR(lstTmp);
366 }
367 562519 tmp[nbytes] = '\0';
368 /* fprintf(stderr, "stringDelimitList(%s)=>%s\n", anyString(lstHead), anyString(MMC_TAGPTR(res))); */
369 562519 p = MMC_TAGPTR(res);
370 MMC_CHECK_STRING(p);
371 562519 return p;
372 }
373
374 55089 modelica_metatype boxptr_stringGetStringChar(threadData_t *threadData,metamodelica_string str, modelica_metatype iix)
375 {
376 modelica_metatype res;
377 55089 int ix = MMC_UNTAGFIXNUM(iix);
378 MMC_CHECK_STRING(str);
379
3/4
✓ Branch 0 taken 55089 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 55088 times.
55089 if (ix < 1 || ix > (long) MMC_STRLEN(str))
380 1 MMC_THROW_INTERNAL();
381 55088 return mmc_strings_len1[(size_t)MMC_STRINGDATA(str)[ix-1]];
382 }
383
384 4544114 modelica_integer nobox_stringGet(threadData_t *threadData,metamodelica_string str, modelica_integer ix)
385 {
386
2/4
✓ Branch 0 taken 4544114 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4544114 times.
4544114 if (ix < 1 || ix > (long) MMC_STRLEN(str))
387 ✗ MMC_THROW_INTERNAL();
388 4544114 return ((unsigned char*)MMC_STRINGDATA(str))[ix-1];
389 }
390
391 ✗ modelica_metatype boxptr_stringUpdateStringChar(threadData_t *threadData,metamodelica_string str, metamodelica_string c, modelica_metatype iix)
392 {
393 ✗ int ix = MMC_UNTAGFIXNUM(iix);
394 int length = 0;
395 ✗ unsigned header = MMC_GETHDR(str);
396 ✗ unsigned nwords = MMC_HDRSLOTS(header) + 1;
397 struct mmc_string *p = NULL;
398 void *res = NULL;
399
400 MMC_CHECK_STRING(str);
401 MMC_CHECK_STRING(c);
402 /* fprintf(stderr, "stringUpdateStringChar(%s,%s,%ld)\n", MMC_STRINGDATA(str),MMC_STRINGDATA(c),ix); */
403
404 ✗ if (ix < 1 || MMC_STRLEN(c) != 1)
405 ✗ MMC_THROW_INTERNAL();
406 ✗ length = MMC_STRLEN(str);
407 ✗ if (ix > length)
408 ✗ MMC_THROW_INTERNAL();
409 p = (struct mmc_string *) mmc_alloc_words_atomic(nwords);
410 ✗ p->header = header;
411 ✗ memcpy(p->data, MMC_STRINGDATA(str), length+1 /* include NULL */);
412 ✗ p->data[ix-1] = MMC_STRINGDATA(c)[0];
413 ✗ res = MMC_TAGPTR(p);
414 MMC_CHECK_STRING(res);
415 ✗ return res;
416 }
417
418 /* List Operations */
419
420 178644635 modelica_metatype listReverse(modelica_metatype lst)
421 {
422 modelica_metatype res = NULL;
423
4/4
✓ Branch 0 taken 161678224 times.
✓ Branch 1 taken 16966411 times.
✓ Branch 2 taken 79352511 times.
✓ Branch 3 taken 82325713 times.
178644635 if (MMC_NILTEST(lst) || MMC_NILTEST(MMC_CDR(lst))) {
424 // 0/1 elements are already reversed
425 return lst;
426 }
427 res = mmc_mk_nil();
428 do {
429 364571509 res = mmc_mk_cons(MMC_CAR(lst),res);
430 364571509 lst = MMC_CDR(lst);
431
2/2
✓ Branch 0 taken 285218998 times.
✓ Branch 1 taken 79352511 times.
364571509 } while (!MMC_NILTEST(lst));
432 return res;
433 }
434
435 210891021 modelica_metatype listReverseInPlace(modelica_metatype lst)
436 {
437 modelica_metatype prev = mmc_mk_nil();
438
2/2
✓ Branch 0 taken 360694360 times.
✓ Branch 1 taken 210891021 times.
571585381 while (!MMC_NILTEST(lst))
439 {
440 360694360 modelica_metatype oldcdr = MMC_CDR(lst);
441 360694360 MMC_CDR(lst) = prev;
442 prev = lst;
443 lst = oldcdr;
444 }
445 210891021 return prev;
446 }
447
448 2122079 void boxptr_listSetRest(threadData_t *threadData, modelica_metatype cellToDestroy, modelica_metatype newRest)
449 {
450
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2122079 times.
2122079 if (MMC_NILTEST(cellToDestroy)) {
451 ✗ MMC_THROW_INTERNAL();
452 }
453 2122079 MMC_CDR(cellToDestroy) = newRest;
454 2122079 }
455
456 113 void boxptr_listSetFirst(threadData_t *threadData, modelica_metatype cellToDestroy, modelica_metatype newContent)
457 {
458
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 113 times.
113 if (MMC_NILTEST(cellToDestroy)) {
459 ✗ MMC_THROW_INTERNAL();
460 }
461 113 MMC_CAR(cellToDestroy) = newContent;
462 113 }
463
464 123 modelica_metatype listAppendDestroy(modelica_metatype lstFirstDestroyed, modelica_metatype listSecondKept)
465 {
466 modelica_metatype lst = lstFirstDestroyed;
467
2/2
✓ Branch 0 taken 122 times.
✓ Branch 1 taken 1 time.
123 if (MMC_NILTEST(lstFirstDestroyed)) {
468 return listSecondKept;
469 }
470
2/2
✓ Branch 0 taken 199 times.
✓ Branch 1 taken 122 times.
321 while (!MMC_NILTEST(MMC_CDR(lst))) {
471 lst = MMC_CDR(lst);
472 }
473 /* reached the end, set the element */
474 122 MMC_CDR(lst) = listSecondKept;
475 122 return lstFirstDestroyed;
476 }
477
478 275058111 modelica_metatype listAppend(modelica_metatype l1, modelica_metatype l2)
479 {
480 int length = 0, i = 0;
481 struct mmc_cons_struct *res = NULL;
482 struct mmc_cons_struct *p = NULL;
483
2/2
✓ Branch 0 taken 122164231 times.
✓ Branch 1 taken 152893880 times.
275058111 if (MMC_NILTEST(l2)) /* If l2 is empty, simply return l1; huge performance gain for some uses of listAppend */
484 return l1;
485 122164231 length = listLength(l1);
486
2/2
✓ Branch 0 taken 17326758 times.
✓ Branch 1 taken 104837473 times.
122164231 if (length == 0) /* We need to check for empty l1 */
487 return l2;
488 17326758 res = (struct mmc_cons_struct*)mmc_alloc_words( length * 3 /*(sizeof(struct mmc_cons_struct)/sizeof(void*))*/ ); /* Do one single big alloc. It's cheaper */
489
2/2
✓ Branch 0 taken 20304485 times.
✓ Branch 1 taken 17326758 times.
37631243 for (i=0; i<length-1; i++) { /* Write all except the last element... */
490 20304485 p = res+i;
491 20304485 p->header = MMC_STRUCTHDR(2, MMC_CONS_CTOR);
492 20304485 p->data[0] = MMC_CAR(l1);
493 20304485 p->data[1] = MMC_TAGPTR(res+i+1);
494 20304485 l1 = MMC_CDR(l1);
495 }
496 /* The last element is a bit special. It points to l2. */
497 17326758 p = res+length-1;
498 17326758 p->header = MMC_STRUCTHDR(2, MMC_CONS_CTOR);
499 17326758 p->data[0] = MMC_CAR(l1);
500 17326758 p->data[1] = l2;
501 17326758 return MMC_TAGPTR(res);
502 }
503
504 224368657 modelica_integer listLength(modelica_metatype lst)
505 {
506 modelica_integer res = 0;
507
2/2
✓ Branch 0 taken 248609397 times.
✓ Branch 1 taken 224368657 times.
472978054 while (!MMC_NILTEST(lst))
508 {
509 248609397 lst = MMC_CDR(lst);
510 248609397 res++;
511 }
512 224368657 return res;
513 }
514
515 10556742 modelica_boolean listMember(modelica_metatype obj, modelica_metatype lst)
516 {
517
2/2
✓ Branch 0 taken 49548806 times.
✓ Branch 1 taken 9122208 times.
58671014 while (!MMC_NILTEST(lst))
518 {
519
2/2
✓ Branch 1 taken 48114272 times.
✓ Branch 2 taken 1434534 times.
49548806 if (valueEq(MMC_CAR(lst), obj)) {
520 return 1;
521 }
522 48114272 lst = MMC_CDR(lst);
523 }
524 return 0;
525 }
526
527 3959883 modelica_metatype boxptr_listGet(threadData_t *threadData,modelica_metatype lst, modelica_metatype ii)
528 {
529 modelica_metatype res;
530 3959883 int i = mmc_unbox_integer(ii);
531
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3959877 times.
3959883 if (i < 1)
532 6 MMC_THROW_INTERNAL();
533
2/2
✓ Branch 0 taken 38298426 times.
✓ Branch 1 taken 925 times.
38299351 while (!MMC_NILTEST(lst))
534 {
535
2/2
✓ Branch 0 taken 3958952 times.
✓ Branch 1 taken 34339474 times.
38298426 if (i == 1) {
536 3958952 return MMC_CAR(lst);
537 }
538 34339474 lst = MMC_CDR(lst);
539 34339474 i--;
540 }
541 925 MMC_THROW_INTERNAL(); /* List was not long enough */
542 }
543
544 85 modelica_metatype boxptr_listDelete(threadData_t *threadData, modelica_metatype lst, modelica_metatype iix)
545 {
546 /* TODO: If we assume the index exists we can do this in a much better way */
547 85 int ix = mmc_unbox_integer(iix);
548 modelica_metatype *tmpArr = NULL;
549 int i = 0;
550
551
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
85 if (ix <= 0) {
552 ✗ MMC_THROW_INTERNAL();
553 }
554
555 85 tmpArr = (modelica_metatype *) mmc_alloc_words(ix-1); /* We know the size of the first part of the list */
556 if (tmpArr == NULL) {
557 fprintf(stderr, "%s:%d: malloc failed", __FILE__, __LINE__);
558 EXIT(1);
559 }
560
561
2/2
✓ Branch 0 taken 973 times.
✓ Branch 1 taken 85 times.
1058 for (i=0; i<ix-1; i++) {
562
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 973 times.
973 if (listEmpty(lst)) {
563 if (tmpArr) {
564 ✗ GC_free(tmpArr);
565 }
566 ✗ MMC_THROW_INTERNAL();
567 }
568 973 tmpArr[i] = MMC_CAR(lst);
569 973 lst = MMC_CDR(lst);
570 }
571
572
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 85 times.
85 if (listEmpty(lst)) {
573 ✗ GC_free(tmpArr);
574 ✗ MMC_THROW_INTERNAL();
575 }
576 85 lst = MMC_CDR(lst);
577
578
2/2
✓ Branch 0 taken 973 times.
✓ Branch 1 taken 85 times.
1058 for (i=ix-2; i>=0; i--) {
579 973 lst = mmc_mk_cons(tmpArr[i], lst);
580 }
581 85 GC_free(tmpArr);
582
583 85 return lst;
584 }
585
586 90753794 modelica_metatype boxptr_listRest(threadData_t *threadData, modelica_metatype lst)
587 {
588
2/2
✓ Branch 0 taken 90753727 times.
✓ Branch 1 taken 67 times.
90753794 if (!MMC_NILTEST(lst)) {
589 90753727 return MMC_CDR(lst);
590 }
591 67 MMC_THROW_INTERNAL();
592 }
593
594 334877134 modelica_metatype boxptr_listHead(threadData_t *threadData, modelica_metatype lst)
595 {
596
2/2
✓ Branch 0 taken 332725904 times.
✓ Branch 1 taken 2151230 times.
334877134 if (!MMC_NILTEST(lst)) {
597 332725904 return MMC_CAR(lst);
598 }
599 2151230 MMC_THROW_INTERNAL();
600 }
601
602 /* Array Operations */
603
604
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2235093 times.
2235093 modelica_metatype arrayList(modelica_metatype arr)
605 {
606 2235093 int nelts = arrayLength(arr)-1;
607 2235093 void **vecp = MMC_STRUCTDATA(arr);
608 void *res = mmc_mk_nil();
609
2/2
✓ Branch 0 taken 1492322 times.
✓ Branch 1 taken 2235093 times.
3727415 for(; nelts >= 0; --nelts) {
610 1492322 res = mmc_mk_cons(vecp[nelts],res);
611 }
612 2235093 return res;
613 }
614
615 3238032 modelica_metatype listArray(modelica_metatype lst)
616 {
617 3238032 int nelts = listLength(lst);
618 3238032 void* arr = (struct mmc_struct*)mmc_mk_box_no_assign(nelts, MMC_ARRAY_TAG, MMC_IS_IMMEDIATE(MMC_CAR(lst)));
619 3238032 void **arrp = MMC_STRUCTDATA(arr);
620 int i = 0;
621
2/2
✓ Branch 0 taken 3880159 times.
✓ Branch 1 taken 3238032 times.
7118191 for(i=0; i<nelts; i++) {
622 3880159 arrp[i] = MMC_CAR(lst);
623 3880159 lst = MMC_CDR(lst);
624 }
625 3238032 return arr;
626 }
627
628 12790 modelica_metatype listArrayLiteral(modelica_metatype lst)
629 {
630 12790 return listArray(lst);
631 }
632
633
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1336279 times.
1336279 modelica_metatype arrayCopy(modelica_metatype arr)
634 {
635 1336279 int nelts = arrayLength(arr);
636 1336279 void* res = (struct mmc_struct*)mmc_mk_box_no_assign(nelts, MMC_ARRAY_TAG, MMC_IS_IMMEDIATE(MMC_STRUCTDATA(arr)[0]));
637 1336279 void **arrp = MMC_STRUCTDATA(arr);
638 1336279 void **resp = MMC_STRUCTDATA(res);
639 1336279 memcpy(resp, arrp, sizeof(modelica_metatype)*nelts);
640 1336279 return res;
641 }
642
643
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 158 times.
158 modelica_metatype arrayAppend(modelica_metatype arr1, modelica_metatype arr2)
644 {
645
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 158 times.
158 int nelts1 = arrayLength(arr1);
646 158 int nelts2 = arrayLength(arr2);
647 158 void* res = (struct mmc_struct*)mmc_mk_box_no_assign(nelts1 + nelts2, MMC_ARRAY_TAG, MMC_IS_IMMEDIATE(MMC_STRUCTDATA(arr1)[0]));
648 158 void **arr1p = MMC_STRUCTDATA(arr1);
649 158 void **arr2p = MMC_STRUCTDATA(arr2);
650 158 void **resp = MMC_STRUCTDATA(res);
651 int i;
652
2/2
✓ Branch 0 taken 4602 times.
✓ Branch 1 taken 158 times.
4760 for (i=0; i<nelts1; ++i) {
653 4602 resp[i] = arr1p[i];
654 }
655
2/2
✓ Branch 0 taken 14936 times.
✓ Branch 1 taken 158 times.
15094 for (i=0; i<nelts2; ++i) {
656 14936 resp[i+nelts1] = arr2p[i];
657 }
658 158 return res;
659 }
660
661 /* Misc Operations */
662 1 modelica_integer tick(void)
663 {
664 static modelica_integer curTick = 0;
665 1 return curTick++;
666 }
667
668 3 void boxptr_print(threadData_t *threadData,modelica_metatype str)
669 {
670 3 fputs(MMC_STRINGDATA(str), stdout);
671 3 }
672
673 ✗ modelica_real mmc_clock(void)
674 {
675 static double start_t;
676 static int init = 1;
677 ✗ if (init) {
678 ✗ start_t = ((double)clock())/CLOCKS_PER_SEC;
679 ✗ init = 0;
680 ✗ return 0.0;
681 }
682 ✗ return (clock()-start_t)/CLOCKS_PER_SEC;
683 }
684
685 4 void boxptr_equality(threadData_t *threadData,modelica_metatype in1, modelica_metatype in2)
686 {
687
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 3 times.
4 if (!valueEq(in1, in2)) {
688 /* fprintf(stderr, "%s != %s\n", anyString(in1), anyString(in2)); */
689 1 MMC_THROW_INTERNAL();
690 }
691 3 }
692
693 108558325 modelica_metatype nobox_getGlobalRoot(threadData_t *threadData, modelica_integer ix) {
694 void *val = 0;
695
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 108558325 times.
108558325 if (ix < 0 || ix >= MMC_GC_GLOBAL_ROOTS_SIZE) {
696 ✗ MMC_THROW_INTERNAL();
697
2/2
✓ Branch 0 taken 108287653 times.
✓ Branch 1 taken 270672 times.
108558325 } else if (ix > 8) {
698 108287653 val = mmc_GC_state->global_roots[ix];
699 } else {
700 270672 val = threadData->localRoots[ix];
701 }
702
2/2
✓ Branch 0 taken 12170 times.
✓ Branch 1 taken 108546155 times.
108558325 if (!val) {
703 12170 MMC_THROW_INTERNAL();
704 }
705 108546155 return val;
706 }
707
708 2158918 void boxptr_setGlobalRoot(threadData_t *threadData, modelica_metatype i, modelica_metatype val) {
709 2158918 int ix = mmc_unbox_integer(i);
710
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2158918 times.
2158918 if (ix < 0 || ix >= MMC_GC_GLOBAL_ROOTS_SIZE) {
711 ✗ MMC_THROW_INTERNAL();
712
2/2
✓ Branch 0 taken 2062934 times.
✓ Branch 1 taken 95984 times.
2158918 } else if (ix > 8) {
713 2062934 mmc_GC_state->global_roots[ix] = val;
714 } else {
715 95984 threadData->localRoots[ix] = val;
716 }
717 2158918 }
718
719 ✗ modelica_boolean setStackOverflowSignal(modelica_boolean inSignal)
720 {
721 /* return for now what we got */
722 ✗ return inSignal;
723 }
724
725 #if (defined(__linux__) && defined(__GLIBC__)) || defined(__APPLE_CC__) || defined(__FreeBSD__)
726 #include <execinfo.h>
727 ✗ metamodelica_string referenceDebugString(modelica_metatype fnptr)
728 {
729 void *res;
730 ✗ char **str = backtrace_symbols(&fnptr, 1);
731 ✗ if (str == 0) {
732 ✗ return mmc_mk_scon("Unknown symbol");
733 }
734 ✗ res = mmc_mk_scon(*str);
735 ✗ free(str);
736 ✗ return res;
737 }
738 #else
739 metamodelica_string referenceDebugString(modelica_metatype fnptr)
740 {
741 return mmc_mk_scon("Unknown symbol");
742 }
743 #endif
744
745 ✗ metamodelica_string referencePointerString(modelica_metatype ptr)
746 {
747 // 2 chars per byte + 3 for "0x" and null terminator.
748 char str[sizeof(void*)*2 + 3];
749 snprintf(str, sizeof(void*)*2 + 3, "%p", ptr);
750 ✗ return mmc_mk_scon(str);
751 }
752
753 const char* SourceInfo_SOURCEINFO__desc__fields[7] = {"fileName","isReadOnly","lineNumberStart","columnNumberStart","lineNumberEnd","columnNumberEnd","lastEditTime"};
754 struct record_description SourceInfo_SOURCEINFO__desc = {
755 "SourceInfo_SOURCEINFO",
756 "SourceInfo.SOURCEINFO",
757 SourceInfo_SOURCEINFO__desc__fields
758 };
759