Skip to content

Commit e0d99fb

Browse files
committed
FDATE extension implementation: get date and time in ctime format
reference to gfortran fdate https://gcc.gnu.org/onlinedocs/gfortran/FDATE.html usage: CHARACTER(32) :: time CALL fdate(time) WRITE(*,*) time
1 parent 1ad920f commit e0d99fb

File tree

6 files changed

+55
-1
lines changed

6 files changed

+55
-1
lines changed

flang/docs/Intrinsics.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -751,7 +751,7 @@ This phase currently supports all the intrinsic procedures listed above but the
751751
| Object characteristic inquiry functions | ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, IS_CONTIGUOUS, PRESENT, RANK, SAME_TYPE, STORAGE_SIZE |
752752
| Type inquiry intrinsic functions | BIT_SIZE, DIGITS, EPSILON, HUGE, KIND, MAXEXPONENT, MINEXPONENT, NEW_LINE, PRECISION, RADIX, RANGE, TINY|
753753
| Non-standard intrinsic functions | AND, OR, XOR, SHIFT, ZEXT, IZEXT, COSD, SIND, TAND, ACOSD, ASIND, ATAND, ATAN2D, COMPL, EQV, NEQV, INT8, JINT, JNINT, KNINT, QCMPLX, DREAL, DFLOAT, QEXT, QFLOAT, QREAL, DNUM, NUM, JNUM, KNUM, QNUM, RNUM, RAN, RANF, ILEN, SIZEOF, MCLOCK, SECNDS, COTAN, IBCHNG, ISHA, ISHC, ISHL, IXOR, IARG, IARGC, NARGS, NUMARG, BADDRESS, IADDR, CACHESIZE, EOF, FP_CLASS, INT_PTR_KIND, ISNAN, MALLOC |
754-
| Intrinsic subroutines |MVBITS (elemental), CPU_TIME, DATE_AND_TIME, EVENT_QUERY, EXECUTE_COMMAND_LINE, GET_COMMAND, GET_COMMAND_ARGUMENT, GET_ENVIRONMENT_VARIABLE, MOVE_ALLOC, RANDOM_INIT, RANDOM_NUMBER, RANDOM_SEED, SYSTEM_CLOCK |
754+
| Intrinsic subroutines |MVBITS (elemental), CPU_TIME, DATE_AND_TIME, EVENT_QUERY, EXECUTE_COMMAND_LINE, FDATE, GET_COMMAND, GET_COMMAND_ARGUMENT, GET_ENVIRONMENT_VARIABLE, MOVE_ALLOC, RANDOM_INIT, RANDOM_NUMBER, RANDOM_SEED, SYSTEM_CLOCK |
755755
| Atomic intrinsic subroutines | ATOMIC_ADD |
756756
| Collective intrinsic subroutines | CO_REDUCE |
757757

flang/include/flang/Runtime/command.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ extern "C" {
2323
// integer kind.
2424
std::int32_t RTNAME(ArgumentCount)();
2525

26+
// Try to get the the current date (same format as CTIME: convert to a string)
27+
// Return a STATUS as described in the standard.
28+
std::int32_t RTNAME(FDate)(
29+
const Descriptor *argument = nullptr, const Descriptor *errmsg = nullptr);
30+
2631
// 16.9.82 GET_COMMAND
2732
// Try to get the value of the whole command. All of the parameters are
2833
// optional.

flang/include/flang/Runtime/extensions.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ void FORTRAN_PROCEDURE_NAME(flush)(const int &unit);
2424
// GNU Fortran 77 compatibility function IARGC.
2525
std::int32_t FORTRAN_PROCEDURE_NAME(iargc)();
2626

27+
void FORTRAN_PROCEDURE_NAME(fdate)(std::int8_t *string, std::int64_t length);
28+
2729
// GNU Fortran 77 compatibility subroutine GETARG(N, ARG).
2830
void FORTRAN_PROCEDURE_NAME(getarg)(
2931
std::int32_t &n, std::int8_t *arg, std::int64_t length);

flang/runtime/command.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "flang/Runtime/descriptor.h"
1515
#include <cstdlib>
1616
#include <limits>
17+
#include <time.h>
1718

1819
namespace Fortran::runtime {
1920
std::int32_t RTNAME(ArgumentCount)() {
@@ -125,6 +126,33 @@ static bool FitsInDescriptor(
125126
kind, terminator, value);
126127
}
127128

129+
void removeNewLine(char *str) {
130+
char *newlinePos = strchr(str, '\n');
131+
if (newlinePos != NULL) {
132+
*newlinePos = '\0'; // Replace with null terminator
133+
}
134+
}
135+
136+
std::int32_t RTNAME(FDate)(const Descriptor *value, const Descriptor *errmsg) {
137+
FillWithSpaces(*value);
138+
139+
time_t current_time;
140+
time(&current_time);
141+
142+
char *time_string = ctime(&current_time);
143+
removeNewLine(time_string);
144+
std::int64_t stringLen{StringLength(time_string)};
145+
if (stringLen <= 0) {
146+
return ToErrmsg(errmsg, StatMissingArgument);
147+
}
148+
149+
if (value) {
150+
return CopyToDescriptor(*value, time_string, stringLen, errmsg);
151+
}
152+
153+
return StatOk;
154+
}
155+
128156
std::int32_t RTNAME(GetCommandArgument)(std::int32_t n, const Descriptor *value,
129157
const Descriptor *length, const Descriptor *errmsg, const char *sourceFile,
130158
int line) {

flang/runtime/extensions.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ void FORTRAN_PROCEDURE_NAME(flush)(const int &unit) {
3030
// RESULT = IARGC()
3131
std::int32_t FORTRAN_PROCEDURE_NAME(iargc)() { return RTNAME(ArgumentCount)(); }
3232

33+
void FORTRAN_PROCEDURE_NAME(fdate)(std::int8_t *arg, std::int64_t length) {
34+
Descriptor value{*Descriptor::Create(1, length, arg, 0)};
35+
(void)RTNAME(FDate)(&value, nullptr);
36+
}
37+
3338
// CALL GETARG(N, ARG)
3439
void FORTRAN_PROCEDURE_NAME(getarg)(
3540
std::int32_t &n, std::int8_t *arg, std::int64_t length) {

flang/unittests/Runtime/CommandTest.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,12 @@ TEST_F(ZeroArguments, GetCommandArgument) {
225225
CheckMissingArgumentValue(1);
226226
}
227227

228+
TEST_F(ZeroArguments, FDate) {
229+
CheckMissingArgumentValue(-1);
230+
CheckArgumentValue(commandOnlyArgv[0], 0);
231+
CheckMissingArgumentValue(1);
232+
}
233+
228234
TEST_F(ZeroArguments, GetCommand) { CheckCommandValue(commandOnlyArgv, 1); }
229235

230236
static const char *oneArgArgv[]{"aProgram", "anArgumentOfLength20"};
@@ -242,6 +248,13 @@ TEST_F(OneArgument, GetCommandArgument) {
242248
CheckMissingArgumentValue(2);
243249
}
244250

251+
TEST_F(OneArgument, FDate) {
252+
CheckMissingArgumentValue(-1);
253+
CheckArgumentValue(oneArgArgv[0], 0);
254+
CheckArgumentValue(oneArgArgv[1], 1);
255+
CheckMissingArgumentValue(2);
256+
}
257+
245258
TEST_F(OneArgument, GetCommand) { CheckCommandValue(oneArgArgv, 2); }
246259

247260
static const char *severalArgsArgv[]{
@@ -284,6 +297,7 @@ TEST_F(SeveralArguments, ArgValueTooShort) {
284297
ASSERT_NE(tooShort, nullptr);
285298
EXPECT_EQ(RTNAME(GetCommandArgument)(1, tooShort.get()), -1);
286299
CheckDescriptorEqStr(tooShort.get(), severalArgsArgv[1]);
300+
EXPECT_EQ(RTNAME(FDate)(tooShort.get()), -1);
287301

288302
OwningPtr<Descriptor> length{EmptyIntDescriptor()};
289303
ASSERT_NE(length, nullptr);

0 commit comments

Comments
 (0)