Opened 11 years ago
Closed 11 years ago
#2603 closed defect (fixed)
generated C code contains newlines in string literals
Reported by: | Bill Janssen | Owned by: | Martin Sjölund |
---|---|---|---|
Priority: | critical | Milestone: | 1.9.1 |
Component: | Code Generation | Version: | trunk |
Keywords: | Cc: |
Description
My generated simulation code doesn't compile, because of constructs like this. Note that C code only allows newlines in string literals if they are escaped.
tmp3980 = cat_modelica_string(" Temperature T (= ",tmp3979); tmp3981 = cat_modelica_string(tmp3980," K) is not in the allowed range (");
Change History (27)
comment:1 by , 11 years ago
comment:2 by , 11 years ago
Status: | new → accepted |
---|
comment:3 by , 11 years ago
Which is why we have code that escapes string literals... I would guess it helps if we knew what expression caused this (\r, \n are escaped properly).
comment:4 by , 11 years ago
I got an email from janssen which (non public) model has this issue.
I'll have a look at how the assert expression looks like and come back with some more info.
comment:5 by , 11 years ago
Seems the error comes from MSL Media PartialMedium or all the other Mediums:
redeclare replaceable model extends BaseProperties equation assert(T >= T_min and T <= T_max, " Temperature T (= " + String(T) + " K) is not in the allowed range (" + String(T_min) + " K <= T <= " + String(T_max) + " K) required from medium model \"" + mediumName + "\". "); // ... end BaseProperties;
However, strangely I can simulate the model fine:
adrpo@ida-liu050 /c/dev/avm $ ~/dev/OpenModelica/build/bin/omc +locale=C vu.mos true "" true "" true record SimulationResult resultFile = "", simulationOptions = "startTime = 0.0, stopTime = 30.0, numberOfIntervals = 500, tolerance = 1e-006, method = 'dassl', fileNamePrefix = 'C2M2L_Decl.C2M2L_Delivered_Component_Implementations.Drive_Line.Cross_Drive_Transmission.Test_cross_drive_PTO_Steer', options = '', outputFormat = 'mat', variableFilter = '.*', measureTime = false, cflags = '', simflags = ''", messages = "Simulation execution failed for model: C2M2L_Decl.C2M2L_Delivered_Component_Implementations.Drive_Line.Cross_Drive_Transmission.Test_cross_drive_PTO_Steer stdout | warning | Error in initialization. Storing results and exiting. | | | | Use -lv=LOG_INIT -w for more information. ", timeFrontend = 7.677711035848936, timeBackend = 1.62388912798616, timeSimCode = 0.8358188328751135, timeTemplates = 3.080788487196918, timeCompile = 7.874059468752382 end SimulationResult;
well, more or less as there is an error at initialization, but it can compile.
Where vu.mos looks like:
loadModel(Modelica); getErrorString(); loadFile("VU/C2M2L_Decl/package.mo"); getErrorString(); simulate(C2M2L_Decl.C2M2L_Delivered_Component_Implementations.Drive_Line.Cross_Drive_Transmission.Test_cross_drive_PTO_Steer); getErrorString();
You could do "make distclean" and recompile
OpenModelica as it seems something went
horribly wrong.
comment:8 by , 11 years ago
Checked out an update, and rebuilt. Same problem.
<Gripe> "make distclean" is really a non-starter. For one thing, it blows away config.log, which records my carefully crafted configure line. </Gripe>
So maybe this is really a bug report about the makefiles.
comment:9 by , 11 years ago
Ouch. Sorry about the config.log.
How do you try to build the model? From OMEdit? With omc + script? What OS?
comment:11 by , 11 years ago
Sorry, I should have said I was using a Unix machine. A Snow Leopard Mac, to be precise.
comment:12 by , 11 years ago
I use omc on the command-line to generate the simulation code, then invoke make on the generated makefile.
comment:13 by , 11 years ago
I asked sjoelund.se to have a look at this.
Seems is working if dos2unix is used on the .mo files loaded.
I guess the old everybody with its own line ending \n vs. \r vs. \n\r stuff :)
comment:14 by , 11 years ago
I guess that's one way to look at it. But it seems that the code which is doing the Modelica-to-C transliteration is making some unwarranted assumptions.
comment:15 by , 11 years ago
I guess not too many unwarranted assumptions as this
would have been apparent in all the testing quite a lot.
This is the function. Can anybody spot the issue?
extern char* omc__escapedString(const char* str, int nl) { int len1,len2; char *res; int i=0; len1 = strlen(str); len2 = omc__escapedStringLength(str,nl); if(len1 == len2) return NULL; res = (char*) malloc(len2+1); while(*str) { switch (*str) { case '"': res[i++] = '\\'; res[i++] = '"'; break; case '\\': res[i++] = '\\'; res[i++] = '\\'; break; case '\a': res[i++] = '\\'; res[i++] = 'a'; break; case '\b': res[i++] = '\\'; res[i++] = 'b'; break; case '\f': res[i++] = '\\'; res[i++] = 'f'; break; case '\v': res[i++] = '\\'; res[i++] = 'v'; break; case '\r': if(nl) {res[i++] = '\\'; res[i++] = 'n'; if(str[1] == '\n') str++;} else {res[i++] = *str;} break; case '\n': if(nl) {res[i++] = '\\'; res[i++] = 'n'; if(str[1] == '\r') str++;} else {res[i++] = *str;} break; default: res[i++] = *str; } str++; } res[i] = '\0'; return res; }
follow-up: 21 comment:17 by , 11 years ago
There is no world in which \n followed by \r is a newline, so the case for '\n' doesn't seem right. But that's not the problem.
follow-up: 20 comment:18 by , 11 years ago
I don't get the both else cases. I would just leave them out - but I know that this is already well tested. So probably it's just me.
comment:19 by , 11 years ago
The nl flag comes from above to tell this function to either escape or not the new lines.
But as far as I can see, in the compiler is called with true to transform a Modelica to a C string.
comment:20 by , 11 years ago
Replying to lochel:
I don't get the both else cases. I would just leave them out - but I know that this is already well tested. So probably it's just me.
That's not true.
comment:21 by , 11 years ago
Replying to janssen:
There is no world in which \n followed by \r is a newline, so the case for '\n' doesn't seem right. But that's not the problem.
You mean except old-world Mac? (Or wait, that was only \r?)
Anyway, the problem is the logic that if old strlen is same as new strlen, we don't need to run the algorithm. "abc\r\n"
=> "abc\\\n"
follow-up: 24 comment:22 by , 11 years ago
You think it would run on old-world Mac?
It probably should just quote any control character, instead of considering specific cases.
But if this function is being called consistently, there should be no \r characters in the output, and there clearly are. So I'm guessing there's some path for code generation of assertions that doesn't invoke this function.
comment:24 by , 11 years ago
Replying to janssen:
But if this function is being called consistently, there should be no \r characters in the output, and there clearly are. So I'm guessing there's some path for code generation of assertions that doesn't invoke this function.
Read above. The algorithm is not run for specific cases. I'm running the testsuite now.
comment:25 by , 11 years ago
Yep. The unwarranted assumption was that appropriate quoting would always change the length of the string.
comment:26 by , 11 years ago
Owner: | changed from | to
---|---|
Status: | accepted → assigned |
Traced this back to an assert statement in the library I'm using. It contains Modelica string literals with CR LF newlines in it, which are copied literally into the C code. We can't just copy them; Modelica string literals allow unescaped newlines, C string literals don't. Perhaps there are other differences as well, though none come immediately to mind.