<commit_before>/*******************************************************************************
 *
 * MIT License
 *
 * Copyright (c) 2019 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 *******************************************************************************/

#include <miopen/miopen.h>
#include <miopen/conv_algo_name.hpp>

#include <string>
#include <unordered_map>
namespace miopen {

miopenConvFwdAlgorithm_t StringToConvolutionFwdAlgo(const std::string& s)
{
    static const std::unordered_map<std::string, miopenConvFwdAlgorithm_t> data{
        {"miopenConvolutionFwdAlgoGEMM", miopenConvolutionFwdAlgoGEMM},
        {"miopenConvolutionFwdAlgoDirect", miopenConvolutionFwdAlgoDirect},
        {"miopenConvolutionFwdAlgoFFT", miopenConvolutionFwdAlgoFFT},
        {"miopenConvolutionFwdAlgoWinograd", miopenConvolutionFwdAlgoWinograd},
        {"miopenConvolutionFwdAlgoImplicitGEMM", miopenConvolutionFwdAlgoImplicitGEMM},
        {"miopenConvolutionFwdAlgoStaticCompiledGEMM", miopenConvolutionFwdAlgoStaticCompiledGEMM},
    };
    return data.at(s);
}

miopenConvBwdDataAlgorithm_t StringToConvolutionBwdDataAlgo(const std::string& s)
{
    static const std::unordered_map<std::string, miopenConvBwdDataAlgorithm_t> data{
        {"miopenConvolutionBwdDataAlgoGEMM", miopenConvolutionBwdDataAlgoGEMM},
        {"miopenConvolutionBwdDataAlgoDirect", miopenConvolutionBwdDataAlgoDirect},
        {"miopenConvolutionBwdDataAlgoFFT", miopenConvolutionBwdDataAlgoFFT},
        {"miopenConvolutionBwdDataAlgoWinograd", miopenConvolutionBwdDataAlgoWinograd},
        {"miopenTransposeBwdDataAlgoGEMM", miopenTransposeBwdDataAlgoGEMM},
        {"miopenConvolutionBwdDataAlgoImplicitGEMM", miopenConvolutionBwdDataAlgoImplicitGEMM},
    };
    return data.at(s);
}

miopenConvBwdWeightsAlgorithm_t StringToConvolutionBwdWeightsAlgo(const std::string& s)
{
    static const std::unordered_map<std::string, miopenConvBwdWeightsAlgorithm_t> data{
        {"miopenConvolutionBwdWeightsAlgoGEMM", miopenConvolutionBwdWeightsAlgoGEMM},
        {"miopenConvolutionBwdWeightsAlgoDirect", miopenConvolutionBwdWeightsAlgoDirect},
        {"miopenConvolutionBwdWeightsAlgoWinograd", miopenConvolutionBwdWeightsAlgoWinograd},
        {"miopenConvolutionBwdWeightsAlgoImplicitGEMM",
         miopenConvolutionBwdWeightsAlgoImplicitGEMM},
    };
    return data.at(s);
}

std::string ConvolutionAlgoToString(const miopenConvAlgorithm_t algo)
{
    switch(algo)
    {
    case miopenConvolutionAlgoGEMM: return "miopenConvolutionAlgoGEMM";
    case miopenConvolutionAlgoDirect: return "miopenConvolutionAlgoDirect";
    case miopenConvolutionAlgoFFT: return "miopenConvolutionAlgoFFT";
    case miopenConvolutionAlgoWinograd: return "miopenConvolutionAlgoWinograd";
    case miopenConvolutionAlgoImplicitGEMM: return "miopenConvolutionAlgoImplicitGEMM";
    case miopenConvolutionAlgoStaticCompiledGEMM: return "miopenConvolutionAlgoStaticCompiledGEMM";
    }
    return "<invalid algorithm>";
}

std::string ConvolutionAlgoToDirectionalString(const miopenConvAlgorithm_t algo,
                                               miopenConvDirection_t dir)
{

    switch(dir)
    {
    case miopenConvFwd:
    {
        switch(algo)
        {
        case miopenConvolutionAlgoGEMM: return "miopenConvolutionFwdAlgoGEMM";
        case miopenConvolutionAlgoDirect: return "miopenConvolutionFwdAlgoDirect";
        case miopenConvolutionAlgoFFT: return "miopenConvolutionFwdAlgoFFT";
        case miopenConvolutionAlgoWinograd: return "miopenConvolutionFwdAlgoWinograd";
        case miopenConvolutionAlgoImplicitGEMM: return "miopenConvolutionFwdAlgoImplicitGEMM";
        case miopenConvolutionAlgoStaticCompiledGEMM:
            return "miopenConvolutionFwdAlgoStaticCompiledGEMM";
        }
        break;
    }
    case miopenConvBwdData:
    {
        switch(algo)
        {
        case miopenConvolutionAlgoGEMM: return "miopenConvolutionBwdDataAlgoGEMM";
        case miopenConvolutionAlgoDirect: return "miopenConvolutionBwdDataAlgoDirect";
        case miopenConvolutionAlgoFFT: return "miopenConvolutionBwdDataAlgoFFT";
        case miopenConvolutionAlgoWinograd: return "miopenConvolutionBwdDataAlgoWinograd";
        case miopenConvolutionAlgoImplicitGEMM: return "miopenConvolutionBwdDataAlgoImplicitGEMM";
        case miopenConvolutionAlgoStaticCompiledGEMM: break;
        }
        break;
    }
    case miopenConvBwdWeights:
    {
        switch(algo)
        {
        case miopenConvolutionAlgoGEMM: return "miopenConvolutionBwdWeightsAlgoGEMM";
        case miopenConvolutionAlgoDirect: return "miopenConvolutionBwdWeightsAlgoDirect";
        case miopenConvolutionAlgoFFT: return "miopenConvolutionBwdWeightsAlgoFFT";
        case miopenConvolutionAlgoWinograd: return "miopenConvolutionBwdWeigthsAlgoWinograd";
        case miopenConvolutionAlgoImplicitGEMM:
            return "miopenConvolutionBwdWeightsAlgoImplicitGEMM";
        case miopenConvolutionAlgoStaticCompiledGEMM: break;
        }
        break;
    }
    }
    return "<invalid algorithm>";
}

// Interoperability of find-db (Find 1.0 API) and Immediate mode requires this:
static_assert(miopenConvolutionAlgoGEMM ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionFwdAlgoGEMM),
              "");
static_assert(miopenConvolutionAlgoGEMM ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionBwdDataAlgoGEMM),
              "");
static_assert(miopenConvolutionAlgoGEMM ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionBwdWeightsAlgoGEMM),
              "");

static_assert(miopenConvolutionAlgoDirect ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionFwdAlgoDirect),
              "");
static_assert(miopenConvolutionAlgoDirect ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionBwdDataAlgoDirect),
              "");
static_assert(miopenConvolutionAlgoDirect ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionBwdWeightsAlgoDirect),
              "");

static_assert(miopenConvolutionAlgoFFT ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionFwdAlgoFFT),
              "");
static_assert(miopenConvolutionAlgoFFT ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionBwdDataAlgoFFT),
              "");

static_assert(miopenConvolutionAlgoWinograd ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionFwdAlgoWinograd),
              "");
static_assert(miopenConvolutionAlgoWinograd ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionBwdDataAlgoWinograd),
              "");
static_assert(miopenConvolutionAlgoWinograd ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionBwdWeightsAlgoWinograd),
              "");

static_assert(miopenConvolutionAlgoImplicitGEMM ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionFwdAlgoImplicitGEMM),
              "");
static_assert(miopenConvolutionAlgoImplicitGEMM ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionBwdDataAlgoImplicitGEMM),
              "");
static_assert(miopenConvolutionAlgoImplicitGEMM ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionBwdWeightsAlgoImplicitGEMM),
              "");

} // namespace miopen
<commit_msg>algo-to-string-fix2(1) leftover (#2443)<commit_after>/*******************************************************************************
 *
 * MIT License
 *
 * Copyright (c) 2019 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 *******************************************************************************/

#include <miopen/miopen.h>
#include <miopen/conv_algo_name.hpp>

#include <string>
#include <unordered_map>
namespace miopen {

miopenConvFwdAlgorithm_t StringToConvolutionFwdAlgo(const std::string& s)
{
    static const std::unordered_map<std::string, miopenConvFwdAlgorithm_t> data{
        {"miopenConvolutionFwdAlgoGEMM", miopenConvolutionFwdAlgoGEMM},
        {"miopenConvolutionFwdAlgoDirect", miopenConvolutionFwdAlgoDirect},
        {"miopenConvolutionFwdAlgoFFT", miopenConvolutionFwdAlgoFFT},
        {"miopenConvolutionFwdAlgoWinograd", miopenConvolutionFwdAlgoWinograd},
        {"miopenConvolutionFwdAlgoImplicitGEMM", miopenConvolutionFwdAlgoImplicitGEMM},
        {"miopenConvolutionFwdAlgoStaticCompiledGEMM", miopenConvolutionFwdAlgoStaticCompiledGEMM},
    };
    return data.at(s);
}

miopenConvBwdDataAlgorithm_t StringToConvolutionBwdDataAlgo(const std::string& s)
{
    static const std::unordered_map<std::string, miopenConvBwdDataAlgorithm_t> data{
        {"miopenConvolutionBwdDataAlgoGEMM", miopenConvolutionBwdDataAlgoGEMM},
        {"miopenConvolutionBwdDataAlgoDirect", miopenConvolutionBwdDataAlgoDirect},
        {"miopenConvolutionBwdDataAlgoFFT", miopenConvolutionBwdDataAlgoFFT},
        {"miopenConvolutionBwdDataAlgoWinograd", miopenConvolutionBwdDataAlgoWinograd},
        {"miopenTransposeBwdDataAlgoGEMM", miopenTransposeBwdDataAlgoGEMM},
        {"miopenConvolutionBwdDataAlgoImplicitGEMM", miopenConvolutionBwdDataAlgoImplicitGEMM},
    };
    return data.at(s);
}

miopenConvBwdWeightsAlgorithm_t StringToConvolutionBwdWeightsAlgo(const std::string& s)
{
    static const std::unordered_map<std::string, miopenConvBwdWeightsAlgorithm_t> data{
        {"miopenConvolutionBwdWeightsAlgoGEMM", miopenConvolutionBwdWeightsAlgoGEMM},
        {"miopenConvolutionBwdWeightsAlgoDirect", miopenConvolutionBwdWeightsAlgoDirect},
        {"miopenConvolutionBwdWeightsAlgoWinograd", miopenConvolutionBwdWeightsAlgoWinograd},
        {"miopenConvolutionBwdWeightsAlgoImplicitGEMM",
         miopenConvolutionBwdWeightsAlgoImplicitGEMM},
    };
    return data.at(s);
}

std::string ConvolutionAlgoToString(const miopenConvAlgorithm_t algo)
{
    switch(algo)
    {
    case miopenConvolutionAlgoGEMM: return "miopenConvolutionAlgoGEMM";
    case miopenConvolutionAlgoDirect: return "miopenConvolutionAlgoDirect";
    case miopenConvolutionAlgoFFT: return "miopenConvolutionAlgoFFT";
    case miopenConvolutionAlgoWinograd: return "miopenConvolutionAlgoWinograd";
    case miopenConvolutionAlgoImplicitGEMM: return "miopenConvolutionAlgoImplicitGEMM";
    case miopenConvolutionAlgoStaticCompiledGEMM: return "miopenConvolutionAlgoStaticCompiledGEMM";
    }
    return "<invalid algorithm>";
}

std::string ConvolutionAlgoToDirectionalString(const miopenConvAlgorithm_t algo,
                                               miopenConvDirection_t dir)
{

    switch(dir)
    {
    case miopenConvFwd:
    {
        switch(algo)
        {
        case miopenConvolutionAlgoGEMM: return "miopenConvolutionFwdAlgoGEMM";
        case miopenConvolutionAlgoDirect: return "miopenConvolutionFwdAlgoDirect";
        case miopenConvolutionAlgoFFT: return "miopenConvolutionFwdAlgoFFT";
        case miopenConvolutionAlgoWinograd: return "miopenConvolutionFwdAlgoWinograd";
        case miopenConvolutionAlgoImplicitGEMM: return "miopenConvolutionFwdAlgoImplicitGEMM";
        case miopenConvolutionAlgoStaticCompiledGEMM:
            return "miopenConvolutionFwdAlgoStaticCompiledGEMM";
        }
        break;
    }
    case miopenConvBwdData:
    {
        switch(algo)
        {
        case miopenConvolutionAlgoGEMM: return "miopenConvolutionBwdDataAlgoGEMM";
        case miopenConvolutionAlgoDirect: return "miopenConvolutionBwdDataAlgoDirect";
        case miopenConvolutionAlgoFFT: return "miopenConvolutionBwdDataAlgoFFT";
        case miopenConvolutionAlgoWinograd: return "miopenConvolutionBwdDataAlgoWinograd";
        case miopenConvolutionAlgoImplicitGEMM: return "miopenConvolutionBwdDataAlgoImplicitGEMM";
        case miopenConvolutionAlgoStaticCompiledGEMM: break;
        }
        break;
    }
    case miopenConvBwdWeights:
    {
        switch(algo)
        {
        case miopenConvolutionAlgoGEMM: return "miopenConvolutionBwdWeightsAlgoGEMM";
        case miopenConvolutionAlgoDirect: return "miopenConvolutionBwdWeightsAlgoDirect";
        case miopenConvolutionAlgoFFT: return "miopenConvolutionBwdWeightsAlgoFFT";
        case miopenConvolutionAlgoWinograd: return "miopenConvolutionBwdWeightsAlgoWinograd";
        case miopenConvolutionAlgoImplicitGEMM:
            return "miopenConvolutionBwdWeightsAlgoImplicitGEMM";
        case miopenConvolutionAlgoStaticCompiledGEMM: break;
        }
        break;
    }
    }
    return "<invalid algorithm>";
}

// Interoperability of find-db (Find 1.0 API) and Immediate mode requires this:
static_assert(miopenConvolutionAlgoGEMM ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionFwdAlgoGEMM),
              "");
static_assert(miopenConvolutionAlgoGEMM ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionBwdDataAlgoGEMM),
              "");
static_assert(miopenConvolutionAlgoGEMM ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionBwdWeightsAlgoGEMM),
              "");

static_assert(miopenConvolutionAlgoDirect ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionFwdAlgoDirect),
              "");
static_assert(miopenConvolutionAlgoDirect ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionBwdDataAlgoDirect),
              "");
static_assert(miopenConvolutionAlgoDirect ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionBwdWeightsAlgoDirect),
              "");

static_assert(miopenConvolutionAlgoFFT ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionFwdAlgoFFT),
              "");
static_assert(miopenConvolutionAlgoFFT ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionBwdDataAlgoFFT),
              "");

static_assert(miopenConvolutionAlgoWinograd ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionFwdAlgoWinograd),
              "");
static_assert(miopenConvolutionAlgoWinograd ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionBwdDataAlgoWinograd),
              "");
static_assert(miopenConvolutionAlgoWinograd ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionBwdWeightsAlgoWinograd),
              "");

static_assert(miopenConvolutionAlgoImplicitGEMM ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionFwdAlgoImplicitGEMM),
              "");
static_assert(miopenConvolutionAlgoImplicitGEMM ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionBwdDataAlgoImplicitGEMM),
              "");
static_assert(miopenConvolutionAlgoImplicitGEMM ==
                  static_cast<miopenConvAlgorithm_t>(miopenConvolutionBwdWeightsAlgoImplicitGEMM),
              "");

} // namespace miopen
<|endoftext|>


<commit_before>// @(#)root/krb5auth:$Name: PROOF_MLM $:$Id: TKSocket.cxx,v 1.1.4.2 2004/11/02 22:02:54 maartenb Exp $
// Author: Maarten Ballintijn   27/10/2003

#include "config.h"
#include <stdlib.h>

#include <netinet/in.h>

#include "TKSocket.h"
#include "TSocket.h"
#include "TError.h"

extern "C" {
// missing from "krb5.h"
extern int krb5_net_read(/*IN*/ krb5_context context, int fd,
                         /*OUT*/ char *buf,/*IN*/ int len);

extern int krb5_net_write(/*IN*/ krb5_context context, int fd,
                          const char *buf, int len);
}

ClassImp(TKSocket)

krb5_context TKSocket::fgContext = 0;
krb5_ccache TKSocket::fgCCDef = 0;
krb5_principal TKSocket::fgClient = 0;

TKSocket::TKSocket(TSocket *s)
   : fSocket(s), fServer(0), fAuthContext(0)
{
}

TKSocket::~TKSocket()
{
   krb5_free_principal(fgContext, fServer);
   krb5_auth_con_free(fgContext, fAuthContext);
   delete fSocket;
}

TKSocket *TKSocket::Connect(const char *server, Int_t port)
{
   Int_t rc;

   if (fgContext == 0) {
      rc = krb5_init_context(&fgContext);
      if (rc != 0) {
         ::Error("TKSocket::Connect","while initializing krb5 (%d), %s",
                 rc, error_message(rc));
         return 0;
      }

      rc = krb5_cc_default(fgContext, &fgCCDef);
      if (rc != 0) {
         ::Error("TKSocket::Connect","while getting default credential cache (%d), %s",
                 rc, error_message(rc));
         krb5_free_context(fgContext); fgContext = 0;
         return 0;
      }

      rc = krb5_cc_get_principal(fgContext, fgCCDef, &fgClient);
      if (rc != 0) {
         ::Error("TKSocket::Connect","while getting client principal from %s (%d), %s",
                 krb5_cc_get_name(fgContext,fgCCDef), rc, error_message(rc));
         krb5_cc_close(fgContext,fgCCDef); fgCCDef = 0;
         krb5_free_context(fgContext); fgContext = 0;
         return 0;
      }
   }

   TSocket  *s = new TSocket(server, port);

   if (!s->IsValid()) {
      ::SysError("TKSocket::Connect","Cannot connect to %s:%d", server, port);
      delete s;
      return 0;
   }

   TKSocket *ks = new TKSocket(s);

   rc = krb5_sname_to_principal(fgContext, server, "host", KRB5_NT_SRV_HST, &ks->fServer);
   if (rc != 0) {
      ::Error("TKSocket::Connect","while getting server principal (%d), %s",
              rc, error_message(rc));
      delete ks;
      return 0;
   }

   krb5_data cksum_data;
   cksum_data.data = StrDup(server);
   cksum_data.length = strlen(server);

   krb5_error *err_ret;
   krb5_ap_rep_enc_part *rep_ret;

   int sock = ks->fSocket->GetDescriptor();
   rc = krb5_sendauth(fgContext, &ks->fAuthContext, (krb5_pointer) &sock,
                           "KRB5_TCP_Python_v1.0", fgClient, ks->fServer,
                           AP_OPTS_MUTUAL_REQUIRED,
                           &cksum_data,
                           0,           /* no creds, use ccache instead */
                           fgCCDef, &err_ret, &rep_ret, NULL);

   delete [] cksum_data.data;

   if (rc != 0) {
      ::Error("TKSocket::Connect","while sendauth (%d), %s",
              rc, error_message(rc));
      delete ks;
      return 0;
   }

   return ks;
}

Int_t TKSocket::BlockRead(char *&buf, EEncoding &type)
{
   Int_t rc;
   TDesc desc;
   Int_t fd = fSocket->GetDescriptor();

   rc = krb5_net_read(fgContext, fd, (char *)&desc, sizeof(desc));
   if (rc == 0) errno = ECONNABORTED;

   if (rc <= 0) {
      SysError("BlockRead","reading descriptor (%d), %s",
               rc, error_message(rc));
      return -1;
   }

   type = static_cast<EEncoding>(ntohs(desc.type));

   krb5_data enc;
   enc.length = ntohs(desc.length);
   enc.data = new char[enc.length+1];

Info("BlockRead","read descriptor (%d bytes): lenght %d, type %d",sizeof(desc), enc.length, type);

   rc = krb5_net_read(fgContext, fd, enc.data, enc.length);
   enc.data[enc.length] = 0;

   if (rc == 0) errno = ECONNABORTED;

   if (rc <= 0) {
      SysError("BlockRead","reading data (%d), %s",
               rc, error_message(rc));
      return -1;
   } else {
Info("BlockRead","read %d bytes (rc=%d)",enc.length, rc);
   }

   krb5_data out;
   switch (type) {
   case kNone:
         buf = enc.data;
         rc = enc.length;
         break;
   case kSafe:
         rc = krb5_rd_safe(fgContext, fAuthContext, &enc, &out, 0);
         break;
   case kPriv:
         rc = krb5_rd_priv(fgContext, fAuthContext, &enc, &out, 0);
         break;
   default:
         Error("BlockWrite","unknown encoding type (%d)", type);
         return -1;
   }

   if (type != kNone) {
      // copy data to buffer that is new'ed
      buf = new char[out.length+1];
      memcpy(buf, out.data,out.length);
      buf[out.length] = 0;
      free(out.data);
      delete enc.data;
      rc = out.length;
   }

   return rc;
}

Int_t TKSocket::BlockWrite(const char *buf, Int_t length, EEncoding type)
{
   TDesc desc;
   krb5_data in;
   krb5_data enc;
   Int_t rc;
   in.data = const_cast<char*>(buf);
   in.length = length;

   switch (type) {
   case kNone:
         enc.data = in.data;
         enc.length = in.length;
         break;
   case kSafe:
         rc = krb5_mk_safe(fgContext, fAuthContext, &in, &enc, 0);
         break;
   case kPriv:
         rc = krb5_mk_priv(fgContext, fAuthContext, &in, &enc, 0);
         break;
   default:
         Error("BlockWrite","unknown encoding type (%d)", type);
         return -1;
   }

   desc.length = htons(enc.length);
   desc.type = htons(type);

   Int_t fd = fSocket->GetDescriptor();
   rc = krb5_net_write(fgContext, fd, (char *)&desc, sizeof(desc));
   if (rc <= 0) {
      Error("BlockWrite","writing descriptor (%d), %s",
            rc, error_message(rc));
      return -1;
   }

   rc = krb5_net_write(fgContext, fd, (char *)enc.data, enc.length);
   if (rc <= 0) {
      Error("BlockWrite","writing data (%d), %s",
            rc, error_message(rc));
      return -1;
   }

   if (type != kNone) free(enc.data);

   return rc;
}
<commit_msg>include <sys/types.h> is needed on MacOS X.<commit_after>// @(#)root/krb5auth:$Name:  $:$Id: TKSocket.cxx,v 1.1 2005/02/07 18:02:36 rdm Exp $
// Author: Maarten Ballintijn   27/10/2003

#include "config.h"
#include <stdlib.h>

#include <sys/types.h>
#include <netinet/in.h>

#include "TKSocket.h"
#include "TSocket.h"
#include "TError.h"

extern "C" {
// missing from "krb5.h"
extern int krb5_net_read(/*IN*/ krb5_context context, int fd,
                         /*OUT*/ char *buf,/*IN*/ int len);

extern int krb5_net_write(/*IN*/ krb5_context context, int fd,
                          const char *buf, int len);
}

ClassImp(TKSocket)

krb5_context TKSocket::fgContext = 0;
krb5_ccache TKSocket::fgCCDef = 0;
krb5_principal TKSocket::fgClient = 0;

TKSocket::TKSocket(TSocket *s)
   : fSocket(s), fServer(0), fAuthContext(0)
{
}

TKSocket::~TKSocket()
{
   krb5_free_principal(fgContext, fServer);
   krb5_auth_con_free(fgContext, fAuthContext);
   delete fSocket;
}

TKSocket *TKSocket::Connect(const char *server, Int_t port)
{
   Int_t rc;

   if (fgContext == 0) {
      rc = krb5_init_context(&fgContext);
      if (rc != 0) {
         ::Error("TKSocket::Connect","while initializing krb5 (%d), %s",
                 rc, error_message(rc));
         return 0;
      }

      rc = krb5_cc_default(fgContext, &fgCCDef);
      if (rc != 0) {
         ::Error("TKSocket::Connect","while getting default credential cache (%d), %s",
                 rc, error_message(rc));
         krb5_free_context(fgContext); fgContext = 0;
         return 0;
      }

      rc = krb5_cc_get_principal(fgContext, fgCCDef, &fgClient);
      if (rc != 0) {
         ::Error("TKSocket::Connect","while getting client principal from %s (%d), %s",
                 krb5_cc_get_name(fgContext,fgCCDef), rc, error_message(rc));
         krb5_cc_close(fgContext,fgCCDef); fgCCDef = 0;
         krb5_free_context(fgContext); fgContext = 0;
         return 0;
      }
   }

   TSocket  *s = new TSocket(server, port);

   if (!s->IsValid()) {
      ::SysError("TKSocket::Connect","Cannot connect to %s:%d", server, port);
      delete s;
      return 0;
   }

   TKSocket *ks = new TKSocket(s);

   rc = krb5_sname_to_principal(fgContext, server, "host", KRB5_NT_SRV_HST, &ks->fServer);
   if (rc != 0) {
      ::Error("TKSocket::Connect","while getting server principal (%d), %s",
              rc, error_message(rc));
      delete ks;
      return 0;
   }

   krb5_data cksum_data;
   cksum_data.data = StrDup(server);
   cksum_data.length = strlen(server);

   krb5_error *err_ret;
   krb5_ap_rep_enc_part *rep_ret;

   int sock = ks->fSocket->GetDescriptor();
   rc = krb5_sendauth(fgContext, &ks->fAuthContext, (krb5_pointer) &sock,
                           "KRB5_TCP_Python_v1.0", fgClient, ks->fServer,
                           AP_OPTS_MUTUAL_REQUIRED,
                           &cksum_data,
                           0,           /* no creds, use ccache instead */
                           fgCCDef, &err_ret, &rep_ret, NULL);

   delete [] cksum_data.data;

   if (rc != 0) {
      ::Error("TKSocket::Connect","while sendauth (%d), %s",
              rc, error_message(rc));
      delete ks;
      return 0;
   }

   return ks;
}

Int_t TKSocket::BlockRead(char *&buf, EEncoding &type)
{
   Int_t rc;
   TDesc desc;
   Int_t fd = fSocket->GetDescriptor();

   rc = krb5_net_read(fgContext, fd, (char *)&desc, sizeof(desc));
   if (rc == 0) errno = ECONNABORTED;

   if (rc <= 0) {
      SysError("BlockRead","reading descriptor (%d), %s",
               rc, error_message(rc));
      return -1;
   }

   type = static_cast<EEncoding>(ntohs(desc.type));

   krb5_data enc;
   enc.length = ntohs(desc.length);
   enc.data = new char[enc.length+1];

Info("BlockRead","read descriptor (%d bytes): lenght %d, type %d",sizeof(desc), enc.length, type);

   rc = krb5_net_read(fgContext, fd, enc.data, enc.length);
   enc.data[enc.length] = 0;

   if (rc == 0) errno = ECONNABORTED;

   if (rc <= 0) {
      SysError("BlockRead","reading data (%d), %s",
               rc, error_message(rc));
      return -1;
   } else {
Info("BlockRead","read %d bytes (rc=%d)",enc.length, rc);
   }

   krb5_data out;
   switch (type) {
   case kNone:
         buf = enc.data;
         rc = enc.length;
         break;
   case kSafe:
         rc = krb5_rd_safe(fgContext, fAuthContext, &enc, &out, 0);
         break;
   case kPriv:
         rc = krb5_rd_priv(fgContext, fAuthContext, &enc, &out, 0);
         break;
   default:
         Error("BlockWrite","unknown encoding type (%d)", type);
         return -1;
   }

   if (type != kNone) {
      // copy data to buffer that is new'ed
      buf = new char[out.length+1];
      memcpy(buf, out.data,out.length);
      buf[out.length] = 0;
      free(out.data);
      delete enc.data;
      rc = out.length;
   }

   return rc;
}

Int_t TKSocket::BlockWrite(const char *buf, Int_t length, EEncoding type)
{
   TDesc desc;
   krb5_data in;
   krb5_data enc;
   Int_t rc;
   in.data = const_cast<char*>(buf);
   in.length = length;

   switch (type) {
   case kNone:
         enc.data = in.data;
         enc.length = in.length;
         break;
   case kSafe:
         rc = krb5_mk_safe(fgContext, fAuthContext, &in, &enc, 0);
         break;
   case kPriv:
         rc = krb5_mk_priv(fgContext, fAuthContext, &in, &enc, 0);
         break;
   default:
         Error("BlockWrite","unknown encoding type (%d)", type);
         return -1;
   }

   desc.length = htons(enc.length);
   desc.type = htons(type);

   Int_t fd = fSocket->GetDescriptor();
   rc = krb5_net_write(fgContext, fd, (char *)&desc, sizeof(desc));
   if (rc <= 0) {
      Error("BlockWrite","writing descriptor (%d), %s",
            rc, error_message(rc));
      return -1;
   }

   rc = krb5_net_write(fgContext, fd, (char *)enc.data, enc.length);
   if (rc <= 0) {
      Error("BlockWrite","writing data (%d), %s",
            rc, error_message(rc));
      return -1;
   }

   if (type != kNone) free(enc.data);

   return rc;
}
<|endoftext|>


<commit_before>/**
 * This file implements the event logging.
 */

#include <d2/detail/basic_mutex.hpp>
#include <d2/events.hpp>

#define BOOST_SPIRIT_DEBUG 0
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/assert.hpp>
#include <boost/phoenix.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/qi.hpp>
#include <cstddef>
#include <iostream>
#include <iterator>
#include <vector>

namespace qi = boost::spirit::qi;
namespace karma = boost::spirit::karma;
namespace phx = boost::phoenix;
namespace fsn = boost::fusion;

namespace d2 {
namespace detail {

template <typename Iterator>
struct event_parser : qi::grammar<Iterator, event()> {
    event_parser() : event_parser::base_type(one_event) {
        using namespace qi;

        typedef stream_parser<char, thread> ThreadParser;
        typedef stream_parser<char, sync_object> SyncObjectParser;

        one_event %= skip(ascii::space)[acquire | release | start | join];

        acquire
            =   (ThreadParser() >> lit("acquires") >> SyncObjectParser())
            [
                _val = phx::construct<acquire_event>(_2, _1)
            ]
            ;

        release
            =   (ThreadParser() >> lit("releases") >> SyncObjectParser())
            [
                _val = phx::construct<release_event>(_2, _1)
            ]
            ;

        start
            =   (ThreadParser() >> lit("starts") >> ThreadParser())
            [
                _val = phx::construct<start_event>(_1, _2)
            ]
            ;

        join
            =   (ThreadParser() >> lit("joins") >> ThreadParser())
            [
                _val = phx::construct<join_event>(_1, _2)
            ]
            ;

#if BOOST_SPIRIT_DEBUG
        BOOST_SPIRIT_DEBUG_NODE(one_event);
        BOOST_SPIRIT_DEBUG_NODE(acquire);
        BOOST_SPIRIT_DEBUG_NODE(release);
        BOOST_SPIRIT_DEBUG_NODE(start);
        BOOST_SPIRIT_DEBUG_NODE(join);
#endif
    }

private:
    qi::rule<Iterator, event()> one_event;
    qi::rule<Iterator, acquire_event()> acquire;
    qi::rule<Iterator, release_event()> release;
    qi::rule<Iterator, start_event()> start;
    qi::rule<Iterator, join_event()> join;
};

template <typename Iterator>
struct event_generator : karma::grammar<Iterator, event()> {

    event_generator() : event_generator::base_type(one_event) {
        using namespace karma;

        one_event = (acquire | release | start | join);

        acquire
            =   (stream << " acquires " << stream)
            [
                _1 = &_val->*&acquire_event::thread,
                _2 = &_val->*&acquire_event::lock
            ]
            ;

        release
            =   (stream << " releases " << stream)
            [
                _1 = &_val->*&release_event::thread,
                _2 = &_val->*&release_event::lock
            ]
            ;

        start
            =   (stream << " starts " << stream)
            [
                _1 = &_val->*&start_event::parent,
                _2 = &_val->*&start_event::child
            ]
            ;

        join
            =   (stream << " joins " << stream)
            [
                _1 = &_val->*&join_event::parent,
                _2 = &_val->*&join_event::child
            ]
            ;
    }

private:
    karma::rule<Iterator, event()> one_event;
    karma::rule<Iterator, acquire_event()> acquire;
    karma::rule<Iterator, release_event()> release;
    karma::rule<Iterator, start_event()> start;
    karma::rule<Iterator, join_event()> join;
};

static basic_mutex sink_lock;
static bool is_enabled = false;
static std::ostream* event_sink = NULL;
static event_generator<std::ostream_iterator<char> > generate_event;

extern void push_event_impl(event const& e) {
    sink_lock.lock();
    if (is_enabled) {
        BOOST_ASSERT_MSG(event_sink != NULL,
                                    "logging events in an invalid NULL sink");

        bool success = karma::generate(
                        std::ostream_iterator<char>(*event_sink),
                        generate_event,
                        e);
        // until we fix the generate_event << '\n' problem
        *event_sink << '\n';
        (void)success;

        BOOST_ASSERT_MSG(success,
                    "unable to generate the event using the karma generator");
    }
    sink_lock.unlock();
}

} // end namespace detail

extern void set_event_sink(std::ostream* sink) {
    BOOST_ASSERT_MSG(sink != NULL, "setting an invalid NULL sink");
    detail::sink_lock.lock();
    detail::event_sink = sink;
    detail::sink_lock.unlock();
}

extern void disable_event_logging() {
    detail::sink_lock.lock();
    detail::is_enabled = false;
    detail::sink_lock.unlock();
}

extern void enable_event_logging() {
    detail::sink_lock.lock();
    detail::is_enabled = true;
    detail::sink_lock.unlock();
}

extern std::vector<event> load_events(std::istream& source) {
    detail::event_parser<std::string::const_iterator> parse_event;
    std::string const input((std::istream_iterator<char>(source)),
                             std::istream_iterator<char>());

    std::vector<event> events;
    std::string::const_iterator first(boost::begin(input)),
                                last(boost::end(input));
    bool success = qi::parse(first, last, parse_event % '\n', events);
    (void)success;
    BOOST_ASSERT_MSG(success && first == last,
                            "unable to parse events using the qi grammar");

    return events;
}

} // end namespace d2
<commit_msg>Fix qi parsing of events.<commit_after>/**
 * This file implements the event logging.
 */

#include <d2/detail/basic_mutex.hpp>
#include <d2/events.hpp>

#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/assert.hpp>
#include <boost/phoenix.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/qi.hpp>
#include <cstddef>
#include <iostream>
#include <iterator>
#include <vector>

namespace qi = boost::spirit::qi;
namespace karma = boost::spirit::karma;
namespace phx = boost::phoenix;
namespace fsn = boost::fusion;

namespace d2 {
namespace detail {

template <typename Iterator>
struct event_parser : qi::grammar<Iterator, event()> {
    event_parser() : event_parser::base_type(one_event) {
        using namespace qi;

        one_event %= skip(ascii::space)[acquire | release | start | join];

        acquire
            =   (parse_thread >> "acquires" >> parse_sync_object)
            [
                _val = phx::construct<acquire_event>(_2, _1)
            ]
            ;

        release
            =   (parse_thread >> "releases" >> parse_sync_object)
            [
                _val = phx::construct<release_event>(_2, _1)
            ]
            ;

        start
            =   (parse_thread >> "starts" >> parse_thread)
            [
                _val = phx::construct<start_event>(_1, _2)
            ]
            ;

        join
            =   (parse_thread >> "joins" >> parse_thread)
            [
                _val = phx::construct<join_event>(_1, _2)
            ]
            ;

        parse_sync_object %= stream_parser<char, sync_object>();

        parse_thread %= stream_parser<char, thread>();
    }

private:
    qi::rule<Iterator, event()> one_event;
    qi::rule<Iterator, acquire_event()> acquire;
    qi::rule<Iterator, release_event()> release;
    qi::rule<Iterator, start_event()> start;
    qi::rule<Iterator, join_event()> join;
    qi::rule<Iterator, sync_object()> parse_sync_object;
    qi::rule<Iterator, thread()> parse_thread;
};

template <typename Iterator>
struct event_generator : karma::grammar<Iterator, event()> {

    event_generator() : event_generator::base_type(one_event) {
        using namespace karma;

        one_event = (acquire | release | start | join);

        acquire
            =   (stream << " acquires " << stream)
            [
                _1 = &_val->*&acquire_event::thread,
                _2 = &_val->*&acquire_event::lock
            ]
            ;

        release
            =   (stream << " releases " << stream)
            [
                _1 = &_val->*&release_event::thread,
                _2 = &_val->*&release_event::lock
            ]
            ;

        start
            =   (stream << " starts " << stream)
            [
                _1 = &_val->*&start_event::parent,
                _2 = &_val->*&start_event::child
            ]
            ;

        join
            =   (stream << " joins " << stream)
            [
                _1 = &_val->*&join_event::parent,
                _2 = &_val->*&join_event::child
            ]
            ;
    }

private:
    karma::rule<Iterator, event()> one_event;
    karma::rule<Iterator, acquire_event()> acquire;
    karma::rule<Iterator, release_event()> release;
    karma::rule<Iterator, start_event()> start;
    karma::rule<Iterator, join_event()> join;
};

static basic_mutex sink_lock;
static bool is_enabled = false;
static std::ostream* event_sink = NULL;
static event_generator<std::ostream_iterator<char> > generate_event;

extern void push_event_impl(event const& e) {
    sink_lock.lock();
    if (is_enabled) {
        BOOST_ASSERT_MSG(event_sink != NULL,
                                    "logging events in an invalid NULL sink");

        bool success = karma::generate(
                        std::ostream_iterator<char>(*event_sink),
                        generate_event,
                        e);
        // until we fix the generate_event << '\n' problem
        *event_sink << '\n';
        (void)success;

        BOOST_ASSERT_MSG(success,
                    "unable to generate the event using the karma generator");
    }
    sink_lock.unlock();
}

} // end namespace detail

extern void set_event_sink(std::ostream* sink) {
    BOOST_ASSERT_MSG(sink != NULL, "setting an invalid NULL sink");
    detail::sink_lock.lock();
    detail::event_sink = sink;
    detail::sink_lock.unlock();
}

extern void disable_event_logging() {
    detail::sink_lock.lock();
    detail::is_enabled = false;
    detail::sink_lock.unlock();
}

extern void enable_event_logging() {
    detail::sink_lock.lock();
    detail::is_enabled = true;
    detail::sink_lock.unlock();
}

extern std::vector<event> load_events(std::istream& source) {
    detail::event_parser<std::string::const_iterator> parse_event;
    std::string const input((std::istream_iterator<char>(source)),
                             std::istream_iterator<char>());

    std::vector<event> events;
    std::string::const_iterator first(boost::begin(input)),
                                last(boost::end(input));
    bool success = qi::parse(first, last, parse_event % '\n', events);
    (void)success;
    BOOST_ASSERT_MSG(success && first == last,
                            "unable to parse events using the qi grammar");

    return events;
}

} // end namespace d2
<|endoftext|>


<commit_before>/*
    This file is part of KMail, the KDE mail client.
    Copyright (c) 2000 Don Sanders <sanders@kde.org>

    KMail is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License, version 2, as
    published by the Free Software Foundation.

    KMail 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 more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include <config.h>

#include "kmstartup.h"

#include "kmkernel.h" //control center
#include "kcursorsaver.h"

#include <klocale.h>
#include <ksimpleconfig.h>
#include <kstandarddirs.h>
#include <kmessagebox.h>
#include <dcopclient.h>
#include <kcrash.h>
#include <kglobal.h>
#include <kapplication.h>
#include <kaboutdata.h>
#include <kiconloader.h>

#include <errno.h>
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#undef Status // stupid X headers

extern "C" {

// Crash recovery signal handler
void kmsignalHandler(int sigId)
{
  kmsetSignalHandler(SIG_DFL);
  fprintf(stderr, "*** KMail got signal %d (Exiting)\n", sigId);
  // try to cleanup all windows
  if (kmkernel) kmkernel->dumpDeadLetters();
  ::exit(-1); //
}

// Crash recovery signal handler
void kmcrashHandler(int sigId)
{
  kmsetSignalHandler(SIG_DFL);
  fprintf(stderr, "*** KMail got signal %d (Crashing)\n", sigId);
  // try to cleanup all windows
  if (kmkernel) kmkernel->dumpDeadLetters();
  // Return to DrKonqi.
}
//-----------------------------------------------------------------------------

void kmsetSignalHandler(void (*handler)(int))
{
  signal(SIGKILL, handler);
  signal(SIGTERM, handler);
  signal(SIGHUP,  handler);
  KCrash::setEmergencySaveFunction(kmcrashHandler);
}

}
//-----------------------------------------------------------------------------

namespace {
  QString getMyHostName() {
    char hostNameC[256];
    // null terminate this C string
    hostNameC[255] = 0;
    // set the string to 0 length if gethostname fails
    if(gethostname(hostNameC, 255))
      hostNameC[0] = 0;
    return QString::fromLocal8Bit(hostNameC);
  }
} // anon namespace

namespace KMail {

void checkConfigUpdates() {
  static const char * const updates[] = {
    "9",
    "3.1-update-identities",
    "3.1-use-identity-uoids",
    "3.1-new-mail-notification",
    "3.2-update-loop-on-goto-unread-settings",
    "3.1.4-dont-use-UOID-0-for-any-identity",
    "3.2-misc",
    "3.2-moves",
    "3.3-use-ID-for-accounts",
    "3.3-update-filter-rules",
    "3.3-move-identities-to-own-file",
    "3.3-aegypten-kpgprc-to-kmailrc",
    "3.3-aegypten-kpgprc-to-libkleopatrarc",
    "3.3-aegypten-emailidentities-split-sign-encr-keys",
    "3.3-misc",
    "3.3b1-misc",
    "3.4-misc",
    "3.4a",
    "3.4b",
    "3.4.1"
  };
  static const int numUpdates = sizeof updates / sizeof *updates;
  // Warning: do not remove entries in the above array, or the update-level check below will break

  KConfig * config = KMKernel::config();
  KConfigGroup startup( config, "Startup" );
  const int configUpdateLevel = startup.readNumEntry( "update-level", 0 );
  if ( configUpdateLevel == numUpdates ) // Optimize for the common case that everything is OK
    return;

  for ( int i = configUpdateLevel ; i < numUpdates ; ++i ) {
    config->checkUpdate( updates[i], "kmail.upd" );
  }
  startup.writeEntry( "update-level", numUpdates );
}

void lockOrDie() {
// Check and create a lock file to prevent concurrent access to kmail files
  QString appName = kapp->instanceName();
  if ( appName.isEmpty() )
    appName = "kmail";

  QString programName;
  const KAboutData *about = kapp->aboutData();
  if ( about )
    programName = about->programName();
  if ( programName.isEmpty() )
    programName = i18n("KMail");

  QString lockLocation = locateLocal("data", "kmail/lock");
  KSimpleConfig config(lockLocation);
  int oldPid = config.readNumEntry("pid", -1);
  const QString oldHostName = config.readEntry("hostname");
  const QString oldAppName = config.readEntry( "appName", appName );
  const QString oldProgramName = config.readEntry( "programName", programName );
  const QString hostName = getMyHostName();
  bool first_instance = false;
  if ( oldPid == -1 )
      first_instance = true;
  // check if the lock file is stale by trying to see if
  // the other pid is currently running.
  // Not 100% correct but better safe than sorry
  else if (hostName == oldHostName && oldPid != getpid()) {
      if ( kill(oldPid, 0) == -1 )
          first_instance = ( errno == ESRCH );
  }

  if ( !first_instance ) {
    QString msg;
    if ( oldHostName == hostName ) {
      // this can only happen if the user is running this application on
      // different displays on the same machine. All other cases will be
      // taken care of by KUniqueApplication()
      if ( oldAppName == appName )
        msg = i18n("%1 already seems to be running on another display on "
                   "this machine. Running %2 more than once "
                   "can cause the loss of mail. You should not start %1 "
                   "unless you are sure that it is not already running.")
              .arg( programName, programName );
              // QString::arg( st ) only replaces the first occurrence of %1
              // with st while QString::arg( s1, s2 ) replacess all occurrences
              // of %1 with s1 and all occurrences of %2 with s2. So don't
              // even think about changing the above to .arg( programName ).
      else
        msg = i18n("%1 seems to be running on another display on this "
                   "machine. Running %1 and %2 at the same "
                   "time can cause the loss of mail. You should not start %2 "
                   "unless you are sure that %1 is not running.")
              .arg( oldProgramName, programName );
    }
    else {
      if ( oldAppName == appName )
        msg = i18n("%1 already seems to be running on %2. Running %1 more "
                   "than once can cause the loss of mail. You should not "
                   "start %1 on this computer unless you are sure that it is "
                   "not already running on %2.")
              .arg( programName, oldHostName );
      else
        msg = i18n("%1 seems to be running on %3. Running %1 and %2 at the "
                   "same time can cause the loss of mail. You should not "
                   "start %2 on this computer unless you are sure that %1 is "
                   "not running on %3.")
              .arg( oldProgramName, programName, oldHostName );
    }

    KCursorSaver idle( KBusyPtr::idle() );
    if ( KMessageBox::No ==
         KMessageBox::warningYesNo( 0, msg, QString::null,
                                    i18n("Start %1").arg( programName ),
                                    i18n("Exit") ) ) {
      exit(1);
    }
  }

  config.writeEntry("pid", getpid());
  config.writeEntry("hostname", hostName);
  config.writeEntry( "appName", appName );
  config.writeEntry( "programName", programName );
  config.sync();
}

void insertLibraryCataloguesAndIcons() {
  static const char * const catalogues[] = {
    "libkdenetwork",
    "libkdepim",
    "libksieve",
    "libkleopatra",
  };

  KLocale * l = KGlobal::locale();
  KIconLoader * il = KGlobal::iconLoader();
  for ( unsigned int i = 0 ; i < sizeof catalogues / sizeof *catalogues ; ++i ) {
    l->insertCatalogue( catalogues[i] );
    il->addAppDir( catalogues[i] );
  }

}

void cleanup()
{
  const QString lockLocation = locateLocal("data", "kmail/lock");
  KSimpleConfig config(lockLocation);
  config.writeEntry("pid", -1);
  config.sync();
}
}
<commit_msg>insert libkmime catalog (3 strings were missing in KMail)<commit_after>/*
    This file is part of KMail, the KDE mail client.
    Copyright (c) 2000 Don Sanders <sanders@kde.org>

    KMail is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License, version 2, as
    published by the Free Software Foundation.

    KMail 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 more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include <config.h>

#include "kmstartup.h"

#include "kmkernel.h" //control center
#include "kcursorsaver.h"

#include <klocale.h>
#include <ksimpleconfig.h>
#include <kstandarddirs.h>
#include <kmessagebox.h>
#include <dcopclient.h>
#include <kcrash.h>
#include <kglobal.h>
#include <kapplication.h>
#include <kaboutdata.h>
#include <kiconloader.h>

#include <errno.h>
#include <sys/types.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#undef Status // stupid X headers

extern "C" {

// Crash recovery signal handler
void kmsignalHandler(int sigId)
{
  kmsetSignalHandler(SIG_DFL);
  fprintf(stderr, "*** KMail got signal %d (Exiting)\n", sigId);
  // try to cleanup all windows
  if (kmkernel) kmkernel->dumpDeadLetters();
  ::exit(-1); //
}

// Crash recovery signal handler
void kmcrashHandler(int sigId)
{
  kmsetSignalHandler(SIG_DFL);
  fprintf(stderr, "*** KMail got signal %d (Crashing)\n", sigId);
  // try to cleanup all windows
  if (kmkernel) kmkernel->dumpDeadLetters();
  // Return to DrKonqi.
}
//-----------------------------------------------------------------------------

void kmsetSignalHandler(void (*handler)(int))
{
  signal(SIGKILL, handler);
  signal(SIGTERM, handler);
  signal(SIGHUP,  handler);
  KCrash::setEmergencySaveFunction(kmcrashHandler);
}

}
//-----------------------------------------------------------------------------

namespace {
  QString getMyHostName() {
    char hostNameC[256];
    // null terminate this C string
    hostNameC[255] = 0;
    // set the string to 0 length if gethostname fails
    if(gethostname(hostNameC, 255))
      hostNameC[0] = 0;
    return QString::fromLocal8Bit(hostNameC);
  }
} // anon namespace

namespace KMail {

void checkConfigUpdates() {
  static const char * const updates[] = {
    "9",
    "3.1-update-identities",
    "3.1-use-identity-uoids",
    "3.1-new-mail-notification",
    "3.2-update-loop-on-goto-unread-settings",
    "3.1.4-dont-use-UOID-0-for-any-identity",
    "3.2-misc",
    "3.2-moves",
    "3.3-use-ID-for-accounts",
    "3.3-update-filter-rules",
    "3.3-move-identities-to-own-file",
    "3.3-aegypten-kpgprc-to-kmailrc",
    "3.3-aegypten-kpgprc-to-libkleopatrarc",
    "3.3-aegypten-emailidentities-split-sign-encr-keys",
    "3.3-misc",
    "3.3b1-misc",
    "3.4-misc",
    "3.4a",
    "3.4b",
    "3.4.1"
  };
  static const int numUpdates = sizeof updates / sizeof *updates;
  // Warning: do not remove entries in the above array, or the update-level check below will break

  KConfig * config = KMKernel::config();
  KConfigGroup startup( config, "Startup" );
  const int configUpdateLevel = startup.readNumEntry( "update-level", 0 );
  if ( configUpdateLevel == numUpdates ) // Optimize for the common case that everything is OK
    return;

  for ( int i = configUpdateLevel ; i < numUpdates ; ++i ) {
    config->checkUpdate( updates[i], "kmail.upd" );
  }
  startup.writeEntry( "update-level", numUpdates );
}

void lockOrDie() {
// Check and create a lock file to prevent concurrent access to kmail files
  QString appName = kapp->instanceName();
  if ( appName.isEmpty() )
    appName = "kmail";

  QString programName;
  const KAboutData *about = kapp->aboutData();
  if ( about )
    programName = about->programName();
  if ( programName.isEmpty() )
    programName = i18n("KMail");

  QString lockLocation = locateLocal("data", "kmail/lock");
  KSimpleConfig config(lockLocation);
  int oldPid = config.readNumEntry("pid", -1);
  const QString oldHostName = config.readEntry("hostname");
  const QString oldAppName = config.readEntry( "appName", appName );
  const QString oldProgramName = config.readEntry( "programName", programName );
  const QString hostName = getMyHostName();
  bool first_instance = false;
  if ( oldPid == -1 )
      first_instance = true;
  // check if the lock file is stale by trying to see if
  // the other pid is currently running.
  // Not 100% correct but better safe than sorry
  else if (hostName == oldHostName && oldPid != getpid()) {
      if ( kill(oldPid, 0) == -1 )
          first_instance = ( errno == ESRCH );
  }

  if ( !first_instance ) {
    QString msg;
    if ( oldHostName == hostName ) {
      // this can only happen if the user is running this application on
      // different displays on the same machine. All other cases will be
      // taken care of by KUniqueApplication()
      if ( oldAppName == appName )
        msg = i18n("%1 already seems to be running on another display on "
                   "this machine. Running %2 more than once "
                   "can cause the loss of mail. You should not start %1 "
                   "unless you are sure that it is not already running.")
              .arg( programName, programName );
              // QString::arg( st ) only replaces the first occurrence of %1
              // with st while QString::arg( s1, s2 ) replacess all occurrences
              // of %1 with s1 and all occurrences of %2 with s2. So don't
              // even think about changing the above to .arg( programName ).
      else
        msg = i18n("%1 seems to be running on another display on this "
                   "machine. Running %1 and %2 at the same "
                   "time can cause the loss of mail. You should not start %2 "
                   "unless you are sure that %1 is not running.")
              .arg( oldProgramName, programName );
    }
    else {
      if ( oldAppName == appName )
        msg = i18n("%1 already seems to be running on %2. Running %1 more "
                   "than once can cause the loss of mail. You should not "
                   "start %1 on this computer unless you are sure that it is "
                   "not already running on %2.")
              .arg( programName, oldHostName );
      else
        msg = i18n("%1 seems to be running on %3. Running %1 and %2 at the "
                   "same time can cause the loss of mail. You should not "
                   "start %2 on this computer unless you are sure that %1 is "
                   "not running on %3.")
              .arg( oldProgramName, programName, oldHostName );
    }

    KCursorSaver idle( KBusyPtr::idle() );
    if ( KMessageBox::No ==
         KMessageBox::warningYesNo( 0, msg, QString::null,
                                    i18n("Start %1").arg( programName ),
                                    i18n("Exit") ) ) {
      exit(1);
    }
  }

  config.writeEntry("pid", getpid());
  config.writeEntry("hostname", hostName);
  config.writeEntry( "appName", appName );
  config.writeEntry( "programName", programName );
  config.sync();
}

void insertLibraryCataloguesAndIcons() {
  static const char * const catalogues[] = {
    "libkdenetwork",
    "libkdepim",
    "libksieve",
    "libkleopatra",
    "libkmime"
  };

  KLocale * l = KGlobal::locale();
  KIconLoader * il = KGlobal::iconLoader();
  for ( unsigned int i = 0 ; i < sizeof catalogues / sizeof *catalogues ; ++i ) {
    l->insertCatalogue( catalogues[i] );
    il->addAppDir( catalogues[i] );
  }

}

void cleanup()
{
  const QString lockLocation = locateLocal("data", "kmail/lock");
  KSimpleConfig config(lockLocation);
  config.writeEntry("pid", -1);
  config.sync();
}
}
<|endoftext|>


<commit_before>#include "tests.h"
#include "memory.h"
#include "runtime.h"
#include "stream.h"
#include "container/range.h"
#include <sstream>

namespace elpa {

using container::range;

template<class Env>
struct Tester
{
    typedef typename Env::Allocator Allocator;
    typedef typename Env::elpa_ostream elpa_ostream;
    typedef typename Env::elpa_istream elpa_istream;
    typedef typename elpa_istream::Names Names;
    typedef typename Env::elpa_ostream::ElpaManip ElpaManip;

    typedef typename Env::Scheme::pcell_t pcell_t;
    typedef typename Env::Scheme::elem_t elem_t;

    template<class T>
    using auto_root_ref = typename Allocator::template auto_root_ref<T>;

    template<class T>
    using auto_root = typename Allocator::template auto_root<T>;

    static auto parse( Allocator& allocator, const std::string& in, const Names& names ) -> auto_root_ref<elem_t>
    {
        std::istringstream iss( in );
        elem_t elem;
        elpa_istream( iss, allocator ) >> elem;
        return auto_root_ref<elem_t>( allocator, elem );
    }

    static auto parse( Allocator& allocator, const std::string& in ) -> auto_root_ref<elem_t>
    {
    	Names names( allocator );
    	return parse( allocator, in, names );
    }

    static auto print( elem_t e, ElpaManip m=flat ) -> std::string
    {
        std::ostringstream oss;
        elpa_ostream( oss ) << m << e;
        return oss.str();
    }

    static void test_ostream()
    {TEST
        Allocator a( 1024 );

        auto_root<elem_t> p( a, a.new_Cell(
                        1,
                        a.new_Cell(
                            a.new_Cell( 3, 3 ),
                            2 ) ) );

        auto found_flat = print( p, flat );
        auto expected_flat = "[1 [3 3] 2]";
        test( found_flat == expected_flat, "Incorrect flat printing found '" + found_flat + "'\nExpected '" + expected_flat + "'" );

        auto found_deep = print( p, deep );
        auto expected_deep = "[1 [[3 3] 2]]";
        test( found_deep == expected_deep, "Incorrect deep printing found '" + found_deep + "'\nExpected '" + expected_deep + "'" );
    }

    static void test_io( const std::string& in, ElpaManip m=flat, std::string out="" )
    {
        if( out.empty() )
            out = in;

        Allocator a( 1024 );
        std::ostringstream oss;

        auto found = print( parse( a, in ), m );

        test( found == out, "IO failed for: '" + in + "'\nExpected: '" + out + "'\nFound:    '" + found + "'" );
    }

    template<class SubType=AnyType>
    static void test_io_error( const std::string& in, const std::string& msg )
    {
        Allocator a( 1024 );

        std::string found;
        try
        {
            found = print( parse( a, in ) );
        }
        catch( const Error<Syntax,SubType>& e )
        {
            test( e.message() == msg, "IO failed for: '" + in + "'\nExpected error: '" + msg + "'\nFound:          '" + e.message() + "'" );
            return pass();
        }

        test( false, "IO failed for: '" + in + "'\nExpected error: '" + msg + "'\nFound:    '" + found + "'" );
    }

    static void test_iostream()
    {TEST
        test_io( "3" );
        test_io( " 3 ", flat, "3" );
        test_io( "[0 [1 2]]", flat, "[0 1 2]" );
        test_io( " [ 0 [ 1\n 2]\t]\t", flat, "[0 1 2]" );
        test_io( "[0 1 2]", deep, "[0 [1 2]]" );
        test_io( "[0 [1 [2 3] 4] 5 6]", flat );
        test_io( "[0 [1 [2 3] 4] 5 6]", deep, "[0 [[1 [[2 3] 4]] [5 6]]]" );
        test_io( "[[0 1] 2]", deep );
        test_io( "[[0 1] 2]", flat );
        test_io( "[[[0 1] [2 3]] [[4 5] [6 7]]]", deep );
        test_io( "[[[0 1] [2 3]] [[4 5] [6 7]]]", flat, "[[[0 1] 2 3] [4 5] 6 7]" );
        test_io( "[[[0 1] 2 3] [4 5] 6 7]", flat );

        test_io_error<EOS>( "[", "Unexpected end of input" );
        test_io_error( "]", "Unexpected ']'" );
        test_io_error( "[0]", "Unexpected singleton" );
        test_io_error( "[[0] 2]", "Unexpected singleton" );
        test_io_error( "[]", "Unexpected empty cell" );
        test_io_error( "[[] 2]", "Unexpected empty cell" );
    }

    static void test_gc()
    {TEST
        try
        {
            Allocator a( 1 );
            auto_root<elem_t> p( a, a.new_Cell( 1, 1 ) );
            a.new_Cell( 1, 1 );

            fail( "Failed to catch out of memory" );
        }
        catch( const Error<Runtime,OutOfMemory>& ) { pass(); }

        {
            Allocator a( 10 );
            auto_root<elem_t> p( a, a.new_Cell( 1, 2 ) );
            a.new_Cell( 1, 1 );

            test( a.num_allocated() == 2, "Failed to register allocated cells" );

            test( p->head().is_byte() && p->head().byte() == 1, "Cell head incorrect before GC" );
            test( p->tail().is_byte() && p->tail().byte() == 2, "Cell tail incorrect before GC" );

            a.gc();

            test( p->head().is_byte() && p->head().byte() == 1, "Cell head incorrect after GC" );
            test( p->tail().is_byte() && p->tail().byte() == 2, "Cell tail incorrect after GC" );

            test( a.num_allocated() == 1, "Failed to cleanup after GC" );
        }

        {
            Allocator a( 1024 );
            auto_root<elem_t> p( parse( a, "[0 [1 [2 3] 4] 5 6]" ) );
            auto_root<elem_t> q( parse( a, "[0 [1 [2 3] 4] 5 6]" ) );

            a.gc();

            test( a.gc_count() > 0, "GC failed to run with 2 roots" );
            test( a.num_allocated() == 12, "Failed to hold all cells in GC" );

            test( print( p ) == "[0 [1 [2 3] 4] 5 6]", "Complex tree (1) altered by GC" );
            test( print( q ) == "[0 [1 [2 3] 4] 5 6]", "Complex tree (2) altered by GC" );
        }

        {
            Allocator a( 1024 );
            elem_t pp = parse( a, "[0 [1 [2 3] 4] 5 6]" );
            {
            	auto_root<elem_t> p( a, pp );
            	parse( a, "[0 [1 [2 3] 4] 5 6]" );

            	a.gc();

	            test( a.gc_count() > 0, "GC failed to run with 1 root" );
 	           test( a.num_allocated() == 6, "Failed to hold and cleanup all cells in GC" );

	            test( print( p ) == "[0 [1 [2 3] 4] 5 6]", "Complex tree (3) altered by GC" );
	            pp = p;
            }

            auto_root<elem_t> t( a, pp->tail() );

            a.gc();

            test( a.num_allocated() == 5, "Failed to hold and cleanup tail cells in GC" );
            test( print( t ) == "[[1 [2 3] 4] 5 6]", "Complex tree tail altered by GC" );
        }

        {
            //Test with minimal memory to create memory churn
            for( auto n : range(1,11) )
            {
                try
                {
                    Allocator a( n );
                    parse( a, "[0 [1 [2 3] 4] 5 6]" );
                    fail( "Parsed in low memory enviroment" );
                }
                catch( const Error<Runtime,OutOfMemory>& )
                {
                    pass();
                }
            }
        }

        {
            //Test with minimal memory to create memory churn
            for( auto n : range(11,20) )
            {
                Allocator a( n );
                auto_root<elem_t> p( parse( a, "[0 [1 [2 3] 4] 5 6]" ) );

                test( a.gc_count() > 0, "GC failed to run during low memory parse" );

                a.gc();

                test( print( p ) == "[0 [1 [2 3] 4] 5 6]", "Low memory parse tree tail altered by GC" );
                test( a.num_allocated() == 6, "Failed to hold and cleanup all cells in GC" );
            }
        }
    }

    static void run_tests()
    {
        std::cout << "TEST: " << TYPENAME( Env );

        test_ostream();
        test_iostream();
        test_gc();

        std::cout << "\n\n";
    }
};

void run_tests()
{
    Tester< Env< Debug, SimpleScheme, TestAllocator, NullInterpreter > >::run_tests();
    Tester< Env< Debug, SimpleScheme, SimpleAllocator, NullInterpreter > >::run_tests();
}

}	//namespace<commit_msg>Adding named element test<commit_after>#include "tests.h"
#include "memory.h"
#include "runtime.h"
#include "stream.h"
#include "container/range.h"
#include <sstream>

namespace elpa {

using container::range;

template<class Env>
struct Tester
{
    typedef typename Env::Allocator Allocator;
    typedef typename Env::elpa_ostream elpa_ostream;
    typedef typename Env::elpa_istream elpa_istream;
    typedef typename elpa_istream::Names Names;
    typedef typename Env::elpa_ostream::ElpaManip ElpaManip;

    typedef typename Env::Scheme::pcell_t pcell_t;
    typedef typename Env::Scheme::elem_t elem_t;

    template<class T>
    using auto_root_ref = typename Allocator::template auto_root_ref<T>;

    template<class T>
    using auto_root = typename Allocator::template auto_root<T>;

    static auto parse( Allocator& allocator, const std::string& in, const Names& names ) -> auto_root_ref<elem_t>
    {
        std::istringstream iss( in );
        elem_t elem;
        elpa_istream( iss, allocator ) >> elem;
        return auto_root_ref<elem_t>( allocator, elem );
    }

    static auto parse( Allocator& allocator, const std::string& in ) -> auto_root_ref<elem_t>
    {
    	Names names( allocator );
    	return parse( allocator, in, names );
    }

    static auto print( elem_t e, ElpaManip m=flat ) -> std::string
    {
        std::ostringstream oss;
        elpa_ostream( oss ) << m << e;
        return oss.str();
    }

    static void test_ostream()
    {TEST
        Allocator a( 1024 );

        auto_root<elem_t> p( a, a.new_Cell(
                        1,
                        a.new_Cell(
                            a.new_Cell( 3, 3 ),
                            2 ) ) );

        auto found_flat = print( p, flat );
        auto expected_flat = "[1 [3 3] 2]";
        test( found_flat == expected_flat, "Incorrect flat printing found '" + found_flat + "'\nExpected '" + expected_flat + "'" );

        auto found_deep = print( p, deep );
        auto expected_deep = "[1 [[3 3] 2]]";
        test( found_deep == expected_deep, "Incorrect deep printing found '" + found_deep + "'\nExpected '" + expected_deep + "'" );
    }

    static void test_istream()
    {TEST
    	Allocator a( 1024 );

        Names names( a );
        names["a"] = parse( a, "0" );

        auto test_i = [&a, &names]( std::string s ){
        	test( print( parse( a, s, names ) ) == s, "Named parse incorrect" );
        };

    	test_i( "0" );
    }

    static void test_io( const std::string& in, ElpaManip m=flat, std::string out="" )
    {
        if( out.empty() )
            out = in;

        Allocator a( 1024 );
        std::ostringstream oss;

        auto found = print( parse( a, in ), m );

        test( found == out, "IO failed for: '" + in + "'\nExpected: '" + out + "'\nFound:    '" + found + "'" );
    }

    template<class SubType=AnyType>
    static void test_io_error( const std::string& in, const std::string& msg )
    {
        Allocator a( 1024 );

        std::string found;
        try
        {
            found = print( parse( a, in ) );
        }
        catch( const Error<Syntax,SubType>& e )
        {
            test( e.message() == msg, "IO failed for: '" + in + "'\nExpected error: '" + msg + "'\nFound:          '" + e.message() + "'" );
            return pass();
        }

        test( false, "IO failed for: '" + in + "'\nExpected error: '" + msg + "'\nFound:    '" + found + "'" );
    }

    static void test_iostream()
    {TEST
        test_io( "3" );
        test_io( " 3 ", flat, "3" );
        test_io( "[0 [1 2]]", flat, "[0 1 2]" );
        test_io( " [ 0 [ 1\n 2]\t]\t", flat, "[0 1 2]" );
        test_io( "[0 1 2]", deep, "[0 [1 2]]" );
        test_io( "[0 [1 [2 3] 4] 5 6]", flat );
        test_io( "[0 [1 [2 3] 4] 5 6]", deep, "[0 [[1 [[2 3] 4]] [5 6]]]" );
        test_io( "[[0 1] 2]", deep );
        test_io( "[[0 1] 2]", flat );
        test_io( "[[[0 1] [2 3]] [[4 5] [6 7]]]", deep );
        test_io( "[[[0 1] [2 3]] [[4 5] [6 7]]]", flat, "[[[0 1] 2 3] [4 5] 6 7]" );
        test_io( "[[[0 1] 2 3] [4 5] 6 7]", flat );

        test_io_error<EOS>( "[", "Unexpected end of input" );
        test_io_error( "]", "Unexpected ']'" );
        test_io_error( "[0]", "Unexpected singleton" );
        test_io_error( "[[0] 2]", "Unexpected singleton" );
        test_io_error( "[]", "Unexpected empty cell" );
        test_io_error( "[[] 2]", "Unexpected empty cell" );
    }

    static void test_gc()
    {TEST
        try
        {
            Allocator a( 1 );
            auto_root<elem_t> p( a, a.new_Cell( 1, 1 ) );
            a.new_Cell( 1, 1 );

            fail( "Failed to catch out of memory" );
        }
        catch( const Error<Runtime,OutOfMemory>& ) { pass(); }

        {
            Allocator a( 10 );
            auto_root<elem_t> p( a, a.new_Cell( 1, 2 ) );
            a.new_Cell( 1, 1 );

            test( a.num_allocated() == 2, "Failed to register allocated cells" );

            test( p->head().is_byte() && p->head().byte() == 1, "Cell head incorrect before GC" );
            test( p->tail().is_byte() && p->tail().byte() == 2, "Cell tail incorrect before GC" );

            a.gc();

            test( p->head().is_byte() && p->head().byte() == 1, "Cell head incorrect after GC" );
            test( p->tail().is_byte() && p->tail().byte() == 2, "Cell tail incorrect after GC" );

            test( a.num_allocated() == 1, "Failed to cleanup after GC" );
        }

        {
            Allocator a( 1024 );
            auto_root<elem_t> p( parse( a, "[0 [1 [2 3] 4] 5 6]" ) );
            auto_root<elem_t> q( parse( a, "[0 [1 [2 3] 4] 5 6]" ) );

            a.gc();

            test( a.gc_count() > 0, "GC failed to run with 2 roots" );
            test( a.num_allocated() == 12, "Failed to hold all cells in GC" );

            test( print( p ) == "[0 [1 [2 3] 4] 5 6]", "Complex tree (1) altered by GC" );
            test( print( q ) == "[0 [1 [2 3] 4] 5 6]", "Complex tree (2) altered by GC" );
        }

        {
            Allocator a( 1024 );
            elem_t pp = parse( a, "[0 [1 [2 3] 4] 5 6]" );
            {
            	auto_root<elem_t> p( a, pp );
            	parse( a, "[0 [1 [2 3] 4] 5 6]" );

            	a.gc();

	            test( a.gc_count() > 0, "GC failed to run with 1 root" );
 	           test( a.num_allocated() == 6, "Failed to hold and cleanup all cells in GC" );

	            test( print( p ) == "[0 [1 [2 3] 4] 5 6]", "Complex tree (3) altered by GC" );
	            pp = p;
            }

            auto_root<elem_t> t( a, pp->tail() );

            a.gc();

            test( a.num_allocated() == 5, "Failed to hold and cleanup tail cells in GC" );
            test( print( t ) == "[[1 [2 3] 4] 5 6]", "Complex tree tail altered by GC" );
        }

        {
            //Test with minimal memory to create memory churn
            for( auto n : range(1,11) )
            {
                try
                {
                    Allocator a( n );
                    parse( a, "[0 [1 [2 3] 4] 5 6]" );
                    fail( "Parsed in low memory enviroment" );
                }
                catch( const Error<Runtime,OutOfMemory>& )
                {
                    pass();
                }
            }
        }

        {
            //Test with minimal memory to create memory churn
            for( auto n : range(11,20) )
            {
                Allocator a( n );
                auto_root<elem_t> p( parse( a, "[0 [1 [2 3] 4] 5 6]" ) );

                test( a.gc_count() > 0, "GC failed to run during low memory parse" );

                a.gc();

                test( print( p ) == "[0 [1 [2 3] 4] 5 6]", "Low memory parse tree tail altered by GC" );
                test( a.num_allocated() == 6, "Failed to hold and cleanup all cells in GC" );
            }
        }
    }

    static void run_tests()
    {
        std::cout << "TEST: " << TYPENAME( Env );

        test_ostream();
        test_istream();
        test_iostream();
        test_gc();

        std::cout << "\n\n";
    }
};

void run_tests()
{
    Tester< Env< Debug, SimpleScheme, TestAllocator, NullInterpreter > >::run_tests();
    Tester< Env< Debug, SimpleScheme, SimpleAllocator, NullInterpreter > >::run_tests();
}

}	//namespace<|endoftext|>


<commit_before>/*
 *     Copyright (C) 2003 by Mark Bucciarelli <mark@hubcapconsutling.com>
 *                   2007 the ktimetracker developers
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, 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 more details.
 *
 *   You should have received a copy of the GNU General Public License along
 *   with this program; if not, write to the
 *      Free Software Foundation, Inc.
 *      51 Franklin Street, Fifth Floor
 *      Boston, MA  02110-1301  USA.
 *
 */

#include "timekard.h"

#include <cassert>

#include <QDateTime>
#include <QList>
#include <QMap>

#include <KDebug>
#include <KGlobal>
#include <KLocale>

#include <kcal/event.h>

#include "karmstorage.h"
#include "karmutility.h"        // formatTime()
#include "task.h"
#include "taskview.h"

const int taskWidth = 40;
const int timeWidth = 6;
const int totalTimeWidth = 7;
const int reportWidth = taskWidth + timeWidth;

const QString cr = QString::fromLatin1("\n");

QString TimeKard::totalsAsText(TaskView* taskview, ReportCriteria rc)
{
  kDebug(5970) << "Entering function";
  QString retval;
  QString line;
  QString buf;
  long sum;
  bool justThisTask=!rc.allTasks;

  line.fill('-', reportWidth);
  line += cr;

  // header
  retval += i18n("Task Totals") + cr;
  retval += KGlobal::locale()->formatDateTime(QDateTime::currentDateTime());
  retval += cr + cr;
  retval += QString(QString::fromLatin1("%1    %2"))
    .arg(i18n("Time"), timeWidth)
    .arg(i18n("Task"));
  retval += cr;
  retval += line;

  // tasks
  if (taskview->currentItem())
  {
    if (justThisTask)
    {
      if (!rc.sessionTimes) sum = taskview->currentItem()->totalTime();
      else sum = taskview->currentItem()->totalSessionTime();
      printTask(taskview->currentItem(), retval, 0, rc);
    }
    else // print all tasks
    {
      sum = 0;
      for ( int i = 0; i < taskview->topLevelItemCount(); ++i ) {
        Task *task = static_cast< Task* >( taskview->topLevelItem( i ) );
        if (!rc.sessionTimes) sum += task->totalTime();
        else sum += task->totalSessionTime();
        if ( (task->totalTime() && (!rc.sessionTimes)) || (task->totalSessionTime() && rc.sessionTimes) )
          printTask(task, retval, 0, rc);
      }
    }

    // total
    buf.fill('-', reportWidth);
    retval += QString(QString::fromLatin1("%1")).arg(buf, timeWidth) + cr;
    retval += QString(QString::fromLatin1("%1 %2"))
      .arg(formatTime(sum),timeWidth)
      .arg(i18nc( "total time of all tasks", "Total" ));
  }
  else
    retval += i18n("No tasks.");

  return retval;
}

// Print out "<indent for level> <task total> <task>", for task and subtasks. Used by totalsAsText.
void TimeKard::printTask(Task *task, QString &s, int level, const ReportCriteria &rc)
{
  kDebug(5970) <<"Entering TimeKard::printTask";
  QString buf;

  s += buf.fill(' ', level);
  if (!rc.sessionTimes)
  {
    s += QString(QString::fromLatin1("%1    %2"))
      .arg(formatTime(task->totalTime()), timeWidth)
      .arg(task->name());
  }
  else // print session times
  {
    s += QString(QString::fromLatin1("%1    %2"))
      .arg(formatTime(task->totalSessionTime()), timeWidth)
      .arg(task->name());
  }
  s += cr;

  for ( int i = 0; i < task->childCount(); ++i ) {
    Task *subTask = static_cast< Task* >( task->child( i ) );
    if ( !rc.sessionTimes )
    {
      if ( subTask->totalTime() ) // to avoid 00:00 entries
        printTask(subTask, s, level+1, rc);
    }
    else
    {
      if ( subTask->totalSessionTime() ) // to avoid 00:00 entries
        printTask(subTask, s, level+1, rc);
    }
  }
}

void TimeKard::printTaskHistory(const Task *task,
    const QMap<QString,long>& taskdaytotals,
    QMap<QString,long>& daytotals,
    const QDate& from,
    const QDate& to,
    const int level, QString& s, bool totalsOnly)
{
  kDebug(5970) <<"Entering TimeKard::printTaskHistory";
  long sectionsum = 0;
  for ( QDate day = from; day <= to; day = day.addDays(1) )
  {
    QString daykey = day.toString(QString::fromLatin1("yyyyMMdd"));
    QString daytaskkey = QString::fromLatin1("%1_%2")
                         .arg(daykey)
                         .arg(task->uid());

    if (taskdaytotals.contains(daytaskkey))
    {
      if ( !totalsOnly )
      {
        s += QString::fromLatin1("%1")
             .arg(formatTime(taskdaytotals[daytaskkey]/60), timeWidth);
      }
      sectionsum += taskdaytotals[daytaskkey];  // in seconds

      if (daytotals.contains(daykey))
        daytotals.insert(daykey, daytotals[daykey] + taskdaytotals[daytaskkey]);
      else
        daytotals.insert(daykey, taskdaytotals[daytaskkey]);
    }
    else if ( !totalsOnly )
    {
      QString buf;
      buf.fill(' ', timeWidth);
      s += buf;
    }
  }

  // Total for task this section (e.g. week)
  s += QString::fromLatin1("%1").arg(formatTime(sectionsum/60), totalTimeWidth);

  // Task name
  QString buf;
  s += buf.fill(' ', level + 1);
  s += QString::fromLatin1("%1").arg(task->name());
  s += cr;

  for ( int i = 0; i < task->childCount(); ++i ) {
    Task *subTask = static_cast< Task* >( task->child( i ) );
    // recursive
    printTaskHistory(subTask, taskdaytotals, daytotals, from, to, level+1, s, totalsOnly);
  }
}

QString TimeKard::sectionHistoryAsText(
  TaskView* taskview,
  const QDate& sectionFrom, const QDate& sectionTo,
  const QDate& from, const QDate& to,
  const QString& name,
  bool justThisTask, bool totalsOnly)
{
  kDebug(5970) << "Entering function";
  const int sectionReportWidth = taskWidth + ( totalsOnly ? 0 : sectionFrom.daysTo(sectionTo) * timeWidth ) + totalTimeWidth;
  assert( sectionReportWidth > 0 );
  QString line;
  line.fill('-', sectionReportWidth);
  line += cr;

  QList<HistoryEvent> events;
  if ( sectionFrom < from && sectionTo > to)
  {
    events = taskview->getHistory(from, to);
  }
  else if ( sectionFrom < from )
  {
    events = taskview->getHistory(from, sectionTo);
  }
  else if ( sectionTo > to)
  {
    events = taskview->getHistory(sectionFrom, to);
  }
  else
  {
    events = taskview->getHistory(sectionFrom, sectionTo);
  }

  QMap<QString, long> taskdaytotals;
  QMap<QString, long> daytotals;

  // Build lookup dictionary used to output data in table cells.  keys are
  // in this format: YYYYMMDD_NNNNNN, where Y = year, M = month, d = day and
  // NNNNN = the VTODO uid.  The value is the total seconds logged against
  // that task on that day.  Note the UID is the todo id, not the event id,
  // so times are accumulated for each task.
  for (QList<HistoryEvent>::iterator event = events.begin(); event != events.end(); ++event)
  {
    QString daykey = (*event).start().date().toString(QString::fromLatin1("yyyyMMdd"));
    QString daytaskkey = QString::fromLatin1("%1_%2")
                         .arg(daykey)
                         .arg((*event).todoUid());

    if (taskdaytotals.contains(daytaskkey))
      taskdaytotals.insert(daytaskkey,
                            taskdaytotals[daytaskkey] + (*event).duration());
    else
      taskdaytotals.insert(daytaskkey, (*event).duration());
  }

  QString retval;
  // section name (e.g. week name)
  retval += cr + cr;
  QString buf;
  if ( name.length() < sectionReportWidth )
    buf.fill(' ', int((sectionReportWidth - name.length()) / 2));
  retval += buf + name + cr;

  if ( !totalsOnly )
  {
    // day headings
    for (QDate day = sectionFrom; day <= sectionTo; day = day.addDays(1))
    {
      retval += QString::fromLatin1("%1").arg(day.day(), timeWidth);
    }
    retval += cr;
    retval += line;
  }

  // the tasks
  if (events.empty())
  {
    retval += "  ";
    retval += i18n("No hours logged.");
  }
  else
  {
    if (justThisTask)
    {
      printTaskHistory(taskview->currentItem(), taskdaytotals, daytotals,
                       sectionFrom, sectionTo, 0, retval, totalsOnly);
    }
    else
    {
      Task *task = taskview->currentItem();
      if ( task->parent() ) {
        for ( int i = task->parent()->indexOfChild( task );
              i < task->parent()->childCount(); ++i ) {
          task = static_cast< Task* >(task->parent()->child( i ) );
          printTaskHistory( task, taskdaytotals, daytotals,
                            sectionFrom, sectionTo, 0, retval, totalsOnly );
        }
      } else {
        for ( int i = taskview->indexOfTopLevelItem( task );
              i < taskview->topLevelItemCount(); ++i ) {
          task = static_cast< Task* >(taskview->topLevelItem( i ) );
          printTaskHistory( task, taskdaytotals, daytotals,
                            sectionFrom, sectionTo, 0, retval, totalsOnly );
        }
      }
    }
    retval += line;

    // per-day totals at the bottom of the section
    long sum = 0;
    for (QDate day = sectionFrom; day <= sectionTo; day = day.addDays(1))
    {
      QString daykey = day.toString(QString::fromLatin1("yyyyMMdd"));

      if (daytotals.contains(daykey))
      {
        if ( !totalsOnly )
        {
          retval += QString::fromLatin1("%1")
                    .arg(formatTime(daytotals[daykey]/60), timeWidth);
        }
        sum += daytotals[daykey];  // in seconds
      }
      else if ( !totalsOnly )
      {
        buf.fill(' ', timeWidth);
        retval += buf;
      }
    }

    retval += QString::fromLatin1("%1 %2")
              .arg(formatTime(sum/60), totalTimeWidth)
              .arg( i18nc( "total time of all tasks", "Total" ) );
  }
  return retval;
}

QString TimeKard::historyAsText(TaskView* taskview, const QDate& from,
    const QDate& to, bool justThisTask, bool perWeek, bool totalsOnly)
{
  kDebug(5970) << "Entering function";
  // header
  QString retval;
  retval += totalsOnly ? i18n("Task Totals") : i18n("Task History");
  retval += cr;
  retval += i18n("From %1 to %2",
     KGlobal::locale()->formatDate(from),
     KGlobal::locale()->formatDate(to));
  retval += cr;
  retval += i18n("Printed on: %1",
     KGlobal::locale()->formatDateTime(QDateTime::currentDateTime()));

  if ( perWeek )
  {
    // output one time card table for each week in the date range
    QList<Week> weeks = Week::weeksFromDateRange(from, to);
    for (QList<Week>::iterator week = weeks.begin(); week != weeks.end(); ++week)
    {
      retval += sectionHistoryAsText( taskview, (*week).start(), (*week).end(), from, to, (*week).name(), justThisTask, totalsOnly );
    }
  } else
  {
    retval += sectionHistoryAsText( taskview, from, to, from, to, "", justThisTask, totalsOnly );
  }
  return retval;
}

Week::Week() {}

Week::Week( const QDate &from )
{
  _start = from;
}

QDate Week::start() const
{
  return _start;
}

QDate Week::end() const
{
  return _start.addDays(6);
}

QString Week::name() const
{
  return i18n("Week of %1", KGlobal::locale()->formatDate(start()));
}

QList<Week> Week::weeksFromDateRange(const QDate& from, const QDate& to)
{
  QDate start;
  QList<Week> weeks;

  // The QDate weekNumber() method always puts monday as the first day of the
  // week.
  //
  // Not that it matters here, but week 1 always includes the first Thursday
  // of the year.  For example, January 1, 2000 was a Saturday, so
  // QDate(2000,1,1).weekNumber() returns 52.

  // Since report always shows a full week, we generate a full week of dates,
  // even if from and to are the same date.  The week starts on the day
  // that is set in the locale settings.
  start = from.addDays(
      -((7 - KGlobal::locale()->weekStartDay() + from.dayOfWeek()) % 7));

  for (QDate d = start; d <= to; d = d.addDays(7))
    weeks.append(Week(d));

  return weeks;
}

<commit_msg>Fighting entropy<commit_after>/*
 *     Copyright (C) 2003 by Mark Bucciarelli <mark@hubcapconsutling.com>
 *                   2007 the ktimetracker developers
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, 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 more details.
 *
 *   You should have received a copy of the GNU General Public License along
 *   with this program; if not, write to the
 *      Free Software Foundation, Inc.
 *      51 Franklin Street, Fifth Floor
 *      Boston, MA  02110-1301  USA.
 *
 */

#include "timekard.h"

#include <cassert>

#include <QDateTime>
#include <QList>
#include <QMap>

#include <KDebug>
#include <KGlobal>
#include <KLocale>

#include <kcal/event.h>

#include "karmstorage.h"
#include "karmutility.h"        // formatTime()
#include "task.h"
#include "taskview.h"

const int taskWidth = 40;
const int timeWidth = 6;
const int totalTimeWidth = 7;
const int reportWidth = taskWidth + timeWidth;

const QString cr = QString::fromLatin1("\n");

QString TimeKard::totalsAsText(TaskView* taskview, ReportCriteria rc)
{
  kDebug(5970) << "Entering function";
  QString retval;
  QString line;
  QString buf;
  long sum;
  bool justThisTask=!rc.allTasks;

  line.fill('-', reportWidth);
  line += cr;

  // header
  retval += i18n("Task Totals") + cr;
  retval += KGlobal::locale()->formatDateTime(QDateTime::currentDateTime());
  retval += cr + cr;
  retval += QString(QString::fromLatin1("%1    %2"))
    .arg(i18n("Time"), timeWidth)
    .arg(i18n("Task"));
  retval += cr;
  retval += line;

  // tasks
  if (taskview->currentItem())
  {
    if (justThisTask)
    {
      if (!rc.sessionTimes) sum = taskview->currentItem()->totalTime();
      else sum = taskview->currentItem()->totalSessionTime();
      printTask(taskview->currentItem(), retval, 0, rc);
    }
    else // print all tasks
    {
      sum = 0;
      for ( int i = 0; i < taskview->topLevelItemCount(); ++i ) {
        Task *task = static_cast< Task* >( taskview->topLevelItem( i ) );
        if (!rc.sessionTimes) sum += task->totalTime();
        else sum += task->totalSessionTime();
        if ( (task->totalTime() && (!rc.sessionTimes)) || (task->totalSessionTime() && rc.sessionTimes) )
          printTask(task, retval, 0, rc);
      }
    }

    // total
    buf.fill('-', reportWidth);
    retval += QString(QString::fromLatin1("%1")).arg(buf, timeWidth) + cr;
    retval += QString(QString::fromLatin1("%1 %2"))
      .arg(formatTime(sum),timeWidth)
      .arg(i18nc( "total time of all tasks", "Total" ));
  }
  else
    retval += i18n("No tasks.");

  return retval;
}

// Print out "<indent for level> <task total> <task>", for task and subtasks. Used by totalsAsText.
void TimeKard::printTask(Task *task, QString &s, int level, const ReportCriteria &rc)
{
  kDebug(5970) << "Entering function";
  QString buf;

  s += buf.fill(' ', level);
  if (!rc.sessionTimes)
  {
    s += QString(QString::fromLatin1("%1    %2"))
      .arg(formatTime(task->totalTime()), timeWidth)
      .arg(task->name());
  }
  else // print session times
  {
    s += QString(QString::fromLatin1("%1    %2"))
      .arg(formatTime(task->totalSessionTime()), timeWidth)
      .arg(task->name());
  }
  s += cr;

  for ( int i = 0; i < task->childCount(); ++i ) {
    Task *subTask = static_cast< Task* >( task->child( i ) );
    if ( !rc.sessionTimes )
    {
      if ( subTask->totalTime() ) // to avoid 00:00 entries
        printTask(subTask, s, level+1, rc);
    }
    else
    {
      if ( subTask->totalSessionTime() ) // to avoid 00:00 entries
        printTask(subTask, s, level+1, rc);
    }
  }
}

Week::Week() {}

Week::Week( const QDate &from )
{
  _start = from;
}

QDate Week::start() const
{
  return _start;
}

QDate Week::end() const
{
  return _start.addDays(6);
}

QString Week::name() const
{
  return i18n("Week of %1", KGlobal::locale()->formatDate(start()));
}

QList<Week> Week::weeksFromDateRange(const QDate& from, const QDate& to)
{
  QDate start;
  QList<Week> weeks;

  // The QDate weekNumber() method always puts monday as the first day of the
  // week.
  //
  // Not that it matters here, but week 1 always includes the first Thursday
  // of the year.  For example, January 1, 2000 was a Saturday, so
  // QDate(2000,1,1).weekNumber() returns 52.

  // Since report always shows a full week, we generate a full week of dates,
  // even if from and to are the same date.  The week starts on the day
  // that is set in the locale settings.
  start = from.addDays(
      -((7 - KGlobal::locale()->weekStartDay() + from.dayOfWeek()) % 7));

  for (QDate d = start; d <= to; d = d.addDays(7))
    weeks.append(Week(d));

  return weeks;
}

<|endoftext|>