Skip to content

Commit

Permalink
Add ModelicaDuplicateString and ModelicaDuplicateStringWithErrorRetur…
Browse files Browse the repository at this point in the history
…n (new in Modelica Language Specification version 3.5) (modelica#3686)

* Add ModelicaDuplicateString and ModelicaDuplicateStringWithErrorReturn

* Utilize ModelicaDuplicateString and ModelicaDuplicateStringWithErrorReturn

* Rename format specifying arguments

* Utilize ModelicaDuplicateString and ModelicaDuplicateStringWithErrorReturn

* Rely on assert

Co-authored-by: Henrik Tidefelt <henrikt@wolfram.com>

* Update spelling

Co-authored-by: Henrik Tidefelt <henrikt@wolfram.com>

* Call ModelicaError as stated in MLS 12.9.6.2

---------

Co-authored-by: Henrik Tidefelt <henrikt@wolfram.com>
  • Loading branch information
beutlich and henrikt-ma committed Jan 17, 2024
1 parent 68aa656 commit da81bb7
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 42 deletions.
22 changes: 21 additions & 1 deletion .CI/Test/Common.c
Expand Up @@ -2,17 +2,37 @@
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

char* ModelicaAllocateString(size_t len) {
void *data = malloc(len + 1); /* Never free'd in the test programs */
assert(data);
if (NULL == data) {
ModelicaError("Failed to allocate string");
}
return data;
}

char* ModelicaAllocateStringWithErrorReturn(size_t len) {
return malloc(len + 1); /* Never free'd in the test programs */
}

char* ModelicaDuplicateString(const char* str) {
void *data = malloc(strlen(str) + 1); /* Never free'd in the test programs */
if (NULL == data) {
ModelicaError("Failed to duplicate string");
}
strcpy(data, str);
return data;
}

char* ModelicaDuplicateStringWithErrorReturn(const char* str) {
void *data = malloc(strlen(str) + 1); /* Never free'd in the test programs */
if (NULL != data) {
strcpy(data, str);
}
return data;
}

void ModelicaMessage(const char *string) {
printf("%s\n", string);
}
Expand Down
36 changes: 24 additions & 12 deletions .CI/Test/ModelicaUtilities.h
Expand Up @@ -131,19 +131,16 @@ void ModelicaMessage(const char *string);
Output the message string (no format control).
*/


void ModelicaFormatMessage(const char *string, ...) MODELICA_FORMATATTR_PRINTF;
void ModelicaFormatMessage(const char *format, ...) MODELICA_FORMATATTR_PRINTF;
/*
Output the message under the same format control as the C-function printf.
*/


void ModelicaVFormatMessage(const char *string, va_list args) MODELICA_FORMATATTR_VPRINTF;
void ModelicaVFormatMessage(const char *format, va_list args) MODELICA_FORMATATTR_VPRINTF;
/*
Output the message under the same format control as the C-function vprintf.
*/


MODELICA_NORETURN void ModelicaError(const char *string) MODELICA_NORETURNATTR;
/*
Output the error message string (no format control). This function
Expand All @@ -156,32 +153,30 @@ void ModelicaWarning(const char *string);
Output the warning message string (no format control).
*/

void ModelicaFormatWarning(const char *string, ...) MODELICA_FORMATATTR_PRINTF;
void ModelicaFormatWarning(const char *format, ...) MODELICA_FORMATATTR_PRINTF;
/*
Output the warning message under the same format control as the C-function printf.
*/

void ModelicaVFormatWarning(const char *string, va_list args) MODELICA_FORMATATTR_VPRINTF;
void ModelicaVFormatWarning(const char *format, va_list args) MODELICA_FORMATATTR_VPRINTF;
/*
Output the warning message under the same format control as the C-function vprintf.
*/

MODELICA_NORETURN void ModelicaFormatError(const char *string, ...) MODELICA_NORETURNATTR MODELICA_FORMATATTR_PRINTF;
MODELICA_NORETURN void ModelicaFormatError(const char *format, ...) MODELICA_NORETURNATTR MODELICA_FORMATATTR_PRINTF;
/*
Output the error message under the same format control as the C-function
printf. This function never returns to the calling function,
but handles the error similarly to an assert in the Modelica code.
*/


MODELICA_NORETURN void ModelicaVFormatError(const char *string, va_list args) MODELICA_NORETURNATTR MODELICA_FORMATATTR_VPRINTF;
MODELICA_NORETURN void ModelicaVFormatError(const char *format, va_list args) MODELICA_NORETURNATTR MODELICA_FORMATATTR_VPRINTF;
/*
Output the error message under the same format control as the C-function
vprintf. This function never returns to the calling function,
but handles the error similarly to an assert in the Modelica code.
*/


char* ModelicaAllocateString(size_t len);
/*
Allocate memory for a Modelica string which is used as return
Expand All @@ -191,7 +186,6 @@ calling program, as for any other array. If an error occurs, this
function does not return, but calls "ModelicaError".
*/


char* ModelicaAllocateStringWithErrorReturn(size_t len);
/*
Same as ModelicaAllocateString, except that in case of error, the
Expand All @@ -201,6 +195,24 @@ resources use ModelicaError or ModelicaFormatError to signal
the error.
*/

char* ModelicaDuplicateString(const char* str);
/*
Duplicate (= allocate memory and deep copy) a Modelica string which
is used as return argument of an external Modelica function. Note,
that the storage for string arrays (= pointer to string array) is still
provided by the calling program, as for any other array. If an error
occurs, this function does not return, but calls "ModelicaError".
*/

char* ModelicaDuplicateStringWithErrorReturn(const char* str);
/*
Same as ModelicaDuplicateString, except that in case of error, the
function returns 0. This allows the external function to close files
and free other open resources in case of error. After cleaning up
resources use, ModelicaError or ModelicaFormatError to signal
the error.
*/

#if defined(__cplusplus)
}
#endif
Expand Down
38 changes: 16 additions & 22 deletions Modelica/Resources/C-Sources/ModelicaInternal.c
@@ -1,6 +1,6 @@
/* ModelicaInternal.c - External functions for Modelica.Utilities
Copyright (C) 2002-2023, Modelica Association and contributors
Copyright (C) 2002-2024, Modelica Association and contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -30,6 +30,10 @@
*/

/* Changelog:
Jan. 15, 2024: by Thomas Beutlich
Utilized ModelicaDuplicateString and
ModelicaDuplicateStringWithErrorReturn (ticket #3686)
Nov. 17, 2020: by Thomas Beutlich
Fixed reading files with Unix-style line endings on Windows
for ModelicaInternal_readLine/_readFile (ticket #3631)
Expand Down Expand Up @@ -525,7 +529,7 @@ void ModelicaInternal_readDirectory(_In_z_ const char* directory, int nFiles,
}

/* Allocate Modelica memory for file/directory name and copy name */
pName = ModelicaAllocateStringWithErrorReturn(strlen(pinfo->d_name));
pName = ModelicaDuplicateStringWithErrorReturn(pinfo->d_name);
if ( pName == NULL ) {
errnoTemp = errno;
closedir(pdir);
Expand All @@ -538,7 +542,6 @@ void ModelicaInternal_readDirectory(_In_z_ const char* directory, int nFiles,
directory, strerror(errnoTemp));
}
}
strcpy(pName, pinfo->d_name);

/* Save pointer to file */
files[iFiles] = pName;
Expand Down Expand Up @@ -622,8 +625,7 @@ _Ret_z_ const char* ModelicaInternal_fullPathName(_In_z_ const char* name) {
name, strerror(errno));
return "";
}
fullName = ModelicaAllocateString(strlen(tempName));
strcpy(fullName, tempName);
fullName = ModelicaDuplicateString(tempName);
ModelicaConvertToUnixDirectorySeparator(fullName);
return fullName;
#elif (_BSD_SOURCE || _XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED || _POSIX_VERSION >= 200112L)
Expand All @@ -635,8 +637,7 @@ _Ret_z_ const char* ModelicaInternal_fullPathName(_In_z_ const char* name) {
if (tempName == NULL) {
goto FALLBACK_getcwd;
}
fullName = ModelicaAllocateString(strlen(tempName) + 1);
strcpy(fullName, tempName);
fullName = ModelicaDuplicateString(tempName);
ModelicaConvertToUnixDirectorySeparator(fullName);
/* Retain trailing slash to match _fullpath behaviour */
len = strlen(name);
Expand Down Expand Up @@ -688,8 +689,7 @@ _Ret_z_ const char* ModelicaInternal_temporaryFileName(void) {
ModelicaFormatError("Not possible to get temporary filename\n%s", strerror(errno));
return "";
}
fullName = ModelicaAllocateString(strlen(tempName));
strcpy(fullName, tempName);
fullName = ModelicaDuplicateString(tempName);
ModelicaConvertToUnixDirectorySeparator(fullName);

return fullName;
Expand Down Expand Up @@ -1011,12 +1011,11 @@ void ModelicaInternal_readFile(_In_z_ const char* fileName,
while (iLines <= nLines) {
readLine(&buf, &bufLen, fp);

line = ModelicaAllocateStringWithErrorReturn(strlen(buf));
line = ModelicaDuplicateStringWithErrorReturn(buf);
if ( line == NULL ) {
goto Modelica_OOM_ERROR1;
}

strcpy(line, buf);
string[iLines - 1] = line;
iLines++;
}
Expand Down Expand Up @@ -1063,12 +1062,11 @@ _Ret_z_ const char* ModelicaInternal_readLine(_In_z_ const char* fileName,
}
}

line = ModelicaAllocateStringWithErrorReturn(strlen(buf));
line = ModelicaDuplicateStringWithErrorReturn(buf);
if (line == NULL) {
goto Modelica_OOM_ERROR2;
}

strcpy(line, buf);
CacheFileForReading(fp, fileName, lineNumber, buf, bufLen);
*endOfFile = 0;
return line;
Expand All @@ -1078,8 +1076,7 @@ _Ret_z_ const char* ModelicaInternal_readLine(_In_z_ const char* fileName,
fclose(fp);
CloseCachedFile(fileName);
*endOfFile = 1;
line = ModelicaAllocateString(0);
line[0] = '\0';
line = ModelicaDuplicateString("");
return line;

Modelica_OOM_ERROR2:
Expand Down Expand Up @@ -1134,8 +1131,7 @@ _Ret_z_ const char* ModelicaInternal_getcwd(int dummy) {
cwd = "";
}
#endif
directory = ModelicaAllocateString(strlen(cwd));
strcpy(directory, cwd);
directory = ModelicaDuplicateString(cwd);
ModelicaConvertToUnixDirectorySeparator(directory);
return directory;
}
Expand All @@ -1156,18 +1152,16 @@ void ModelicaInternal_getenv(_In_z_ const char* name, int convertToSlash,
#endif

if (value == NULL) {
result = ModelicaAllocateString(0);
result[0] = '\0';
result = ModelicaDuplicateString("");
*exist = 0;
}
else {
#if defined(_MSC_VER) && _MSC_VER >= 1400
result = ModelicaAllocateStringWithErrorReturn(len); /* (len - 1) actually is sufficient */
result = ModelicaDuplicateStringWithErrorReturn(value);
if (result) {
#else
result = ModelicaAllocateString(strlen(value));
result = ModelicaDuplicateString(value);
#endif
strcpy(result, value);
if ( convertToSlash == 1 ) {
ModelicaConvertToUnixDirectorySeparator(result);
}
Expand Down
14 changes: 7 additions & 7 deletions Modelica/Resources/C-Sources/ModelicaStrings.c
@@ -1,6 +1,6 @@
/* ModelicaStrings.c - External functions for Modelica.Utilities.Strings
Copyright (C) 2002-2020, Modelica Association and contributors
Copyright (C) 2002-2024, Modelica Association and contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -30,6 +30,10 @@
*/

/* Changelog:
Jan. 15, 2024: by Thomas Beutlich
Utilized ModelicaDuplicateString and
ModelicaDuplicateStringWithErrorReturn (ticket #3686)
Mar. 15, 2020: by Thomas Beutlich
Improved fault-tolerance of ModelicaStrings_substring w.r.t.
index arguments (ticket #3503)
Expand Down Expand Up @@ -231,9 +235,7 @@ void ModelicaStrings_scanIdentifier(_In_z_ const char* string,
/* Token missing or not identifier. */
*nextIndex = startIndex;
{
char* s = ModelicaAllocateString(0);
s[0] = '\0';
*identifier = s;
*identifier = ModelicaDuplicateString("");
}
return;
}
Expand Down Expand Up @@ -458,9 +460,7 @@ void ModelicaStrings_scanString(_In_z_ const char* string, int startIndex,

Modelica_ERROR:
{
char* s = ModelicaAllocateString(0);
s[0] = '\0';
*result = s;
*result = ModelicaDuplicateString("");
}
*nextIndex = startIndex;
return;
Expand Down

0 comments on commit da81bb7

Please sign in to comment.