Index: flang/include/flang/Runtime/iostat.h =================================================================== --- flang/include/flang/Runtime/iostat.h +++ flang/include/flang/Runtime/iostat.h @@ -74,6 +74,9 @@ IostatBadWaitUnit, IostatBOZInputOverflow, IostatIntegerInputOverflow, + IostatRealInputOverflow, + IostatOpenAlreadyConnected, + IostatCannotReposition, }; const char *IostatErrorString(int); Index: flang/runtime/file.h =================================================================== --- flang/runtime/file.h +++ flang/runtime/file.h @@ -28,8 +28,8 @@ using FileOffset = std::int64_t; const char *path() const { return path_.get(); } - void set_path(OwningPtr &&, std::size_t bytes); std::size_t pathLength() const { return pathLength_; } + void set_path(OwningPtr &&, std::size_t bytes); bool mayRead() const { return mayRead_; } bool mayWrite() const { return mayWrite_; } bool mayPosition() const { return mayPosition_; } Index: flang/runtime/file.cpp =================================================================== --- flang/runtime/file.cpp +++ flang/runtime/file.cpp @@ -371,7 +371,7 @@ SetPosition(at); return true; } else { - handler.SignalErrno(); + handler.SignalError(IostatCannotReposition); return false; } } Index: flang/runtime/io-api.cpp =================================================================== --- flang/runtime/io-api.cpp +++ flang/runtime/io-api.cpp @@ -431,7 +431,9 @@ Terminator oom{sourceFile, sourceLine}; auto trimmed{ SaveDefaultCharacter(path, TrimTrailingSpaces(path, pathLength), oom)}; - if (ExternalFileUnit * unit{ExternalFileUnit::LookUp(trimmed.get())}) { + if (ExternalFileUnit * + unit{ExternalFileUnit::LookUp( + trimmed.get(), std::strlen(trimmed.get()))}) { // INQUIRE(FILE=) to a connected unit return &unit->BeginIoStatement( *unit, sourceFile, sourceLine); Index: flang/runtime/iostat.cpp =================================================================== --- flang/runtime/iostat.cpp +++ flang/runtime/iostat.cpp @@ -92,6 +92,13 @@ return "B/O/Z input value overflows variable"; case IostatIntegerInputOverflow: return "Integer input value overflows variable"; + case IostatRealInputOverflow: + return "Real or complex input value overflows type"; + case IostatCannotReposition: + return "Attempt to reposition a unit which is connected to a file that can " + "only be processed sequentially"; + case IostatOpenAlreadyConnected: + return "OPEN of file already connected to another unit"; default: return nullptr; } Index: flang/runtime/unit-map.h =================================================================== --- flang/runtime/unit-map.h +++ flang/runtime/unit-map.h @@ -37,9 +37,9 @@ } // Unit look-up by name is needed for INQUIRE(FILE="...") - ExternalFileUnit *LookUp(const char *path) { + ExternalFileUnit *LookUp(const char *path, std::size_t pathLen) { CriticalSection critical{lock_}; - return Find(path); + return Find(path, pathLen); } ExternalFileUnit &NewUnit(const Terminator &); @@ -84,7 +84,7 @@ } return nullptr; } - ExternalFileUnit *Find(const char *path); + ExternalFileUnit *Find(const char *path, std::size_t pathLen); ExternalFileUnit &Create(int, const Terminator &); Index: flang/runtime/unit-map.cpp =================================================================== --- flang/runtime/unit-map.cpp +++ flang/runtime/unit-map.cpp @@ -111,12 +111,13 @@ } } -ExternalFileUnit *UnitMap::Find(const char *path) { +ExternalFileUnit *UnitMap::Find(const char *path, std::size_t pathLen) { if (path) { // TODO: Faster data structure for (int j{0}; j < buckets_; ++j) { for (Chain *p{bucket_[j].get()}; p; p = p->next.get()) { - if (p->unit.path() && std::strcmp(p->unit.path(), path) == 0) { + if (p->unit.path() && p->unit.pathLength() == pathLen && + std::memcmp(p->unit.path(), path, pathLen) == 0) { return &p->unit; } } Index: flang/runtime/unit.h =================================================================== --- flang/runtime/unit.h +++ flang/runtime/unit.h @@ -50,7 +50,7 @@ int unit, const Terminator &, bool &wasExtant); static ExternalFileUnit &LookUpOrCreateAnonymous(int unit, Direction, std::optional isUnformatted, const Terminator &); - static ExternalFileUnit *LookUp(const char *path); + static ExternalFileUnit *LookUp(const char *path, std::size_t pathLen); static ExternalFileUnit &CreateNew(int unit, const Terminator &); static ExternalFileUnit *LookUpForClose(int unit); static ExternalFileUnit &NewUnit(const Terminator &, bool forChildIo); Index: flang/runtime/unit.cpp =================================================================== --- flang/runtime/unit.cpp +++ flang/runtime/unit.cpp @@ -73,8 +73,9 @@ return result; } -ExternalFileUnit *ExternalFileUnit::LookUp(const char *path) { - return GetUnitMap().LookUp(path); +ExternalFileUnit *ExternalFileUnit::LookUp( + const char *path, std::size_t pathLen) { + return GetUnitMap().LookUp(path, pathLen); } ExternalFileUnit &ExternalFileUnit::CreateNew( @@ -124,6 +125,16 @@ FlushOutput(handler); Close(CloseStatus::Keep, handler); } + if (newPath.get() && newPathLength > 0) { + if (const auto *already{ + GetUnitMap().LookUp(newPath.get(), newPathLength)}) { + handler.SignalError(IostatOpenAlreadyConnected, + "OPEN(UNIT=%d,FILE='%.*s'): file is already connected to unit %d", + unitNumber_, static_cast(newPathLength), newPath.get(), + already->unitNumber_); + return; + } + } set_path(std::move(newPath), newPathLength); Open(status.value_or(OpenStatus::Unknown), action, position, handler); auto totalBytes{knownSize()};