// $Id: Rw11UnitTerm.cpp 1114 2019-02-23 18:01:55Z mueller $ // // Copyright 2013-2018 by Walter F.J. Mueller // // This program is free software; you may redistribute and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation, either version 3, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for complete details. // // Revision History: // Date Rev Version Comment // 2018-12-19 1090 1.1.7 use RosPrintf(bool) // 2018-12-17 1085 1.1.6 use std::lock_guard instead of boost // 2018-12-14 1081 1.1.5 use std::bind instead of boost // 2018-12-09 1080 1.1.4 use HasVirt(); Virt() returns ref // 2018-12-01 1076 1.1.3 use unique_ptr // 2017-04-07 868 1.1.2 Dump(): add detail arg // 2017-02-25 855 1.1.1 RcvNext() --> RcvQueueNext(); WakeupCntl() now pure // 2013-05-03 515 1.1 use AttachDone(),DetachCleanup(),DetachDone() // 2013-04-13 504 1.0 Initial version // 2013-02-19 490 0.1 First draft // --------------------------------------------------------------------------- /*! \file \brief Implemenation of Rw11UnitTerm. */ #include #include "librtools/RparseUrl.hpp" #include "librtools/RosFill.hpp" #include "librtools/RosPrintf.hpp" #include "librtools/Rexception.hpp" #include "Rw11UnitTerm.hpp" using namespace std; using namespace std::placeholders; /*! \class Retro::Rw11UnitTerm \brief FIXME_docs */ // all method definitions in namespace Retro namespace Retro { //------------------------------------------+----------------------------------- //! Constructor Rw11UnitTerm::Rw11UnitTerm(Rw11Cntl* pcntl, size_t index) : Rw11UnitVirt(pcntl, index), fTo7bit(false), fToEnpc(false), fTi7bit(false), fRcvQueue(), fLogFname(), fLogStream(), fLogOptCrlf(false), fLogCrPend(false), fLogLfLast(false) { fStats.Define(kStatNPreAttDrop, "NPreAttDrop", "snd bytes dropped prior attach"); } //------------------------------------------+----------------------------------- //! Destructor Rw11UnitTerm::~Rw11UnitTerm() {} //------------------------------------------+----------------------------------- //! FIXME_docs const std::string& Rw11UnitTerm::ChannelId() const { if (HasVirt()) return Virt().ChannelId(); static string nil; return nil; } //------------------------------------------+----------------------------------- //! FIXME_docs void Rw11UnitTerm::SetLog(const std::string& fname) { if (fLogStream.is_open()) { if (fLogCrPend) fLogStream << "\r"; fLogCrPend = false; fLogStream.close(); } fLogFname.clear(); if (fname.length() == 0) return; RparseUrl purl; RerrMsg emsg; if (!purl.Set(fname, "|app|bck=|crlf|", emsg)) throw Rexception(emsg); if (!Rtools::CreateBackupFile(purl, emsg)) throw Rexception(emsg); ios_base::openmode mode = ios_base::out; if (purl.FindOpt("app")) mode |= ios_base::app; fLogStream.open(purl.Path(), mode); if (!fLogStream.is_open()) { throw Rexception("Rw11UnitTerm::SetLog", string("failed to open '")+purl.Path()+"'"); } fLogFname = fname; fLogOptCrlf = purl.FindOpt("crlf"); fLogCrPend = false; fLogLfLast = false; return; } //------------------------------------------+----------------------------------- //! FIXME_docs uint8_t Rw11UnitTerm::RcvQueueNext() { if (RcvQueueEmpty()) return 0; uint8_t ochr = fRcvQueue.front(); fRcvQueue.pop_front(); return ochr; } //------------------------------------------+----------------------------------- //! FIXME_docs size_t Rw11UnitTerm::Rcv(uint8_t* buf, size_t count) { uint8_t* p = buf; for (size_t i=0; i bufmod; const uint8_t* bufout = buf; size_t bufcnt = count; if (fTo7bit || fToEnpc) { for (size_t i=0; i=040 && ochr<177) || ochr=='\t' || ochr=='\n' || ochr=='\r') { bufmod.push_back(ochr); } else { if (ochr != 0) { bufmod.push_back('<'); bufmod.push_back('0' + ((ochr>>6)&07) ); bufmod.push_back('0' + ((ochr>>3)&07) ); bufmod.push_back('0' + (ochr &07) ); bufmod.push_back('>'); } } } else { bufmod.push_back(ochr); } } bufout = bufmod.data(); bufcnt = bufmod.size(); } if (fLogStream.is_open()) { for (size_t i=0; i \n // \r\r\n -> \n (any number of \r) // \n\r -> \n // \n\r\r -> \n (any number of \r) // and to ignore \0 chars if (fLogOptCrlf) { // crlf filtering on if (ochr == 0) continue; // ignore \0 chars if (fLogCrPend) { if (ochr == '\r') continue; // collapes multiple \r if (ochr != '\n') fLogStream << '\r'; // log \r if not followed by \n fLogCrPend = false; } if (ochr == '\r') { // \r seen fLogCrPend = !fLogLfLast; // remember \r if last wasn't \n continue; } } fLogStream << char(ochr); fLogLfLast = (ochr == '\n'); } } if (HasVirt()) { // if virtual device attached RerrMsg emsg; ok = Virt().Snd(bufout, bufcnt, emsg); // FIXME_code: handler errors } else { // no virtual device attached if (Name() == "tta0") { // is it main console ? for (size_t i=0; i lock(Connect()); bool que_empty_old = fRcvQueue.empty(); for (size_t i=0; i lock(Connect()); size_t size = fRcvQueue.size(); os << bl << " fRcvQueue.size: " << fRcvQueue.size() << endl; if (size > 0) { os << bl << " fRcvQueue: \""; size_t ocount = 0; for (size_t i=0; i= 50) { os << "..."; break; } uint8_t byt = fRcvQueue[i]; if (byt >= 040 && byt <= 0176) { os << char(byt); ocount += 1; } else { os << "<" << RosPrintf(byt,"o0",3) << ">"; ocount += 5; } } os << "\"" << endl; } } os << bl << " fLogFname: " << fLogFname << endl; os << bl << " fLogStream.is_open: " << RosPrintf(fLogStream.is_open())<::Dump(os, ind, " ^", detail); return; } //------------------------------------------+----------------------------------- //! FIXME_docs void Rw11UnitTerm::AttachDone() { Virt().SetupRcvCallback(std::bind(&Rw11UnitTerm::RcvCallback, this, _1, _2)); return; } } // end namespace Retro