ROOT logo
// $Id: Gled.cxx 2316 2010-01-01 11:23:28Z matevz $

// Copyright (C) 1999-2008, Matevz Tadel. All rights reserved.
// This file is part of GLED, released under GNU General Public License version 2.
// For the licensing terms see $GLEDSYS/LICENSE or http://www.gnu.org/.

#include "Gled.h"
#include "gled-config-build.h"

#include <Gled/GledNS.h>
#include <Gled/GMutex.h>
#include <Gled/GCondition.h>
#include <Gled/GThread.h>
#include <Gled/GKeyRSA.h>
#include <Ephra/Saturn.h>
#include <Glasses/ZQueen.h>
#include <Glasses/SaturnInfo.h>
#include <Glasses/ShellInfo.h>

#include <TSystem.h>
#include <TROOT.h>
#include <TInterpreter.h>
#include <TRint.h>
#include <TMath.h>
#include <TSocket.h>
#include <TObjectTable.h>
#include <TSystemDirectory.h>
#include <TThread.h>
#include <Getline.h>

extern void *GledCore_GLED_init;

ClassImp(Gled);

/**************************************************************************/

Gled* Gled::theOne = 0;
Gled* gGled        = 0;

/**************************************************************************/

void Gled::next_arg_or_die(lStr_t& args, lStr_i& i)
{
  lStr_i j = i;
  if (++j == args.end())
  {
    cerr <<"Option "<< *i <<" requires an argument\n";
    exit(1);
  }
  i = j;
}

/**************************************************************************/

Gled::Gled() :
  mSaturn       (0),
  bIsSun        (false),
  bQuit         (false),
  bShowSplash   (true),
  bPreExec      (false),
  bAutoSpawn    (false),
  bAllowMoons   (false),
  bRintRunning  (false),
  mRint         (0),
  mLoggingMutex (GMutex::recursive),
  mLogFile      (0),
  mOutFile      (0),
  mExitCondVar  (0),
  mRintThread   (0),
  mExitThread   (0)
{
  if (theOne)
  {
    fprintf(stderr, "Gled::Gled trying to instantiate another Gled object.\n");
    exit(1);
  }

  gGled = theOne = this;

  // Set-up SaturnInfo, set defaults

  mSaturnInfo = new SaturnInfo;
  mSaturnInfo->SetHostName(gSystem->HostName());

  SysInfo_t sys; gSystem->GetSysInfo(&sys);
  MemInfo_t mem; gSystem->GetMemInfo(&mem);

  mSaturnInfo->SetOS        (sys.fOS);
  mSaturnInfo->SetCPU_Model (sys.fModel);
  mSaturnInfo->SetCPU_Type  (sys.fCpuType);
  mSaturnInfo->SetCPU_Freq  (sys.fCpuSpeed);
  mSaturnInfo->SetCPU_Num   (sys.fCpus);
  mSaturnInfo->SetMemory    (mem.fMemTotal);
  mSaturnInfo->SetSwap      (mem.fSwapTotal);

  mLogFileName = "<stdout>"; mLogFile = 0;
  mOutFileName = "<stdout>"; mOutFile = 0;

  // Figure out libdir and datadir, can also be passed as arguments later.
  TString gsys(gSystem->Getenv("GLEDSYS"));
  if (gsys.IsNull())
  {
#ifdef GLED_PREFIX
    mLibDir  = GLED_LIB_DIR;
    mDataDir = GLED_DATA_DIR;
#endif
  }
  else
  {
    mLibDir  = gsys + "/lib";
    mDataDir = gsys;
  }
  mHomeDir = gSystem->HomeDirectory();

  mAuthDir = GForm("%s/.gled/auth", mHomeDir.Data());
  mDefEyeIdentity = "guest";
}

void Gled::AddArgument(const char* arg)
{
  // Add a command-line argument.

  mArgs.push_back(arg);
}

void Gled::ReadArguments(int argc, char **argv)
{
  // Read given command-line arguments, zeroth argument is taken as
  // command name.

  mCmdName = argv[0];
  for (int i = 1; i < argc; ++i)
  {
    mArgs.push_back(argv[i]);
  }
}

void Gled::ParseArguments()
{
  // Parse command-line arguments.

  lStr_i i  = mArgs.begin();
  while (i != mArgs.end())
  {
    lStr_i start = i;

    if(*i == "-h" || *i == "-help" || *i == "--help" || *i == "-?")
    {
      printf(
             "Arguments: [options] [dir] [file(s)]\n"
             "                     dir   ~ cd to dir prior to exec of files\n"
             "                     files ~ ROOT macro scripts to process\n"
             "Gled options:\n"
             "-------------\n"
             "  -datadir   <dir>   directory containing Gled data\n"
             "  -libdir    <dir>   directory containing Gled libraries\n"
             "  -preexec <m1:m2..> pre-exec specified macros\n"
             "  -r[un]             spawn Saturn/Sun immediately (before processing files)\n"
             "                     Saturn if -master is specified, Sun otherwise\n"
             "  -allowmoons        accept moon connections\n"
             "  -s[ssize]  <num>   specify size of sun-space (can be eg. 2e20)\n"
             "  -p[ort]    <num>   specify server port (def: 9061)\n"
             "  -portscan  <num>   if server port can not be opened, try <num> higher ports\n"
             "  -m[aster] <host>[:<port>] master Saturn address (def port: 9061)\n"
             "  -n[ame]    <str>   name of Saturn\n"
             "  -t[itle]   <str>   title of Saturn\n"
             "  -l                 no splash info\n"
             "\n"
             "Logging options:\n"
             "  -log[file] <file>  specify log file name (saturn:'<stdout>', gled:'<null>')\n"
             "  -out[file] <file>  specify output file name (def: '<stdout>')\n"
             "                     <file> shorthands: '-' => '<null>', '+' => '<stdout>'\n"
             "\n"
             "Authentication options:\n"
             "  -auth              use authentication\n"
             "  -authdir   <str>   directory containing auth data (def: ~/.gled/auth)\n"
             "  -saturnid  <str>   identity of the Saturn (def: 'sun.absolute' or 'saturn')\n"
             "  -eyeid     <str>   default identity of Eyes (def: 'guest')\n"
             "Renderer loading options:\n"
             "  -rnr <r1>:<r2>:... specify which rendering libraries to load (for gled: GL)\n"
             );
      bQuit = true;
      return;
    }
    else if (*i == "-datadir")
    {
      next_arg_or_die(mArgs, i);
      mDataDir = *i;
      mArgs.erase(start, ++i);
    }
    else if (*i == "-libdir")
    {
      next_arg_or_die(mArgs, i);
      mLibDir = *i;
      mArgs.erase(start, ++i);
    }
    else if (*i == "-preexec")
    {
      next_arg_or_die(mArgs, i);
      bPreExec = true;
      mPreExecString   = *i;
      mArgs.erase(start, ++i);
    }
    else if (*i ==  "-r" || *i == "-run")
    {
      bAutoSpawn = true;
      mArgs.erase(start, ++i);
    }
    else if (*i == "-allowmoons")
    {
      bAllowMoons = true;
      mArgs.erase(start, ++i);
    }
    else if (*i == "-s" || *i == "-sssize")
    {
      next_arg_or_die(mArgs, i);
      if(index(*i, 'e')) {
	int m, e, num = sscanf(*i, "%de%d", &m, &e);
	if(num != 2) { cerr <<"-sssize poor exp format: "<< *i <<endl; exit(1); }
	mSaturnInfo->SetSunSpaceSize( ID_t(TMath::Power(m, e)) );
      } else {
	mSaturnInfo->SetSunSpaceSize( ID_t(atoll(*i)) );
      }
      mArgs.erase(start, ++i);
    }
    else if (*i == "-p" || *i == "-port")
    {
      next_arg_or_die(mArgs, i);
      mSaturnInfo->SetServerPort( atoi(*i) );
      mArgs.erase(start, ++i);
    }
    else if (*i == "-portscan")
    {
      next_arg_or_die(mArgs, i);
      mSaturnInfo->SetServPortScan( atoi(*i) );
      mArgs.erase(start, ++i);
    }
    else if (*i == "-m" || *i == "-master")
    {
      next_arg_or_die(mArgs, i);
      // !!! Cast required by gcc-4.4.1-1ubuntu3, Aug 2009. Seems strange.
      char* col = (char*) strchr(*i, ':');
      if(col) {
	*(col++) = 0;
	UShort_t p = UShort_t(atoi(col));
	mSaturnInfo->SetMasterPort(p);
      }
      mSaturnInfo->SetMasterName(*i);
      mArgs.erase(start, ++i);
    }
    else if (*i == "-n" || *i == "-name")
    {
      next_arg_or_die(mArgs, i);
      mSaturnInfo->SetName(*i);
      mArgs.erase(start, ++i);
    }
    else if (*i == "-t" || *i == "-title")
    {
      next_arg_or_die(mArgs, i);
      mSaturnInfo->SetTitle(*i);
      mArgs.erase(start, ++i);
    }
    else if (*i == "-l")
    {
      bShowSplash = false;
      mArgs.erase(start, ++i);
    }

    // Logging options

    else if (*i == "-log" || *i == "-logfile")
    {
      next_arg_or_die(mArgs, i);
      if (*i == "-" || *i == "<null>")
      {
	mLogFileName = "<null>";
      }
      else if (*i == "+" || *i == "<stdout>")
      {
	mLogFileName = "<stdout>";
      }
      else
      {
	mLogFileName = *i;
      }
      mArgs.erase(start, ++i);
    }
    else if (*i == "-out" || *i == "-outfile")
    {
      next_arg_or_die(mArgs, i);
      if (*i == "-" || *i == "<null>")
      {
	mOutFileName = "<null>";
      }
      else if (*i == "+" || *i == "<stdout>")
      {
	mOutFileName = "<stdout>";
      }
      else
      {
	mOutFileName = *i;
      }
      mArgs.erase(start, ++i);
    }

    // Authentication options

    else if (*i == "-auth")
    {
      mSaturnInfo->SetUseAuth(true);
      mArgs.erase(start, ++i);
    }
    else if (*i == "-authdir")
    {
      next_arg_or_die(mArgs, i);
      mAuthDir = *i;
      mArgs.erase(start, ++i);
    }
    else if (*i == "-saturnid")
    {
      next_arg_or_die(mArgs, i);
      mSaturnInfo->SetLogin(*i);;
      mArgs.erase(start, ++i);
    }
    else if (*i == "-eyeid")
    {
      next_arg_or_die(mArgs, i);
      mDefEyeIdentity = *i;
      mArgs.erase(start, ++i);
    }

    // Renderer loading options

    else if (*i == "-rnr")
    {
      next_arg_or_die(mArgs, i);
      mRenderers = *i;
      mArgs.erase(start, ++i);
    }
    else
    {
      ++i;
    }
  }

  if (mLibDir.IsNull() || mDataDir.IsNull())
  {
    cerr << "libdir or datadir unknown.\n";
    exit(1);
  }
}

void Gled::InitLogging()
{
  if (mLogFileName == "<null>")
    mLogFile = 0;
  else if (mLogFileName = "<stdout>")
    mLogFile = stdout;
  else
  {
    mLogFile = fopen(mLogFileName, "w");
    if (mLogFile == 0) {
      perror("Gled::InitLogging opening of log file failed");
      exit(1);
    }
  }

  if (mOutFileName =="<null>")
    mOutFile = 0;
  else if (mOutFileName == "<stdout>")
    mOutFile = stdout;
  else if (mOutFileName == mLogFileName)
    mOutFile = mLogFile;
  else
  {
    mOutFile = fopen(mOutFileName, "w");
    if (mLogFile == 0) {
      perror("Gled::InitLogging opening of output file failed");
      exit(1);
    }
  }

  if(bShowSplash) {
    GMutexHolder mh(mLoggingMutex);
    message("+----------------------------------------------------------+");
    message(GForm("| This is Gled, version %s", GLED_BUILD_VERSION));
    message(GForm("|   Build date: %s", GLED_BUILD_DATE));
    message(GForm("|      SVN Rev: %s", GLED_BUILD_SVN_REV));
    message(GForm("|      SVN URL: %s", GLED_BUILD_SVN_URL));
    message("| Gled is free software, released under GNU GPL version 2");
    message("| For further information visit http://www.gled.org/");
    message("+----------------------------------------------------------+");
    message("Gled now bootstraping.");
  }
}

void Gled::InitGledCore()
{
  gROOT->SetMacroPath(GForm(".:%s/.gled:%s/macros", mHomeDir.Data(), mDataDir.Data()));
  gInterpreter->AddIncludePath(GForm("%s/.gled",  mHomeDir.Data()));
  gInterpreter->AddIncludePath(GForm("%s/macros", mDataDir.Data()));
  gInterpreter->SetProcessLineLock(false);

  GledNS::GledRoot = new TDirectory("Gled", "Gled root directory");
  GledNS::InitFD(0, GledNS::GledRoot);

  TThread a_root_thread; // Enforce ROOT thread init.

  ((void(*)())GledCore_GLED_init)();

  if (mRenderers != "")
  {
    lStr_t rnrs;
    GledNS::split_string(mRenderers.Data(), rnrs, ':');
    for (lStr_i r = rnrs.begin(); r != rnrs.end(); ++r)
      GledNS::AddRenderer(*r);

    GledNS::AssertRenderers();
  }
}

void Gled::ProcessCmdLineMacros()
{
  // Prepare remaining args for ROOT, weed out remaining options

  static const Exc_t _eh("Gled::ProcessCmdLineMacros ");

  // Argument count and strings to be passed to root.
  int         rargc = 0;
  const char* rargv[mArgs.size() + 3];

  rargv[rargc++] = mCmdName;
  rargv[rargc++] = "-q"; // This enforces return from TRint::Run() after macro processing
  if (!bShowSplash)
    rargv[rargc++] = "-l";
  for (lStr_i i = mArgs.begin(); i != mArgs.end(); ++i)
  {
    if ((*i)[0] == '-')
    {
      warning(GForm("Ignoring option '%s'.", i->Data()));
    } else {
      rargv[rargc++] = i->Data();
    }
  }

  // Call pre-exec macros if any.
  if (bPreExec)
  {
    PreExec();
  }

  // Spawn TRint
  if (bShowSplash)
  {
    printf("Staring ROOT command-line interpreter ...\n");
  }

  mRint = new TRint("TRint", &rargc, (char**) rargv);
  mRint->SetPrompt(mCmdName + "[%d] ");

  // Spawn saturn
  if (bAutoSpawn)
  {
    SpawnSunOrSaturn();
  }

  // Process macros; -q added to options, so it exits after macro processing
  try
  {
    GThread::OwnerChanger _chown(mSaturnInfo);

    mRint->Run(true);
  }
  catch(exception& exc)
  {
    fprintf(stderr, "%sexception caught during macro processing:\n%s\n",
	    _eh.Data(), exc.what());
    exit(1);
  }

  if (mRint->InputFiles())
  {
    mRint->ClearInputFiles();
  } else {
    Getlinem(kCleanUp, 0);
  }
  Getlinem(kInit, mRint->GetPrompt());

  if (bAllowMoons)
  {
    AllowMoonConnections();
  }
}

void Gled::StopLogging()
{
  message("Logging stopped.");

  GMutexHolder mh(mLoggingMutex);

  if (mOutFile && mOutFile != stdin) {
    fclose(mOutFile);
  }
  if (mLogFile && mLogFile != stdin && mLogFile != mOutFile) {
    fclose(mLogFile);
  }
  mOutFile = mLogFile = 0;
}

Gled::~Gled()
{
  delete mSaturn;
  delete mRint;
}

/**************************************************************************/

void Gled::PreExec()
{
  lStr_t l;
  GledNS::split_string(mPreExecString, l, ':');
  for(lStr_i i=l.begin(); i!=l.end(); ++i)
    gROOT->Macro(i->Data());
}

/**************************************************************************/

void Gled::SpawnSunOrSaturn()
{
  if(mSaturnInfo->RefMasterName().IsNull()) {
    SpawnSun();
  } else {
    SpawnSaturn();
  }
}

void Gled::SpawnSun()
{
  static const Exc_t _eh("Gled::SpawnSun ");

  if(mSaturn) return;
  mSaturnInfo->SetMasterPort(0);

  if(strcmp(mSaturnInfo->GetName(), "SaturnInfo") == 0)
    mSaturnInfo->SetName(GForm("Sun at %s", gSystem->HostName()));
  if(strcmp(mSaturnInfo->GetLogin(), "") == 0)
    mSaturnInfo->SetLogin("sun.absolute");

  CheckAuthDir();

  if(mSaturnInfo->GetUseAuth()) {
    GKeyRSA::init_ssl();
    if(GetPrivKeyFile(mSaturnInfo->mLogin) == 0) {
      cerr << _eh << "can not open server private key\n";
      exit(1);
    }
  }

  mSaturn = new Saturn;
  mSaturn->Create(mSaturnInfo);
  bIsSun = true;
}

void Gled::SpawnSaturn()
{
  static const Exc_t _eh("Gled::SpawnSaturn ");

  if(mSaturn) return;
  if(strcmp(mSaturnInfo->GetName(), "SaturnInfo") == 0)
    mSaturnInfo->SetName(GForm("Saturn at %s", gSystem->HostName()));
  if(strcmp(mSaturnInfo->GetLogin(), "") == 0)
    mSaturnInfo->SetLogin("saturn");

  CheckAuthDir();

  // Initialize authentication
  GKeyRSA::init_ssl();
  // Warn for missing RSA-key files
  if(GetPrivKeyFile(mSaturnInfo->mLogin, false) == 0)
    ISwarn(_eh + "private key for Saturn identity not found");
  if(GetPrivKeyFile(mDefEyeIdentity, false) == 0)
    ISwarn(_eh + "private key for default Eye identity not found");

  mSaturn = new Saturn;
  try {
    SaturnInfo* si = mSaturn->Connect(mSaturnInfo);
    if(si) {
      delete mSaturnInfo;
      mSaturnInfo = si;
    } else {
      cerr << _eh <<"failed ... dying\n";
      exit(1);
    }
    WaitUntillQueensLoaded();
  }
  catch(Exc_t& exc) {
    cerr << _eh <<" failed ... dying at:\n  "<< exc <<endl;
    exit(1);
  }
}

/**************************************************************************/

void Gled::CheckAuthDir()
{
  if(gSystem->AccessPathName(mAuthDir.Data(), kReadPermission)) {
    printf("Gled::CheckAuthDir auth dir '%s' not accessible\n", mAuthDir.Data());
    printf("Gled::CheckAuthDir use gled-auth-init command to create one\n");
  }
}

const char* Gled::PubKeyFile(TString& id)
{
  return GForm("%s/public_keys/%s", mAuthDir.Data(), id.Data());
}

const char* Gled::PrivKeyFile(TString& id)
{
  return GForm("%s/private_keys/%s", mAuthDir.Data(), id.Data());
}

const char* Gled::GetPubKeyFile(TString& id, Bool_t use_exc)
{
  static const Exc_t _eh("Gled::GetPubKeyFile ");

  const char* ret = PubKeyFile(id);
  if(gSystem->AccessPathName(ret, kReadPermission)) {
    if(use_exc)
      throw(_eh + "can not access file:" + ret + ".");
    else
      ret = 0;
  }
  return ret;
}

const char* Gled::GetPrivKeyFile(TString& id, Bool_t use_exc)
{
  static const Exc_t _eh("Gled::GetPrivKeyFile ");

  const char* ret = PrivKeyFile(id);
  if(gSystem->AccessPathName(ret, kReadPermission)) {
    if(use_exc)
      throw(_eh + "can not access file:" + ret + ".");
    else
      ret = 0;
  }
  return ret;
}

/**************************************************************************/

Bool_t Gled::IsIdentityInGroup(const char* id, const char* group)
{
  //printf("Gled::IsIdentityInGroup checking if %s in group %s\n", id, group);
  return (gSystem->Exec(GForm("grep -q %s %s/groups/%s",
			      id, mAuthDir.Data(), group)) == 0) ? true : false;;
}

/**************************************************************************/

void Gled::WaitUntillQueensLoaded()
{
  // Wait until number of arriving queens is zero.

  mSaturn->RefQueenLoadCnd().Lock();
  while(1) {
    int n = mSaturn->GetQueenLoadNum();
    ISmess(GForm("Gled::WaitUntillQueensLoaded() #queens=%d", n));
    if(n==0) {
      mSaturn->RefQueenLoadCnd().Unlock();
      break;
    }
    mSaturn->RefQueenLoadCnd().Wait();
  }
}

void Gled::AllowMoonConnections()
{
  // Signal Saturn to allow connections by Moons.

  if(mSaturn) mSaturn->AllowMoons();
}

/**************************************************************************/
// Gled stuff
/**************************************************************************/

void Gled::Exit()
{
  static GMutex exit_moo;
  {
    GMutexHolder lck(exit_moo);
    if (mExitThread)
      return;
    mExitThread = new GThread("Gled Terminator", Exit_tl, 0, true);
  }
  mExitThread->Spawn();
}

void* Gled::Exit_tl(void*)
{
  theOne->ExitVirtual();
  GledNS::ShutdownLibSets();
  // Shutdown GledCore manually, when needed.
  return 0;
}

void Gled::ExitVirtual()
{
  if (mSaturn)
  {
    mSaturn->Shutdown();
  }
  bQuit = true;
  if (mExitCondVar)
  {
    mExitCondVar->Lock();
    mExitCondVar->Signal();
    mExitCondVar->Unlock();
  }
}

/**************************************************************************/

Int_t Gled::LoadLibSet(const Text_t* lib_set)
{
  if (lib_set == 0 || strlen(lib_set) == 0)
  {
    warning("Gled::LoadLibSet() called with an empty argument. Ignoring.");
    return 9;
  }
  return GledNS::LoadSoSet(lib_set);
}

Int_t Gled::LoadLibSet(LID_t lid)
{
  if(GledNS::IsLoaded(lid)) {
    return 0;
  } else {
    Text_t buf[80];
    FILE* f = fopen(GForm("%s/gled_lid_%u", mLibDir.Data(), lid), "r");
    if(f == 0) {
      ISerr(GForm("Gled::LoadLibSet lid %u can not be demangled", lid));
      return -1;
    }
    fgets(buf, 80, f);
    fclose(f);
    int i = 0; while(i<79 && (isalnum(buf[i]) || buf[i]=='_')) {++i;} buf[i]=0;
    return LoadLibSet(buf);
  }
}

/**************************************************************************/

void Gled::SetDebugLevel(Int_t d)
{
  if(d<0) d=0;
  G_DEBUG = d;
}

/**************************************************************************/
// Info Stream methods
/**************************************************************************/

void Gled::output(const char* s)
{
  if(mOutFile) {
    GThread::CancelDisabler tka;
    GMutexHolder     mh(mLoggingMutex);
    if(mOutFile == mLogFile)
      fputs("OUT: ", mOutFile);
    fputs(s, mOutFile);
    putc(10, mOutFile);
  }
}

void Gled::message(const char* s)
{
  if(mLogFile) {
    GThread::CancelDisabler tka;
    GMutexHolder     mh(mLoggingMutex);
    fputs("MSG: ", mLogFile);
    fputs(s, mLogFile);
    putc(10, mLogFile);
  }
}

void Gled::warning(const char* s)
{
  if(mLogFile) {
    GThread::CancelDisabler tka;
    GMutexHolder     mh(mLoggingMutex);
    fputs("WRN: ", mLogFile);
    fputs(s, mLogFile);
    putc(10, mLogFile);
  }
}

void Gled::error(const char* s)
{
  if(mLogFile) {
    GThread::CancelDisabler tka;
    GMutexHolder     mh(mLoggingMutex);
    fputs("ERR: ", mLogFile);
    fputs(s, mLogFile);
    putc(10, mLogFile);
  }
}

/**************************************************************************/

EyeInfo* Gled::SpawnEye(const char* libset, const char* eyector)
{
  if(mSaturn == 0) {
    ISerr("Gled::SpawnEye Saturn has not been spawned");
    return 0;
  }

  return SpawnEye(0, 0, libset, eyector);
}

/**************************************************************************/

void Gled::AssertLibSet(const Text_t* lib_set)
{
  // Makes sure libset 'lib_set' is loaded.

  if(GledNS::IsLoaded(lib_set) == false)
    theOne->LoadLibSet(lib_set);
}

namespace {
  void chomp_tail(TString& s, char c='.') {
    Ssiz_t p = s.Last(c);
    if(p != kNPOS)
      s.Remove(p);
  }
}

void Gled::AssertMacro(const Text_t* mac)
{
  // Load and execute macro 'mac' if it has not been loaded yet.

  TString foo(mac); chomp_tail(foo);
  if(gROOT->GetGlobalFunction(foo.Data(), 0, true) == 0) {
    gROOT->Macro(mac);
  }
}

void Gled::Macro(const Text_t* mac)
{
  // Execute macro 'mac'. Do not reload the macro.

  TString foo(mac); chomp_tail(foo);
  if(gROOT->GetGlobalFunction(foo.Data(), 0, true) == 0)
    gROOT->LoadMacro(mac);

  foo += "()";
  gROOT->ProcessLine(foo.Data());
}

void Gled::LoadMacro(const Text_t* mac)
{
  // Makes sure that macro 'mac' is loaded, but do not reload it.

  TString foo(mac); chomp_tail(foo);
  if(gROOT->GetGlobalFunction(foo.Data(), 0, true) == 0)
    gROOT->LoadMacro(mac);
}

/**************************************************************************/
// Thread foos
/**************************************************************************/

#include <TSysEvtHandler.h>

namespace
{
class GExceptionHandler : public TStdExceptionHandler
{
public:
  GExceptionHandler() : TStdExceptionHandler() { Add(); }
  virtual ~GExceptionHandler()                 { Remove(); }

  virtual EStatus  Handle(std::exception& exc)
  {
    // Handle exceptions deriving from TEveException.

    Exc_t* ex = dynamic_cast<Exc_t*>(&exc);
    if (ex) {
      cout <<"TRint runner caught exception: "<< ex << endl;
      cout <<"TRint runner reentering event loop ...\n";
      return kSEHandled;
    } else {
      cout <<"TRint runner caught std exception: "<< exc.what() <<endl;
      return kSEProceed;
    }
  }
};

class GTerminateHandler : public TSignalHandler
{
public:
  GTerminateHandler() : TSignalHandler(kSigTermination, kTRUE) { Add(); }
  virtual ~GTerminateHandler() {}

  virtual Bool_t Notify() { gSystem->ExitLoop(); return kFALSE; }
};
}


GThread* Gled::SpawnTRintThread(const TString& name_prefix)
{
  // Spawns thread running ROOT's main event loop.
  // Makes sure the stack size is at least 8MB.

  static const Exc_t _eh("Gled::SpawnTRintThread ");

  GThread* thr = new GThread(name_prefix + "-TRintRunner",
                    (GThread_foo) TRint_runner_tl, 0, false);
  thr->SetStackSize(8*1024*1024);
  if (thr->Spawn())
  {
    perror(_eh + "can not create Rint thread, aborting.");
    exit(1);
    return 0;
  }
  return thr;
}

void* Gled::TRint_runner_tl(void*)
{
  // Runs the ROOT application.
  // Ownership set to mSaturnInfo.

  GThread* self = GThread::Self();

  self->set_owner(Gled::theOne->mSaturnInfo);

  Gled::theOne->mRintThread = self;

  // Those two will be deleted in ~TROOT().
  new GTerminateHandler;
  new GExceptionHandler;

  self->SetEndFoo((GThread_cu_foo) TRint_cleanup_tl);
  self->SetEndArg(0);

  Gled::theOne->ProcessCmdLineMacros();

  Gled::theOne->bRintRunning = true;
  Gled::theOne->mRint->TApplication::Run(true);
  Gled::theOne->bRintRunning = false;
  cout << "Gint terminated ...\n";

  self->SetEndFoo(0);
  self->SetEndArg(0);

  if (Gled::theOne->GetQuit() == false)
    Gled::theOne->Exit();

  Gled::theOne->mRintThread = 0;

  return 0;
}

void Gled::TRint_cleanup_tl(void*)
{
  cout << "Gint canceled ... expect trouble.\n";
  Gled::theOne->mRint->Terminate(0);
}

/**************************************************************************/
/**************************************************************************/
// Info stream functions
/**************************************************************************/
/**************************************************************************/

void InfoStream(InfoStream_e type, const char* s)
{
  switch (type) {
  case ISoutput:  Gled::theOne->output(s);  break;
  case ISmessage: Gled::theOne->message(s); break;
  case ISwarning: Gled::theOne->warning(s); break;
  case ISerror:   Gled::theOne->error(s);   break;
  }
}

void InfoStream(InfoStream_e type, const TString& s)
{
  InfoStream(type, s.Data());
}

void InfoStream(InfoStream_e type, const string& s)
{
  InfoStream(type, s.c_str());
}

/**************************************************************************/
/**************************************************************************/
 Gled.cxx:1
 Gled.cxx:2
 Gled.cxx:3
 Gled.cxx:4
 Gled.cxx:5
 Gled.cxx:6
 Gled.cxx:7
 Gled.cxx:8
 Gled.cxx:9
 Gled.cxx:10
 Gled.cxx:11
 Gled.cxx:12
 Gled.cxx:13
 Gled.cxx:14
 Gled.cxx:15
 Gled.cxx:16
 Gled.cxx:17
 Gled.cxx:18
 Gled.cxx:19
 Gled.cxx:20
 Gled.cxx:21
 Gled.cxx:22
 Gled.cxx:23
 Gled.cxx:24
 Gled.cxx:25
 Gled.cxx:26
 Gled.cxx:27
 Gled.cxx:28
 Gled.cxx:29
 Gled.cxx:30
 Gled.cxx:31
 Gled.cxx:32
 Gled.cxx:33
 Gled.cxx:34
 Gled.cxx:35
 Gled.cxx:36
 Gled.cxx:37
 Gled.cxx:38
 Gled.cxx:39
 Gled.cxx:40
 Gled.cxx:41
 Gled.cxx:42
 Gled.cxx:43
 Gled.cxx:44
 Gled.cxx:45
 Gled.cxx:46
 Gled.cxx:47
 Gled.cxx:48
 Gled.cxx:49
 Gled.cxx:50
 Gled.cxx:51
 Gled.cxx:52
 Gled.cxx:53
 Gled.cxx:54
 Gled.cxx:55
 Gled.cxx:56
 Gled.cxx:57
 Gled.cxx:58
 Gled.cxx:59
 Gled.cxx:60
 Gled.cxx:61
 Gled.cxx:62
 Gled.cxx:63
 Gled.cxx:64
 Gled.cxx:65
 Gled.cxx:66
 Gled.cxx:67
 Gled.cxx:68
 Gled.cxx:69
 Gled.cxx:70
 Gled.cxx:71
 Gled.cxx:72
 Gled.cxx:73
 Gled.cxx:74
 Gled.cxx:75
 Gled.cxx:76
 Gled.cxx:77
 Gled.cxx:78
 Gled.cxx:79
 Gled.cxx:80
 Gled.cxx:81
 Gled.cxx:82
 Gled.cxx:83
 Gled.cxx:84
 Gled.cxx:85
 Gled.cxx:86
 Gled.cxx:87
 Gled.cxx:88
 Gled.cxx:89
 Gled.cxx:90
 Gled.cxx:91
 Gled.cxx:92
 Gled.cxx:93
 Gled.cxx:94
 Gled.cxx:95
 Gled.cxx:96
 Gled.cxx:97
 Gled.cxx:98
 Gled.cxx:99
 Gled.cxx:100
 Gled.cxx:101
 Gled.cxx:102
 Gled.cxx:103
 Gled.cxx:104
 Gled.cxx:105
 Gled.cxx:106
 Gled.cxx:107
 Gled.cxx:108
 Gled.cxx:109
 Gled.cxx:110
 Gled.cxx:111
 Gled.cxx:112
 Gled.cxx:113
 Gled.cxx:114
 Gled.cxx:115
 Gled.cxx:116
 Gled.cxx:117
 Gled.cxx:118
 Gled.cxx:119
 Gled.cxx:120
 Gled.cxx:121
 Gled.cxx:122
 Gled.cxx:123
 Gled.cxx:124
 Gled.cxx:125
 Gled.cxx:126
 Gled.cxx:127
 Gled.cxx:128
 Gled.cxx:129
 Gled.cxx:130
 Gled.cxx:131
 Gled.cxx:132
 Gled.cxx:133
 Gled.cxx:134
 Gled.cxx:135
 Gled.cxx:136
 Gled.cxx:137
 Gled.cxx:138
 Gled.cxx:139
 Gled.cxx:140
 Gled.cxx:141
 Gled.cxx:142
 Gled.cxx:143
 Gled.cxx:144
 Gled.cxx:145
 Gled.cxx:146
 Gled.cxx:147
 Gled.cxx:148
 Gled.cxx:149
 Gled.cxx:150
 Gled.cxx:151
 Gled.cxx:152
 Gled.cxx:153
 Gled.cxx:154
 Gled.cxx:155
 Gled.cxx:156
 Gled.cxx:157
 Gled.cxx:158
 Gled.cxx:159
 Gled.cxx:160
 Gled.cxx:161
 Gled.cxx:162
 Gled.cxx:163
 Gled.cxx:164
 Gled.cxx:165
 Gled.cxx:166
 Gled.cxx:167
 Gled.cxx:168
 Gled.cxx:169
 Gled.cxx:170
 Gled.cxx:171
 Gled.cxx:172
 Gled.cxx:173
 Gled.cxx:174
 Gled.cxx:175
 Gled.cxx:176
 Gled.cxx:177
 Gled.cxx:178
 Gled.cxx:179
 Gled.cxx:180
 Gled.cxx:181
 Gled.cxx:182
 Gled.cxx:183
 Gled.cxx:184
 Gled.cxx:185
 Gled.cxx:186
 Gled.cxx:187
 Gled.cxx:188
 Gled.cxx:189
 Gled.cxx:190
 Gled.cxx:191
 Gled.cxx:192
 Gled.cxx:193
 Gled.cxx:194
 Gled.cxx:195
 Gled.cxx:196
 Gled.cxx:197
 Gled.cxx:198
 Gled.cxx:199
 Gled.cxx:200
 Gled.cxx:201
 Gled.cxx:202
 Gled.cxx:203
 Gled.cxx:204
 Gled.cxx:205
 Gled.cxx:206
 Gled.cxx:207
 Gled.cxx:208
 Gled.cxx:209
 Gled.cxx:210
 Gled.cxx:211
 Gled.cxx:212
 Gled.cxx:213
 Gled.cxx:214
 Gled.cxx:215
 Gled.cxx:216
 Gled.cxx:217
 Gled.cxx:218
 Gled.cxx:219
 Gled.cxx:220
 Gled.cxx:221
 Gled.cxx:222
 Gled.cxx:223
 Gled.cxx:224
 Gled.cxx:225
 Gled.cxx:226
 Gled.cxx:227
 Gled.cxx:228
 Gled.cxx:229
 Gled.cxx:230
 Gled.cxx:231
 Gled.cxx:232
 Gled.cxx:233
 Gled.cxx:234
 Gled.cxx:235
 Gled.cxx:236
 Gled.cxx:237
 Gled.cxx:238
 Gled.cxx:239
 Gled.cxx:240
 Gled.cxx:241
 Gled.cxx:242
 Gled.cxx:243
 Gled.cxx:244
 Gled.cxx:245
 Gled.cxx:246
 Gled.cxx:247
 Gled.cxx:248
 Gled.cxx:249
 Gled.cxx:250
 Gled.cxx:251
 Gled.cxx:252
 Gled.cxx:253
 Gled.cxx:254
 Gled.cxx:255
 Gled.cxx:256
 Gled.cxx:257
 Gled.cxx:258
 Gled.cxx:259
 Gled.cxx:260
 Gled.cxx:261
 Gled.cxx:262
 Gled.cxx:263
 Gled.cxx:264
 Gled.cxx:265
 Gled.cxx:266
 Gled.cxx:267
 Gled.cxx:268
 Gled.cxx:269
 Gled.cxx:270
 Gled.cxx:271
 Gled.cxx:272
 Gled.cxx:273
 Gled.cxx:274
 Gled.cxx:275
 Gled.cxx:276
 Gled.cxx:277
 Gled.cxx:278
 Gled.cxx:279
 Gled.cxx:280
 Gled.cxx:281
 Gled.cxx:282
 Gled.cxx:283
 Gled.cxx:284
 Gled.cxx:285
 Gled.cxx:286
 Gled.cxx:287
 Gled.cxx:288
 Gled.cxx:289
 Gled.cxx:290
 Gled.cxx:291
 Gled.cxx:292
 Gled.cxx:293
 Gled.cxx:294
 Gled.cxx:295
 Gled.cxx:296
 Gled.cxx:297
 Gled.cxx:298
 Gled.cxx:299
 Gled.cxx:300
 Gled.cxx:301
 Gled.cxx:302
 Gled.cxx:303
 Gled.cxx:304
 Gled.cxx:305
 Gled.cxx:306
 Gled.cxx:307
 Gled.cxx:308
 Gled.cxx:309
 Gled.cxx:310
 Gled.cxx:311
 Gled.cxx:312
 Gled.cxx:313
 Gled.cxx:314
 Gled.cxx:315
 Gled.cxx:316
 Gled.cxx:317
 Gled.cxx:318
 Gled.cxx:319
 Gled.cxx:320
 Gled.cxx:321
 Gled.cxx:322
 Gled.cxx:323
 Gled.cxx:324
 Gled.cxx:325
 Gled.cxx:326
 Gled.cxx:327
 Gled.cxx:328
 Gled.cxx:329
 Gled.cxx:330
 Gled.cxx:331
 Gled.cxx:332
 Gled.cxx:333
 Gled.cxx:334
 Gled.cxx:335
 Gled.cxx:336
 Gled.cxx:337
 Gled.cxx:338
 Gled.cxx:339
 Gled.cxx:340
 Gled.cxx:341
 Gled.cxx:342
 Gled.cxx:343
 Gled.cxx:344
 Gled.cxx:345
 Gled.cxx:346
 Gled.cxx:347
 Gled.cxx:348
 Gled.cxx:349
 Gled.cxx:350
 Gled.cxx:351
 Gled.cxx:352
 Gled.cxx:353
 Gled.cxx:354
 Gled.cxx:355
 Gled.cxx:356
 Gled.cxx:357
 Gled.cxx:358
 Gled.cxx:359
 Gled.cxx:360
 Gled.cxx:361
 Gled.cxx:362
 Gled.cxx:363
 Gled.cxx:364
 Gled.cxx:365
 Gled.cxx:366
 Gled.cxx:367
 Gled.cxx:368
 Gled.cxx:369
 Gled.cxx:370
 Gled.cxx:371
 Gled.cxx:372
 Gled.cxx:373
 Gled.cxx:374
 Gled.cxx:375
 Gled.cxx:376
 Gled.cxx:377
 Gled.cxx:378
 Gled.cxx:379
 Gled.cxx:380
 Gled.cxx:381
 Gled.cxx:382
 Gled.cxx:383
 Gled.cxx:384
 Gled.cxx:385
 Gled.cxx:386
 Gled.cxx:387
 Gled.cxx:388
 Gled.cxx:389
 Gled.cxx:390
 Gled.cxx:391
 Gled.cxx:392
 Gled.cxx:393
 Gled.cxx:394
 Gled.cxx:395
 Gled.cxx:396
 Gled.cxx:397
 Gled.cxx:398
 Gled.cxx:399
 Gled.cxx:400
 Gled.cxx:401
 Gled.cxx:402
 Gled.cxx:403
 Gled.cxx:404
 Gled.cxx:405
 Gled.cxx:406
 Gled.cxx:407
 Gled.cxx:408
 Gled.cxx:409
 Gled.cxx:410
 Gled.cxx:411
 Gled.cxx:412
 Gled.cxx:413
 Gled.cxx:414
 Gled.cxx:415
 Gled.cxx:416
 Gled.cxx:417
 Gled.cxx:418
 Gled.cxx:419
 Gled.cxx:420
 Gled.cxx:421
 Gled.cxx:422
 Gled.cxx:423
 Gled.cxx:424
 Gled.cxx:425
 Gled.cxx:426
 Gled.cxx:427
 Gled.cxx:428
 Gled.cxx:429
 Gled.cxx:430
 Gled.cxx:431
 Gled.cxx:432
 Gled.cxx:433
 Gled.cxx:434
 Gled.cxx:435
 Gled.cxx:436
 Gled.cxx:437
 Gled.cxx:438
 Gled.cxx:439
 Gled.cxx:440
 Gled.cxx:441
 Gled.cxx:442
 Gled.cxx:443
 Gled.cxx:444
 Gled.cxx:445
 Gled.cxx:446
 Gled.cxx:447
 Gled.cxx:448
 Gled.cxx:449
 Gled.cxx:450
 Gled.cxx:451
 Gled.cxx:452
 Gled.cxx:453
 Gled.cxx:454
 Gled.cxx:455
 Gled.cxx:456
 Gled.cxx:457
 Gled.cxx:458
 Gled.cxx:459
 Gled.cxx:460
 Gled.cxx:461
 Gled.cxx:462
 Gled.cxx:463
 Gled.cxx:464
 Gled.cxx:465
 Gled.cxx:466
 Gled.cxx:467
 Gled.cxx:468
 Gled.cxx:469
 Gled.cxx:470
 Gled.cxx:471
 Gled.cxx:472
 Gled.cxx:473
 Gled.cxx:474
 Gled.cxx:475
 Gled.cxx:476
 Gled.cxx:477
 Gled.cxx:478
 Gled.cxx:479
 Gled.cxx:480
 Gled.cxx:481
 Gled.cxx:482
 Gled.cxx:483
 Gled.cxx:484
 Gled.cxx:485
 Gled.cxx:486
 Gled.cxx:487
 Gled.cxx:488
 Gled.cxx:489
 Gled.cxx:490
 Gled.cxx:491
 Gled.cxx:492
 Gled.cxx:493
 Gled.cxx:494
 Gled.cxx:495
 Gled.cxx:496
 Gled.cxx:497
 Gled.cxx:498
 Gled.cxx:499
 Gled.cxx:500
 Gled.cxx:501
 Gled.cxx:502
 Gled.cxx:503
 Gled.cxx:504
 Gled.cxx:505
 Gled.cxx:506
 Gled.cxx:507
 Gled.cxx:508
 Gled.cxx:509
 Gled.cxx:510
 Gled.cxx:511
 Gled.cxx:512
 Gled.cxx:513
 Gled.cxx:514
 Gled.cxx:515
 Gled.cxx:516
 Gled.cxx:517
 Gled.cxx:518
 Gled.cxx:519
 Gled.cxx:520
 Gled.cxx:521
 Gled.cxx:522
 Gled.cxx:523
 Gled.cxx:524
 Gled.cxx:525
 Gled.cxx:526
 Gled.cxx:527
 Gled.cxx:528
 Gled.cxx:529
 Gled.cxx:530
 Gled.cxx:531
 Gled.cxx:532
 Gled.cxx:533
 Gled.cxx:534
 Gled.cxx:535
 Gled.cxx:536
 Gled.cxx:537
 Gled.cxx:538
 Gled.cxx:539
 Gled.cxx:540
 Gled.cxx:541
 Gled.cxx:542
 Gled.cxx:543
 Gled.cxx:544
 Gled.cxx:545
 Gled.cxx:546
 Gled.cxx:547
 Gled.cxx:548
 Gled.cxx:549
 Gled.cxx:550
 Gled.cxx:551
 Gled.cxx:552
 Gled.cxx:553
 Gled.cxx:554
 Gled.cxx:555
 Gled.cxx:556
 Gled.cxx:557
 Gled.cxx:558
 Gled.cxx:559
 Gled.cxx:560
 Gled.cxx:561
 Gled.cxx:562
 Gled.cxx:563
 Gled.cxx:564
 Gled.cxx:565
 Gled.cxx:566
 Gled.cxx:567
 Gled.cxx:568
 Gled.cxx:569
 Gled.cxx:570
 Gled.cxx:571
 Gled.cxx:572
 Gled.cxx:573
 Gled.cxx:574
 Gled.cxx:575
 Gled.cxx:576
 Gled.cxx:577
 Gled.cxx:578
 Gled.cxx:579
 Gled.cxx:580
 Gled.cxx:581
 Gled.cxx:582
 Gled.cxx:583
 Gled.cxx:584
 Gled.cxx:585
 Gled.cxx:586
 Gled.cxx:587
 Gled.cxx:588
 Gled.cxx:589
 Gled.cxx:590
 Gled.cxx:591
 Gled.cxx:592
 Gled.cxx:593
 Gled.cxx:594
 Gled.cxx:595
 Gled.cxx:596
 Gled.cxx:597
 Gled.cxx:598
 Gled.cxx:599
 Gled.cxx:600
 Gled.cxx:601
 Gled.cxx:602
 Gled.cxx:603
 Gled.cxx:604
 Gled.cxx:605
 Gled.cxx:606
 Gled.cxx:607
 Gled.cxx:608
 Gled.cxx:609
 Gled.cxx:610
 Gled.cxx:611
 Gled.cxx:612
 Gled.cxx:613
 Gled.cxx:614
 Gled.cxx:615
 Gled.cxx:616
 Gled.cxx:617
 Gled.cxx:618
 Gled.cxx:619
 Gled.cxx:620
 Gled.cxx:621
 Gled.cxx:622
 Gled.cxx:623
 Gled.cxx:624
 Gled.cxx:625
 Gled.cxx:626
 Gled.cxx:627
 Gled.cxx:628
 Gled.cxx:629
 Gled.cxx:630
 Gled.cxx:631
 Gled.cxx:632
 Gled.cxx:633
 Gled.cxx:634
 Gled.cxx:635
 Gled.cxx:636
 Gled.cxx:637
 Gled.cxx:638
 Gled.cxx:639
 Gled.cxx:640
 Gled.cxx:641
 Gled.cxx:642
 Gled.cxx:643
 Gled.cxx:644
 Gled.cxx:645
 Gled.cxx:646
 Gled.cxx:647
 Gled.cxx:648
 Gled.cxx:649
 Gled.cxx:650
 Gled.cxx:651
 Gled.cxx:652
 Gled.cxx:653
 Gled.cxx:654
 Gled.cxx:655
 Gled.cxx:656
 Gled.cxx:657
 Gled.cxx:658
 Gled.cxx:659
 Gled.cxx:660
 Gled.cxx:661
 Gled.cxx:662
 Gled.cxx:663
 Gled.cxx:664
 Gled.cxx:665
 Gled.cxx:666
 Gled.cxx:667
 Gled.cxx:668
 Gled.cxx:669
 Gled.cxx:670
 Gled.cxx:671
 Gled.cxx:672
 Gled.cxx:673
 Gled.cxx:674
 Gled.cxx:675
 Gled.cxx:676
 Gled.cxx:677
 Gled.cxx:678
 Gled.cxx:679
 Gled.cxx:680
 Gled.cxx:681
 Gled.cxx:682
 Gled.cxx:683
 Gled.cxx:684
 Gled.cxx:685
 Gled.cxx:686
 Gled.cxx:687
 Gled.cxx:688
 Gled.cxx:689
 Gled.cxx:690
 Gled.cxx:691
 Gled.cxx:692
 Gled.cxx:693
 Gled.cxx:694
 Gled.cxx:695
 Gled.cxx:696
 Gled.cxx:697
 Gled.cxx:698
 Gled.cxx:699
 Gled.cxx:700
 Gled.cxx:701
 Gled.cxx:702
 Gled.cxx:703
 Gled.cxx:704
 Gled.cxx:705
 Gled.cxx:706
 Gled.cxx:707
 Gled.cxx:708
 Gled.cxx:709
 Gled.cxx:710
 Gled.cxx:711
 Gled.cxx:712
 Gled.cxx:713
 Gled.cxx:714
 Gled.cxx:715
 Gled.cxx:716
 Gled.cxx:717
 Gled.cxx:718
 Gled.cxx:719
 Gled.cxx:720
 Gled.cxx:721
 Gled.cxx:722
 Gled.cxx:723
 Gled.cxx:724
 Gled.cxx:725
 Gled.cxx:726
 Gled.cxx:727
 Gled.cxx:728
 Gled.cxx:729
 Gled.cxx:730
 Gled.cxx:731
 Gled.cxx:732
 Gled.cxx:733
 Gled.cxx:734
 Gled.cxx:735
 Gled.cxx:736
 Gled.cxx:737
 Gled.cxx:738
 Gled.cxx:739
 Gled.cxx:740
 Gled.cxx:741
 Gled.cxx:742
 Gled.cxx:743
 Gled.cxx:744
 Gled.cxx:745
 Gled.cxx:746
 Gled.cxx:747
 Gled.cxx:748
 Gled.cxx:749
 Gled.cxx:750
 Gled.cxx:751
 Gled.cxx:752
 Gled.cxx:753
 Gled.cxx:754
 Gled.cxx:755
 Gled.cxx:756
 Gled.cxx:757
 Gled.cxx:758
 Gled.cxx:759
 Gled.cxx:760
 Gled.cxx:761
 Gled.cxx:762
 Gled.cxx:763
 Gled.cxx:764
 Gled.cxx:765
 Gled.cxx:766
 Gled.cxx:767
 Gled.cxx:768
 Gled.cxx:769
 Gled.cxx:770
 Gled.cxx:771
 Gled.cxx:772
 Gled.cxx:773
 Gled.cxx:774
 Gled.cxx:775
 Gled.cxx:776
 Gled.cxx:777
 Gled.cxx:778
 Gled.cxx:779
 Gled.cxx:780
 Gled.cxx:781
 Gled.cxx:782
 Gled.cxx:783
 Gled.cxx:784
 Gled.cxx:785
 Gled.cxx:786
 Gled.cxx:787
 Gled.cxx:788
 Gled.cxx:789
 Gled.cxx:790
 Gled.cxx:791
 Gled.cxx:792
 Gled.cxx:793
 Gled.cxx:794
 Gled.cxx:795
 Gled.cxx:796
 Gled.cxx:797
 Gled.cxx:798
 Gled.cxx:799
 Gled.cxx:800
 Gled.cxx:801
 Gled.cxx:802
 Gled.cxx:803
 Gled.cxx:804
 Gled.cxx:805
 Gled.cxx:806
 Gled.cxx:807
 Gled.cxx:808
 Gled.cxx:809
 Gled.cxx:810
 Gled.cxx:811
 Gled.cxx:812
 Gled.cxx:813
 Gled.cxx:814
 Gled.cxx:815
 Gled.cxx:816
 Gled.cxx:817
 Gled.cxx:818
 Gled.cxx:819
 Gled.cxx:820
 Gled.cxx:821
 Gled.cxx:822
 Gled.cxx:823
 Gled.cxx:824
 Gled.cxx:825
 Gled.cxx:826
 Gled.cxx:827
 Gled.cxx:828
 Gled.cxx:829
 Gled.cxx:830
 Gled.cxx:831
 Gled.cxx:832
 Gled.cxx:833
 Gled.cxx:834
 Gled.cxx:835
 Gled.cxx:836
 Gled.cxx:837
 Gled.cxx:838
 Gled.cxx:839
 Gled.cxx:840
 Gled.cxx:841
 Gled.cxx:842
 Gled.cxx:843
 Gled.cxx:844
 Gled.cxx:845
 Gled.cxx:846
 Gled.cxx:847
 Gled.cxx:848
 Gled.cxx:849
 Gled.cxx:850
 Gled.cxx:851
 Gled.cxx:852
 Gled.cxx:853
 Gled.cxx:854
 Gled.cxx:855
 Gled.cxx:856
 Gled.cxx:857
 Gled.cxx:858
 Gled.cxx:859
 Gled.cxx:860
 Gled.cxx:861
 Gled.cxx:862
 Gled.cxx:863
 Gled.cxx:864
 Gled.cxx:865
 Gled.cxx:866
 Gled.cxx:867
 Gled.cxx:868
 Gled.cxx:869
 Gled.cxx:870
 Gled.cxx:871
 Gled.cxx:872
 Gled.cxx:873
 Gled.cxx:874
 Gled.cxx:875
 Gled.cxx:876
 Gled.cxx:877
 Gled.cxx:878
 Gled.cxx:879
 Gled.cxx:880
 Gled.cxx:881
 Gled.cxx:882
 Gled.cxx:883
 Gled.cxx:884
 Gled.cxx:885
 Gled.cxx:886
 Gled.cxx:887
 Gled.cxx:888
 Gled.cxx:889
 Gled.cxx:890
 Gled.cxx:891
 Gled.cxx:892
 Gled.cxx:893
 Gled.cxx:894
 Gled.cxx:895
 Gled.cxx:896
 Gled.cxx:897
 Gled.cxx:898
 Gled.cxx:899
 Gled.cxx:900
 Gled.cxx:901
 Gled.cxx:902
 Gled.cxx:903
 Gled.cxx:904
 Gled.cxx:905
 Gled.cxx:906
 Gled.cxx:907
 Gled.cxx:908
 Gled.cxx:909
 Gled.cxx:910
 Gled.cxx:911
 Gled.cxx:912
 Gled.cxx:913
 Gled.cxx:914
 Gled.cxx:915
 Gled.cxx:916
 Gled.cxx:917
 Gled.cxx:918
 Gled.cxx:919
 Gled.cxx:920
 Gled.cxx:921
 Gled.cxx:922
 Gled.cxx:923
 Gled.cxx:924
 Gled.cxx:925
 Gled.cxx:926
 Gled.cxx:927
 Gled.cxx:928
 Gled.cxx:929
 Gled.cxx:930
 Gled.cxx:931
 Gled.cxx:932
 Gled.cxx:933
 Gled.cxx:934
 Gled.cxx:935
 Gled.cxx:936
 Gled.cxx:937
 Gled.cxx:938
 Gled.cxx:939
 Gled.cxx:940
 Gled.cxx:941
 Gled.cxx:942
 Gled.cxx:943
 Gled.cxx:944
 Gled.cxx:945
 Gled.cxx:946
 Gled.cxx:947
 Gled.cxx:948
 Gled.cxx:949
 Gled.cxx:950
 Gled.cxx:951
 Gled.cxx:952
 Gled.cxx:953
 Gled.cxx:954
 Gled.cxx:955
 Gled.cxx:956
 Gled.cxx:957
 Gled.cxx:958
 Gled.cxx:959
 Gled.cxx:960
 Gled.cxx:961
 Gled.cxx:962
 Gled.cxx:963
 Gled.cxx:964
 Gled.cxx:965
 Gled.cxx:966
 Gled.cxx:967
 Gled.cxx:968
 Gled.cxx:969
 Gled.cxx:970
 Gled.cxx:971
 Gled.cxx:972
 Gled.cxx:973
 Gled.cxx:974
 Gled.cxx:975
 Gled.cxx:976
 Gled.cxx:977
 Gled.cxx:978
 Gled.cxx:979
 Gled.cxx:980
 Gled.cxx:981
 Gled.cxx:982
 Gled.cxx:983
 Gled.cxx:984
 Gled.cxx:985
 Gled.cxx:986
 Gled.cxx:987
 Gled.cxx:988
 Gled.cxx:989
 Gled.cxx:990
 Gled.cxx:991
 Gled.cxx:992
 Gled.cxx:993
 Gled.cxx:994
 Gled.cxx:995
 Gled.cxx:996
 Gled.cxx:997
 Gled.cxx:998
 Gled.cxx:999
 Gled.cxx:1000