QStringList NewClassWidget::files() const
{
    QStringList rc;
    const QDir dir = QDir(path());
    rc.push_back(expandFileName(dir, headerFileName(), headerExtension()));
    rc.push_back(expandFileName(dir, sourceFileName(), sourceExtension()));
    if (isFormInputVisible())
        rc.push_back(expandFileName(dir, formFileName(), formExtension()));
    return rc;
}
Beispiel #2
0
int tellstdfunc::GDSexportLIB::execute()
{
   bool x2048           = getBoolValue();
   std::string filename = getStringValue();
   telldata::ttlist *lll = static_cast<telldata::ttlist*>(OPstack.top());OPstack.pop();

   // Convert layer map
   USMap gdsLays;
   telldata::tthsh* nameh;
   for (unsigned i = 0; i < lll->size(); i++)
   {
      nameh = static_cast<telldata::tthsh*>((lll->mlist())[i]);
      gdsLays[nameh->key().value()] = nameh->value().value();
   }

   if (expandFileName(filename))
   {
      DATC->lockDB(false);
         LayerMapGds default_map(gdsLays, NULL);
         DATC->GDSexport(default_map, filename, x2048);
      DATC->unlockDB();
      LogFile << LogFile.getFN() << "( "
              << *lll << ", "
              << "\""<< filename << "\", "
              << LogFile._2bool(x2048) <<");";
      LogFile.flush();
   }
   else
   {
      std::string info = "Filename \"" + filename + "\" can't be expanded properly";
      tell_log(console::MT_ERROR,info);
   }
   delete lll;
   return EXEC_NEXT;
}
Beispiel #3
0
int tellstdfunc::TDTloadlib::execute()
{
   std::string filename = getStringValue();
   if (expandFileName(filename))
   {
      nameList top_cell_list;
      int libID = DATC->TDTloadlib(filename);
      if (0 <= libID)
      {
         laydata::tdtlibrary* LTDB = DATC->getLib(libID);
         // Gatering the used layers & update the layer definitions
         laydata::TDTHierTree* root = LTDB->hiertree()->GetFirstRoot(libID);
         do
         {
            top_cell_list.push_back(std::string(root->GetItem()->name()));
         } while (NULL != (root = root->GetNextRoot(libID)));
         updateLayerDefinitions(DATC->TEDLIB(), top_cell_list, libID);
         DATC->TEDLIB()->cleanUndefLib();
         // populating cell hierarchy browser
         browsers::addTDTtab(true);
         LogFile << LogFile.getFN() << "(\""<< filename << "\");"; LogFile.flush();
      }
      else
      {
         std::string info = "Can't load \"" + filename + "\" as a library";
         tell_log(console::MT_ERROR,info);
      }
   }
   else
   {
      std::string info = "Filename \"" + filename + "\" can't be expanded properly";
      tell_log(console::MT_ERROR,info);
   }
   return EXEC_NEXT;
}
Beispiel #4
0
int tellstdfunc::CIFexportLIB::execute()
{
   bool  verbose = getBoolValue();
   std::string filename = getStringValue();
   telldata::ttlist *lll = static_cast<telldata::ttlist*>(OPstack.top());OPstack.pop();
   // Convert layer map
   USMap* cifLays = DEBUG_NEW USMap();
   telldata::tthsh* nameh;
   for (unsigned i = 0; i < lll->size(); i++)
   {
      nameh = static_cast<telldata::tthsh*>((lll->mlist())[i]);
      (*cifLays)[nameh->key().value()] = nameh->value().value();
   }
   if (expandFileName(filename))
   {
      DATC->lockDB(false);
      DATC->CIFexport(cifLays, verbose, filename);
      DATC->unlockDB();
      LogFile << LogFile.getFN() << "( "
              << (*lll) << ", \""
              << filename << "\", "
              << LogFile._2bool(verbose)
              << " );"; LogFile.flush();
   }
   else
   {
      std::string info = "Filename \"" + filename + "\" can't be expanded properly";
      tell_log(console::MT_ERROR,info);
   }
   delete cifLays;
   delete lll;
   return EXEC_NEXT;
}
Beispiel #5
0
int tellstdfunc::PSexportTOP::execute()
{
   std::string filename = getStringValue();
   std::string cellname = getStringValue();
   if (expandFileName(filename))
   {
      laydata::tdtcell *excell = NULL;
      laydata::tdtdesign* ATDB = DATC->lockDB(false);
         excell = ATDB->checkcell(cellname);
         if (NULL != excell)
            DATC->PSexport(excell, filename);
      DATC->unlockDB();
      if (NULL != excell)
      {
         LogFile << LogFile.getFN() << "(\""<< cellname << "\"," 
                                    << ",\"" << filename << "\");";
         LogFile.flush();
      }
      else
      {
         std::string message = "Cell " + cellname + " not found in the database";
         tell_log(console::MT_ERROR,message);
      }
   }
   else
   {
      std::string info = "Filename \"" + filename + "\" can't be expanded properly";
      tell_log(console::MT_ERROR,info);
   }
   return EXEC_NEXT;
}
Beispiel #6
0
int tellstdfunc::TDTreadIFF::execute()
{
   TpdTime timeSaved(getStringValue());
   TpdTime timeCreated(getStringValue());
   std::string filename = getStringValue();
   if (!(timeSaved.status() && timeCreated.status()))
   {
      tell_log(console::MT_ERROR,"Bad time format in read command");
   }
   else if (expandFileName(filename))
   {
      bool start_ignoring = false;
      if (DATC->TDTcheckread(filename, timeCreated, timeSaved, start_ignoring))
      {
         DATC->TDTread(filename);
         laydata::tdtdesign* ATDB = DATC->lockDB(false);
            // Initialize call back functions
            ATDB->btreeAddMember    = &browsers::treeAddMember;
            ATDB->btreeRemoveMember = &browsers::treeRemoveMember;
            // time stamps
            TpdTime timec(ATDB->created());
            TpdTime timeu(ATDB->lastUpdated());
            // Gatering the used layers & update the layer definitions
            std::list<std::string> top_cell_list;
            laydata::TDTHierTree* root = ATDB->hiertree()->GetFirstRoot(TARGETDB_LIB);
            do
            {
               top_cell_list.push_back(std::string(root->GetItem()->name()));
            } while (NULL != (root = root->GetNextRoot(TARGETDB_LIB)));
            updateLayerDefinitions(DATC->TEDLIB(), top_cell_list, TARGETDB_LIB);
         DATC->unlockDB();
         // populate the cell hierarchy browser
         browsers::addTDTtab(true);
         LogFile << LogFile.getFN() << "(\""<< filename << "\",\"" <<  timec() <<
               "\",\"" <<  timeu() << "\");"; LogFile.flush();
         // reset UNDO buffers;
         UNDOcmdQ.clear();
         while (!UNDOPstack.empty()) {
            delete UNDOPstack.front(); UNDOPstack.pop_front();
         }
      }
      if (start_ignoring) set_ignoreOnRecovery(true);
   }
   else
   {
      std::string info = "Filename \"" + filename + "\" can't be expanded properly";
      tell_log(console::MT_ERROR,info);
   }
   return EXEC_NEXT;
}
Beispiel #7
0
int tellstdfunc::CIFexportTOP::execute()
{
   bool  verbose = getBoolValue();
   std::string filename = getStringValue();
   telldata::ttlist *lll = static_cast<telldata::ttlist*>(OPstack.top());OPstack.pop();
   bool  recur = getBoolValue();
   std::string cellname = getStringValue();

   // Convert layer map
   USMap* cifLays = DEBUG_NEW USMap();
   telldata::tthsh* nameh;
   for (unsigned i = 0; i < lll->size(); i++)
   {
      nameh = static_cast<telldata::tthsh*>((lll->mlist())[i]);
      (*cifLays)[nameh->key().value()] = nameh->value().value();
   }

   if (expandFileName(filename))
   {
      laydata::tdtcell *excell = NULL;
      laydata::tdtdesign* ATDB = DATC->lockDB(false);
         excell = ATDB->checkcell(cellname);
         if (NULL != excell)
         {
            DATC->CIFexport(excell, cifLays, recur, verbose, filename);
            LogFile << LogFile.getFN() << "( \""
                    << cellname << "\", " 
                    << LogFile._2bool(recur) << ", "
                    << (*lll) << ", \""
                    << filename << "\", "
                    << LogFile._2bool(verbose) << ");";
            LogFile.flush();
         }
         else
         {
            std::string message = "Cell " + cellname + " not found in the database";
            tell_log(console::MT_ERROR,message);
         }
      DATC->unlockDB();
   }
   else
   {
      std::string info = "Filename \"" + filename + "\" can't be expanded properly";
      tell_log(console::MT_ERROR,info);
   }
   cifLays->clear();
   delete cifLays;
   delete lll;
   return EXEC_NEXT;
}
Beispiel #8
0
int tellstdfunc::GDSexportTOP::execute()
{
   bool  x2048 = getBoolValue();
   std::string filename = getStringValue();
   telldata::ttlist *lll = static_cast<telldata::ttlist*>(OPstack.top());OPstack.pop();
   bool  recur = getBoolValue();
   std::string cellname = getStringValue();

   // Convert layer map
   USMap gdsLays;
   telldata::tthsh* nameh;
   for (unsigned i = 0; i < lll->size(); i++)
   {
      nameh = static_cast<telldata::tthsh*>((lll->mlist())[i]);
      gdsLays[nameh->key().value()] = nameh->value().value();
   }
   if (expandFileName(filename))
   {
      laydata::tdtcell *excell = NULL;
      laydata::tdtdesign* ATDB = DATC->lockDB(false);
         excell = ATDB->checkcell(cellname);

         if (NULL != excell)
         {
            LayerMapGds default_map(gdsLays, NULL);

            DATC->GDSexport(excell, default_map, recur, filename, x2048);
            LogFile  << LogFile.getFN() 
                     << "(\""<< cellname << "\"," 
                     << LogFile._2bool(recur) << ", "
                     << *lll << ", "
                     << "\"" << filename << "\","
                     << LogFile._2bool(x2048) <<");"; 
            LogFile.flush();
         }
         else
         {
            std::string message = "Cell " + cellname + " not found in the database";
            tell_log(console::MT_ERROR,message);
         }
      DATC->unlockDB();
   }
   else
   {
      std::string info = "Filename \"" + filename + "\" can't be expanded properly";
      tell_log(console::MT_ERROR,info);
   }
   delete lll;
   return EXEC_NEXT;
}
Beispiel #9
0
int tellstdfunc::CIFread::execute() {
   std::string filename = getStringValue();
   telldata::ttlist* topcells = DEBUG_NEW telldata::ttlist(telldata::tn_string);
   if (expandFileName(filename))
   {
      switch (DATC->CIFparse(filename))
      {
         case CIFin::cfs_POK:
         {
            // add CIF tab in the browser
            browsers::addCIFtab();
            // Collect the top structures
            std::list<std::string> top_cell_list;
            CIFin::CifFile* ACIFDB = DATC->lockCIF();
            CIFin::CIFHierTree* root = ACIFDB->hiertree()->GetFirstRoot(TARGETDB_LIB);
            assert(root);
            do
               top_cell_list.push_back(std::string(root->GetItem()->name()));
            while (NULL != (root = root->GetNextRoot(TARGETDB_LIB)));
            DATC->unlockCIF();
            // Convert the string list to TLISTOF(telldata::tn_string)
            std::list<std::string>::const_iterator CN;
            for (CN = top_cell_list.begin(); CN != top_cell_list.end(); CN ++)
               topcells->add(DEBUG_NEW telldata::ttstring(*CN));
            // Push the top structures in the data stack
            LogFile << LogFile.getFN() << "(\""<< filename << "\");"; LogFile.flush();
            break;
         }
         case CIFin::cfs_FNF:
         {
            std::string info = "File \"" + filename + "\" not found or not readable";
            tell_log(console::MT_ERROR,info);
            break;
         }
         default:
         {
            std::string info = "File \"" + filename + "\" doesn't seem to appear a valid CIF file";
            tell_log(console::MT_ERROR,info);
         }
      }
   }
   else
   {
      std::string info = "Filename \"" + filename + "\" can't be expanded properly";
      tell_log(console::MT_ERROR,info);
   }
   OPstack.push(topcells);
   return EXEC_NEXT;
}
Beispiel #10
0
int tellstdfunc::GDSexportLIB::execute()
{
   std::string filename = getStringValue();
   if (expandFileName(filename))
   {
      DATC->lockDB(false);
         DATC->GDSexport(filename);
      DATC->unlockDB();
      LogFile << LogFile.getFN() << "(\""<< filename << ");"; LogFile.flush();
   }
   else
   {
      std::string info = "Filename \"" + filename + "\" can't be expanded properly";
      tell_log(console::MT_ERROR,info);
   }
   return EXEC_NEXT;
}
Beispiel #11
0
int tellstdfunc::GDSread::execute() {
   std::string filename = getStringValue();
   telldata::ttlist* topcells;
   if (expandFileName(filename))
   {
      std::list<std::string> top_cell_list;
      if (DATC->GDSparse(filename))
      {
         // add GDS tab in the browser
         browsers::addGDStab();
         //
         GDSin::GdsFile* AGDSDB = DATC->lockGDS();

            GDSin::GDSHierTree* root = AGDSDB->hierTree()->GetFirstRoot(TARGETDB_LIB);
            assert(root);
            do 
            {
               top_cell_list.push_back(std::string(root->GetItem()->name()));
            } while (NULL != (root = root->GetNextRoot(TARGETDB_LIB)));
         DATC->unlockGDS();
         topcells = DEBUG_NEW telldata::ttlist(telldata::tn_string);
         for (std::list<std::string>::const_iterator CN = top_cell_list.begin();
                                                   CN != top_cell_list.end(); CN ++)
            topcells->add(DEBUG_NEW telldata::ttstring(*CN));
         LogFile << LogFile.getFN() << "(\""<< filename << "\");"; LogFile.flush();
      }
      else
      {
         std::string info = "File \"" + filename + "\" doesn't seem to appear a valid GDSII file";
         tell_log(console::MT_ERROR,info);
      }
   }
   else
   {
      std::string info = "Filename \"" + filename + "\" can't be expanded properly";
      tell_log(console::MT_ERROR,info);
   }
   // Make sure you always return what you have to return - a list in this case even if
   // it's empty. Otherwise the following tell function will crash, because it can't
   // retrieve from the operand stack the required number of parameters. Empty list
   // is still a list and everybody should deal with them
   OPstack.push(topcells);
   return EXEC_NEXT;
}
Beispiel #12
0
int tellstdfunc::TDTread::execute()
{
   std::string filename = getStringValue();
   if (expandFileName(filename))
   {
      nameList top_cell_list;
      if (DATC->TDTread(filename))
      {
         std::string info = "Generating cell hierarchy ...";
         tell_log(console::MT_INFO,info);
         laydata::tdtdesign* ATDB = DATC->lockDB(false);
            laydata::TDTHierTree* root = ATDB->hiertree()->GetFirstRoot();
            do
            {
               top_cell_list.push_back(std::string(root->GetItem()->name()));
            } while (NULL != (root = root->GetNextRoot()));
            ATDB->btreeAddMember    = &browsers::treeAddMember;
            ATDB->btreeRemoveMember = &browsers::treeRemoveMember;
            browsers::addTDTtab(ATDB->name(), ATDB->hiertree());
            info = "... done";
            tell_log(console::MT_INFO,info);
            TpdTime timec(ATDB->created());
            TpdTime timeu(ATDB->lastUpdated());
            updateLayerDefinitions(ATDB, top_cell_list);
         DATC->unlockDB();
   info = "... DB unlocked";
   tell_log(console::MT_INFO,info);
         LogFile << LogFile.getFN() << "(\""<< filename << "\",\"" <<  timec() <<
               "\",\"" <<  timeu() << "\");"; LogFile.flush();
         // reset UNDO buffers;
         UNDOcmdQ.clear();
         while (!UNDOPstack.empty()) {
            delete UNDOPstack.front(); UNDOPstack.pop_front();
         }
      }
   }
   else
   {
      std::string info = "Filename \"" + filename + "\" can't be expanded properly";
      tell_log(console::MT_ERROR,info);
   }
   return EXEC_NEXT;
}
Beispiel #13
0
static status
initialiseDirectory(Directory d, Name name)
{ char path[MAXPATHLEN];
  Name expanded;
  const char *ufn;

  if ( !(expanded = expandFileName(name)) )
    fail;

  ufn = nameToUTF8(expanded);
  if ( absolutePath(ufn, path, sizeof(path)) < 0 )
    return errorPce(d, NAME_representation, NAME_nameTooLong);

  assign(d, path, UTF8ToName(path));
  assign(d, name, UTF8ToName(baseName(ufn)));
  d->modified = MODIFIED_NOT_SET;

  succeed;
}
Beispiel #14
0
int tellstdfunc::TDTsaveas::execute() {
   std::string filename = getStringValue();
   if (expandFileName(filename))
   {
      laydata::tdtdesign* ATDB = DATC->lockDB(false);
         ATDB->try_unselect_all();
         DATC->TDTwrite(filename.c_str());
         TpdTime timec(ATDB->created());
         TpdTime timeu(ATDB->lastUpdated());
      DATC->unlockDB();
      LogFile << LogFile.getFN() << "(\""<< filename << "\" , \"" << timec() <<
            "\" , \"" << timeu() << "\");"; LogFile.flush();
   }
   else
   {
      std::string info = "Filename \"" + filename + "\" can't be expanded properly";
      tell_log(console::MT_ERROR,info);
   }
   return EXEC_NEXT;
}
Beispiel #15
0
int tellstdfunc::GDSread::execute() {
   std::string filename = getStringValue();
   if (expandFileName(filename))
   {
      std::list<std::string> top_cell_list;
      if (DATC->GDSparse(filename))
      {
         // add GDS tab in the browser
         browsers::addGDStab();
         //
         GDSin::GDSFile* AGDSDB = DATC->lockGDS();

            GDSin::GDSHierTree* root = AGDSDB->hiertree()->GetFirstRoot(TARGETDB_LIB);
            assert(root);
            do 
            {
               top_cell_list.push_back(std::string(root->GetItem()->Get_StrName()));
            } while (NULL != (root = root->GetNextRoot(TARGETDB_LIB)));
         DATC->unlockGDS();
         telldata::ttlist* topcells = DEBUG_NEW telldata::ttlist(telldata::tn_string);
         for (std::list<std::string>::const_iterator CN = top_cell_list.begin();
                                                   CN != top_cell_list.end(); CN ++)
            topcells->add(DEBUG_NEW telldata::ttstring(*CN));
         OPstack.push(topcells);
         LogFile << LogFile.getFN() << "(\""<< filename << "\");"; LogFile.flush();
      }
      else
      {
         std::string info = "File \"" + filename + "\" doesn't seem to appear a valid GDSII file";
         tell_log(console::MT_ERROR,info);
      }
   }
   else
   {
      std::string info = "Filename \"" + filename + "\" can't be expanded properly";
      tell_log(console::MT_ERROR,info);
   }
   return EXEC_NEXT;
}
Beispiel #16
0
int main(int argc,
	 char * argv[]) {
  struct DOODLE_SuffixTree * tree;
  char astring[DEPTH+1];
  char bstring[DEPTH+DIST+1];
  int i;
  int j;
  time_t start;
  time_t end;
  int pow;
  char * exp;

  exp = expandFileName(argv[0]);
  unlink(DBNAME);
  tree = DOODLE_tree_create(&my_log,
			    NULL,
			    DBNAME);
  time(&start);
  memset(astring, 0, DEPTH+1);
  pow = 1;
  for (i=0;i<DEPTH;i++) {
    pow = pow * ('H' - 'A');
    astring[i] = 'A';
  }
  for (i=0;i<pow-1;i++) {
    j = 0;
    do {
      astring[j++]++;
    } while (astring[j-1] == 'H');
    j--;
    while (j > 0)
      astring[--j] = 'A';

    if (0 != DOODLE_tree_expand(tree,
				astring,
				exp))
      ABORT();
  }
  time(&end);
  printf("%d expansions took %us.\n",
	 pow,
	 (unsigned int) (end - start));

  for (i=0;i<DEPTH+DIST;i++)
    bstring[i] = 'A';
  bstring[DEPTH+DIST] = '\0';
  time(&start);
  for (i=0;i<COUNT;i++)
    if (0 != DOODLE_tree_search(tree,
				bstring,
				NULL,
				NULL))
      ABORT();
  time(&end);
  printf("%d (cached) searches took %us.\n",
	 COUNT,
	 (unsigned int) (end - start));

  for (j=0;j<DIST-1;j++) {
    time(&start);
    for (i=0;i<COUNT;i++)
      if (0 != DOODLE_tree_search_approx(tree,
					 j,
					 0,
					 bstring,
					 NULL,
					 NULL))
	ABORT();
    time(&end);
    printf("%d (cached) %d-searches took %us.\n",
	   COUNT,
	   j,
	   (unsigned int) (end - start));
  }
  DOODLE_tree_destroy(tree);
  unlink(DBNAME);
  free(exp);
  return 0;
}
Beispiel #17
0
/**
 * Main worker thread.  Register FAM events and process.
 */
static void * worker(void * arg) {
  DIC * cls = arg;
  int i;
  int more;
  int wasMore;
  int ret;
  void * unused;
  char * fn;
  PTHREAD_T helperThread;

  cls->log(cls->logContext,
	   DOODLE_LOG_VERY_VERBOSE,
	   _("Main worker thread created.\n"));
  cls->eventCount = 0;
  cls->continueRunning = 1;
  cls->events = NULL;
  cls->signal = SEMAPHORE_NEW(0);
  if (0 != PTHREAD_CREATE(&helperThread,
			  &processEvents,
			  cls,
			  64 * 1024)) {
    cls->log(cls->logContext,
	     DOODLE_LOG_CRITICAL,
	     _("Failed to spawn event processing thread.\n"));
    run_shutdown(0);
    return NULL;
  }

  cls->log(cls->logContext,
	   DOODLE_LOG_VERBOSE,
	   _("Registering with FAM for file system events.\n"));
  for (i=0;i<cls->argc;i++) {
    char * exp;

    cls->log(cls->logContext,
	     DOODLE_LOG_VERY_VERBOSE,
	     _("Indexing '%s'\n"),
	     cls->argv[i]);
    exp = expandFileName(cls->argv[i]);
    if (-1 == do_index(exp,
		       cls)) {
      ret = -1;
      free(exp);
      break;
    }
    free(exp);
  }
  DOODLE_tree_destroy(cls->tree);
  cls->treePresent = 0;
  cls->tree = NULL;

  cls->log(cls->logContext,
	   DOODLE_LOG_VERBOSE,
	   _("doodled startup complete.  Now waiting for FAM events.\n"));

  wasMore = 0;
  while ( (cls->continueRunning) &&
	  (0 == testShutdown()) ) {
    SEMAPHORE_DOWN(cls->signal);
    cls->log(cls->logContext,
	     DOODLE_LOG_INSANELY_VERBOSE,
	     "Received signal to process fam event.\n");
    MUTEX_LOCK(&cls->lock);
    if (cls->eventCount > 0) {
      fn = cls->events[cls->eventCount-1];
      GROW(cls->events,
	   cls->eventCount,
	   cls->eventCount-1);
      more = cls->eventCount > 0;
      cls->log(cls->logContext,
	       DOODLE_LOG_INSANELY_VERBOSE,
	       "Processing fam event '%s'.\n",
	       fn);
    } else {
      fn = NULL;
      more = 0;
    }
    if (! wasMore) {
      cls->treePresent++;
      if (cls->treePresent == 1)
	cls->tree = DOODLE_tree_create((DOODLE_Logger) cls->log,
				       cls->logContext,
				       cls->ename);
    }
    MUTEX_UNLOCK(&cls->lock);
    if (fn != NULL) {
      do_index(fn, cls);
      free(fn);
    }
    MUTEX_LOCK(&cls->lock);
    if (! more) {
      cls->treePresent--;
      if (cls->treePresent == 0)
	DOODLE_tree_destroy(cls->tree);
    }
    MUTEX_UNLOCK(&cls->lock);
    wasMore = more;
  } /* forever (until signal) */

  cls->continueRunning = 0;
  if (0 != FAMClose(&cls->fc)) {
    cls->log(cls->logContext,
	   DOODLE_LOG_CRITICAL,
	   _("Error disconnecting from fam.\n"));
  }
  PTHREAD_KILL(&helperThread, SIGTERM);
  PTHREAD_JOIN(&helperThread, &unused);
  SEMAPHORE_FREE(cls->signal);

  if (cls->treePresent > 0)
    DOODLE_tree_destroy(cls->tree);
  return NULL;
}
Beispiel #18
0
/**
 * Make sure the DB is current and then go into FAM-monitored mode
 * updating the DB all the time in the background.  Exits after a
 * signal (i.e.  SIGHUP/SIGINT) is received.
 */
static int build(const char * libraries,
		 const char * dbName,
		 size_t mem_limit,
		 const char * log,
		 int argc,		
		 char * argv[]) {
  int i;
  unsigned int ret;
  DIC cls;
  char * ename;
  FILE * logfile;
  PTHREAD_T workerThread;
  void * unused;

  cls.argc = argc;
  cls.argv = argv;
  cls.deferredCount = 0;
  cls.deferredTruncations = NULL;
  logfile = NULL;
  if (log != NULL) {
    logfile = fopen(log, "w+");
    if (logfile == NULL)
      my_log(stderr,
	     DOODLE_LOG_CRITICAL,
	     _("Could not open '%s' for logging: %s.\n"),
	     log,
	     strerror(errno));
  }
  cls.logContext = logfile;
  cls.log = &my_log;


  if (dbName == NULL) {
    my_log(logfile,
	   DOODLE_LOG_CRITICAL,
	   _("No database specified.  Aborting.\n"));
    return -1;
  }
  for (i=strlen(dbName);i>=0;i--) {
    if (dbName[i] == ':') {
      my_log(logfile,
	     DOODLE_LOG_CRITICAL,
	     _("'%s' is an invalid database filename (has a colon) for building database (option '%s').\n"),
	     dbName,
	     "-b");
      return -1;
    }
  }
  ename = expandFileName(dbName);
  if (ename == NULL)
    return -1;
  cls.ename = ename;
  cls.tree = DOODLE_tree_create(&my_log,
				logfile,
				ename);
  cls.treePresent = 1;
  if (cls.tree == NULL)
    return -1;
  if (mem_limit != 0)
    DOODLE_tree_set_memory_limit(cls.tree,
				 mem_limit);
  cls.elist = forkExtractor(do_default,
			    libraries,
			    &my_log,
			    logfile);
  if (cls.elist == NULL) {
    DOODLE_tree_destroy(cls.tree);
    return -1;
  }
  if (0 != FAMOpen2(&cls.fc, "doodled")) {
    my_log(logfile,
	   DOODLE_LOG_CRITICAL,
	   _("Failed to connect to fam.  Aborting.\n"));
    DOODLE_tree_destroy(cls.tree);
    return -1;
  }
  cls.fr = NULL;
  cls.frPos = 0;
  cls.frSize = 0;
  GROW(cls.fr,
       cls.frSize,
       128);
  cls.frNames = NULL;
  ret = 0;
  GROW(cls.frNames,
       ret,
       128);
  ret = 0;


  MUTEX_CREATE(&cls.lock);
  if (0 != PTHREAD_CREATE(&workerThread,
			  &worker,
			  &cls,
			  64 * 1024)) {
    my_log(logfile,
	   DOODLE_LOG_CRITICAL,
	   _("Failed to create worker thread: %s"),
	   strerror(errno));
    ret = -1;
  } else {
    wait_for_shutdown();
    cls.continueRunning = 0;
    SEMAPHORE_UP(cls.signal);
    PTHREAD_JOIN(&workerThread, &unused);
  }
  MUTEX_DESTROY(&cls.lock);

  my_log(logfile,
	 DOODLE_LOG_VERBOSE,
	 _("doodled is shutting down.\n"));
  if (cls.frPos == 0) {
    my_log(logfile,
	   DOODLE_LOG_CRITICAL,
	   _("No files exist that doodled would monitor for changes.  Exiting.\n"));
  }


  for (i=0;i<cls.frSize;i++) {
    if (cls.frNames[i] != NULL) {
      my_log(logfile,
	     DOODLE_LOG_VERBOSE,
	     _("Cancelling fam monitor '%s'.\n"),
	     cls.frNames[i]);
      free(cls.frNames[i]);
    }
  }

  for (i=cls.deferredCount-1;i>=0;i--)
    free(cls.deferredTruncations[i]);
  GROW(cls.deferredTruncations,
       cls.deferredCount,
       0);
  i = cls.frSize;
  GROW(cls.fr,
       cls.frSize,
       0);
  cls.frSize = i;
  GROW(cls.frNames,
       cls.frSize,
       0);
  my_log(logfile,
	 DOODLE_LOG_VERBOSE,
	 _("Unloading libextractor plugins.\n"));
  joinExtractor(cls.elist);
  free(ename);
  if (logfile != NULL)
    fclose(logfile);
  return ret;
}