Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 44.1% 109 / 0 / 247
Functions: -% 0 / 1 / 1
Branches: 27.5% 50 / 0 / 182

OMCompiler/Compiler/Main/Main.mo
Line Branch Exec Source
1 /*
2 * This file is part of OpenModelica.
3 *
4 * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC),
5 * c/o Linköpings universitet, Department of Computer and Information Science,
6 * SE-58183 Linköping, Sweden.
7 *
8 * All rights reserved.
9 *
10 * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR
11 * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8.
12 * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES
13 * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL
14 * VERSION 3, ACCORDING TO RECIPIENTS CHOICE.
15 *
16 * The OpenModelica software and the OSMC (Open Source Modelica Consortium)
17 * Public License (OSMC-PL) are obtained from OSMC, either from the above
18 * address, from the URLs:
19 * http://www.openmodelica.org or
20 * https://github.com/OpenModelica/ or
21 * http://www.ida.liu.se/projects/OpenModelica,
22 * and in the OpenModelica distribution.
23 *
24 * GNU AGPL version 3 is obtained from:
25 * https://www.gnu.org/licenses/licenses.html#GPL
26 *
27 * This program is distributed WITHOUT ANY WARRANTY; without
28 * even the implied warranty of MERCHANTABILITY or FITNESS
29 * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH
30 * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL.
31 *
32 * See the full OSMC Public License conditions for more details.
33 *
34 */
35
36 encapsulated package Main
37 " file: Main.mo
38 package: Main
39 description: Modelica main program
40
41
42 This is the main program in the Modelica specification.
43 It either translates a file given as a command line argument
44 or starts a server loop communicating through ZeroMQ or sockets"
45
46 protected
47 import Absyn;
48 import ProgramUtil;
49 import AbsynJLDumpTpl;
50 import AbsynUtil;
51 import Autoconf;
52 import BackendInterfaceImplementation;
53 import CevalScript;
54 import CevalScriptBackend;
55 import ClockIndexes;
56 import Config;
57 import Debug;
58 import Dump;
59 import DumpGraphviz;
60 import Error;
61 import ErrorExt;
62 import ExecStat.{execStat,execStatReset};
63 import FCore;
64 import FGraph;
65 import Flags;
66 import FlagsUtil;
67 import GCExt;
68 import Global;
69 import GlobalScript;
70 import Interactive;
71 import List;
72 import Parser;
73 import Print;
74 import Settings;
75 import Socket;
76 import StackOverflow;
77 import SymbolTable;
78 import System;
79 import Testsuite;
80 import TplMain;
81 import Util;
82 import ZeroMQ;
83
84 protected function makeDebugResult
85 input Flags.DebugFlag inFlag;
86 input String res;
87 output String res_1;
88 algorithm
89 res_1 := matchcontinue inFlag
90 local
91 String debugstr,res_with_debug,flagstr;
92 case Flags.DEBUG_FLAG(name = flagstr)
93 algorithm
94 ✗ true := Flags.isSet(inFlag);
95 ✗ debugstr := Print.getString();
96 ✗ res_with_debug := stringAppendList({res,"\n---DEBUG(",flagstr,")---\n",debugstr,"\n---/DEBUG(",flagstr,")---\n"});
97 then res_with_debug;
98 else res;
99 end matchcontinue;
100 end makeDebugResult;
101
102 protected function parseCommand
103 "Helper function to handleCommand. First tries to parse the given command as a
104 list of statements, and if that fails tries to parse it as a collection of
105 classes. Returns either GlobalScript.Statements or Absyn.Program based on
106 which parser succeeds, or neither if a parser error occured."
107 input String inCommand;
108 output Option<GlobalScript.Statements> outStatements;
109 output Option<Absyn.Program> outProgram;
110 algorithm
111 (outStatements, outProgram) := matchcontinue inCommand
112 local
113 GlobalScript.Statements stmts;
114 Absyn.Program prog;
115
116 case _
117 algorithm
118 ✗ ErrorExt.setCheckpoint("parsestring");
119 ✗ stmts := Parser.parsestringexp(inCommand, "<interactive>");
120 ✗ ErrorExt.delCheckpoint("parsestring");
121 then
122 (SOME(stmts), NONE());
123
124 case _
125 algorithm
126 ✗ ErrorExt.rollBack("parsestring");
127 ✗ prog := Parser.parsestring(inCommand, "<interactive>");
128 then
129 (NONE(), SOME(prog));
130
131 else (NONE(), NONE());
132
133 end matchcontinue;
134 end parseCommand;
135
136 public function handleCommand
137 "This function handles the commands in form of strings send to the server.
138 If the command is quit, the function returns false, otherwise it sends the
139 string to the parse function and returns true."
140 input String inCommand;
141 output Boolean outContinue;
142 output String outResult;
143 protected
144 Option<GlobalScript.Statements> stmts;
145 Option<Absyn.Program> prog;
146 algorithm
147 ✗ Print.clearBuf();
148
149 ✗ if Util.strncmp("quit()", inCommand, 6) then
150 outContinue := false;
151 outResult := "Ok\n";
152 else
153 outContinue := true;
154
155 ✗ (stmts, prog) := parseCommand(inCommand);
156 ✗ outResult := handleCommand2(stmts, prog, inCommand);
157 ✗ outResult := makeDebugResult(Flags.DUMP, outResult);
158 ✗ outResult := makeDebugResult(Flags.DUMP_GRAPHVIZ, outResult);
159 end if;
160
161 ✗ System.reportProgress(-1, 0) "PHASE_IDLE";
162 end handleCommand;
163
164 protected function handleCommand2
165 input Option<GlobalScript.Statements> inStatements;
166 input Option<Absyn.Program> inProgram;
167 input String inCommand;
168 output String outResult;
169 algorithm
170 outResult := matchcontinue(inStatements, inProgram)
171 local
172 GlobalScript.Statements stmts;
173 Absyn.Program prog, prog2, ast;
174 String result;
175 list<InteractiveTypes.Variable> vars;
176 SymbolTable table;
177
178 // Interactively evaluate an algorithm statement or expression.
179 case (SOME(stmts), NONE())
180 algorithm
181 ✗ result := Interactive.evaluate(stmts, false);
182 then result;
183
184 // Add a class or function to the interactive symbol table.
185 case (NONE(), SOME(prog))
186 algorithm
187 ✗ table := SymbolTable.get();
188 ✗ ast := table.ast;
189 ✗ vars := table.vars;
190 ✗ prog2 := Interactive.addScope(prog, vars);
191 ✗ prog2 := ProgramUtil.updateProgram(prog2, ast);
192 ✗ if Flags.isSet(Flags.DUMP) then
193 ✗ Debug.trace("\n--------------- Parsed program ---------------\n");
194 ✗ Print.printBuf(Dump.unparseStr(prog2));
195 end if;
196 ✗ if Flags.isSet(Flags.DUMP_GRAPHVIZ) then
197 ✗ DumpGraphviz.dump(prog2);
198 end if;
199 ✗ result := makeClassDefResult(prog) "Return vector of toplevel classnames.";
200 ✗ SymbolTable.setAbsyn(prog2);
201 then result;
202
203 // A parser error occured in parseCommand, display the error message. This
204 // is handled here instead of in parseCommand, since parseCommand does not
205 // return a result string.
206 case (NONE(), NONE())
207 algorithm
208 ✗ Print.printBuf("Error occurred building AST\n");
209 ✗ result := Print.getString();
210 ✗ result := stringAppend(result, "Syntax Error\n");
211 ✗ result := stringAppend(result, Error.printMessagesStr(false));
212 then result;
213
214 // A non-parser error occured, display the error message.
215 case (_, _)
216 algorithm
217 ✗ true := isSome(inStatements) or isSome(inProgram);
218 ✗ result := Error.printMessagesStr(false);
219 then result;
220
221 else
222 algorithm
223 ✗ true := isSome(inStatements) or isSome(inProgram);
224 ✗ Error.addMessage(Error.STACK_OVERFLOW, {inCommand});
225 then "";
226
227 end matchcontinue;
228 end handleCommand2;
229
230 protected function makeClassDefResult
231 "creates a list of classes of the program to be returned from evaluate"
232 input Absyn.Program p;
233 output String res;
234 algorithm
235 res := match p
236 local
237 list<Absyn.Path> names;
238 Absyn.Path scope;
239 list<Absyn.Class> cls;
240
241 case Absyn.PROGRAM(classes=cls,within_=Absyn.WITHIN(scope))
242 algorithm
243 ✗ names := list(Absyn.Path.IDENT(AbsynUtil.className(c)) for c in cls);
244 ✗ names := List.map1(names,AbsynUtil.joinPaths,scope);
245 ✗ res := "{" + stringDelimitList(list(AbsynUtil.pathString(n) for n in names),",") + "}\n";
246 then res;
247
248 case Absyn.PROGRAM(classes=cls,within_=Absyn.TOP())
249 algorithm
250 ✗ names := list(Absyn.Path.IDENT(AbsynUtil.className(c)) for c in cls);
251 ✗ res := "{" + stringDelimitList(list(AbsynUtil.pathString(n) for n in names),",") + "}\n";
252 then res;
253
254 end match;
255 end makeClassDefResult;
256
257 protected function isModelicaFile
258 "Succeeds if filename ends with .mo or .mof"
259 input String inFilename;
260 output Boolean outIsModelicaFile;
261 protected
262 list<String> lst;
263 String file_ext;
264 algorithm
265 3960 lst := System.strtok(inFilename, ".");
266
267
1/2
✓ Branch 0 taken 3960 times.
✗ Branch 1 not taken.
3960 if listEmpty(lst) then
268 outIsModelicaFile := false;
269 else
270 3960 file_ext := List.last(lst);
271
5/8
✓ Branch 0 taken 2566 times.
✓ Branch 1 taken 1394 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2566 times.
✓ Branch 5 taken 1394 times.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 1394 times.
3960 outIsModelicaFile := file_ext == "mo" or file_ext == "mof";
272 end if;
273 end isModelicaFile;
274
275 protected function isEmptyOrFirstIsModelicaFile
276 input list<String> libs;
277 algorithm
278 () := match libs
279 local
280 String f;
281 case {} then ();
282
2/2
✓ Branch 1 taken 1394 times.
✓ Branch 2 taken 1283 times.
2677 case f::_ algorithm true := isModelicaFile(f); then ();
283 end match;
284 end isEmptyOrFirstIsModelicaFile;
285
286 protected function isFlatModelicaFile
287 "Succeeds if filename ends with .mof"
288 input String filename;
289 protected
290 list<String> lst;
291 String last;
292 algorithm
293 ✗ lst := System.strtok(filename, ".");
294 ✗ last :: _ := listReverse(lst);
295 ✗ true := stringEq(last, "mof");
296 end isFlatModelicaFile;
297
298 protected function isModelicaScriptFile
299 "Succeeds if filname end with .mos"
300 input String filename;
301 protected
302 list<String> lst;
303 String last;
304 algorithm
305
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1706 times.
1706 true := System.regularFileExists(filename);
306 1706 lst := System.strtok(filename, ".");
307
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1706 times.
1706 last :: _ := listReverse(lst);
308
3/4
✓ Branch 0 taken 1394 times.
✓ Branch 1 taken 312 times.
✓ Branch 3 taken 1394 times.
✗ Branch 4 not taken.
1706 true := stringEq(last, "mos");
309 end isModelicaScriptFile;
310
311 protected function isCodegenTemplateFile
312 "Succeeds if filname end with .tpl"
313 input String filename;
314 protected
315 list<String> lst;
316 String last;
317 algorithm
318 318 lst := System.strtok(filename, ".");
319
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 318 times.
318 last :: _ := listReverse(lst);
320
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 312 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
318 true := stringEq(last, "tpl");
321 end isCodegenTemplateFile;
322
323 protected function showErrors
324 input String errorString;
325 input String errorMessages;
326 algorithm
327
3/4
✓ Branch 0 taken 2666 times.
✓ Branch 1 taken 18 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2666 times.
2684 if errorString <> "" then
328 18 System.fflush();
329 18 System.fputs(errorString, System.StreamType.STDERR);
330 18 System.fputs("\n", System.StreamType.STDERR);
331 18 System.fflush();
332 end if;
333
334
3/4
✓ Branch 0 taken 2330 times.
✓ Branch 1 taken 354 times.
✓ Branch 3 taken 2330 times.
✗ Branch 4 not taken.
2684 if errorMessages <> "" then
335 354 System.fflush();
336 354 System.fputs(errorMessages, System.StreamType.STDERR);
337 354 System.fputs("\n", System.StreamType.STDERR);
338 354 System.fflush();
339 end if;
340 end showErrors;
341
342 protected function loadLib
343 input String inLib;
344 protected
345 Boolean is_modelica_file;
346 algorithm
347 1283 is_modelica_file := isModelicaFile(inLib);
348 () := matchcontinue is_modelica_file
349 local
350 String mp;
351 Absyn.Program pnew, p;
352 Absyn.Path path;
353
354 // A .mo-file.
355 case true
356 algorithm
357 1283 p := SymbolTable.getAbsyn();
358 1283 pnew := CevalScript.loadFile(inLib, "UTF-8", p, true, true, false);
359 1265 SymbolTable.setAbsyn(pnew);
360 then ();
361
362 // some libs present
363 case false
364 algorithm
365 ✗ path := AbsynUtil.stringPath(inLib);
366 ✗ mp := Settings.getModelicaPath(Testsuite.isRunning());
367 ✗ p := SymbolTable.getAbsyn();
368 ✗ (pnew, true) := CevalScript.loadModel({(path, "command-line argument", {"default"}, false)}, mp, p, true, true, true, false);
369 ✗ SymbolTable.setAbsyn(pnew);
370 then ();
371
372 // problem with the libs, ignore!
373 case false
374 algorithm
375 ✗ Print.printErrorBuf("Failed to load library: " + inLib + "!\n");
376 ✗ then
377 fail();
378
379 case true
380 algorithm
381 18 Print.printErrorBuf("Failed to parse file: " + inLib + "!\n");
382 18 then
383 fail();
384
385 end matchcontinue;
386 end loadLib;
387
388 protected function translateFile
389 "This function invokes the translator on a source file. The argument should be
390 a list with a single file name, with the rest of the list being an optional
391 list of libraries and .mo-files if the file is a .mo-file"
392 input list<String> inStringLst;
393 protected
394 String f;
395 list<String> libs;
396 Absyn.Path cname;
397 Boolean runBackend, runSilent;
398 GlobalScript.Statements stmts;
399 String cls, fileNamePrefix, fmuVersion, fmuType, fmuPlatformsStr;
400 Integer fmuVersionInt;
401 list<String> fmuPlatforms, fmuTypeList;
402 algorithm
403 // Execute the given script if --cmd is used.
404
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 2676 times.
2677 if not stringEmpty(Flags.getConfigString(Flags.EXECUTE_COMMAND)) then
405 1 stmts := Parser.parsestringexp(Flags.getConfigString(Flags.EXECUTE_COMMAND));
406 1 showErrors(Print.getErrorString(), ErrorExt.printMessagesStr(false));
407 1 Interactive.evaluateToStdOut(stmts, true);
408
409 // Return if there's nothing more to do to avoid showing the help message.
410
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
1 if listEmpty(inStringLst) and stringEmpty(Config.classToInstantiate()) then
411 ✗ return;
412 end if;
413 end if;
414
415 () := matchcontinue inStringLst
416 // A .mo-file, followed by an optional list of extra .mo-files and libraries.
417 // The last class in the first file will be instantiated.
418 case libs
419 algorithm
420 //print("Class to instantiate: " + Config.classToInstantiate() + "\n");
421 2677 isEmptyOrFirstIsModelicaFile(libs);
422 1283 execStatReset();
423 // Parse libraries and extra mo-files that might have been given at the command line.
424
2/2
✓ Branch 0 taken 1283 times.
✓ Branch 1 taken 1265 times.
2548 for lib in libs loop
425 1283 loadLib(lib);
426 end for;
427
428
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1265 times.
1265 if Flags.isSet(Flags.DUMP) then
429 ✗ Debug.trace("\n--------------- Parsed program ---------------\n");
430 ✗ Dump.unparseStr(SymbolTable.getAbsyn());
431 ✗ print(Print.getString());
432 end if;
433
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1265 times.
1265 if Flags.isSet(Flags.DUMP_JL) then
434 ✗ Debug.trace("\n--------------- Julia representation of the parsed program ---------------\n");
435 ✗ print(Tpl.tplString(AbsynJLDumpTpl.dump, SymbolTable.getAbsyn()) + "\n");
436 end if;
437
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1265 times.
1265 if Flags.isSet(Flags.DUMP_GRAPHVIZ) then
438 ✗ DumpGraphviz.dump(SymbolTable.getAbsyn());
439 end if;
440
441 1265 execStat("Parsed file");
442
443 1265 cls := Config.classToInstantiate();
444 // If no class was explicitly specified, instantiate the last class in the
445 // program. Otherwise, instantiate the given class name.
446
2/2
✓ Branch 0 taken 1260 times.
✓ Branch 1 taken 5 times.
1265 cname := if stringEmpty(cls) then AbsynUtil.lastClassname(SymbolTable.getAbsyn()) else AbsynUtil.stringPath(cls);
447 1264 fileNamePrefix := Util.stringReplaceChar(AbsynUtil.pathString(cname), ".", "_");
448
449
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1262 times.
1264 if Flags.getConfigBool(Flags.EXPORT_FMU) then
450 2 fmuVersionInt := Flags.getConfigEnum(Flags.FMU_VERSION);
451 fmuVersion := match fmuVersionInt
452 case 10 then "1.0";
453 case 20 then "2.0";
454 case 30 then "3.0";
455 end match;
456 2 FlagsUtil.setConfigString(Flags.FMI_VERSION, fmuVersion);
457 2 fmuTypeList := Flags.getConfigStringList(Flags.FMU_TYPE);
458 2 fmuType := stringDelimitList(fmuTypeList, "_");
459 2 fmuPlatformsStr := Flags.getConfigString(Flags.FMU_PLATFORMS);
460 2 fmuPlatforms := Util.stringSplitAtChar(fmuPlatformsStr, ",");
461 2 CevalScriptBackend.callBuildModelFMU(FCore.emptyCache(), FGraph.empty(), cname,
462 fmuVersion, fmuType, fileNamePrefix, true, fmuPlatforms, NONE());
463 2 showErrors(Print.getErrorString(), ErrorExt.printMessagesStr(false));
464 2 System.fflush();
465 else
466
2/4
✓ Branch 1 taken 1262 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1262 times.
1262 runBackend := Config.simulationCg() or Config.simulation();
467 1262 runSilent := Config.silent();
468
469 1262 CevalScriptBackend.translateModel(FCore.emptyCache(), FGraph.empty(), cname,
470 fileNamePrefix, runBackend, runSilent, NONE());
471 969 showErrors(Print.getErrorString(), ErrorExt.printMessagesStr(false));
472 end if;
473 then ();
474
475 /* Modelica script file .mos */
476 case f::libs
477 algorithm
478 1706 isModelicaScriptFile(f);
479 // loading possible libraries given at the command line
480
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1394 times.
1394 for lib in libs loop
481 ✗ loadLib(lib);
482 end for;
483
484 //System.startTimer();
485 //print("\nParseExp");
486 // parse our algorithm given in the script
487 1394 stmts := Parser.parseexp(f);
488 //System.stopTimer();
489 //print("\nParseExp: " + realString(System.getTimerIntervalTime()));
490
491 // are there any errors?
492 // show errors if there are any
493 1394 showErrors(Print.getErrorString(), ErrorExt.printMessagesStr(false));
494 // evaluate statements and print the result to stdout directly
495 1394 Interactive.evaluateToStdOut(stmts, true);
496 then
497 ();
498
499 case {f} /* A template file .tpl (in the Susan language)*/
500 algorithm
501 318 isCodegenTemplateFile(f);
502 ✗ TplMain.main(f, Flags.getConfigString(Flags.TPL_OUTPUT_DIR));
503 then
504 ();
505
506 // deal with problems
507 case f::_
508 algorithm
509
1/2
✓ Branch 1 taken 318 times.
✗ Branch 2 not taken.
318 if System.regularFileExists(f) then
510 318 print("Error processing file: ");
511 else
512 ✗ print("File does not exist: ");
513 end if;
514
515 318 print(f); print("\n"); System.fflush();
516 // show errors if there are any
517 318 showErrors(Print.getErrorString(), ErrorExt.printMessagesStr(false));
518 318 then
519 fail();
520
521 end matchcontinue;
522 end translateFile;
523
524 protected function interactivemode
525 "Initiate the interactive mode using socket communication."
526 protected
527 Integer shandle;
528 Boolean b;
529 String str,replystr;
530 algorithm
531 ✗ shandle := Socket.waitforconnect(29500);
532 ✗ if shandle == -1 then
533 ✗ fail();
534 end if;
535 while true loop
536 ✗ str := Socket.handlerequest(shandle);
537 ✗ if Flags.isSet(Flags.INTERACTIVE_DUMP) then
538 ✗ Debug.trace("------- Recieved Data from client -----\n");
539 ✗ Debug.trace(str);
540 ✗ Debug.trace("------- End recieved Data-----\n");
541 end if;
542 ✗ (b,replystr) := handleCommand(str) "Print.clearErrorBuf &" ;
543 ✗ replystr := if b then replystr else "quit requested, shutting server down\n";
544 ✗ Socket.sendreply(shandle, replystr);
545 ✗ if not b then
546 ✗ Socket.close(shandle);
547 ✗ Socket.cleanup();
548 break;
549 end if;
550 end while;
551 end interactivemode;
552
553 protected function interactivemodeZMQ
554 "Initiate the interactive mode using ZMQ communication."
555 protected
556 Option<Integer> zmqSocket;
557 Boolean b;
558 String str,replystr,suffix;
559 algorithm
560 ✗ suffix := Flags.getConfigString(Flags.ZEROMQ_FILE_SUFFIX);
561 ✗ zmqSocket := ZeroMQ.initialize(if suffix=="" then "" else ("."+suffix), Flags.isSet(Flags.ZMQ_LISTEN_TO_ALL), Flags.getConfigInt(Flags.INTERACTIVE_PORT));
562 ✗ false := valueEq(SOME(0), zmqSocket);
563 while true loop
564 ✗ str := ZeroMQ.handleRequest(zmqSocket);
565 ✗ if Flags.isSet(Flags.INTERACTIVE_DUMP) then
566 ✗ Debug.trace("------- Recieved Data from client -----\n");
567 ✗ Debug.trace(str);
568 ✗ Debug.trace("------- End recieved Data-----\n");
569 end if;
570 ✗ (b,replystr) := handleCommand(str);
571 ✗ replystr := if b then replystr else "quit requested, shutting server down\n";
572 ✗ ZeroMQ.sendReply(zmqSocket, replystr);
573 ✗ if not b then
574 ✗ ZeroMQ.close(zmqSocket);
575 break;
576 end if;
577 end while;
578 end interactivemodeZMQ;
579
580 public function readSettings
581 " author: x02lucpo
582 Checks if 'settings.mos' exist and uses handleCommand with runScript(...) to execute it.
583 Checks if '-s <file>.mos' has been"
584 input list<String> inArguments;
585 protected
586 String settings_file;
587 algorithm
588 2677 settings_file := Util.flagValue("-s", inArguments);
589
590
2/4
✓ Branch 0 taken 2677 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 2677 times.
✗ Branch 4 not taken.
2677 if settings_file <> "" then
591 ✗ settings_file := System.trim(settings_file, " \"");
592 ✗ readSettingsFile(settings_file);
593 end if;
594 end readSettings;
595
596 protected function readSettingsFile
597 input String filePath;
598 protected
599 String command;
600 algorithm
601 ✗ if System.regularFileExists(filePath) then
602 ✗ command := "runScript(\"" + filePath + "\")";
603 ✗ handleCommand(command);
604 end if;
605 end readSettingsFile;
606
607 public function setWindowsPaths
608 "@author: adrpo
609 Set the windows paths for MSYS.
610 Do some checks on where needed things are present.
611 BIG WARNING: if MinGW gcc version from OMDev or OpenModelica/MinGW
612 changes you will need to change here!"
613 input String inOMHome;
614 algorithm
615 () := match inOMHome
616 local
617 String oldPath, newPath, omHome, omdevPath, msysPath, mingwDir, binDir, libBinDir, msysBinDir, omLibDir;
618 Boolean hasBinDir, hasLibBinDir, isMSVC;
619
620 // check if we have OMDEV set
621 case omHome
622 algorithm
623 ✗ System.setEnv("OPENMODELICAHOME",omHome,true);
624 ✗ omdevPath := Util.makeValueOrDefault(System.readEnv,"OMDEV","");
625 // if we don't have something in OMDEV use OMHOME
626 ✗ if stringEq(omdevPath, "") then
627 omdevPath := omHome;
628 end if;
629 ✗ msysPath := omdevPath + "\\tools\\msys";
630 ✗ mingwDir := System.openModelicaPlatform();
631 ✗ msysBinDir := msysPath + "\\usr\\bin";
632 ✗ binDir := msysPath + "\\" + mingwDir + "\\bin";
633 // An MSVC build ships no MSYS toolchain at all - Compile.bat locates
634 // Visual Studio itself - so there is nothing to search for or report.
635 ✗ isMSVC := 0 == System.stringFind(mingwDir, "msvc");
636 ✗ if isMSVC then
637 libBinDir := binDir;
638 elseif System.getCCompiler() == "gcc" then
639 ✗ libBinDir := msysPath + "\\" + mingwDir + "\\lib\\gcc\\" + System.gccDumpMachine() + "\\" + System.gccVersion();
640 else // if is clang
641 libBinDir := binDir;
642 end if;
643 // do we have bin and lib bin?
644 ✗ hasBinDir := System.directoryExists(binDir);
645 ✗ hasLibBinDir := System.directoryExists(libBinDir);
646 ✗ omLibDir := omHome + "\\lib\\" + Autoconf.triple + "\\omc";
647 ✗ if isMSVC then
648 ✗ oldPath := System.readEnv("PATH");
649 ✗ newPath := stringAppendList({omHome, "\\bin;", omLibDir, ";"});
650 ✗ newPath := System.stringReplace(newPath, "/", "\\") + oldPath;
651 ✗ System.setEnv("PATH",newPath,true);
652 elseif hasBinDir and hasLibBinDir
653 then
654 ✗ oldPath := System.readEnv("PATH");
655 ✗ newPath := stringAppendList({omHome, "\\bin;", omLibDir, ";", binDir + ";", libBinDir + ";", msysBinDir + ";"});
656 ✗ newPath := System.stringReplace(newPath, "/", "\\") + oldPath;
657 // print("Path set: " + newPath + "\n");
658 ✗ System.setEnv("PATH",newPath,true);
659 else
660 // do not display anything if -d=disableWindowsPathCheckWarning
661 ✗ if not Flags.isSet(Flags.DISABLE_WINDOWS_PATH_CHECK_WARNING) then
662 ✗ print("We could not find some needed MINGW paths in $OPENMODELICAHOME or $OMDEV. Searched for paths:\n");
663 ✗ print("\t" + binDir + (if hasBinDir then " [found] " else " [not found] ") + "\n");
664 ✗ print("\t" + libBinDir + (if hasLibBinDir then " [found] " else " [not found] ") + "\n");
665 end if;
666 end if;
667 then ();
668 end match;
669 end setWindowsPaths;
670
671 protected function setDefaultCC "Reads the environment variable CC to change the default CC"
672 algorithm
673 try
674 2677 System.setCCompiler(System.readEnv("CC"));
675 else
676 end try;
677 end setDefaultCC;
678
679 public function init
680 "Does some things and also reads all flags from the command line arguments."
681 input list<String> args "command line arguments";
682 output list<String> args_1 "arguments that are not flags";
683 algorithm
684 // set glib G_SLICE to always-malloc as is rummored to be better for Boehm GC
685 2677 System.setEnv("G_SLICE", "always-malloc", true);
686 // call GC_init() the first thing we do!
687 2677 System.initGarbageCollector();
688 // Experimentally found to make the testsuite pass on asap.openmodelica.org.
689 // 150M for Windows, 300M for others makes the GC try to unmap less and so it crashes less.
690 // Disabling unmap is another alternative that seems to work well (but could cause the memory consumption to not be released, and requires manually calling collect and unmap
691 if true then
692 2677 GCExt.setForceUnmapOnGcollect(Autoconf.os == "Windows_NT");
693 else
694 GCExt.expandHeap(if Autoconf.os == "Windows_NT"
695 then 1024*1024*150
696 else 1024*1024*300);
697 end if;
698 2677 Global.initialize();
699 2677 ErrorExt.registerModelicaFormatError();
700 2677 ErrorExt.initAssertionFunctions();
701 2677 System.realtimeTick(ClockIndexes.RT_CLOCK_SIMULATE_TOTAL);
702 2677 args_1 := FlagsUtil.new(args);
703 2677 FlagsUtil.applyNumProcEnvironment();
704 2677 setDefaultCC();
705 2677 SymbolTable.reset();
706 2677 BackendInterfaceImplementation.initializeBackendInterface();
707 end init;
708
709 public function main
710 "This is the main function that the MetaModelica Compiler (MMC) runtime system
711 calls to start the translation."
712 input list<String> args;
713 protected
714 list<String> args_1;
715 Integer seconds;
716 algorithm
717 2677 execStatReset();
718 try
719 try
720 2677 args_1 := init(args);
721
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2677 times.
2677 if Flags.isSet(Flags.GC_PROF) then
722 ✗ print(GCExt.profStatsStr(GCExt.getProfStats(), head="GC stats after initialization:") + "\n");
723 end if;
724 2677 seconds := Flags.getConfigInt(Flags.ALARM);
725
2/2
✓ Branch 0 taken 2675 times.
✓ Branch 1 taken 2 times.
2677 if seconds > 0 then
726 2675 System.alarm(seconds);
727 end if;
728 2677 main2(args_1);
729 else
730 318 ErrorExt.clearMessages();
731
1/2
✓ Branch 0 taken 318 times.
✗ Branch 1 not taken.
318 failure(FlagsUtil.new(args));
732 ✗ print(ErrorExt.printMessagesStr(false)); print("\n");
733 ✗ fail();
734 end try;
735
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2359 times.
2359 if Flags.isSet(Flags.GC_PROF) then
736 ✗ print(GCExt.profStatsStr(GCExt.getProfStats(), head="GC stats at end of program:") + "\n");
737 end if;
738 else
739 ✗ print(StackOverflow.errorPrefix() + " detected and was not caught.\n" +
740 "Send us a bug report at https://trac.openmodelica.org/OpenModelica/newticket\n" +
741 " Include the following trace:\n");
742 ✗ for s in StackOverflow.readableStacktraceMessages() loop
743 ✗ print(s);
744 ✗ print("\n");
745 end for;
746 end try annotation(__OpenModelica_stackOverflowCheckpoint=true);
747 end main;
748
749 protected function main2
750 "This is not the main function that the MetaModelica Compiler (MMC) runtime
751 system calls to start the translation."
752 input list<String> args;
753 protected
754 String interactiveMode;
755 algorithm
756 // Version requested using --version.
757
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2677 times.
2677 if Config.versionRequest() then
758 ✗ print(Settings.getVersionNr() + "\n");
759 ✗ return;
760 end if;
761
762 // Don't allow running omc as root due to security risks.
763 2677 interactiveMode := Flags.getConfigString(Flags.INTERACTIVE);
764
1/10
✗ Branch 1 not taken.
✓ Branch 2 taken 2677 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
2677 if System.userIsRoot() and (interactiveMode == "tcp" or interactiveMode == "zmq") then
765 ✗ Error.addMessage(Error.ROOT_USER_INTERACTIVE, {});
766 ✗ print(ErrorExt.printMessagesStr(false));
767 ✗ fail();
768 end if;
769
770 // Setup mingw path only once
771 // adrpo: NEVER MOVE THIS CASE FROM HERE OR PUT ANY OTHER CASES BEFORE IT
772 // without asking Adrian.Pop@liu.se
773 if Autoconf.os == "Windows_NT" then
774 setWindowsPaths(Settings.getInstallationDirectoryPath());
775 end if;
776
777 try
778 2677 Settings.getInstallationDirectoryPath();
779
780 2677 readSettings(args);
781
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2677 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
2677 if interactiveMode == "tcp" then
782 ✗ interactivemode();
783 elseif interactiveMode == "zmq" then
784 ✗ interactivemodeZMQ();
785 else // No interactive flag given, try to flatten the file.
786 2677 translateFile(args);
787 end if;
788 else // Something went wrong, print an appropriate error.
789 // OMC called with no arguments, print usage information and quit.
790
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 318 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
318 if listEmpty(args) and Config.classToInstantiate()=="" then
791 ✗ if not Config.helpRequest() then
792 ✗ print(FlagsUtil.printUsage()); System.fflush();
793 end if;
794 ✗ return;
795 end if;
796
797 try
798 318 Settings.getInstallationDirectoryPath();
799 318 print("# Error encountered! Exiting...\n"); System.fflush();
800 318 print("# Please check the error message and the flags.\n"); System.fflush();
801 318 Print.printBuf("\n\n----\n\nError buffer:\n\n"); System.fflush();
802 318 print(Print.getErrorString()); System.fflush();
803 318 print(ErrorExt.printMessagesStr(false)); System.fflush(); print("\n"); System.fflush();
804 else
805 ✗ print("Error: Failed to retrieve the installation directory path!\n"); System.fflush();
806 end try;
807 318 fail();
808 end try;
809 end main2;
810
811 annotation(__OpenModelica_Interface="backend_main");
812 end Main;
813