OMCompiler/SimulationRuntime/c/util/ModelicaUtilities.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 "../ModelicaUtilities.h" | ||
| 29 | #include "modelica_string.h" | ||
| 30 | |||
| 31 | #include <stdio.h> | ||
| 32 | #include <stdlib.h> | ||
| 33 | #include <string.h> | ||
| 34 | #include "omc_error.h" | ||
| 35 | #include "ModelicaUtilitiesExtra.h" | ||
| 36 | #include "../gc/omc_rc.h" | ||
| 37 | |||
| 38 | 27 | void OpenModelica_Simulation_ModelicaVFormatMessage(const char*string, va_list args) { | |
| 39 | 27 | va_infoStreamPrint(OMC_LOG_STDOUT, 0, string, args); | |
| 40 | 27 | } | |
| 41 | |||
| 42 | ✗ | void OpenModelica_Simulation_ModelicaVFormatWarning(const char*string, va_list args) { | |
| 43 | ✗ | va_warningStreamPrint(OMC_LOG_STDOUT, 0, string, args); | |
| 44 | ✗ | } | |
| 45 | |||
| 46 | /* Like OpenModelica_Modelica{,V}FormatError below: a host that runs the | ||
| 47 | simulation in its own process (the Rust omc's wasm-jit target) rebinds these | ||
| 48 | to route an external function's messages into its simulation log. */ | ||
| 49 | void (*OpenModelica_ModelicaVFormatMessage)(const char*,va_list) = OpenModelica_Simulation_ModelicaVFormatMessage; | ||
| 50 | void (*OpenModelica_ModelicaVFormatWarning)(const char*,va_list) = OpenModelica_Simulation_ModelicaVFormatWarning; | ||
| 51 | |||
| 52 | 5 | void ModelicaMessage(const char* string) { | |
| 53 | 5 | ModelicaFormatMessage("%s", string); | |
| 54 | 5 | } | |
| 55 | |||
| 56 | 27 | extern void ModelicaVFormatMessage(const char*string, va_list args) { | |
| 57 | 27 | OpenModelica_ModelicaVFormatMessage(string, args); | |
| 58 | 27 | } | |
| 59 | |||
| 60 | 27 | void ModelicaFormatMessage(const char* string,...) { | |
| 61 | va_list args; | ||
| 62 | 27 | va_start(args, string); | |
| 63 | 27 | ModelicaVFormatMessage(string, args); | |
| 64 | 27 | va_end(args); | |
| 65 | 27 | } | |
| 66 | |||
| 67 | ✗ | void ModelicaWarning(const char* string) { | |
| 68 | ✗ | ModelicaFormatWarning("%s", string); | |
| 69 | ✗ | } | |
| 70 | |||
| 71 | ✗ | extern void ModelicaVFormatWarning(const char*string, va_list args) { | |
| 72 | ✗ | OpenModelica_ModelicaVFormatWarning(string, args); | |
| 73 | ✗ | } | |
| 74 | |||
| 75 | ✗ | void ModelicaFormatWarning(const char* string,...) { | |
| 76 | va_list args; | ||
| 77 | ✗ | va_start(args, string); | |
| 78 | ✗ | ModelicaVFormatWarning(string, args); | |
| 79 | ✗ | va_end(args); | |
| 80 | ✗ | } | |
| 81 | |||
| 82 | MODELICA_NORETURN void OpenModelica_Simulation_ModelicaError(const char* string) MODELICA_NORETURNATTR; | ||
| 83 | 4 | void OpenModelica_Simulation_ModelicaError(const char* string) { | |
| 84 | 4 | throwStreamPrint(NULL, "%s", string); | |
| 85 | } | ||
| 86 | |||
| 87 | MODELICA_NORETURN void OpenModelica_Simulation_ModelicaVFormatError(const char*string, va_list args) MODELICA_NORETURNATTR; | ||
| 88 | 3 | void OpenModelica_Simulation_ModelicaVFormatError(const char*string, va_list args) { | |
| 89 | 3 | va_throwStreamPrint(NULL, string, args); | |
| 90 | } | ||
| 91 | |||
| 92 | void (*OpenModelica_ModelicaError)(const char*) MODELICA_NORETURNATTR = OpenModelica_Simulation_ModelicaError; | ||
| 93 | void (*OpenModelica_ModelicaVFormatError)(const char*,va_list) MODELICA_NORETURNATTR = OpenModelica_Simulation_ModelicaVFormatError; | ||
| 94 | |||
| 95 | 4 | void ModelicaError(const char* string) { | |
| 96 | 4 | OpenModelica_ModelicaError(string); | |
| 97 | ✗ | abort(); // Silence invalid noreturn warning. This is never reached. | |
| 98 | } | ||
| 99 | |||
| 100 | ✗ | void ModelicaVFormatError(const char*string, va_list args) { | |
| 101 | ✗ | OpenModelica_ModelicaVFormatError(string,args); | |
| 102 | ✗ | abort(); // Silence invalid noreturn warning. This is never reached. | |
| 103 | } | ||
| 104 | |||
| 105 | /* omc installs its own error handlers, but a function library dlopened into it | ||
| 106 | links its own runtime and so its own copies of these. */ | ||
| 107 | 114 | void omc_set_modelica_error_handlers(void (*err)(const char*), void (*verr)(const char*,va_list)) | |
| 108 | { | ||
| 109 |
1/2✓ Branch 0 taken 114 times.
✗ Branch 1 not taken.
|
114 | if (err) { |
| 110 | 114 | OpenModelica_ModelicaError = err; | |
| 111 | } | ||
| 112 |
1/2✓ Branch 0 taken 114 times.
✗ Branch 1 not taken.
|
114 | if (verr) { |
| 113 | 114 | OpenModelica_ModelicaVFormatError = verr; | |
| 114 | } | ||
| 115 | 114 | } | |
| 116 | |||
| 117 | 3 | void ModelicaFormatError(const char* string, ...) { | |
| 118 | va_list args; | ||
| 119 | 3 | va_start(args, string); | |
| 120 | 3 | OpenModelica_ModelicaVFormatError(string,args); | |
| 121 | ✗ | va_end(args); | |
| 122 | ✗ | abort(); // Silence invalid noreturn warning. This is never reached. | |
| 123 | } | ||
| 124 | |||
| 125 | #if defined(OMC_METAMODELICA_RUNTIME) | ||
| 126 | |||
| 127 | ✗ | size_t omc_external_strings_mark(void) { return 0; } | |
| 128 | ✗ | void omc_external_strings_release(size_t mark) { (void) mark; } | |
| 129 | #define omc_external_strings_push(P) ((void) (P)) | ||
| 130 | |||
| 131 | #else | ||
| 132 | |||
| 133 | #if defined(_MSC_VER) | ||
| 134 | #define OMC_THREAD_LOCAL __declspec(thread) | ||
| 135 | #else | ||
| 136 | #define OMC_THREAD_LOCAL __thread | ||
| 137 | #endif | ||
| 138 | |||
| 139 | /* A fixed per-thread array; the heap is touched only by a call that overflows | ||
| 140 | it, and that is freed once the call drains. */ | ||
| 141 | #define OMC_EXT_STRINGS_FIXED 64 | ||
| 142 | |||
| 143 | static OMC_THREAD_LOCAL void *extStringsFixed[OMC_EXT_STRINGS_FIXED]; | ||
| 144 | static OMC_THREAD_LOCAL void **extStringsHeap = NULL; | ||
| 145 | static OMC_THREAD_LOCAL size_t extStringsUsed = 0; | ||
| 146 | static OMC_THREAD_LOCAL size_t extStringsSize = OMC_EXT_STRINGS_FIXED; | ||
| 147 | |||
| 148 | 1151 | static void omc_external_strings_push(void *p) | |
| 149 | { | ||
| 150 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1151 times.
|
1151 | if (extStringsUsed == extStringsSize) { |
| 151 | ✗ | size_t grown = 2*extStringsSize; | |
| 152 | ✗ | void **buf = (void**) realloc(extStringsHeap, grown*sizeof(void*)); | |
| 153 | ✗ | if (!buf) { | |
| 154 | ✗ | mmc_do_out_of_memory(); | |
| 155 | } | ||
| 156 | ✗ | if (!extStringsHeap) { | |
| 157 | memcpy(buf, extStringsFixed, OMC_EXT_STRINGS_FIXED*sizeof(void*)); | ||
| 158 | } | ||
| 159 | ✗ | extStringsHeap = buf; | |
| 160 | ✗ | extStringsSize = grown; | |
| 161 | } | ||
| 162 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1151 times.
|
1151 | (extStringsHeap ? extStringsHeap : extStringsFixed)[extStringsUsed++] = p; |
| 163 | 1151 | } | |
| 164 | |||
| 165 | 2785032 | size_t omc_external_strings_mark(void) | |
| 166 | { | ||
| 167 | 2785032 | return extStringsUsed; | |
| 168 | } | ||
| 169 | |||
| 170 | 2785032 | void omc_external_strings_release(size_t mark) | |
| 171 | { | ||
| 172 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2785032 times.
|
2785032 | void **buf = extStringsHeap ? extStringsHeap : extStringsFixed; |
| 173 | |||
| 174 |
2/2✓ Branch 0 taken 1151 times.
✓ Branch 1 taken 2785032 times.
|
2786183 | while (extStringsUsed > mark) { |
| 175 | 1151 | omc_rc_release_inline(buf[--extStringsUsed]); | |
| 176 | } | ||
| 177 |
2/4✓ Branch 0 taken 2785032 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2785032 times.
|
2785032 | if (extStringsUsed == 0 && extStringsHeap) { |
| 178 | ✗ | free(extStringsHeap); | |
| 179 | ✗ | extStringsHeap = NULL; | |
| 180 | ✗ | extStringsSize = OMC_EXT_STRINGS_FIXED; | |
| 181 | } | ||
| 182 | 2785032 | } | |
| 183 | |||
| 184 | #endif | ||
| 185 | |||
| 186 | 991215 | char* ModelicaAllocateString(size_t len) { | |
| 187 | 991215 | char *res = ModelicaAllocateStringWithErrorReturn(len); | |
| 188 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 991215 times.
|
991215 | if (!res) { |
| 189 | ✗ | ModelicaFormatError("%s:%d: ModelicaAllocateString failed", __FILE__, __LINE__); | |
| 190 | } | ||
| 191 | 991215 | return res; | |
| 192 | } | ||
| 193 | |||
| 194 | 991309 | char* ModelicaAllocateStringWithErrorReturn(size_t len) { | |
| 195 | 991309 | char *res = omc_alloc_interface.malloc_string(len+1); | |
| 196 |
1/2✓ Branch 0 taken 991309 times.
✗ Branch 1 not taken.
|
991309 | if (res != NULL) { |
| 197 | 991309 | res[len] = '\0'; | |
| 198 | 1151 | omc_external_strings_push(res); | |
| 199 | } | ||
| 200 | 991309 | return res; | |
| 201 | } | ||
| 202 | |||
| 203 | ✗ | char* ModelicaDuplicateString(const char *str) { | |
| 204 | ✗ | char *res = omc_alloc_interface.malloc_strdup(str); | |
| 205 | ✗ | if (!res) { | |
| 206 | ✗ | ModelicaFormatError("%s:%d: ModelicaAllocateString failed", __FILE__, __LINE__); | |
| 207 | } | ||
| 208 | ✗ | omc_external_strings_push(res); | |
| 209 | ✗ | return res; | |
| 210 | } | ||
| 211 |