Esempio n. 1
0
int
main(int argc, char** argv) {
   clang::CompilerInstance compiler;
#ifndef _WIN32
   compiler.createDiagnostics();
#else
   compiler.createDiagnostics(argc, argv);
#endif
   compiler.createFileManager();
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-qual"

   ProcessArguments processArgument(argc, argv);
   if (argc == 1) {
      processArgument.printUsage(std::cout);
      return 0;
   };
   if (!processArgument.isValid()) {
      processArgument.printUsage(std::cout);
      return 0;
   };

   if (processArgument.isVersion())
      return 0;

   int clang_argc = argc;
   llvm::MutableArrayRef<const char*> Argv((const char**)argv, clang_argc+1);
   for (int i = 0; i<argc; i++)
      Argv[i] = argv[i];
#pragma GCC diagnostic pop
   Argv[clang_argc]="-Qunused-arguments";
   llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine>
      Diag(&compiler.getDiagnostics());
   clang::CompilerInvocation*
      invocation = clang::createInvocationFromCommandLine(Argv,Diag);

   if (!invocation) {
      std::cerr << 
         "Could not create clang invocation; Aborting";
      exit(2);
   }

   invocation->getLangOpts()->CPlusPlus = true;
   invocation->getLangOpts()->Bool = true;
   invocation->getLangOpts()->WChar = true;
   invocation->getLangOpts()->Exceptions = true;
   invocation->getLangOpts()->CXXExceptions = true;
   invocation->getLangOpts()->EmitAllDecls = true;
   invocation->getLangOpts()->GNUInline = true;
   invocation->getLangOpts()->Deprecated = true;
   invocation->getLangOpts()->ShortWChar = true;
   invocation->getLangOpts()->ImplicitInt = false;
   // equivalent command-line option: callers -std=c++11
   // enable to analyze C++11 source code like clang version 3.7.0 (trunk 240320)
   //invocation->getLangOpts()->CPlusPlus11 = true;
   //invocation->getLangOpts()->CPlusPlus11 = false;
   invocation->getFrontendOpts().ProgramAction = clang::frontend::ParseSyntaxOnly;
   compiler.setInvocation(invocation);

   CallersAction callersAction(processArgument.getOutputFile(), 
			       compiler);
   if (processArgument.doesGenerateImplicitMethods())
      callersAction.setGenerateImplicitMethods();
   compiler.ExecuteAction(callersAction);
   return 0;
}
Esempio n. 2
0
/// CheckExceptionSpecSubset - Check whether the second function type's
/// exception specification is a subset (or equivalent) of the first function
/// type. This is used by override and pointer assignment checks.
bool Sema::CheckExceptionSpecSubset(
    const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID,
    const FunctionProtoType *Superset, SourceLocation SuperLoc,
    const FunctionProtoType *Subset, SourceLocation SubLoc) {

  // Just auto-succeed under -fno-exceptions.
  if (!getLangOptions().Exceptions)
    return false;

  // FIXME: As usual, we could be more specific in our error messages, but
  // that better waits until we've got types with source locations.

  if (!SubLoc.isValid())
    SubLoc = SuperLoc;

  // If superset contains everything, we're done.
  if (!Superset->hasExceptionSpec() || Superset->hasAnyExceptionSpec())
    return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc);

  // It does not. If the subset contains everything, we've failed.
  if (!Subset->hasExceptionSpec() || Subset->hasAnyExceptionSpec()) {
    Diag(SubLoc, DiagID);
    if (NoteID.getDiagID() != 0)
      Diag(SuperLoc, NoteID);
    return true;
  }

  // Neither contains everything. Do a proper comparison.
  for (FunctionProtoType::exception_iterator SubI = Subset->exception_begin(),
       SubE = Subset->exception_end(); SubI != SubE; ++SubI) {
    // Take one type from the subset.
    QualType CanonicalSubT = Context.getCanonicalType(*SubI);
    // Unwrap pointers and references so that we can do checks within a class
    // hierarchy. Don't unwrap member pointers; they don't have hierarchy
    // conversions on the pointee.
    bool SubIsPointer = false;
    if (const ReferenceType *RefTy = CanonicalSubT->getAs<ReferenceType>())
      CanonicalSubT = RefTy->getPointeeType();
    if (const PointerType *PtrTy = CanonicalSubT->getAs<PointerType>()) {
      CanonicalSubT = PtrTy->getPointeeType();
      SubIsPointer = true;
    }
    bool SubIsClass = CanonicalSubT->isRecordType();
    CanonicalSubT = CanonicalSubT.getLocalUnqualifiedType();

    CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
                       /*DetectVirtual=*/false);

    bool Contained = false;
    // Make sure it's in the superset.
    for (FunctionProtoType::exception_iterator SuperI =
           Superset->exception_begin(), SuperE = Superset->exception_end();
         SuperI != SuperE; ++SuperI) {
      QualType CanonicalSuperT = Context.getCanonicalType(*SuperI);
      // SubT must be SuperT or derived from it, or pointer or reference to
      // such types.
      if (const ReferenceType *RefTy = CanonicalSuperT->getAs<ReferenceType>())
        CanonicalSuperT = RefTy->getPointeeType();
      if (SubIsPointer) {
        if (const PointerType *PtrTy = CanonicalSuperT->getAs<PointerType>())
          CanonicalSuperT = PtrTy->getPointeeType();
        else {
          continue;
        }
      }
      CanonicalSuperT = CanonicalSuperT.getLocalUnqualifiedType();
      // If the types are the same, move on to the next type in the subset.
      if (CanonicalSubT == CanonicalSuperT) {
        Contained = true;
        break;
      }

      // Otherwise we need to check the inheritance.
      if (!SubIsClass || !CanonicalSuperT->isRecordType())
        continue;

      Paths.clear();
      if (!IsDerivedFrom(CanonicalSubT, CanonicalSuperT, Paths))
        continue;

      if (Paths.isAmbiguous(Context.getCanonicalType(CanonicalSuperT)))
        continue;

      // Do this check from a context without privileges.
      switch (CheckBaseClassAccess(SourceLocation(),
                                   CanonicalSuperT, CanonicalSubT,
                                   Paths.front(),
                                   /*Diagnostic*/ 0,
                                   /*ForceCheck*/ true,
                                   /*ForceUnprivileged*/ true)) {
      case AR_accessible: break;
      case AR_inaccessible: continue;
      case AR_dependent:
        llvm_unreachable("access check dependent for unprivileged context");
        break;
      case AR_delayed:
        llvm_unreachable("access check delayed in non-declaration");
        break;
      }

      Contained = true;
      break;
    }
    if (!Contained) {
      Diag(SubLoc, DiagID);
      if (NoteID.getDiagID() != 0)
        Diag(SuperLoc, NoteID);
      return true;
    }
  }
  // We've run half the gauntlet.
  return CheckParamExceptionSpec(NoteID, Superset, SuperLoc, Subset, SubLoc);
}
Esempio n. 3
0
bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) {
  bool MissingExceptionSpecification = false;
  bool MissingEmptyExceptionSpecification = false;
  if (!CheckEquivalentExceptionSpec(PDiag(diag::err_mismatched_exception_spec),
                                    PDiag(diag::note_previous_declaration),
                                    Old->getType()->getAs<FunctionProtoType>(),
                                    Old->getLocation(),
                                    New->getType()->getAs<FunctionProtoType>(),
                                    New->getLocation(),
                                    &MissingExceptionSpecification,
                                    &MissingEmptyExceptionSpecification))
    return false;

  // The failure was something other than an empty exception
  // specification; return an error.
  if (!MissingExceptionSpecification && !MissingEmptyExceptionSpecification)
    return true;

  // The new function declaration is only missing an empty exception
  // specification "throw()". If the throw() specification came from a
  // function in a system header that has C linkage, just add an empty
  // exception specification to the "new" declaration. This is an
  // egregious workaround for glibc, which adds throw() specifications
  // to many libc functions as an optimization. Unfortunately, that
  // optimization isn't permitted by the C++ standard, so we're forced
  // to work around it here.
  if (MissingEmptyExceptionSpecification &&
      isa<FunctionProtoType>(New->getType()) &&
      (Old->getLocation().isInvalid() ||
       Context.getSourceManager().isInSystemHeader(Old->getLocation())) &&
      Old->isExternC()) {
    const FunctionProtoType *NewProto 
      = cast<FunctionProtoType>(New->getType());
    QualType NewType = Context.getFunctionType(NewProto->getResultType(),
                                               NewProto->arg_type_begin(),
                                               NewProto->getNumArgs(),
                                               NewProto->isVariadic(),
                                               NewProto->getTypeQuals(),
                                               true, false, 0, 0,
                                               NewProto->getExtInfo());
    New->setType(NewType);
    return false;
  }

  if (MissingExceptionSpecification && isa<FunctionProtoType>(New->getType())) {
    const FunctionProtoType *NewProto 
      = cast<FunctionProtoType>(New->getType());
    const FunctionProtoType *OldProto
      = Old->getType()->getAs<FunctionProtoType>();

    // Update the type of the function with the appropriate exception
    // specification.
    QualType NewType = Context.getFunctionType(NewProto->getResultType(),
                                               NewProto->arg_type_begin(),
                                               NewProto->getNumArgs(),
                                               NewProto->isVariadic(),
                                               NewProto->getTypeQuals(),
                                               OldProto->hasExceptionSpec(),
                                               OldProto->hasAnyExceptionSpec(),
                                               OldProto->getNumExceptions(),
                                               OldProto->exception_begin(),
                                               NewProto->getExtInfo());
    New->setType(NewType);

    // If exceptions are disabled, suppress the warning about missing
    // exception specifications for new and delete operators.
    if (!getLangOptions().Exceptions) {
      switch (New->getDeclName().getCXXOverloadedOperator()) {
      case OO_New:
      case OO_Array_New:
      case OO_Delete:
      case OO_Array_Delete:
        if (New->getDeclContext()->isTranslationUnit())
          return false;
        break;

      default:
        break;
      }
    } 

    // Warn about the lack of exception specification.
    llvm::SmallString<128> ExceptionSpecString;
    llvm::raw_svector_ostream OS(ExceptionSpecString);
    OS << "throw(";
    bool OnFirstException = true;
    for (FunctionProtoType::exception_iterator E = OldProto->exception_begin(),
                                            EEnd = OldProto->exception_end();
         E != EEnd;
         ++E) {
      if (OnFirstException)
        OnFirstException = false;
      else
        OS << ", ";
      
      OS << E->getAsString(Context.PrintingPolicy);
    }
    OS << ")";
    OS.flush();

    SourceLocation AfterParenLoc;
    if (TypeSourceInfo *TSInfo = New->getTypeSourceInfo()) {
      TypeLoc TL = TSInfo->getTypeLoc();
      if (const FunctionTypeLoc *FTLoc = dyn_cast<FunctionTypeLoc>(&TL))
        AfterParenLoc = PP.getLocForEndOfToken(FTLoc->getRParenLoc());
    }

    if (AfterParenLoc.isInvalid())
      Diag(New->getLocation(), diag::warn_missing_exception_specification)
        << New << OS.str();
    else {
      // FIXME: This will get more complicated with C++0x
      // late-specified return types.
      Diag(New->getLocation(), diag::warn_missing_exception_specification)
        << New << OS.str()
        << FixItHint::CreateInsertion(AfterParenLoc, " " + OS.str().str());
    }

    if (!Old->getLocation().isInvalid())
      Diag(Old->getLocation(), diag::note_previous_declaration);

    return false;    
  }

  Diag(New->getLocation(), diag::err_mismatched_exception_spec);
  Diag(Old->getLocation(), diag::note_previous_declaration);
  return true;
}
Esempio n. 4
0
void Sema::actOnTParamCommandParamNameArg(TParamCommandComment *Command,
                                          SourceLocation ArgLocBegin,
                                          SourceLocation ArgLocEnd,
                                          StringRef Arg) {
  // Parser will not feed us more arguments than needed.
  assert(Command->getNumArgs() == 0);

  typedef BlockCommandComment::Argument Argument;
  Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin,
                                                     ArgLocEnd),
                                         Arg);
  Command->setArgs(llvm::makeArrayRef(A, 1));

  if (!isTemplateOrSpecialization()) {
    // We already warned that this \\tparam is not attached to a template decl.
    return;
  }

  const TemplateParameterList *TemplateParameters =
      ThisDeclInfo->TemplateParameters;
  SmallVector<unsigned, 2> Position;
  if (resolveTParamReference(Arg, TemplateParameters, &Position)) {
    Command->setPosition(copyArray(llvm::makeArrayRef(Position)));
    llvm::StringMap<TParamCommandComment *>::iterator PrevCommandIt =
        TemplateParameterDocs.find(Arg);
    if (PrevCommandIt != TemplateParameterDocs.end()) {
      SourceRange ArgRange(ArgLocBegin, ArgLocEnd);
      Diag(ArgLocBegin, diag::warn_doc_tparam_duplicate)
        << Arg << ArgRange;
      TParamCommandComment *PrevCommand = PrevCommandIt->second;
      Diag(PrevCommand->getLocation(), diag::note_doc_tparam_previous)
        << PrevCommand->getParamNameRange();
    }
    TemplateParameterDocs[Arg] = Command;
    return;
  }

  SourceRange ArgRange(ArgLocBegin, ArgLocEnd);
  Diag(ArgLocBegin, diag::warn_doc_tparam_not_found)
    << Arg << ArgRange;

  if (!TemplateParameters || TemplateParameters->size() == 0)
    return;

  StringRef CorrectedName;
  if (TemplateParameters->size() == 1) {
    const NamedDecl *Param = TemplateParameters->getParam(0);
    const IdentifierInfo *II = Param->getIdentifier();
    if (II)
      CorrectedName = II->getName();
  } else {
    CorrectedName = correctTypoInTParamReference(Arg, TemplateParameters);
  }

  if (!CorrectedName.empty()) {
    Diag(ArgLocBegin, diag::note_doc_tparam_name_suggestion)
      << CorrectedName
      << FixItHint::CreateReplacement(ArgRange, CorrectedName);
  }

  return;
}
Esempio n. 5
0
/// CheckEquivalentExceptionSpec - Check if the two types have equivalent
/// exception specifications. Exception specifications are equivalent if
/// they allow exactly the same set of exception types. It does not matter how
/// that is achieved. See C++ [except.spec]p2.
bool Sema::CheckEquivalentExceptionSpec(const PartialDiagnostic &DiagID, 
                                        const PartialDiagnostic & NoteID,
                                        const FunctionProtoType *Old, 
                                        SourceLocation OldLoc,
                                        const FunctionProtoType *New, 
                                        SourceLocation NewLoc,
                                        bool *MissingExceptionSpecification,
                                     bool *MissingEmptyExceptionSpecification)  {
  // Just completely ignore this under -fno-exceptions.
  if (!getLangOptions().Exceptions)
    return false;

  if (MissingExceptionSpecification)
    *MissingExceptionSpecification = false;

  if (MissingEmptyExceptionSpecification)
    *MissingEmptyExceptionSpecification = false;

  bool OldAny = !Old->hasExceptionSpec() || Old->hasAnyExceptionSpec();
  bool NewAny = !New->hasExceptionSpec() || New->hasAnyExceptionSpec();
  if (OldAny && NewAny)
    return false;
  if (OldAny || NewAny) {
    if (MissingExceptionSpecification && Old->hasExceptionSpec() &&
        !New->hasExceptionSpec()) {
      // The old type has an exception specification of some sort, but
      // the new type does not.
      *MissingExceptionSpecification = true;

      if (MissingEmptyExceptionSpecification && 
          !Old->hasAnyExceptionSpec() && Old->getNumExceptions() == 0) {
        // The old type has a throw() exception specification and the
        // new type has no exception specification, and the caller asked
        // to handle this itself.
        *MissingEmptyExceptionSpecification = true;
      }

      return true;
    }

    Diag(NewLoc, DiagID);
    if (NoteID.getDiagID() != 0)
      Diag(OldLoc, NoteID);
    return true;
  }

  bool Success = true;
  // Both have a definite exception spec. Collect the first set, then compare
  // to the second.
  llvm::SmallPtrSet<CanQualType, 8> OldTypes, NewTypes;
  for (FunctionProtoType::exception_iterator I = Old->exception_begin(),
       E = Old->exception_end(); I != E; ++I)
    OldTypes.insert(Context.getCanonicalType(*I).getUnqualifiedType());

  for (FunctionProtoType::exception_iterator I = New->exception_begin(),
       E = New->exception_end(); I != E && Success; ++I) {
    CanQualType TypePtr = Context.getCanonicalType(*I).getUnqualifiedType();
    if(OldTypes.count(TypePtr))
      NewTypes.insert(TypePtr);
    else
      Success = false;
  }

  Success = Success && OldTypes.size() == NewTypes.size();

  if (Success) {
    return false;
  }
  Diag(NewLoc, DiagID);
  if (NoteID.getDiagID() != 0)
    Diag(OldLoc, NoteID);
  return true;
}
Esempio n. 6
0
int32 GPS_Serial_Write_Packet(gpsdevh *fd, GPS_PPacket packet)
{
    size_t ret;
    const char *m1, *m2;
    GPS_Serial_OPacket ser_pkt;
    UC ser_pkt_data[MAX_GPS_PACKET_SIZE * sizeof(UC)];
    US bytes;

    if (packet->type >= 0xff || packet->n >= 0xff) {
	GPS_Error("SEND: Unsupported packet type/size for serial protocol");
        return 0;
    }

    ser_pkt.data = ser_pkt_data;
    bytes = Build_Serial_Packet(packet, &ser_pkt);

    GPS_Diag("Tx Data:");
    Diag(&ser_pkt.dle, 3);
    if((ret=GPS_Serial_Write(fd,(const void *) &ser_pkt.dle,(size_t)3)) == -1)
    {
	perror("write");
	GPS_Error("SEND: Write to GPS failed");
	return 0;
    }
    if(ret!=3)
    {
	GPS_Error("SEND: Incomplete write to GPS");
	return 0;
    }

    Diag(ser_pkt.data, bytes);
    if((ret=GPS_Serial_Write(fd,(const void *)ser_pkt.data,(size_t)bytes)) == -1)
    {
	perror("write");
	GPS_Error("SEND: Write to GPS failed");
	return 0;
    }
    if(ret!=bytes)
    {
	GPS_Error("SEND: Incomplete write to GPS");
	return 0;
    }


    Diag(&ser_pkt.chk, 3);

    GPS_Diag(": ");
    DiagS(ser_pkt.data, bytes);
    DiagS(&ser_pkt.chk, 3);
    m1 = Get_Pkt_Type(ser_pkt.type, ser_pkt.data[0], &m2);
    GPS_Diag("(%-8s%s)\n", m1, m2 ? m2 : "");

    if((ret=GPS_Serial_Write(fd,(const void *)&ser_pkt.chk,(size_t)3)) == -1)
    {
	perror("write");
	GPS_Error("SEND: Write to GPS failed");
	return 0;
    }
    if(ret!=3)
    {
	GPS_Error("SEND: Incomplete write to GPS");
	return 0;
    }


    return 1;
}
Esempio n. 7
0
void Sema::actOnParamCommandParamNameArg(ParamCommandComment *Command,
                                         SourceLocation ArgLocBegin,
                                         SourceLocation ArgLocEnd,
                                         StringRef Arg) {
  // Parser will not feed us more arguments than needed.
  assert(Command->getNumArgs() == 0);

  if (!Command->isDirectionExplicit()) {
    // User didn't provide a direction argument.
    Command->setDirection(ParamCommandComment::In, /* Explicit = */ false);
  }
  typedef BlockCommandComment::Argument Argument;
  Argument *A = new (Allocator) Argument(SourceRange(ArgLocBegin,
                                                     ArgLocEnd),
                                         Arg);
  Command->setArgs(llvm::makeArrayRef(A, 1));

  if (!isFunctionDecl()) {
    // We already warned that this \\param is not attached to a function decl.
    return;
  }

  ArrayRef<const ParmVarDecl *> ParamVars = getParamVars();

  // Check that referenced parameter name is in the function decl.
  const unsigned ResolvedParamIndex = resolveParmVarReference(Arg, ParamVars);
  if (ResolvedParamIndex != ParamCommandComment::InvalidParamIndex) {
    Command->setParamIndex(ResolvedParamIndex);
    if (ParamVarDocs[ResolvedParamIndex]) {
      SourceRange ArgRange(ArgLocBegin, ArgLocEnd);
      Diag(ArgLocBegin, diag::warn_doc_param_duplicate)
        << Arg << ArgRange;
      ParamCommandComment *PrevCommand = ParamVarDocs[ResolvedParamIndex];
      Diag(PrevCommand->getLocation(), diag::note_doc_param_previous)
        << PrevCommand->getParamNameRange();
    }
    ParamVarDocs[ResolvedParamIndex] = Command;
    return;
  }

  SourceRange ArgRange(ArgLocBegin, ArgLocEnd);
  Diag(ArgLocBegin, diag::warn_doc_param_not_found)
    << Arg << ArgRange;

  // No parameters -- can't suggest a correction.
  if (ParamVars.size() == 0)
    return;

  unsigned CorrectedParamIndex = ParamCommandComment::InvalidParamIndex;
  if (ParamVars.size() == 1) {
    // If function has only one parameter then only that parameter
    // can be documented.
    CorrectedParamIndex = 0;
  } else {
    // Do typo correction.
    CorrectedParamIndex = correctTypoInParmVarReference(Arg, ParamVars);
  }
  if (CorrectedParamIndex != ParamCommandComment::InvalidParamIndex) {
    const ParmVarDecl *CorrectedPVD = ParamVars[CorrectedParamIndex];
    if (const IdentifierInfo *CorrectedII = CorrectedPVD->getIdentifier())
      Diag(ArgLocBegin, diag::note_doc_param_name_suggestion)
        << CorrectedII->getName()
        << FixItHint::CreateReplacement(ArgRange, CorrectedII->getName());
  }

  return;
}
Esempio n. 8
0
DoFileSaveAs(void)
{
    /* This routine handles input to the Save dialog box. */
    static CHAR szDefault[ cchMaxFile ];
    extern int vfTextOnlySave;
    extern DoSaveAsFilenameGet(LPSTR,LPSTR,int *,int *,int * ,int *);
    BOOL bDontDelPictures=FALSE;
    int fWordFmt, fTextOnly, fBackup, fOldWrite;
    CHAR szFullNameNewDoc[ cchMaxFile ];      // full name of selection
    CHAR szShortNameNewDoc[ cchMaxFile ];      // file name of selection
    CHAR szDocName[ cchMaxFile ];   // file name of current
    #define szFullNameCurDoc (**((**hpdocdod)[docCur].hszFile))  // full name of current
    #define pDod  ((struct DOD *)&(**hpdocdod)[docCur])

    {
        int cch = 0;
        CHAR szDOSPath[ cchMaxFile ];
        if (FNormSzFile( szDOSPath, "", dtyNormal ))
        {
            if ((cch=CchSz( szDOSPath )-2) > 2)
            {
                Assert( szDOSPath[ cch ] == '\\');
                szDOSPath [cch] = '\0';
            }

#if 0
            if (cch > 3)
                szDOSPath [cch] = '\\';
#endif
        }
        else
            szDOSPath[0] = '\0';

        if (szFullNameCurDoc [0] != '\0')
        {       /* Set default string for filename edit area */
            CHAR szDocPath[ cchMaxFile ];   // path to current

            FreezeHp();
            SplitSzFilename( szFullNameCurDoc, szDocPath, szDocName );

            /* Default filename does not include the document's path if
                it is == the current directory path */
            if (WCompSz( szDOSPath, szDocPath ) == 0)
                bltsz(szDocName, szDefault);
            else
                bltsz(szFullNameCurDoc, szDefault);

            MeltHp();
        }
        else
        {
            szDefault[0] = szDocName[0] = '\0';
        }
    }

    fTextOnly = vfTextOnlySave;
    fBackup = vfBackupSave;
    fWordFmt = vWordFmtMode & ~CONVFROMWORD;
    fOldWrite = vfOldWriteFmt;

    EnableOtherModeless(FALSE);

    while(1)
    {
    if (!DoSaveAsFilenameGet(szDefault,szFullNameNewDoc,&fBackup,&fTextOnly,&fWordFmt,&fOldWrite))
        goto end;
    else
    {
        int dty;

        if (szFullNameNewDoc[0] == '\0')
            goto end;

        if (fOldWrite || fWordFmt || fTextOnly)
        {
            if (!WannaDeletePictures(docCur,fOldWrite ? SF_OLDWRITE : SF_WORD))
                continue;
        }

        StartLongOp();

        szFileExtract(szFullNameNewDoc, szShortNameNewDoc);

#ifdef INTL /* International version */
        /* Read the "Microsoft Word Format" button */

        /* vWordFmtMode is used in WriteFn. If true, will convert
            to Word format, if false, no conversion is done.
            Another value, CONVFROMWORD, can be given during an open
            to allow saving a Word document in Write format. */

        if (fWordFmt)
        /* if set, make the default extension be doc instead of
            wri for word docs */

            dty = dtyWordDoc;
        else
#endif  /* International version */

        dty = dtyNormal;

#if WINVER >= 0x300            
/* Currently: FNormSzFile  *TAKES*   an OEM sz, and
                        *RETURNS*  an ANSI sz ..pault */
#endif
        if ( pDod->fReadOnly &&
                WCompSz( szFullNameNewDoc, szFullNameCurDoc ) == 0)
            {   /* Must save read-only file under a different name */
            Error( IDPMTReadOnly );
            goto NSerious;  /* Error not serious, stay in dialog */
            }
#if WINVER >= 0x300
        else if (WCompSz(szFullNameCurDoc, szFullNameNewDoc) == 0 &&
                    vWordFmtMode == CONVFROMWORD &&
                    vfTextOnlySave == fTextOnly)
            /* User has loaded a text file and is going
                to save under the same name without changing
                formats, *OR* has loaded a Word document and
                is going to save in the same format -- don't
                prompt "replace file?" ..pault 1/17/90 */
            ;
#endif
        else if ((WCompSz(szFullNameCurDoc, szFullNameNewDoc) != 0
#ifdef INTL /* International version */
                /* vWordFmtMode hasn't be reset yet */
                || ( vWordFmtMode == CONVFROMWORD)
#endif  /* International version */
                )
                && FExistsSzFile( dtyNormal, szFullNameNewDoc ) )
        {
            /* User changed the default string and specified
                a filename for which the file already exists.
                Or, we did a Word format conversion, forcing the .WRI
                extension on the file, and a file with that name
                exists.(International version only).o

                Note that vfWordFmtMode will be set to True or False
                below, so this check is made only on the first save
                after a Word conversion.

                Prompt to make sure it's ok to trash the existing one */

            CHAR szFileUp[ cchMaxFile  ];
            CHAR szUserOEM[cchMaxFile]; /* ..converted to OEM */
            CHAR szT[ cchMaxSz ];

            CchCopyUpperSz( szShortNameNewDoc, szFileUp );
            MergeStrings (IDSTRReplaceFile, szFileUp, szT);

#if WINVER >= 0x300
            /* access() expects OEM! */
            AnsiToOem((LPSTR) szFullNameNewDoc, (LPSTR) szUserOEM);

            /* Make sure we don't let someone try to save to 
                a file to which we do not have r/w permission */
            Diag(CommSzNum("fnSaveAs: access(write_perm)==", access(szUserOEM, WRITE_PERMISSION)));
            Diag(CommSzNum("          szExists()==", FExistsSzFile( dtyNormal, szFullNameNewDoc )));
            if (access(szUserOEM, WRITE_PERMISSION) == -1)
                {
                /* THIS COULD BE A CASE OF WRITING TO A FILE
                    WITH R/O ATTRIBUTE, *OR* A SHARING ERROR!
                    IMPROVE ERROR MESSAGE HERE ..pault 11/2/89 */                                
                //Error( IDPMTSDE2 );
                Error( IDPMTReadOnly );
                goto NSerious;  /* Error not serious, stay in dialog */
                }
#endif
            }

            vfTextOnlySave = fTextOnly;
            vfBackupSave = fBackup;
            vfOldWriteFmt = fOldWrite;

#ifdef INTL /* International version */
        /* vWordFmtMode is used in WriteFn. If true, will convert
            to Word format, if false, no conversion is done.
            Another value, CONVFROMWORD, can be given during an open
            to allow saving a Word document in Write format. */

            vWordFmtMode = fWordFmt;

#endif  /* International version */

        /* Record whether a backup was made or not. */

        WriteProfileString( (LPSTR)szWriteProduct, (LPSTR)szBackup,
                vfBackupSave ? (LPSTR)"1" : (LPSTR)"0" );

        /* Save the document */

        CmdXfSave( szFullNameNewDoc,!vfTextOnlySave, vfBackupSave, vhcArrow);

        if (vfDiskFull || vfSysFull)
            goto NSerious;

        /* Case 1: Serious error. Leave the dialog. */
        if (vfDiskError)
        {
            EndLongOp( vhcArrow );
            goto end;
        }

        /* Case 2: Saved OK: set the new title, leave the dialog. */
        else if (!WCompSz( szFullNameNewDoc, szFullNameCurDoc ))
            {
#if defined(OLE)
            ObjRenamedDoc(szFullNameNewDoc);
            ObjSavedDoc();
#endif

            SetTitle(szShortNameNewDoc);
#if WINVER >= 0x300
            FreeUnreferencedFns();
#endif

            /* Update the fReadOnly attribute (9.10.91) v-dougk */
            pDod->fReadOnly = FALSE; // can't be readonly if just saved

            EndLongOp( vhcArrow );
            goto end;
            }

        /* Case 3: Nonserious error (disk full, bad path, etc.).
                stay in dialog. */
        else
            {
NSerious:
            ferror = FALSE;
            EndLongOp( vhcArrow );
StayInDialog:
            CloseEveryRfn( TRUE );
            }
    }
    } // end of while(1)


    end:
    EnableOtherModeless(FALSE);


} /* end of DoFileSaveAs */
Esempio n. 9
0
int Ifpack_Analyze(const Epetra_RowMatrix& A, const bool Cheap,
                   const int NumPDEEqns)
{

  int NumMyRows = A.NumMyRows();
  long long NumGlobalRows = A.NumGlobalRows64();
  long long NumGlobalCols = A.NumGlobalCols64();
  long long MyBandwidth = 0, GlobalBandwidth;
  long long MyLowerNonzeros = 0, MyUpperNonzeros = 0;
  long long GlobalLowerNonzeros, GlobalUpperNonzeros;
  long long MyDiagonallyDominant = 0, GlobalDiagonallyDominant;
  long long MyWeaklyDiagonallyDominant = 0, GlobalWeaklyDiagonallyDominant;
  double MyMin, MyAvg, MyMax;
  double GlobalMin, GlobalAvg, GlobalMax;
  long long GlobalStorage;

  bool verbose = (A.Comm().MyPID() == 0);

  GlobalStorage = sizeof(int*) * NumGlobalRows +
    sizeof(int) * A.NumGlobalNonzeros64() +
    sizeof(double) * A.NumGlobalNonzeros64();

  if (verbose) {
    print();
    Ifpack_PrintLine();
    print<const char*>("Label", A.Label());
    print<long long>("Global rows", NumGlobalRows);
    print<long long>("Global columns", NumGlobalCols);
    print<long long>("Stored nonzeros", A.NumGlobalNonzeros64());
    print<long long>("Nonzeros / row", A.NumGlobalNonzeros64() / NumGlobalRows);
    print<double>("Estimated storage (Mbytes)", 1.0e-6 * GlobalStorage);
  }

  long long NumMyActualNonzeros = 0, NumGlobalActualNonzeros;
  long long NumMyEmptyRows = 0, NumGlobalEmptyRows;
  long long NumMyDirichletRows = 0, NumGlobalDirichletRows;

  std::vector<int> colInd(A.MaxNumEntries());
  std::vector<double> colVal(A.MaxNumEntries());

  Epetra_Vector Diag(A.RowMatrixRowMap());
  Epetra_Vector RowSum(A.RowMatrixRowMap());
  Diag.PutScalar(0.0);
  RowSum.PutScalar(0.0);

  for (int i = 0 ; i < NumMyRows ; ++i) {

    long long GRID = A.RowMatrixRowMap().GID64(i);
    int Nnz;
    IFPACK_CHK_ERR(A.ExtractMyRowCopy(i,A.MaxNumEntries(),Nnz,
                                      &colVal[0],&colInd[0]));

    if (Nnz == 0)
      NumMyEmptyRows++;

    if (Nnz == 1)
      NumMyDirichletRows++;

    for (int j = 0 ; j < Nnz ; ++j) {

      double v = colVal[j];
      if (v < 0) v = -v;
      if (colVal[j] != 0.0)
        NumMyActualNonzeros++;

      long long GCID = A.RowMatrixColMap().GID64(colInd[j]);

      if (GCID != GRID)
        RowSum[i] += v;
      else
        Diag[i] = v;

      if (GCID < GRID)
        MyLowerNonzeros++;
      else if (GCID > GRID)
        MyUpperNonzeros++;
      long long b = GCID - GRID;
      if (b < 0) b = -b;
      if (b > MyBandwidth)
        MyBandwidth = b;
    }

    if (Diag[i] > RowSum[i])
      MyDiagonallyDominant++;

    if (Diag[i] >= RowSum[i])
      MyWeaklyDiagonallyDominant++;

    RowSum[i] += Diag[i];
  }

  // ======================== //
  // summing up global values //
  // ======================== //

  A.Comm().SumAll(&MyDiagonallyDominant,&GlobalDiagonallyDominant,1);
  A.Comm().SumAll(&MyWeaklyDiagonallyDominant,&GlobalWeaklyDiagonallyDominant,1);
  A.Comm().SumAll(&NumMyActualNonzeros, &NumGlobalActualNonzeros, 1);
  A.Comm().SumAll(&NumMyEmptyRows, &NumGlobalEmptyRows, 1);
  A.Comm().SumAll(&NumMyDirichletRows, &NumGlobalDirichletRows, 1);
  A.Comm().SumAll(&MyBandwidth, &GlobalBandwidth, 1);
  A.Comm().SumAll(&MyLowerNonzeros, &GlobalLowerNonzeros, 1);
  A.Comm().SumAll(&MyUpperNonzeros, &GlobalUpperNonzeros, 1);
  A.Comm().SumAll(&MyDiagonallyDominant, &GlobalDiagonallyDominant, 1);
  A.Comm().SumAll(&MyWeaklyDiagonallyDominant, &GlobalWeaklyDiagonallyDominant, 1);

  double NormOne = A.NormOne();
  double NormInf = A.NormInf();
  double NormF   = Ifpack_FrobeniusNorm(A);

  if (verbose) {
    print();
    print<long long>("Actual nonzeros", NumGlobalActualNonzeros);
    print<long long>("Nonzeros in strict lower part", GlobalLowerNonzeros);
    print<long long>("Nonzeros in strict upper part", GlobalUpperNonzeros);
    print();
    print<long long>("Empty rows", NumGlobalEmptyRows,
               100.0 * NumGlobalEmptyRows / NumGlobalRows);
    print<long long>("Dirichlet rows", NumGlobalDirichletRows,
               100.0 * NumGlobalDirichletRows / NumGlobalRows);
    print<long long>("Diagonally dominant rows", GlobalDiagonallyDominant,
               100.0 * GlobalDiagonallyDominant / NumGlobalRows);
    print<long long>("Weakly diag. dominant rows",
               GlobalWeaklyDiagonallyDominant,
               100.0 * GlobalWeaklyDiagonallyDominant / NumGlobalRows);
    print();
    print<long long>("Maximum bandwidth", GlobalBandwidth);

    print();
    print("", "one-norm", "inf-norm", "Frobenius", false);
    print("", "========", "========", "=========", false);
    print();

    print<double>("A", NormOne, NormInf, NormF);
  }

  if (Cheap == false) {

    // create A + A^T and A - A^T

    Epetra_FECrsMatrix AplusAT(Copy, A.RowMatrixRowMap(), 0);
    Epetra_FECrsMatrix AminusAT(Copy, A.RowMatrixRowMap(), 0);

#ifndef EPETRA_NO_32BIT_GLOBAL_INDICES
    if(A.RowMatrixRowMap().GlobalIndicesInt()) {
      for (int i = 0 ; i < NumMyRows ; ++i) {

        int GRID = A.RowMatrixRowMap().GID(i);
        assert (GRID != -1);

        int Nnz;
        IFPACK_CHK_ERR(A.ExtractMyRowCopy(i,A.MaxNumEntries(),Nnz,
                                          &colVal[0],&colInd[0]));

        for (int j = 0 ; j < Nnz ; ++j) {

          int GCID         = A.RowMatrixColMap().GID(colInd[j]);
          assert (GCID != -1);

          double plus_val  = colVal[j];
          double minus_val = -colVal[j];

          if (AplusAT.SumIntoGlobalValues(1,&GRID,1,&GCID,&plus_val) != 0) {
            IFPACK_CHK_ERR(AplusAT.InsertGlobalValues(1,&GRID,1,&GCID,&plus_val));
          }

          if (AplusAT.SumIntoGlobalValues(1,&GCID,1,&GRID,&plus_val) != 0) {
            IFPACK_CHK_ERR(AplusAT.InsertGlobalValues(1,&GCID,1,&GRID,&plus_val));
          }

          if (AminusAT.SumIntoGlobalValues(1,&GRID,1,&GCID,&plus_val) != 0) {
            IFPACK_CHK_ERR(AminusAT.InsertGlobalValues(1,&GRID,1,&GCID,&plus_val));
          }

          if (AminusAT.SumIntoGlobalValues(1,&GCID,1,&GRID,&minus_val) != 0) {
            IFPACK_CHK_ERR(AminusAT.InsertGlobalValues(1,&GCID,1,&GRID,&minus_val));
          }

        }
      }
    }
        else
#endif
#ifndef EPETRA_NO_64BIT_GLOBAL_INDICES
    if(A.RowMatrixRowMap().GlobalIndicesLongLong()) {
      for (int i = 0 ; i < NumMyRows ; ++i) {

        long long GRID = A.RowMatrixRowMap().GID64(i);
        assert (GRID != -1);

        int Nnz;
        IFPACK_CHK_ERR(A.ExtractMyRowCopy(i,A.MaxNumEntries(),Nnz,
                                          &colVal[0],&colInd[0]));

        for (int j = 0 ; j < Nnz ; ++j) {

          long long GCID         = A.RowMatrixColMap().GID64(colInd[j]);
          assert (GCID != -1);

          double plus_val  = colVal[j];
          double minus_val = -colVal[j];

          if (AplusAT.SumIntoGlobalValues(1,&GRID,1,&GCID,&plus_val) != 0) {
            IFPACK_CHK_ERR(AplusAT.InsertGlobalValues(1,&GRID,1,&GCID,&plus_val));
          }

          if (AplusAT.SumIntoGlobalValues(1,&GCID,1,&GRID,&plus_val) != 0) {
            IFPACK_CHK_ERR(AplusAT.InsertGlobalValues(1,&GCID,1,&GRID,&plus_val));
          }

          if (AminusAT.SumIntoGlobalValues(1,&GRID,1,&GCID,&plus_val) != 0) {
            IFPACK_CHK_ERR(AminusAT.InsertGlobalValues(1,&GRID,1,&GCID,&plus_val));
          }

          if (AminusAT.SumIntoGlobalValues(1,&GCID,1,&GRID,&minus_val) != 0) {
            IFPACK_CHK_ERR(AminusAT.InsertGlobalValues(1,&GCID,1,&GRID,&minus_val));
          }

        }
      }
        }
        else
#endif
      throw "Ifpack_Analyze: GlobalIndices type unknown";

    AplusAT.FillComplete();
    AminusAT.FillComplete();

    AplusAT.Scale(0.5);
    AminusAT.Scale(0.5);

    NormOne = AplusAT.NormOne();
    NormInf = AplusAT.NormInf();
    NormF   = Ifpack_FrobeniusNorm(AplusAT);

    if (verbose) {
      print<double>("A + A^T", NormOne, NormInf, NormF);
    }

    NormOne = AminusAT.NormOne();
    NormInf = AminusAT.NormInf();
    NormF   = Ifpack_FrobeniusNorm(AminusAT);

    if (verbose) {
      print<double>("A - A^T", NormOne, NormInf, NormF);
    }
  }

  if (verbose) {
    print();
    print<const char*>("", "min", "avg", "max", false);
    print<const char*>("", "===", "===", "===", false);
  }

  MyMax = -DBL_MAX;
  MyMin = DBL_MAX;
  MyAvg = 0.0;

  for (int i = 0 ; i < NumMyRows ; ++i) {

    int Nnz;
    IFPACK_CHK_ERR(A.ExtractMyRowCopy(i,A.MaxNumEntries(),Nnz,
                                      &colVal[0],&colInd[0]));

    for (int j = 0 ; j < Nnz ; ++j) {
      MyAvg += colVal[j];
      if (colVal[j] > MyMax) MyMax = colVal[j];
      if (colVal[j] < MyMin) MyMin = colVal[j];
    }
  }

  A.Comm().MaxAll(&MyMax, &GlobalMax, 1);
  A.Comm().MinAll(&MyMin, &GlobalMin, 1);
  A.Comm().SumAll(&MyAvg, &GlobalAvg, 1);
  GlobalAvg /= A.NumGlobalNonzeros64();

  if (verbose) {
    print();
    print<double>(" A(i,j)", GlobalMin, GlobalAvg, GlobalMax);
  }

  MyMax = 0.0;
  MyMin = DBL_MAX;
  MyAvg = 0.0;

  for (int i = 0 ; i < NumMyRows ; ++i) {

    int Nnz;
    IFPACK_CHK_ERR(A.ExtractMyRowCopy(i,A.MaxNumEntries(),Nnz,
                                      &colVal[0],&colInd[0]));

    for (int j = 0 ; j < Nnz ; ++j) {
      double v = colVal[j];
      if (v < 0) v = -v;
      MyAvg += v;
      if (colVal[j] > MyMax) MyMax = v;
      if (colVal[j] < MyMin) MyMin = v;
    }
  }

  A.Comm().MaxAll(&MyMax, &GlobalMax, 1);
  A.Comm().MinAll(&MyMin, &GlobalMin, 1);
  A.Comm().SumAll(&MyAvg, &GlobalAvg, 1);
  GlobalAvg /= A.NumGlobalNonzeros64();

  if (verbose) {
    print<double>("|A(i,j)|", GlobalMin, GlobalAvg, GlobalMax);
  }

  // ================= //
  // diagonal elements //
  // ================= //

  Diag.MinValue(&GlobalMin);
  Diag.MaxValue(&GlobalMax);
  Diag.MeanValue(&GlobalAvg);

  if (verbose) {
    print();
    print<double>(" A(k,k)", GlobalMin, GlobalAvg, GlobalMax);
  }

  Diag.Abs(Diag);
  Diag.MinValue(&GlobalMin);
  Diag.MaxValue(&GlobalMax);
  Diag.MeanValue(&GlobalAvg);
  if (verbose) {
    print<double>("|A(k,k)|", GlobalMin, GlobalAvg, GlobalMax);
  }

  // ============================================== //
  // cycle over all equations for diagonal elements //
  // ============================================== //

  if (NumPDEEqns > 1 ) {

    if (verbose) print();

    for (int ie = 0 ; ie < NumPDEEqns ; ie++) {

      MyMin = DBL_MAX;
      MyMax = -DBL_MAX;
      MyAvg = 0.0;

      for (int i = ie ; i < Diag.MyLength() ; i += NumPDEEqns) {
        double d = Diag[i];
        MyAvg += d;
        if (d < MyMin)
          MyMin = d;
        if (d > MyMax)
          MyMax = d;
      }
      A.Comm().MinAll(&MyMin, &GlobalMin, 1);
      A.Comm().MaxAll(&MyMax, &GlobalMax, 1);
      A.Comm().SumAll(&MyAvg, &GlobalAvg, 1);
      // does not really work fine if the number of global
      // elements is not a multiple of NumPDEEqns
          GlobalAvg /= (Diag.GlobalLength64() / NumPDEEqns);

      if (verbose) {
        char str[80];
        sprintf(str, " A(k,k), eq %d", ie);
        print<double>(str, GlobalMin, GlobalAvg, GlobalMax);
      }
    }
  }

  // ======== //
  // row sums //
  // ======== //

  RowSum.MinValue(&GlobalMin);
  RowSum.MaxValue(&GlobalMax);
  RowSum.MeanValue(&GlobalAvg);

  if (verbose) {
    print();
    print<double>(" sum_j A(k,j)", GlobalMin, GlobalAvg, GlobalMax);
  }

  // ===================================== //
  // cycle over all equations for row sums //
  // ===================================== //

  if (NumPDEEqns > 1 ) {

    if (verbose) print();

    for (int ie = 0 ; ie < NumPDEEqns ; ie++) {

      MyMin = DBL_MAX;
      MyMax = -DBL_MAX;
      MyAvg = 0.0;

      for (int i = ie ; i < Diag.MyLength() ; i += NumPDEEqns) {
        double d = RowSum[i];
        MyAvg += d;
        if (d < MyMin)
          MyMin = d;
        if (d > MyMax)
          MyMax = d;
      }
      A.Comm().MinAll(&MyMin, &GlobalMin, 1);
      A.Comm().MaxAll(&MyMax, &GlobalMax, 1);
      A.Comm().SumAll(&MyAvg, &GlobalAvg, 1);
      // does not really work fine if the number of global
      // elements is not a multiple of NumPDEEqns
          GlobalAvg /= (Diag.GlobalLength64() / NumPDEEqns);

      if (verbose) {
        char str[80];
        sprintf(str, " sum_j A(k,j), eq %d", ie);
        print<double>(str, GlobalMin, GlobalAvg, GlobalMax);
      }
    }
  }

  if (verbose)
    Ifpack_PrintLine();

  return(0);
}
Esempio n. 10
0
// Open the entry
VXIcacheResult SBcacheEntryDetails::Open(VXIlogInterface       *log,
					 const SBcacheString   &moduleName,
					 const SBcacheKey      &key,
					 const SBcachePath     &path,
					 VXIcacheOpenMode       mode,
					 VXIint32               flags,
					 VXIulong               maxSizeBytes,
					 const VXIMap          *properties,
					 VXIMap                *streamInfo,
					 VXIcacheStream       **stream)
{
  VXIcacheResult rc = VXIcache_RESULT_SUCCESS;
  FILE *filePtr = NULL;

  // Lock and copy input data
  switch ( mode ) {
  case CACHE_MODE_WRITE:
    if ( _rwMutex.Lock( ) != VXItrd_RESULT_SUCCESS ) {
      Error (log, 110, L"%s%s", L"mutex", L"cache entry rw mutex, writer");
      rc = VXIcache_RESULT_SYSTEM_ERROR;
    } else {
      // If the open fails due to directory not existing, call
      // path.CreateDirectories( ) to create the dir tree then open
      // again
      if ( ! _invalidated ) {
	filePtr = fopen (path.c_str( ), "wb");
        int retries = 10; // work around possible race condition w/ rmdir
	while ((retries-- > 0) &&
            ( ! filePtr ) &&
            ( path.CreateDirectories( ) == VXIcache_RESULT_SUCCESS ))
	  filePtr = fopen (path.c_str( ), "wb");
      }

      if ( ! filePtr ) {
	if ( _invalidated ) {
	  // Invalidated or another thread attempted an open for write
	  // and failed, we only got here due to a race condition
	  // where we were waiting on the mutex to start our write
	  // before the failure/invalidation happened by the previous
	  // writer
	  rc = VXIcache_RESULT_FAILURE;
	} else {
	  // File open error
	  LogIOError (log, 213, path);
	  rc = VXIcache_RESULT_IO_ERROR;
	}

	_fileExists = false;
	_rwMutex.Unlock( );
      } else {
	_fileExists = true;
	_creationCost = CACHE_CREATION_COST_DEFAULT;
	_flags = flags;
	_sizeBytes = 0;

        // Only set the path and key if they differ
        if (path != _path || key != _key) {
          _path = path;
          _key = key;
        }

	// Load properties
	if ( properties ) {
	  const VXIValue *value =
	    VXIMapGetProperty (properties, CACHE_CREATION_COST);
	  if ( value ) {
	    if ( VXIValueGetType(value) == VALUE_INTEGER )
	      _creationCost = (VXIcacheCreationCost)
		VXIIntegerValue ((const VXIInteger *) value);
	    else
	      Error (log, 301, L"%s%d", L"VXIValueType",
		     VXIValueGetType(value));
	  }
	}
      }
    }
    break;

  case CACHE_MODE_READ:
    if ( _rwMutex.StartRead( ) != VXItrd_RESULT_SUCCESS ) {
      Error (log, 110, L"%s%s", L"mutex", L"cache entry rw mutex, reader");
      rc = VXIcache_RESULT_SYSTEM_ERROR;
    } else {
      if (( _fileExists ) && ( ! _invalidated )) {
	filePtr = fopen (_path.c_str( ), "rb");
	if ( ! filePtr ) {
	  _fileExists = false;
	  LogIOError (log, 214, _path);
	  _rwMutex.EndRead( );
	  rc = VXIcache_RESULT_IO_ERROR;
	}
      } else {
	// Invalidated or another thread attempted an open for write
	// and failed, we only got here due to a race condition where
	// we were waiting on the mutex to start our read before the
	// failure/invalidation happened by the writer
	_rwMutex.EndRead( );
	rc = VXIcache_RESULT_FAILURE;
      }
    }
    break;

  default:
    Error (log, 215, L"%s%d", L"mode", mode);
    rc = VXIcache_RESULT_UNSUPPORTED;
  }

  if ( rc == VXIcache_RESULT_SUCCESS ) {
    // Update the accessed time
    _lastAccessed = time(0);
    if (mode == CACHE_MODE_WRITE)
      _lastModified = _lastAccessed;

    // Return stream information
    if ( streamInfo ) {
      if (( VXIMapSetProperty (streamInfo, CACHE_INFO_LAST_MODIFIED,
			       (VXIValue *) VXIIntegerCreate(_lastModified)) !=
	    VXIvalue_RESULT_SUCCESS ) ||
	  ( VXIMapSetProperty (streamInfo, CACHE_INFO_SIZE_BYTES,
			       (VXIValue *) VXIIntegerCreate (_sizeBytes)) !=
	    VXIvalue_RESULT_SUCCESS )) {
	Error (log, 100, NULL);
	rc = VXIcache_RESULT_OUT_OF_MEMORY;
      }
    }
  }

  // Return the stream
  if ( rc == VXIcache_RESULT_SUCCESS ) {
    SBcacheEntry entry(this);
    *stream = new SBcacheStream (log, GetDiagBase( ), moduleName, key,
				 entry, mode,
				 ((flags & CACHE_FLAG_NONBLOCKING_IO) == 0),
				 maxSizeBytes, filePtr);
    if ( ! *stream ) {
      Error (log, 100, NULL);
      fclose (filePtr);
      Close (log, mode, 0, true);
      rc = VXIcache_RESULT_OUT_OF_MEMORY;
    }
  }

  Diag (log, SBCACHE_ENTRY_TAGID, L"Open", L"%s, %S, 0x%x, 0x%x: rc = %d",
	key.c_str( ), path.c_str( ), mode, flags, rc);
  return rc;
}
Esempio n. 11
0
VXIinetResult
SBinetFileStream::Open(VXIint32                  flags,
		       const VXIMap             *properties,
		       VXIMap                   *streamInfo)
{
  VXIinetResult returnValue = VXIinet_RESULT_SUCCESS;

  /*
     Get the flag to determine whether to open local files. Also check
     the validator to see if it contains INET_INFO_VALIDATOR and if it
     does contain the modified time. */
  SBinetValidator validator(GetLog(), GetDiagBase());
  const VXIValue *validatorVal = NULL;
  if (properties)
  {
    const VXIValue *val = VXIMapGetProperty(properties, INET_OPEN_LOCAL_FILE);
    if (val != NULL)
    {
      if (VXIValueGetType(val) == VALUE_INTEGER)
      {
        if (VXIIntegerValue((const VXIInteger *) val) == FALSE)
          returnValue = VXIinet_RESULT_LOCAL_FILE;
      }
      else
      {
        Diag(MODULE_SBINET_STREAM_TAGID, L"SBinetFileStream::Open",
             L"Passed invalid type for INET_OPEN_LOCAL_FILE property");
      }
    }

    // SBinetValidator::Create() logs errors for us
    validatorVal = VXIMapGetProperty(properties, INET_OPEN_IF_MODIFIED);
    if((validatorVal != NULL) &&
       (validator.Create(validatorVal) != VXIinet_RESULT_SUCCESS))
      validatorVal = NULL;
  }

  Diag(MODULE_SBINET_STREAM_TAGID, L"SBinetFileStream::Open",
       _url->getAbsolute( ));

  // Stat the file to make sure it exists and to get the length and
  // last modified time
  VXIStatStruct statInfo;
  if (VXIStat(SBinetNString(_url->getPath()).c_str(), &statInfo) != 0) {
    Error(222, L"%s%s", L"File", _url->getPath());
    return(VXIinet_RESULT_NOT_FOUND);
  }

  _content_length = statInfo.st_size;

  // If there is a conditional open using a validator, see if the
  // validator is still valid (no need to re-read and re-process)
  if (validatorVal)
  {
    if (! validator.isModified(statInfo.st_mtime, statInfo.st_size))
    {
      Diag(MODULE_SBINET_STREAM_TAGID, L"SBinetFileStream::Open",
           L"Validator OK, returning NOT_MODIFIED");
      returnValue = VXIinet_RESULT_NOT_MODIFIED;
    }
    else
    {
      Diag(MODULE_SBINET_STREAM_TAGID, L"SBinetFileStream::Open",
           L"Validator modified, must re-fetch");
    }
  }

  if (returnValue != VXIinet_RESULT_LOCAL_FILE)
  {
    // Use fopen for now. Note: Open support reads for now
    _pFile = ::fopen( SBinetNString(_url->getPath()).c_str(), "rb" );
    if(!_pFile){
      Error(223, L"%s%s", L"File", _url->getPath());
      return(VXIinet_RESULT_NOT_FOUND);
    }
    _ReadSoFar = 0;
  }

  if (streamInfo != NULL)
  {
    // Set FILE data source information   
    VXIMapSetProperty(streamInfo, INET_INFO_DATA_SOURCE, 
                     (VXIValue*) VXIIntegerCreate(INET_DATA_SOURCE_FILE));
    
    // Use extension mapping algorithm to determine MIME content type
    VXIString *guessContent = _url->getContentTypeFromUrl();
    if (guessContent == NULL) {
      guessContent = VXIStringCreate(_channel->getDefaultMimeType());
      // This error message is useful, but unfortunately it gets printed
      // for all the grammar files etc. whose extensions are unknown...
      //Error (303, L"%s%s", L"URL", _url->getPath());
    }
    VXIMapSetProperty(streamInfo, INET_INFO_MIME_TYPE, (VXIValue*) guessContent);

    // Set the absolute path, any file:// prefix and host name is
    // already stripped prior to this method being invoked
    VXIMapSetProperty(streamInfo, INET_INFO_ABSOLUTE_NAME,
		      (VXIValue*)VXIStringCreate( _url->getPath() ));

    // Set the validator property
    VXIValue *newValidator = NULL;
    if (returnValue == VXIinet_RESULT_NOT_MODIFIED) {
      newValidator = VXIValueClone(validatorVal);
    } else {
      SBinetValidator validator(GetLog(), GetDiagBase());
      if (validator.Create(_url->getPath(), statInfo.st_size,
                           statInfo.st_mtime) == VXIinet_RESULT_SUCCESS)
      {
	newValidator = (VXIValue *) validator.serialize();
      }
    }

    if (newValidator)
      VXIMapSetProperty(streamInfo, INET_INFO_VALIDATOR, newValidator);
    else {
      Error(103, NULL);
      returnValue = VXIinet_RESULT_OUT_OF_MEMORY;
    }

    // Set the size
    VXIMapSetProperty(streamInfo, INET_INFO_SIZE_BYTES,
		      (VXIValue*)VXIIntegerCreate( _content_length));
  }

  if (!validatorVal && (returnValue == VXIinet_RESULT_NOT_MODIFIED))
    return VXIinet_RESULT_SUCCESS;

  return returnValue;
}
Esempio n. 12
0
bool InstallFiles()
{
    ButtonBar.Clear();
    ButtonBar.AddButton("C", "Cancel");
    ButtonBar.Draw();

    char *msg;
    char *dbuttons[2] = { GetTranslation("Continue"), GetTranslation("Exit program") };
    
    if ((InstallInfo.dest_dir_type == DEST_SELECT) || (InstallInfo.dest_dir_type == DEST_DEFAULT))
    {
        msg = CreateText(GetTranslation("This will install %s to the following directory:\n%s\nContinue?"),
                                   InstallInfo.program_name.c_str(), MakeCString(InstallInfo.dest_dir));
    }
    else
    {
        msg = CreateText(GetTranslation("This will install %s\nContinue?"), InstallInfo.program_name.c_str());
    }

    CCDKDialog Diag(CDKScreen, CENTER, CENTER, msg, dbuttons, 2);
    Diag.SetBgColor(26);
        
    int sel = Diag.Activate();
    
    Diag.Destroy();
    refreshCDKScreen(CDKScreen);
                
    if (sel == 1)
        return false;
    
    CCDKSWindow InstallOutput(CDKScreen, 0, 6, GetDefaultHeight()-5, -1,
                              CreateText("<C></29/B>%s", GetTranslation("Install output")), 2000);
    InstallOutput.SetBgColor(5);
    nodelay(WindowOf(InstallOutput.GetSWin()), true); // Make sure input doesn't block

    const int maxx = getmaxx(InstallOutput.GetSWin()->win);

    CCDKSWindow ProggWindow(CDKScreen, 0, 2, 5, maxx, NULL, 4);
    ProggWindow.SetBgColor(5);
    ProggWindow.AddText("");
    ProggWindow.AddText(CreateText("</B/29>%s:<!29!B>", GetTranslation("Status")));
    ProggWindow.AddText(CreateText("%s (1/%d)", GetTranslation("Extracting files"), InstallInfo.command_entries.size()+1),
                        true, BOTTOM, 24);
    
    CCDKHistogram ProgressBar(CDKScreen, 25, 3, 1, maxx-29, HORIZONTAL,
                              CreateText("<C></29/B>%s", GetTranslation("Progress")), false);
    ProgressBar.SetBgColor(5);
    ProgressBar.SetHistogram(vPERCENT, TOP, 0, 100, 0, COLOR_PAIR (24) | A_REVERSE | ' ', A_BOLD);
    
    setCDKSwindowLLChar(ProggWindow.GetSWin(), ACS_LTEE);
    setCDKSwindowLRChar(ProggWindow.GetSWin(), ACS_RTEE);
    
    InstallOutput.Draw();
    ProggWindow.Draw();
    
    // Check if we need root access
    char *passwd = NULL;
    LIBSU::CLibSU SuHandler;
    SuHandler.SetUser("root");
    SuHandler.SetTerminalOutput(false);

    bool askpass = false;
    
    for (std::list<command_entry_s *>::iterator it=InstallInfo.command_entries.begin();
        it!=InstallInfo.command_entries.end(); it++)
    {
        if ((*it)->need_root != NO_ROOT)
        {
            // Command may need root permission, check if it is so
            if ((*it)->need_root == DEPENDED_ROOT)
            {
                param_entry_s *p = GetParamByVar((*it)->dep_param);
                if (p && !WriteAccess(p->value))
                {
                    (*it)->need_root = NEED_ROOT;
                    if (!askpass) askpass = true;
                }
            }
            else if (!askpass) askpass = true;
        }
    }

    if (!askpass)
        askpass = !WriteAccess(InstallInfo.dest_dir);
    
    // Ask root password if one of the command entries need root access and root isn't passwordless
    if (askpass && SuHandler.NeedPassword())
    {
        CCDKEntry entry(CDKScreen, CENTER, CENTER,
                        GetTranslation("This installation requires root(administrator) privileges in order to continue\n"
                                       "Please enter the password of the root user"), "", 60, 0, 256, vHMIXED);
        entry.SetHiddenChar('*');
        entry.SetBgColor(26);

        while(1)
        {
            char *sz = entry.Activate();

            if ((entry.ExitType() != vNORMAL) || !sz || !sz[0])
            {
                if (YesNoBox(GetTranslation("Root access is required to continue\nAbort installation?")))
                    EndProg();
                refreshCDKScreen(CDKScreen);
            }
            else
            {
                if (SuHandler.TestSU(sz))
                {
                    passwd = strdup(sz);
                    for (short s=0;s<strlen(sz);s++) sz[s] = 0;
                    break;
                }

                for (short s=0;s<strlen(sz);s++) sz[s] = 0;
                entry.Clean();
                
                // Some error appeared
                if (SuHandler.GetError() == LIBSU::CLibSU::SU_ERROR_INCORRECTPASS)
                {
                    WarningBox(GetTranslation("Incorrect password given for root user\nPlease retype"));
                }
                else
                {
                    throwerror(true, GetTranslation("Could not use su to gain root access\n"
                               "Make sure you can use su(adding the current user to the wheel group may help)"));
                }
            }
        }
        // Restore screen
        entry.Destroy();
        refreshCDKScreen(CDKScreen);
    }

    short percent = 0;
    
    bool alwaysroot = false;
    if (!WriteAccess(InstallInfo.dest_dir))
    {
        CExtractAsRootFunctor Extracter;
        Extracter.SetUpdateProgFunc(SUUpdateProgress, &ProgressBar);
        Extracter.SetUpdateTextFunc(SUUpdateText, &InstallOutput);
        
        if (!Extracter(passwd))
        {
            CleanPasswdString(passwd);
            passwd = NULL;
            throwerror(true, "Error during extracting files");
        }

        InstallOutput.AddText("Done!\n");
        alwaysroot = true; // Install commands need root now too
    }
    else
    {

        while(percent<100)
        {
            std::string curfile;
            percent = ExtractArchive(curfile);
            
            InstallOutput.AddText("Extracting file: " + curfile, false);
            if (percent==100) InstallOutput.AddText("Done!", false);
            else if (percent==-1) throwerror(true, "Error during extracting files");
    
            ProgressBar.SetValue(0, 100, percent/(1+InstallInfo.command_entries.size()));
            ProgressBar.Draw();
    
            chtype input = getch();
            if (input == 'c')
            {
                if (YesNoBox(GetTranslation("Install commands are still running\n"
                    "If you abort now this may lead to a broken installation\n"
                    "Are you sure?")))
                {
                    CleanPasswdString(passwd);
                    passwd = NULL;
                    EndProg();
                }
            }
        }
    }

    SuHandler.SetThinkFunc(InstThinkFunc, passwd);
    SuHandler.SetOutputFunc(PrintInstOutput, &InstallOutput);

    percent = 100/(1+InstallInfo.command_entries.size()); // Convert to overall progress
    
    short step = 2; // Not 1, because extracting files is also a step
    for (std::list<command_entry_s*>::iterator it=InstallInfo.command_entries.begin();
         it!=InstallInfo.command_entries.end(); it++, step++)
    {
        if ((*it)->command.empty()) continue;

        ProggWindow.Clear();
        ProggWindow.AddText("");
        ProggWindow.AddText(CreateText("</B/29>%s:<!29!B>", GetTranslation("Status")));
        ProggWindow.AddText(CreateText("%s (%d/%d)", GetTranslation((*it)->description.c_str()), step,
                            InstallInfo.command_entries.size()+1), true, BOTTOM, 24);

        ProgressBar.Draw();
        
        std::string command = (*it)->command + " " + GetParameters(*it);
        InstallOutput.AddText("");
        InstallOutput.AddText(CreateText("Execute: %s", command.c_str()));
        InstallOutput.AddText("");
        InstallOutput.AddText("");
        
        if (((*it)->need_root == NEED_ROOT) || alwaysroot)
        {
            SuHandler.SetPath((*it)->path.c_str());
            SuHandler.SetCommand(command);
            if (!SuHandler.ExecuteCommand(passwd))
            {
                if ((*it)->exit_on_failure)
                {
                    CleanPasswdString(passwd);
                    passwd = NULL;
                    throwerror(true, "%s\n('%s')", GetTranslation("Failed to execute install command"),
                               SuHandler.GetErrorMsgC());
                }
            }
        }
        else
        {
            // Redirect stderr to stdout, so that errors will be displayed too
            command += " 2>&1";
            
            setenv("PATH", (*it)->path.c_str(), 1);
            FILE *pipe = popen(command.c_str(), "r");
            char term[1024];
            if (pipe)
            {
                while (fgets(term, sizeof(term), pipe))
                {
                    InstallOutput.AddText(term);

                    chtype input = getch();
                    if (input == 'c') /*injectCDKSwindow(InstallOutput.GetSWin(), input);*/
                    {
                        if (YesNoBox(GetTranslation("Install commands are still running\n"
                                                    "If you abort now this may lead to a broken installation\n"
                                                    "Are you sure?")))
                        {
                            CleanPasswdString(passwd);
                            passwd = NULL;
                            EndProg();
                        }
                    }
                }
                
                // Check if command exitted normally and close pipe
                int state = pclose(pipe);
                if (!WIFEXITED(state) || (WEXITSTATUS(state) == 127)) // SH returns 127 if command execution failes
                {
                    if ((*it)->exit_on_failure)
                    {
                        CleanPasswdString(passwd);
                        passwd = NULL;
                        throwerror(true, "Failed to execute install command");
                    }
                }
            }
            else
            {
                CleanPasswdString(passwd);
                passwd = NULL;
                throwerror(true, "Could not execute installation commands (could not open pipe)");
            }
            
#if 0
            // Need to find a good way to safely suspend a process...this code doesn't always work :(
            
            int pipefd[2];

            pipe(pipefd);
            pid_t pid = fork();
            if (pid == -1) throwerror(true, "Error during command execution: Could not fork process");
            else if (pid) // Parent process
            {
                close(pipefd[1]); // We're not going to write here

                std::string out;
                char c;
                int compid = -1; // PID of the executed command

                while(read(pipefd[0], &c, sizeof(c)) > 0)
                {
                    out += c;
                    if (c == '\n')
                    {
                        if (compid == -1)
                        {
                            compid = atoi(out.c_str());
                            InstallOutput.AddText(CreateText("pid: %d compid: %d", pid, compid), false);
                        }
                        else InstallOutput.AddText(out, false);
                        out.clear();
                    }

                    chtype input = getch();
                    if (input != ERR) /*injectCDKSwindow(InstallOutput.GetSWin(), input);*/
                    {
                        if (kill(compid, SIGTSTP) < 0) // Pause command execution
                            WarningBox("PID Error: %s\n", strerror(errno));
                        
                        char *buttons[2] = { GetTranslation("Yes"), GetTranslation("No") };
                        CCharListHelper msg;
    
                        msg.AddItem(GetTranslation("This will abort the installation"));
                        msg.AddItem(GetTranslation("Are you sure?"));
    
                        CCDKDialog dialog(CDKScreen, CENTER, CENTER, msg, msg.Count(), buttons, 2);
                        dialog.SetBgColor(26);
                        int ret = dialog.Activate();
                        bool cont = ((ret == 1) || (dialog.ExitType() != vNORMAL));

                        dialog.Destroy();
                        refreshCDKScreen(CDKScreen);

                        if (!cont)
                        {
                            kill(pid, SIGTERM);
                            EndProg();
                        }

                        kill(compid, SIGCONT); // Continue command execution
                    }
                }
                close (pipefd[0]);

                int status;
                //waitpid(pid, &status, 0);
            }
            else // Child process
            {
                // Redirect stdout to pipe
                close(STDOUT_FILENO);
                dup (pipefd[1]);
                
                close (pipefd[0]); // No need to read here

                // Make sure no errors are printed and write pid of new command
                command += " 2> /dev/null &  echo $!";
                execl("/bin/sh", "sh", "-c", command.c_str(), NULL);
                system(CreateText("echo %s", strerror(errno)));
                _exit(1);
            }
#endif
        }

        percent += (1.0f/((float)InstallInfo.command_entries.size()+1.0f))*100.0f;
        ProgressBar.SetValue(0, 100, percent);
    }

    ProgressBar.SetValue(0, 100, 100);
    ProgressBar.Draw();
    
    CleanPasswdString(passwd);
    passwd = NULL;
    
    ButtonBar.Clear();
    ButtonBar.AddButton("Arrows", "Scroll install output");
    ButtonBar.AddButton("Enter", (FileExists(InstallInfo.own_dir + "/config/finish")) ? "Continue" : "Finish"); // HACK
    ButtonBar.Draw();

    WarningBox("Installation of %s complete!", InstallInfo.program_name.c_str());

    InstallOutput.Activate();
    return (InstallOutput.ExitType() == vNORMAL);
}
Esempio n. 13
0
int main(int argc, char** argv)
{	initSystem(argc, argv);

	//Parse command-line
	S2quadType quadType = QuadEuler;
	int nBeta = 12;
	if(argc > 1)
	{	if(!S2quadTypeMap.getEnum(argv[1], quadType))
			die("<quad> must be one of %s\n", S2quadTypeMap.optionList().c_str());
		if(quadType==QuadEuler)
		{	if(argc < 3) die("<nBeta> must be specified for Euler quadratures.\n")
			nBeta = atoi(argv[2]);
			if(nBeta <= 0) die("<nBeta> must be non-negative.")
		}
	}
	
	//Setup simulation grid:
	GridInfo gInfo;
	gInfo.S = vector3<int>(1, 1, 4096);
	const double hGrid = 0.0625;
	gInfo.R = Diag(hGrid * gInfo.S);
	gInfo.initialize();

	double T = 298*Kelvin;
	FluidComponent component(FluidComponent::H2O, T, FluidComponent::ScalarEOS);
	component.s2quadType = quadType;
	component.quad_nBeta = nBeta;
	component.representation = FluidComponent::Pomega;
	FluidMixture fluidMixture(gInfo, T);
	component.addToFluidMixture(&fluidMixture);
	double p = 1.01325*Bar;
	logPrintf("pV = %le\n", p*gInfo.detR);
	fluidMixture.initialize(p);

	//Initialize external potential (repel O from a cube)
	double Dfield = 1.0 * eV/Angstrom;
	const double zWall = 8.0 - 1e-3;
	const double& gridLength = gInfo.R(2,2);
	ScalarField phiApplied(ScalarFieldData::alloc(gInfo)), phiWall(ScalarFieldData::alloc(gInfo));
	applyFunc_r(gInfo, setPhi, phiApplied->data(), phiWall->data(), gridLength, Dfield, zWall);
	const double ZO = component.molecule.sites[0]->chargeKernel(0);
	component.idealGas->V[0] = ZO * phiApplied + phiWall;
	component.idealGas->V[1] = -0.5*ZO * phiApplied + phiWall;

	//----- Initialize state -----
	fluidMixture.initState(0.01);

	//----- FDtest and CG -----
	MinimizeParams mp;
	mp.fpLog = globalLog;
	mp.nDim = gInfo.nr * fluidMixture.get_nIndep();
	mp.energyLabel = "Phi";
	mp.nIterations=1500;
	mp.energyDiffThreshold=1e-16;
	
	fluidMixture.minimize(mp);
	
	//------ Outputs ---------
	ostringstream quadName;
	quadName << S2quadTypeMap.getString(quadType);
	if(quadType == QuadEuler) quadName << nBeta;
	
	ScalarFieldArray N;
	fluidMixture.getFreeEnergy(FluidMixture::Outputs(&N));
	FILE* fp = fopen((quadName.str()+".Nplanar").c_str(), "w");
	double* NOdata = N[0]->data();
	double* NHdata = N[1]->data();
	double nlInv = 1./component.idealGas->get_Nbulk();
	for(int i=0; i<gInfo.S[2]/2; i++)
		fprintf(fp, "%le\t%le\t%le\n", i*hGrid, nlInv*NOdata[i], 0.5*nlInv*NHdata[i]);
	fclose(fp);
	
	finalizeSystem();
	return 0;
}
Esempio n. 14
0
bool CFileDialog::Activate()
{
    char *buttons[] = { GetTranslation("Open directory"), GetTranslation("Select directory"), GetTranslation("Cancel") };
    char label[] = "Dir: ";
    char curdir[1024];
    
    ButtonBar.Push();
    ButtonBar.AddButton("TAB", "Next button");
    ButtonBar.AddButton("ENTER", "Activate button");
    ButtonBar.AddButton("Arrows", "Navigate menu");
    ButtonBar.AddButton("C", "Create directory");
    ButtonBar.AddButton("A", "About");
    ButtonBar.AddButton("ESC", "Cancel");
    ButtonBar.Draw();

    if (!getcwd(curdir, sizeof(curdir))) throwerror(true, "Could not read current directory");
    
    if (chdir(m_szStartDir.c_str()) != 0)
        throwerror(true, "Could not open directory '%s'", m_szStartDir.c_str());

    if (!ReadDir(m_szStartDir)) throwerror(true, "Could not read directory '%s'", m_szStartDir.c_str());
    
    CCDKButtonBox ButtonBox(CDKScreen, CENTER, GetDefaultHeight(), 1, GetDefaultWidth(), 0, 1, 3, buttons, 3);
    ButtonBox.SetBgColor(5);

    if (!m_pCurDirWin && !m_pFileList)
    {
        m_pCurDirWin = new CCDKSWindow(CDKScreen, CENTER, getbegy(ButtonBox.GetBBox()->win)-2, 2, GetDefaultWidth()+1,
                                                           NULL, 1);
        m_pCurDirWin->SetBgColor(5);

        if (!m_pFileList)
        {
            m_pFileList = new CCDKAlphaList(CDKScreen, CENTER, 2, getbegy(m_pCurDirWin->GetSWin()->win)-1, GetDefaultWidth()+1,
                                            const_cast<char*>(m_szTitle.c_str()), label, &m_DirItems[0], m_DirItems.size());
            m_pFileList->SetBgColor(5);
            setCDKEntryPreProcess(m_pFileList->GetAList()->entryField, CreateDirCB, this);
    
            //m_pFileList->GetAList()->entryField->dispType = vVIEWONLY;  // HACK: Disable backspace
        }
    
        setCDKAlphalistLLChar(m_pFileList->GetAList(), ACS_LTEE);
        setCDKAlphalistLRChar(m_pFileList->GetAList(), ACS_RTEE);
        setCDKLabelLLChar(m_pCurDirWin->GetSWin(), ACS_LTEE);
        setCDKLabelLRChar(m_pCurDirWin->GetSWin(), ACS_RTEE);
        setCDKButtonboxULChar(ButtonBox.GetBBox(), ACS_LTEE);
        setCDKButtonboxURChar(ButtonBox.GetBBox(), ACS_RTEE);
    }
    
    m_pFileList->Draw();
    m_pCurDirWin->Draw();
    ButtonBox.Draw();
    
    m_pFileList->Bind(KEY_TAB, SwitchButtonK, ButtonBox.GetBBox()); // Pas TAB through ButtonBox

    m_szDestDir = m_szStartDir;
    UpdateCurDirText();
    
    while(true)
    {
        // HACK: Give textbox content
        setCDKEntryValue(m_pFileList->GetAList()->entryField,
                         chtype2Char(m_pFileList->GetAList()->scrollField->item[m_pFileList->GetAList()->scrollField->currentItem]));

        char *selection = m_pFileList->Activate();

        if ((m_pFileList->ExitType() != vNORMAL) || (ButtonBox.GetCurrent() == 2)) break;
        if (!selection || !selection[0]) continue;

        if (ButtonBox.GetCurrent() == 1)
        {
            if (m_bAskWAccess && !WriteAccess(m_szDestDir))
            {
                char *dbuttons[2] = { GetTranslation("Continue as root"), GetTranslation("Choose another directory") };
                CCDKDialog Diag(CDKScreen, CENTER, CENTER,
                                GetTranslation("You don't have write permissions for this directory.\n"
                                        "The files can be extracted as the root user,\n"
                                        "but you'll need to enter the root password for this later."), dbuttons, 2);
                Diag.SetBgColor(26);
        
                int sel = Diag.Activate();
    
                Diag.Destroy();
                refreshCDKScreen(CDKScreen);
                if (sel)
                    continue;
            }
            break;
        }
        
        if (!FileExists(selection))
        {
            if (YesNoBox(GetTranslation("Directory does not exist\nDo you want to create it?")))
            {
                if (mkdir(selection, (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH)) != 0)
                {
                    WarningBox("%s\n%.75s\n%.75s", GetTranslation("Could not create directory"), selection,
                               strerror(errno));
                    continue;
                }
            }
            else
                continue;
        }
        
        UpdateFileList(selection);
    }
    
    bool success = ((m_pFileList->ExitType() != vESCAPE_HIT) && (ButtonBox.GetCurrent() == 1));
    
    ButtonBar.Pop();

    if (m_bRestoreDir)
        chdir(curdir); // Return back to original directory
    
    return success;
}