Exemplo n.º 1
0
void testInputFiles(int numFilenames, char* filename[]) {
  inputFilenames = (const char**)malloc((numFilenames+1)*sizeof(char*));
  int i;
  char achar;

  for (i = 0; i < numFilenames; i++) {
    if (!isRecognizedSource(filename[i])) {
      USR_FATAL(astr("file '",
                     filename[i],
                     "' does not have a recognized suffix"));
    }
    // WE SHOULDN"T TRY TO OPEN .h files, just .c and .chpl and .o
    if (!isCHeader(filename[i])) {
      FILE* testfile = openInputFile(filename[i]);
      if (fscanf(testfile, "%c", &achar) != 1) {
        USR_FATAL(astr("source file '",
                       filename[i],
                       "' is either empty or a directory"));
      }

      closeInputFile(testfile);
    }

    inputFilenames[i] = astr(filename[i]);
  }

  inputFilenames[i] = NULL;

  if (!foundChplSource)
    USR_FATAL("Command line contains no .chpl source files");
}
Exemplo n.º 2
0
const char* createDebuggerFile(const char* debugger, int argc, char* argv[]) {
  const char* dbgfilename = genIntermediateFilename(astr(debugger, ".commands"));
  FILE* dbgfile = openfile(dbgfilename);
  int i;

  if (strcmp(debugger, "gdb") == 0) {
    fprintf(dbgfile, "set args");
  } else if (strcmp(debugger, "lldb") == 0) {
    fprintf(dbgfile, "settings set -- target.run-args");
  } else {
      INT_FATAL(astr("createDebuggerFile doesn't know how to handle the given "
                     "debugger: '", debugger, "'"));
  }
  for (i=1; i<argc; i++) {
    if (strcmp(argv[i], astr("--", debugger)) != 0) {
      fprintf(dbgfile, " %s", argv[i]);
    }
  }

  fprintf(dbgfile, "\n");
  closefile(dbgfile);
  mysystem(astr("cat ", CHPL_HOME, "/compiler/etc/", debugger, ".commands >> ",
                dbgfilename),
           astr("appending ", debugger, " commands"),
           false);

  return dbgfilename;
}
Exemplo n.º 3
0
const char* makeTempDir(const char* dirPrefix) {
  const char* tmpdirprefix = astr(getTempDir(), "/", dirPrefix);
  const char* tmpdirsuffix = ".deleteme";

  pid_t mypid = getpid();
#ifdef DEBUGTMPDIR
  mypid = 0;
#endif

  char mypidstr[MAX_CHARS_PER_PID];
  snprintf(mypidstr, MAX_CHARS_PER_PID, "-%d", (int)mypid);

  struct passwd* passwdinfo = getpwuid(geteuid());
  const char* userid;
  if (passwdinfo == NULL) {
    userid = "anon";
  } else {
    userid = passwdinfo->pw_name;
  }
  char* myuserid = strdup(userid);
  removeSpacesBackslashesFromString(myuserid);

  const char* tmpDir = astr(tmpdirprefix, myuserid, mypidstr, tmpdirsuffix);
  ensureDirExists(tmpDir, "making temporary directory");

  free(myuserid); myuserid = NULL;

  return tmpDir;
}
Exemplo n.º 4
0
// NOTE: We are leaking memory here by dropping astr() results on the ground.
static void recordCodeGenStrings(int argc, char* argv[]) {
  compileCommand = astr("chpl ");
  // WARNING: This does not handle arbitrary sequences of escaped characters
  //  in string arguments
  for (int i = 1; i < argc; i++) {
    char *arg = argv[i];
    // Handle " and \" in strings
    while (char *dq = strchr(arg, '"')) {
      char targ[strlen(argv[i])+4];
      memcpy(targ, arg, dq-arg);
      if ((dq==argv[i]) || ((dq!=argv[i]) && (*(dq-1)!='\\'))) {
        targ[dq-arg] = '\\';
        targ[dq-arg+1] = '"';
        targ[dq-arg+2] = '\0';
      } else {
        targ[dq-arg] = '"';
        targ[dq-arg+1] = '\0';
      }
      arg = dq+1;
      compileCommand = astr(compileCommand, targ);
      if (arg == NULL) break;
    }
    if (arg)
      compileCommand = astr(compileCommand, arg, " ");
  }
  get_version(compileVersion);
}
Exemplo n.º 5
0
static void create_arg_bundle_class(FnSymbol* fn, CallExpr* fcall, ModuleSymbol* mod, BundleArgsFnData &baData) {
  INT_ASSERT(!baData.ctype);
  SET_LINENO(fn);

// Here, 'fcall' is the first of fn's callees and so it acts as a
// representative of all the other callees, if any.
// As of this writing, this should be OK because the callees are
// obtained by duplicating the original call, which resulted in
// outlining a block into 'fn' and so is unique.
// To eliminate 'fcall' in create_arg_bundle_class(), we need
// to rely on fn's formal types instead of fcall's actual types.

  // create a new class to capture refs to locals
  AggregateType* ctype = new AggregateType(AGGREGATE_CLASS);
  TypeSymbol* new_c = new TypeSymbol(astr("_class_locals", fn->name), ctype);
  new_c->addFlag(FLAG_NO_OBJECT);
  new_c->addFlag(FLAG_NO_WIDE_CLASS);

  // add the function args as fields in the class
  int i = 0;    // Fields are numbered for uniqueness.
  for_actuals(arg, fcall) {
    SymExpr *s = toSymExpr(arg);
    Symbol  *var = s->var; // arg or var
    if (var->type->symbol->hasFlag(FLAG_REF) || isClass(var->type))
      // Only a variable that is passed by reference out of its current scope
      // is concurrently accessed -- which means that it has to be passed by
      // reference.
      var->addFlag(FLAG_CONCURRENTLY_ACCESSED);
    VarSymbol* field = new VarSymbol(astr("_", istr(i), "_", var->name), var->type);
    ctype->fields.insertAtTail(new DefExpr(field));
    i++;
  }
Exemplo n.º 6
0
void openCFile(fileinfo* fi, const char* name, const char* ext) {
  if (ext)
    fi->filename = astr(name, ".", ext);
  else
    fi->filename = astr(name);

  fi->pathname = genIntermediateFilename(fi->filename);
  openfile(fi, "w");
}
Exemplo n.º 7
0
void appendCFile(fileinfo* fi, const char* name, const char* ext) {
  if (ext)
    fi->filename = astr(name, ".", ext);
  else
    fi->filename = astr(name);

  fi->pathname = genIntermediateFilename(fi->filename);
  fi->fptr     = fopen(fi->pathname, "a+");
}
Exemplo n.º 8
0
const char* getDirectory(const char* filename) {
  const char* filenamebase = strrchr(filename, '/');
  if (filenamebase == NULL) {
    return astr(".");
  } else {
    char dir[FILENAME_MAX];
    const int len = filenamebase - filename;
    strncpy(dir, filename, len);
    dir[len] = '\0';
    return astr(dir);
  }
}
Exemplo n.º 9
0
static void setupEnvVar(std::istringstream& iss, const char** var, const char* varname) {
  std::string line;
  std::string value;

  std::getline(iss, line);
  if (!iss.good() || line.find(varname) == std::string::npos) {
    INT_FATAL(astr("Parsing ", varname));
  }
  value = line.substr(line.find('=')+1, std::string::npos);

  *var = astr(value.c_str());  // astr call is to canonicalize
  parseCmdLineConfig(varname, astr("\"", *var, "\""));
}
Exemplo n.º 10
0
void addSourceFiles(int numNewFilenames, const char* filename[]) {
  static int numInputFiles = 0;
  int cursor = numInputFiles;
  char achar;
  numInputFiles += numNewFilenames;
  inputFilenames = (const char**)realloc(inputFilenames,
                                         (numInputFiles+1)*sizeof(char*));

  for (int i = 0; i < numNewFilenames; i++) {
    if (!isRecognizedSource(filename[i])) {
      USR_FATAL(astr("file '",
                     filename[i],
                     "' does not have a recognized suffix"));
    }
    // WE SHOULDN"T TRY TO OPEN .h files, just .c and .chpl and .o
    if (!isCHeader(filename[i])) {
      FILE* testfile = openInputFile(filename[i]);
      if (fscanf(testfile, "%c", &achar) != 1) {
        USR_FATAL(astr("source file '",
                       filename[i],
                       "' is either empty or a directory"));
      }

      closeInputFile(testfile);
    }

    //
    // Don't add the same file twice -- it's unnecessary and can mess
    // up things like unprotected headers
    //
    bool duplicate = false;
    const char* newFilename = astr(filename[i]);
    for (int j = 0; j < cursor; j++) {
      if (inputFilenames[j] == newFilename) {  // legal due to astr()
        duplicate = true;
        break;
      }
    }
    if (duplicate) {
      numInputFiles--;
    } else {
      inputFilenames[cursor++] = newFilename;
    }
  }
  inputFilenames[cursor] = NULL;

  if (!foundChplSource && fUseIPE == false)
    USR_FATAL("Command line contains no .chpl source files");
}
Exemplo n.º 11
0
//
// Do a breadth first search starting from functions generated for local blocks
// for all function calls in each level of the search, if they directly cause
// communication, add a local temp that isn't wide. If it is a resolved call,
// meaning that it isn't a primitive or external function, clone it and add it
// to the queue of functions to handle at the next iteration of the BFS.
//
static void handleLocalBlocks() {
  Map<FnSymbol*,FnSymbol*> cache; // cache of localized functions
  Vec<BlockStmt*> queue; // queue of blocks to localize

  forv_Vec(BlockStmt, block, gBlockStmts) {
    if (block->parentSymbol) {
      // NOAKES 2014/11/25 Transitional.  Avoid calling blockInfoGet()
      if (block->isLoopStmt() == true) {

      } else if (block->blockInfoGet()) {
        if (block->blockInfoGet()->isPrimitive(PRIM_BLOCK_LOCAL)) {
          queue.add(block);
        }
      }
    }
  }

  forv_Vec(BlockStmt, block, queue) {
    std::vector<CallExpr*> calls;
    collectCallExprs(block, calls);
    for_vector(CallExpr, call, calls) {
      localizeCall(call);
      if (FnSymbol* fn = call->isResolved()) {
        SET_LINENO(fn);
        if (FnSymbol* alreadyLocal = cache.get(fn)) {
          call->baseExpr->replace(new SymExpr(alreadyLocal));
        } else {
          if (!fn->hasFlag(FLAG_EXTERN)) {
            FnSymbol* local = fn->copy();
            local->addFlag(FLAG_LOCAL_FN);
            local->name = astr("_local_", fn->name);
            local->cname = astr("_local_", fn->cname);
            fn->defPoint->insertBefore(new DefExpr(local));
            call->baseExpr->replace(new SymExpr(local));
            queue.add(local->body);
            cache.put(fn, local);
            cache.put(local, local); // to handle recursion
            if (local->retType->symbol->hasFlag(FLAG_WIDE_REF)) {
              CallExpr* ret = toCallExpr(local->body->body.tail);
              INT_ASSERT(ret && ret->isPrimitive(PRIM_RETURN));
              // Capture the return expression in a local temp.
              insertLocalTemp(ret->get(1));
              local->retType = ret->get(1)->typeInfo();
            }
          }
        }
      }
    }
Exemplo n.º 12
0
static void
buildWideClass(Type* type) {
  SET_LINENO(type->symbol);
  AggregateType* wide = new AggregateType(AGGREGATE_RECORD);
  TypeSymbol* wts = new TypeSymbol(astr("__wide_", type->symbol->cname), wide);
  wts->addFlag(FLAG_WIDE_CLASS);
  theProgram->block->insertAtTail(new DefExpr(wts));
  wide->fields.insertAtTail(new DefExpr(new VarSymbol("locale", dtLocaleID)));
  wide->fields.insertAtTail(new DefExpr(new VarSymbol("addr", type)));

  //
  // Strings need an extra field in their wide class to hold their length
  //
  if (type == dtString) {
    wide->fields.insertAtTail(new DefExpr(new VarSymbol("size", dtInt[INT_SIZE_DEFAULT])));
    if (wideStringType) {
      INT_FATAL("Created two wide string types");
    }
    wideStringType = wide;
  }

  //
  // set reference type of wide class to reference type of class since
  // it will be widened
  //
  if (type->refType)
    wide->refType = type->refType;

  wideClassMap.put(type, wide);
}
Exemplo n.º 13
0
const char* genIntermediateFilename(const char* filename) {
  const char* slash = "/";

  ensureTmpDirExists();

  return astr(intDirName, slash, filename);
}
Exemplo n.º 14
0
static void runCompilerInLLDB(int argc, char* argv[]) {
  const char* lldbCommandFilename = createDebuggerFile("lldb", argc, argv);
  const char* command = astr("lldb -s ", lldbCommandFilename, " ", argv[0]);
  int status = mysystem(command, "running lldb", false);

  clean_exit(status);
}
Exemplo n.º 15
0
void deleteTmpDir() {
  static int inDeleteTmpDir = 0; // break infinite recursion

  if (inDeleteTmpDir) {
    return;
  }
  inDeleteTmpDir = 1;

#ifndef DEBUGTMPDIR
  if (tmpdirname != NULL) {
    if (strlen(tmpdirname) < 1 ||
        strchr(tmpdirname, '*') != NULL ||
        strcmp(tmpdirname, "//") == 0) {
      INT_FATAL("tmp directory name looks fishy");
    }
    const char* rmdircommand = "rm -r ";
    const char* command = astr(rmdircommand, tmpdirname);

    mysystem(command, "removing temporary directory");
    tmpdirname = NULL;
  }
#endif

  inDeleteTmpDir = 0;
}
Exemplo n.º 16
0
bool send_init_oft2(file_transfer *ft, char* file)
{
	aimString astr(file);

	unsigned short len = max(0x100, 0xc0 + astr.getTermSize());

	oft2 *oft = (oft2*)alloca(len);
	memset(oft, 0, len);

	memcpy(oft->protocol_version, "OFT2", 4);
	oft->length = _htons(len);
	oft->type = 0x0101;
	oft->total_files = _htons(ft->pfts.totalFiles);
	oft->num_files_left = _htons(ft->pfts.totalFiles - ft->pfts.currentFileNumber);
	oft->total_parts = _htons(1);
	oft->parts_left = _htons(1);
	oft->total_size = _htonl(ft->pfts.totalBytes);
	oft->size = _htonl(ft->pfts.currentFileSize);
	oft->mod_time = _htonl(ft->pfts.currentFileTime);
	oft->checksum = _htonl(aim_oft_checksum_file(ft->pfts.tszCurrentFile));
	oft->recv_RFchecksum = 0x0000FFFF;
	oft->RFchecksum = 0x0000FFFF;
	oft->recv_checksum = 0x0000FFFF;
	memcpy(oft->idstring, "Cool FileXfer", 13);
	oft->flags = 0x20;
	oft->list_name_offset = 0x1c;
	oft->list_size_offset = 0x11;
	oft->encoding = _htons(astr.isUnicode() ? 2 : 0);
	memcpy(oft->filename, astr.getBuf(), astr.getTermSize());

	if (!ft->requester || ft->pfts.currentFileNumber)
		memcpy(oft->icbm_cookie, ft->icbm_cookie, 8);

	return Netlib_Send(ft->hConn, (char*)oft, len, 0) > 0;
}
Exemplo n.º 17
0
static void runCompilerInGDB(int argc, char* argv[]) {
  const char* gdbCommandFilename = createGDBFile(argc, argv);
  const char* command = astr("gdb -q ", argv[0]," -x ", gdbCommandFilename);
  int status = mysystem(command, "running gdb", 0);

  clean_exit(status);
}
Exemplo n.º 18
0
const char*
istr(int i) {
  char s[64];
  if (sprintf(s, "%d", i) > 63)
    INT_FATAL("istr buffer overflow");
  return astr(s);
}
Exemplo n.º 19
0
void closefile(FILE* thefile) {
  if (fclose(thefile) != 0) {
    const char* errorstr = "closing file: ";
    const char* errormsg = astr(errorstr, strerror(errno));

    USR_FATAL(errormsg);
  }
}
Exemplo n.º 20
0
void AstDumpToHtml::init() {
  if (!(sIndexFP = fopen(astr(log_dir, "index.html"), "w"))) {
    USR_FATAL("cannot open html index file \"%s\" for writing", astr(log_dir, "index.html"));
  }
  
  fprintf(sIndexFP, "<HTML>\n");
  fprintf(sIndexFP, "<HEAD>\n");
  fprintf(sIndexFP, "<TITLE> Compilation Dump </TITLE>\n");
  fprintf(sIndexFP, "<SCRIPT SRC=\"http://chapel.cray.com/developer/mktree.js\" LANGUAGE=\"JavaScript\"></SCRIPT>");
  fprintf(sIndexFP, "<LINK REL=\"stylesheet\" HREF=\"http://chapel.cray.com/developer/mktree.css\">");
  fprintf(sIndexFP, "</HEAD>\n");
  fprintf(sIndexFP, "<div style=\"text-align: center;\"><big><big><span style=\"font-weight: bold;\">");
  fprintf(sIndexFP, "Compilation Dump<br><br></span></big></big>\n");
  fprintf(sIndexFP, "<div style=\"text-align: left;\">\n\n");
  
  fprintf(sIndexFP, "<TABLE CELLPADDING=\"0\" CELLSPACING=\"0\">");
}
Exemplo n.º 21
0
Flag
pragma2flag(const char* str) {
  Flag lookup = (Flag)flagMap.get(astr(str));
  if (lookup == FLAG_UNKNOWN || !flagPragma[lookup])
    return FLAG_UNKNOWN;
  else
    return lookup;
}
Exemplo n.º 22
0
// wstring → string
inline std::string to_astr(const std::wstring& wstr)
{
	setlocale(LC_ALL, "japanese");
	std::string astr(wcstombs(0, wstr.c_str(), 0) + 1, 0);
	wcstombs(&astr[0], wstr.c_str(), astr.size());

	return astr;
}
Exemplo n.º 23
0
void codegen_makefile(fileinfo* mainfile, const char** tmpbinname, bool skip_compile_link) {
  fileinfo makefile;
  openCFile(&makefile, "Makefile");
  const char* tmpDirName = intDirName;
  const char* strippedExeFilename = stripdirectories(executableFilename);
  const char* exeExt = "";
  const char* tmpbin = "";

  fprintf(makefile.fptr, "CHPL_MAKE_HOME = %s\n\n", CHPL_HOME);
  fprintf(makefile.fptr, "TMPDIRNAME = %s\n", tmpDirName);

  // LLVM builds just use the makefile for the launcher and
  // so want to skip the actual program generation.
  if( skip_compile_link ) {
    fprintf(makefile.fptr, "SKIP_COMPILE_LINK = skip\n");
  }

  if (fLibraryCompile) {
    if (fLinkStyle==LS_DYNAMIC) exeExt = ".so";
    else exeExt = ".a";
  }
  fprintf(makefile.fptr, "BINNAME = %s%s\n\n", executableFilename, exeExt);
  // BLC: This munging is done so that cp won't complain if the source
  // and destination are the same file (e.g., a.out and ./a.out)
  tmpbin = astr(tmpDirName, "/", strippedExeFilename, ".tmp", exeExt);
  if( tmpbinname ) *tmpbinname = tmpbin;
  fprintf(makefile.fptr, "TMPBINNAME = %s\n", tmpbin);
  // BLC: We generate a TMPBINNAME which is the name that will be used
  // by the C compiler in creating the executable, and is in the
  // --savec directory (a /tmp directory by default).  We then copy it
  // over to BINNAME -- the name given by the user, or a.out by
  // default -- after linking is done.  As it turns out, this saves a
  // factor of 5 or so in time in running the test system, as opposed
  // to specifying BINNAME on the C compiler command line.

  fprintf(makefile.fptr, "COMP_GEN_CFLAGS =");
  if (ccwarnings) {
    fprintf(makefile.fptr, " $(WARN_GEN_CFLAGS)");
  }
  if (debugCCode) {
    fprintf(makefile.fptr, " $(DEBUG_CFLAGS)");
  }
  if (optimizeCCode) {
    fprintf(makefile.fptr, " $(OPT_CFLAGS)");
  }
  if (specializeCCode) {
    fprintf(makefile.fptr, " $(SPECIALIZE_CFLAGS)");
  }
  if (fieeefloat) {
    fprintf(makefile.fptr, " $(IEEE_FLOAT_GEN_CFLAGS)");
  } else {
    fprintf(makefile.fptr, " $(NO_IEEE_FLOAT_GEN_CFLAGS)");
  }
  if (fLibraryCompile && (fLinkStyle==LS_DYNAMIC))
    fprintf(makefile.fptr, " $(SHARED_LIB_CFLAGS)");
  forv_Vec(const char*, dirName, incDirs) {
    fprintf(makefile.fptr, " -I%s", dirName);
  }
Exemplo n.º 24
0
const char* cleanFilename(BaseAST* ast) {
  const char* astFname = ast->fname();
  if (astFname)
    return cleanFilename(astFname);
  else if (yyfilename)
    return cleanFilename(yyfilename);
  else
    return astr("<unknown>");
}
Exemplo n.º 25
0
fileinfo* openTmpFile(const char* tmpfilename, const char* mode) {
  fileinfo* newfile = (fileinfo*)malloc(sizeof(fileinfo));

  newfile->filename = astr(tmpfilename);
  newfile->pathname = genIntermediateFilename(tmpfilename);
  openfile(newfile, mode);

  return newfile;
}
Exemplo n.º 26
0
const char* cleanFilename(const char* name) {
  static int chplHomeLen = strlen(CHPL_HOME);

  if (!strncmp(name, CHPL_HOME, chplHomeLen)) {
    return astr("$CHPL_HOME", name + chplHomeLen);
  } else {
    return name;
  }
}
Exemplo n.º 27
0
static const char*
subChar(Symbol* sym, const char* ch, const char* x) {
  char* tmp = (char*)malloc(ch-sym->cname+1);
  strncpy(tmp, sym->cname, ch-sym->cname);
  tmp[ch-sym->cname] = '\0';
  sym->cname = astr(tmp, x, ch+1); 
  free(tmp);
  return sym->cname;
}
Exemplo n.º 28
0
ModuleSymbol* IpeModuleRoot::createDeclaration()
{
  ModuleSymbol* retval = new ModuleSymbol("ChapelRoot",
                                          MOD_INTERNAL,
                                          new BlockStmt());

  retval->filename = astr("<ChapelRoot>");

  return retval;
}
Exemplo n.º 29
0
IpeModule* IpeModule::moduleByName(const char* name) const
{
  const char* identifier = astr(name);
  LcnSymbol*  varSym     = mEnv->findVariable(identifier);

  INT_ASSERT(varSym);
  INT_ASSERT(varSym->type == gIpeTypeModule);

  return (IpeModule*) mEnv->fetchPtr(varSym);
}
Exemplo n.º 30
0
void ResolutionCandidate::resolveTypeConstructor(CallInfo& info) {
  SET_LINENO(fn);

  // Ignore tuple constructors; they were generated
  // with their type constructors.
  if (fn->hasFlag(FLAG_PARTIAL_TUPLE) == false) {
    CallExpr* typeConstructorCall = new CallExpr(astr("_type", fn->name));

    for_formals(formal, fn) {
      if (formal->hasFlag(FLAG_IS_MEME) == false) {
        if (fn->_this->type->symbol->hasFlag(FLAG_TUPLE)) {
          if (formal->instantiatedFrom != NULL) {
            typeConstructorCall->insertAtTail(formal->type->symbol);

          } else if (formal->hasFlag(FLAG_INSTANTIATED_PARAM)) {
            typeConstructorCall->insertAtTail(paramMap.get(formal));
          }

        } else {
          if (strcmp(formal->name, "outer") == 0 ||
              formal->type                  == dtMethodToken) {
            typeConstructorCall->insertAtTail(formal);

          } else if (formal->instantiatedFrom != NULL) {
            SymExpr*   se = new SymExpr(formal->type->symbol);
            NamedExpr* ne = new NamedExpr(formal->name, se);

            typeConstructorCall->insertAtTail(ne);

          } else if (formal->hasFlag(FLAG_INSTANTIATED_PARAM)) {
            SymExpr*   se = new SymExpr(paramMap.get(formal));
            NamedExpr* ne = new NamedExpr(formal->name, se);

            typeConstructorCall->insertAtTail(ne);
          }
        }
      }
    }

    info.call->insertBefore(typeConstructorCall);

    // If instead we call resolveCallAndCallee(typeConstructorCall)
    // then the line number reported in an error would change
    // e.g.: domains/deitz/test_generic_class_of_sparse_domain
    // or:   classes/diten/multipledestructor
    resolveCall(typeConstructorCall);

    INT_ASSERT(typeConstructorCall->isResolved());

    resolveFunction(typeConstructorCall->resolvedFunction());

    fn->_this->type = typeConstructorCall->resolvedFunction()->retType;

    typeConstructorCall->remove();
  }