Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion flang/docs/Intrinsics.md
Original file line number Diff line number Diff line change
Expand Up @@ -751,7 +751,7 @@ This phase currently supports all the intrinsic procedures listed above but the
| Object characteristic inquiry functions | ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, IS_CONTIGUOUS, PRESENT, RANK, SAME_TYPE, STORAGE_SIZE |
| Type inquiry intrinsic functions | BIT_SIZE, DIGITS, EPSILON, HUGE, KIND, MAXEXPONENT, MINEXPONENT, NEW_LINE, PRECISION, RADIX, RANGE, TINY|
| 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 |
| 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 |
| 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 |
| Atomic intrinsic subroutines | ATOMIC_ADD |
| Collective intrinsic subroutines | CO_REDUCE |

Expand Down
5 changes: 5 additions & 0 deletions flang/include/flang/Runtime/command.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ extern "C" {
// integer kind.
std::int32_t RTNAME(ArgumentCount)();

// Try to get the the current date (same format as CTIME: convert to a string)
// Return a STATUS as described in the standard.
std::int32_t RTNAME(FDate)(
const Descriptor *argument = nullptr, const Descriptor *errmsg = nullptr);

// 16.9.82 GET_COMMAND
// Try to get the value of the whole command. All of the parameters are
// optional.
Expand Down
2 changes: 2 additions & 0 deletions flang/include/flang/Runtime/extensions.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ void FORTRAN_PROCEDURE_NAME(flush)(const int &unit);
// GNU Fortran 77 compatibility function IARGC.
std::int32_t FORTRAN_PROCEDURE_NAME(iargc)();

void FORTRAN_PROCEDURE_NAME(fdate)(std::int8_t *string, std::int64_t length);

// GNU Fortran 77 compatibility subroutine GETARG(N, ARG).
void FORTRAN_PROCEDURE_NAME(getarg)(
std::int32_t &n, std::int8_t *arg, std::int64_t length);
Expand Down
28 changes: 28 additions & 0 deletions flang/runtime/command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "flang/Runtime/descriptor.h"
#include <cstdlib>
#include <limits>
#include <time.h>

namespace Fortran::runtime {
std::int32_t RTNAME(ArgumentCount)() {
Expand Down Expand Up @@ -125,6 +126,33 @@ static bool FitsInDescriptor(
kind, terminator, value);
}

void removeNewLine(char *str) {
char *newlinePos = strchr(str, '\n');
if (newlinePos != NULL) {
*newlinePos = '\0'; // Replace with null terminator
}
}

std::int32_t RTNAME(FDate)(const Descriptor *value, const Descriptor *errmsg) {
FillWithSpaces(*value);

time_t current_time;
time(&current_time);

char *time_string = ctime(&current_time);
removeNewLine(time_string);
std::int64_t stringLen{StringLength(time_string)};
if (stringLen <= 0) {
return ToErrmsg(errmsg, StatMissingArgument);
}

if (value) {
return CopyToDescriptor(*value, time_string, stringLen, errmsg);
}

return StatOk;
}

std::int32_t RTNAME(GetCommandArgument)(std::int32_t n, const Descriptor *value,
const Descriptor *length, const Descriptor *errmsg, const char *sourceFile,
int line) {
Expand Down
5 changes: 5 additions & 0 deletions flang/runtime/extensions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ void FORTRAN_PROCEDURE_NAME(flush)(const int &unit) {
// RESULT = IARGC()
std::int32_t FORTRAN_PROCEDURE_NAME(iargc)() { return RTNAME(ArgumentCount)(); }

void FORTRAN_PROCEDURE_NAME(fdate)(std::int8_t *arg, std::int64_t length) {
Descriptor value{*Descriptor::Create(1, length, arg, 0)};
(void)RTNAME(FDate)(&value, nullptr);
}

// CALL GETARG(N, ARG)
void FORTRAN_PROCEDURE_NAME(getarg)(
std::int32_t &n, std::int8_t *arg, std::int64_t length) {
Expand Down
14 changes: 14 additions & 0 deletions flang/unittests/Runtime/CommandTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,12 @@ TEST_F(ZeroArguments, GetCommandArgument) {
CheckMissingArgumentValue(1);
}

TEST_F(ZeroArguments, FDate) {
CheckMissingArgumentValue(-1);
CheckArgumentValue(commandOnlyArgv[0], 0);
CheckMissingArgumentValue(1);
}

TEST_F(ZeroArguments, GetCommand) { CheckCommandValue(commandOnlyArgv, 1); }

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

TEST_F(OneArgument, FDate) {
CheckMissingArgumentValue(-1);
CheckArgumentValue(oneArgArgv[0], 0);
CheckArgumentValue(oneArgArgv[1], 1);
CheckMissingArgumentValue(2);
}

TEST_F(OneArgument, GetCommand) { CheckCommandValue(oneArgArgv, 2); }

static const char *severalArgsArgv[]{
Expand Down Expand Up @@ -284,6 +297,7 @@ TEST_F(SeveralArguments, ArgValueTooShort) {
ASSERT_NE(tooShort, nullptr);
EXPECT_EQ(RTNAME(GetCommandArgument)(1, tooShort.get()), -1);
CheckDescriptorEqStr(tooShort.get(), severalArgsArgv[1]);
EXPECT_EQ(RTNAME(FDate)(tooShort.get()), -1);

OwningPtr<Descriptor> length{EmptyIntDescriptor()};
ASSERT_NE(length, nullptr);
Expand Down