ROOT logo
// $Id: ZMIR.cxx 2695 2012-03-11 05:32:54Z 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 "ZMIR.h"
#include <Glasses/SaturnInfo.h>
#include <Gled/GledNS.h>

/**************************************************************************/
// ZMIR
/**************************************************************************/

//________________________________________________________________________
//
// Covering structure for streaming/routing of MIRs.
// Message type defaults to MT_Flare.
// By calling SetRecipient the message type is transmuted to MT_Beam.
//
// Direction is used for determination of routing/exec action in the Saturn.
// SuppressFlareBroadcast can be set during MIR execution on the sun-saturn
// to prevent broadcasting of the MIR to moons.

ClassImp(ZMIR);

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

namespace
{
  const Int_t sROOT_Header_Length = 2*sizeof(UInt_t); // len + type

  const Int_t sRouting_Header_Min_Length = sROOT_Header_Length +
  sizeof(UChar_t) + sizeof(ID_t) + sizeof(ID_t); // MirBits, Caller, A

  const Int_t sFixed_Header_Length = sROOT_Header_Length +
    sizeof(UChar_t) + 4*sizeof(ID_t)  +                // MirBits, Caller,A,B,G
    sizeof(LID_t)   +   sizeof(CID_t) + sizeof(MID_t); // full method id

  const Int_t sMirBits_Length    = sizeof(UChar_t);
  const Int_t sCaller_Length     = sizeof(ID_t);
  const Int_t sRecipient_Length  = sizeof(ID_t);
  const Int_t sResultReq_Length  = sizeof(ID_t) + sizeof(UInt_t);
  const Int_t sMax_Header_Length = sFixed_Header_Length + sRecipient_Length + sResultReq_Length;

  const Int_t sCaller_Offset    = sROOT_Header_Length + sMirBits_Length;
  const Int_t sRecipient_Offset = sCaller_Offset      + sCaller_Length;
  const Int_t sResultReq_Offset = sRecipient_Offset   + sRecipient_Length;
};

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

void ZMIR::_init()
{
  // Set demangled info to null
  fCaller = 0; fRecipient = fResultRecipient = 0;
  fAlpha = fBeta = fGamma = 0;
}

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

ZMIR::ZMIR(ID_t a, ID_t b, ID_t g) :
  TMessage(GledNS::MT_Flare),
  fDirection(D_Unknown), fSuppressFlareBroadcast(false), fRequiresResult(false),
  fMirBits(0), fCallerID(0),
  fRecipientID(0), fResultRecipientID(0), fResultReqHandle(0),
  fAlphaID(a), fBetaID(b), fGammaID(g)
{
  _init();
  fTrueBuffer = 0;
  SetBufferOffset(sMax_Header_Length);
}

ZMIR::ZMIR(ZGlass* a, ZGlass* b, ZGlass* g) :
  TMessage(GledNS::MT_Flare),
  fDirection(D_Unknown), fSuppressFlareBroadcast(false), fRequiresResult(false) ,
  fMirBits(0), fCallerID(0),
  fRecipientID(0), fResultRecipientID(0), fResultReqHandle(0),
  fAlpha(a), fBeta(b), fGamma(g)
{
  fAlphaID = a ? a->GetSaturnID() : 0;
  fBetaID  = b ? b->GetSaturnID() : 0;
  fGammaID = g ? g->GetSaturnID() : 0;
  fTrueBuffer = 0;
  SetBufferOffset(sMax_Header_Length);
  fCaller = 0; fRecipient = fResultRecipient = 0;
}


ZMIR::ZMIR(TMessage*& m) :
  TMessage(m->Buffer(), m->BufferSize()),
  fDirection(D_Unknown),
  fSuppressFlareBroadcast(false), fRequiresResult(false)
{
  m->DetachBuffer(); delete m; m = 0;
  _init();
  fTrueBuffer = 0;
}

ZMIR::ZMIR(void* buf, Int_t size) :
  TMessage(buf,size),
  fDirection(D_Unknown),
  fSuppressFlareBroadcast(false), fRequiresResult(false)
{
  _init();
  fTrueBuffer = 0;
}

ZMIR::~ZMIR()
{
  if(fTrueBuffer) fBuffer = fTrueBuffer;
}

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

Int_t ZMIR::HeaderLength()
{
  Int_t r = sFixed_Header_Length;
  if(fMirBits & MB_HasRecipient) r += sizeof(ID_t);
  if(fMirBits & MB_HasResultReq) r += sResultReq_Length;
  return r;
}

Int_t ZMIR::RoutingHeaderLength()
{
  Int_t r = sRouting_Header_Min_Length;
  if(fMirBits & MB_HasRecipient) r += sizeof(ID_t);
  if(fMirBits & MB_HasResultReq) r += sResultReq_Length;
  return r;
}

void ZMIR::WriteHeader()
{
  // Writes a complete MIR header, including the message type. If
  // Recipient and ResultReq fields are not used, the position of
  // fBuffer is displaced for the appropriate amount.
  // Also ... sets fBufSize to the current buffer position.
  // Do not add further data after this method has been called!

  if (IsWriting())
  {
    if (fMirBits & MB_HeaderWritten) return;
    fMirBits |= MB_HeaderWritten;

    fTrueBuffer = fBuffer;
    fBuffer += sMax_Header_Length - HeaderLength();

    fBufSize  = Length();
    SetBufferOffset(sizeof(UInt_t));

    TBuffer& b = *this;
    b << What() << fMirBits << fCallerID;
    if (fMirBits & MB_HasRecipient) b << fRecipientID;
    if (fMirBits & MB_HasResultReq) b << fResultRecipientID << fResultReqHandle;
    b << fAlphaID << fBetaID << fGammaID;
    b << fLid << fCid << fMid;

    SetBufferOffset(fBufSize);
  }
}

void ZMIR::ReadRoutingHeader()
{
  assert(IsReading()); // or sth ...
  TBuffer& b = *this;
  b >> fMirBits >> fCallerID;
  if(fMirBits & MB_HasRecipient) b >> fRecipientID;
  if(fMirBits & MB_HasResultReq) b >> fResultRecipientID >> fResultReqHandle;
  b >> fAlphaID;
}

void ZMIR::ReadExecHeader()
{
  assert(IsReading()); // or sth else ...
  //if(!IsReading()) { ZGlass* p=0; p->GetName(); }
  TBuffer& b = *this;
  b >> fBetaID >> fGammaID;
  b >> fLid >> fCid >> fMid;
}

void ZMIR::RewindToData()
{
  // Sets Read mode and position to just after the Context header.

  SetReadMode();
  SetBufferOffset(HeaderLength());
}

void ZMIR::RewindToExecHeader()
{
  // Sets Read mode and position to just after the Context header.

  SetReadMode();
  SetBufferOffset(RoutingHeaderLength());
}

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

namespace
{
  const Exc_t demangle_eh("ZMIR::Demangle failed for ");
}

void ZMIR::Demangle(An_ID_Demangler* s) throw(Exc_t)
{
  fCaller = dynamic_cast<ZMirEmittingEntity*>(s->DemangleID(fCallerID));
  if (!fCaller) throw demangle_eh + GForm("Caller(id=%d)", fCallerID);

  // Recipient & Result recipient separated. Called by Saturn when appropriate.

  fAlpha = s->DemangleID(fAlphaID);
  if (!fAlpha) throw demangle_eh + GForm("Alpha [%d]", fAlphaID);
  if (fBetaID)
  {
    fBeta = s->DemangleID(fBetaID);
    if(!fBeta) throw demangle_eh + GForm("Beta", fBetaID);
  }
  if (fGammaID)
  {
    fGamma = s->DemangleID(fGammaID);
    if (!fGamma) throw demangle_eh + GForm("Gamma", fGammaID);
  }
}

void ZMIR::DemangleRecipient(An_ID_Demangler* s) throw(Exc_t)
{
  if(fMirBits & MB_HasRecipient) {
    fRecipient = dynamic_cast<SaturnInfo*>(s->DemangleID(fRecipientID));
    if(!fRecipient) throw(demangle_eh + GForm("Recipient", fRecipientID));
  }
}

void ZMIR::DemangleResultRecipient(An_ID_Demangler* s) throw(Exc_t)
{
  if (fMirBits & MB_HasResultReq)
  {
    fResultRecipient = dynamic_cast<SaturnInfo*>(s->DemangleID(fResultRecipientID));
    if (!fResultRecipient) throw demangle_eh + "ResultRecipient";
  }
}

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

void ZMIR::SetCaller(ZMirEmittingEntity* caller)
{
  fCaller = caller;
  if (IsWriting())
  {
    fCallerID = caller ? caller->GetSaturnID() : 0;
  }
  else
  {
    // Called by Saturn to set Caller identity for MIRs coming from
    // Eyes and being posted by threads.
    fCallerID = caller ? caller->GetSaturnID() : 0;
    Int_t pos = Length();
    SetBufferOffset(sCaller_Offset);
    *this << fCallerID;
    SetBufferOffset(pos);
  }
}

void ZMIR::SetRecipient(SaturnInfo* recipient)
{
  // Can be called for MIR in write mode or for MIR in read mode
  // if it is already a Beam.
  // recipient == 0 means local invocation.

  fRecipientID = recipient ? recipient->GetSaturnID() : 0;
  if(IsReading()) {
    assert(fMirBits | MB_HasRecipient);
    fRecipient = recipient;
    Int_t pos = Length();
    SetBufferOffset(sRecipient_Offset);
    *this << fRecipientID;
    SetBufferOffset(pos);
  } else {
    fMirBits |= MB_HasRecipient;
    SetWhat(GledNS::MT_Beam);
  }
}

void ZMIR::ClearRecipient()
{
  // Can only be called for MIRs in read mode. MIR is transmuted into Flare,
  // but the HasRecipient flag stays on.

  assert(IsReading() && (fMirBits | MB_HasRecipient));
  fRecipientID = 0;
  fRecipient   = 0;

  SetWhat(GledNS::MT_Flare);
  Int_t pos = Length();
  SetBufferOffset(sRecipient_Offset);
  *this << fRecipientID;
  SetBufferOffset(pos);
}

void ZMIR::SetResultReq(SaturnInfo* r_recipient, UInt_t r_handle)
{
  // Sets result request information of the MIR.
  // Beam results can also carry arbitrary streamed information.

  assert(IsWriting());

  fMirBits |= MB_HasResultReq;
  fResultRecipientID = r_recipient->GetSaturnID();
  fResultReqHandle   = r_handle;
}

void ZMIR::SetDetachedExe(bool multix)
{
    assert(IsWriting());

    fMirBits |= (multix) ? MB_DetachedExe | MB_MultixDetachedExe :
                           MB_DetachedExe;
}

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

void ZMIR::CopyToBuffer(TBuffer& b)
{
  // Copies contents of Message from current position until end.

  b.WriteFastArray(fBufCur, fBufSize - Length());
}

void ZMIR::AppendBuffer(TBuffer& b)
{
  // Appends contents of b to the MIR.

  WriteFastArray(b.Buffer(), b.Length());
}

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

void ZMIR::ChainMIR(ZMIR* mir)
{
  // Appends mir to the end of *this.

  fMirBits |= MB_HasChainedMIR;
  mir->WriteHeader();
  mir->SetBufferOffset(0);
  mir->SetReadMode();
  mir->CopyToBuffer(*this);
}

ZMIR* ZMIR::UnchainMIR(An_ID_Demangler* s)
{
  // Creates a secondary mir from current position onwards.
  // This means that *this must be read to its end. Relevant if *this
  // uses custom-buffer.

  assert(HasChainedMIR());
  ZMIR* mir = new ZMIR(Buffer() + Length(), BufferSize() - Length());
  mir->ResetBit(TBuffer::kIsOwner);
  mir->SetCaller(fCaller);
  mir->ReadRoutingHeader();
  mir->ReadExecHeader();
  if(s != 0)
    mir->Demangle(s);
  return mir;
}


/**************************************************************************/
// ZMIR_Result_Report
/**************************************************************************/

//______________________________________________________________________
//
// Structure for reporting result of MIR execution.
// It can contain a custom respone buffer.

ClassImp(ZMIR_Result_Report);

const char* ZMIR_Result_Report::GenError(bool report_buffer)
{
  if(report_buffer) {
    int buflen = HasResult() ? BufferSize() : -1;
    return GForm("ZMIR_RR(buflen=%d, exc=\"%s\")", buflen, fException.Data());
  } else {
    return GForm("ZMIR_RR(exc=\"%s\")", fException.Data());
  }
}
 ZMIR.cxx:1
 ZMIR.cxx:2
 ZMIR.cxx:3
 ZMIR.cxx:4
 ZMIR.cxx:5
 ZMIR.cxx:6
 ZMIR.cxx:7
 ZMIR.cxx:8
 ZMIR.cxx:9
 ZMIR.cxx:10
 ZMIR.cxx:11
 ZMIR.cxx:12
 ZMIR.cxx:13
 ZMIR.cxx:14
 ZMIR.cxx:15
 ZMIR.cxx:16
 ZMIR.cxx:17
 ZMIR.cxx:18
 ZMIR.cxx:19
 ZMIR.cxx:20
 ZMIR.cxx:21
 ZMIR.cxx:22
 ZMIR.cxx:23
 ZMIR.cxx:24
 ZMIR.cxx:25
 ZMIR.cxx:26
 ZMIR.cxx:27
 ZMIR.cxx:28
 ZMIR.cxx:29
 ZMIR.cxx:30
 ZMIR.cxx:31
 ZMIR.cxx:32
 ZMIR.cxx:33
 ZMIR.cxx:34
 ZMIR.cxx:35
 ZMIR.cxx:36
 ZMIR.cxx:37
 ZMIR.cxx:38
 ZMIR.cxx:39
 ZMIR.cxx:40
 ZMIR.cxx:41
 ZMIR.cxx:42
 ZMIR.cxx:43
 ZMIR.cxx:44
 ZMIR.cxx:45
 ZMIR.cxx:46
 ZMIR.cxx:47
 ZMIR.cxx:48
 ZMIR.cxx:49
 ZMIR.cxx:50
 ZMIR.cxx:51
 ZMIR.cxx:52
 ZMIR.cxx:53
 ZMIR.cxx:54
 ZMIR.cxx:55
 ZMIR.cxx:56
 ZMIR.cxx:57
 ZMIR.cxx:58
 ZMIR.cxx:59
 ZMIR.cxx:60
 ZMIR.cxx:61
 ZMIR.cxx:62
 ZMIR.cxx:63
 ZMIR.cxx:64
 ZMIR.cxx:65
 ZMIR.cxx:66
 ZMIR.cxx:67
 ZMIR.cxx:68
 ZMIR.cxx:69
 ZMIR.cxx:70
 ZMIR.cxx:71
 ZMIR.cxx:72
 ZMIR.cxx:73
 ZMIR.cxx:74
 ZMIR.cxx:75
 ZMIR.cxx:76
 ZMIR.cxx:77
 ZMIR.cxx:78
 ZMIR.cxx:79
 ZMIR.cxx:80
 ZMIR.cxx:81
 ZMIR.cxx:82
 ZMIR.cxx:83
 ZMIR.cxx:84
 ZMIR.cxx:85
 ZMIR.cxx:86
 ZMIR.cxx:87
 ZMIR.cxx:88
 ZMIR.cxx:89
 ZMIR.cxx:90
 ZMIR.cxx:91
 ZMIR.cxx:92
 ZMIR.cxx:93
 ZMIR.cxx:94
 ZMIR.cxx:95
 ZMIR.cxx:96
 ZMIR.cxx:97
 ZMIR.cxx:98
 ZMIR.cxx:99
 ZMIR.cxx:100
 ZMIR.cxx:101
 ZMIR.cxx:102
 ZMIR.cxx:103
 ZMIR.cxx:104
 ZMIR.cxx:105
 ZMIR.cxx:106
 ZMIR.cxx:107
 ZMIR.cxx:108
 ZMIR.cxx:109
 ZMIR.cxx:110
 ZMIR.cxx:111
 ZMIR.cxx:112
 ZMIR.cxx:113
 ZMIR.cxx:114
 ZMIR.cxx:115
 ZMIR.cxx:116
 ZMIR.cxx:117
 ZMIR.cxx:118
 ZMIR.cxx:119
 ZMIR.cxx:120
 ZMIR.cxx:121
 ZMIR.cxx:122
 ZMIR.cxx:123
 ZMIR.cxx:124
 ZMIR.cxx:125
 ZMIR.cxx:126
 ZMIR.cxx:127
 ZMIR.cxx:128
 ZMIR.cxx:129
 ZMIR.cxx:130
 ZMIR.cxx:131
 ZMIR.cxx:132
 ZMIR.cxx:133
 ZMIR.cxx:134
 ZMIR.cxx:135
 ZMIR.cxx:136
 ZMIR.cxx:137
 ZMIR.cxx:138
 ZMIR.cxx:139
 ZMIR.cxx:140
 ZMIR.cxx:141
 ZMIR.cxx:142
 ZMIR.cxx:143
 ZMIR.cxx:144
 ZMIR.cxx:145
 ZMIR.cxx:146
 ZMIR.cxx:147
 ZMIR.cxx:148
 ZMIR.cxx:149
 ZMIR.cxx:150
 ZMIR.cxx:151
 ZMIR.cxx:152
 ZMIR.cxx:153
 ZMIR.cxx:154
 ZMIR.cxx:155
 ZMIR.cxx:156
 ZMIR.cxx:157
 ZMIR.cxx:158
 ZMIR.cxx:159
 ZMIR.cxx:160
 ZMIR.cxx:161
 ZMIR.cxx:162
 ZMIR.cxx:163
 ZMIR.cxx:164
 ZMIR.cxx:165
 ZMIR.cxx:166
 ZMIR.cxx:167
 ZMIR.cxx:168
 ZMIR.cxx:169
 ZMIR.cxx:170
 ZMIR.cxx:171
 ZMIR.cxx:172
 ZMIR.cxx:173
 ZMIR.cxx:174
 ZMIR.cxx:175
 ZMIR.cxx:176
 ZMIR.cxx:177
 ZMIR.cxx:178
 ZMIR.cxx:179
 ZMIR.cxx:180
 ZMIR.cxx:181
 ZMIR.cxx:182
 ZMIR.cxx:183
 ZMIR.cxx:184
 ZMIR.cxx:185
 ZMIR.cxx:186
 ZMIR.cxx:187
 ZMIR.cxx:188
 ZMIR.cxx:189
 ZMIR.cxx:190
 ZMIR.cxx:191
 ZMIR.cxx:192
 ZMIR.cxx:193
 ZMIR.cxx:194
 ZMIR.cxx:195
 ZMIR.cxx:196
 ZMIR.cxx:197
 ZMIR.cxx:198
 ZMIR.cxx:199
 ZMIR.cxx:200
 ZMIR.cxx:201
 ZMIR.cxx:202
 ZMIR.cxx:203
 ZMIR.cxx:204
 ZMIR.cxx:205
 ZMIR.cxx:206
 ZMIR.cxx:207
 ZMIR.cxx:208
 ZMIR.cxx:209
 ZMIR.cxx:210
 ZMIR.cxx:211
 ZMIR.cxx:212
 ZMIR.cxx:213
 ZMIR.cxx:214
 ZMIR.cxx:215
 ZMIR.cxx:216
 ZMIR.cxx:217
 ZMIR.cxx:218
 ZMIR.cxx:219
 ZMIR.cxx:220
 ZMIR.cxx:221
 ZMIR.cxx:222
 ZMIR.cxx:223
 ZMIR.cxx:224
 ZMIR.cxx:225
 ZMIR.cxx:226
 ZMIR.cxx:227
 ZMIR.cxx:228
 ZMIR.cxx:229
 ZMIR.cxx:230
 ZMIR.cxx:231
 ZMIR.cxx:232
 ZMIR.cxx:233
 ZMIR.cxx:234
 ZMIR.cxx:235
 ZMIR.cxx:236
 ZMIR.cxx:237
 ZMIR.cxx:238
 ZMIR.cxx:239
 ZMIR.cxx:240
 ZMIR.cxx:241
 ZMIR.cxx:242
 ZMIR.cxx:243
 ZMIR.cxx:244
 ZMIR.cxx:245
 ZMIR.cxx:246
 ZMIR.cxx:247
 ZMIR.cxx:248
 ZMIR.cxx:249
 ZMIR.cxx:250
 ZMIR.cxx:251
 ZMIR.cxx:252
 ZMIR.cxx:253
 ZMIR.cxx:254
 ZMIR.cxx:255
 ZMIR.cxx:256
 ZMIR.cxx:257
 ZMIR.cxx:258
 ZMIR.cxx:259
 ZMIR.cxx:260
 ZMIR.cxx:261
 ZMIR.cxx:262
 ZMIR.cxx:263
 ZMIR.cxx:264
 ZMIR.cxx:265
 ZMIR.cxx:266
 ZMIR.cxx:267
 ZMIR.cxx:268
 ZMIR.cxx:269
 ZMIR.cxx:270
 ZMIR.cxx:271
 ZMIR.cxx:272
 ZMIR.cxx:273
 ZMIR.cxx:274
 ZMIR.cxx:275
 ZMIR.cxx:276
 ZMIR.cxx:277
 ZMIR.cxx:278
 ZMIR.cxx:279
 ZMIR.cxx:280
 ZMIR.cxx:281
 ZMIR.cxx:282
 ZMIR.cxx:283
 ZMIR.cxx:284
 ZMIR.cxx:285
 ZMIR.cxx:286
 ZMIR.cxx:287
 ZMIR.cxx:288
 ZMIR.cxx:289
 ZMIR.cxx:290
 ZMIR.cxx:291
 ZMIR.cxx:292
 ZMIR.cxx:293
 ZMIR.cxx:294
 ZMIR.cxx:295
 ZMIR.cxx:296
 ZMIR.cxx:297
 ZMIR.cxx:298
 ZMIR.cxx:299
 ZMIR.cxx:300
 ZMIR.cxx:301
 ZMIR.cxx:302
 ZMIR.cxx:303
 ZMIR.cxx:304
 ZMIR.cxx:305
 ZMIR.cxx:306
 ZMIR.cxx:307
 ZMIR.cxx:308
 ZMIR.cxx:309
 ZMIR.cxx:310
 ZMIR.cxx:311
 ZMIR.cxx:312
 ZMIR.cxx:313
 ZMIR.cxx:314
 ZMIR.cxx:315
 ZMIR.cxx:316
 ZMIR.cxx:317
 ZMIR.cxx:318
 ZMIR.cxx:319
 ZMIR.cxx:320
 ZMIR.cxx:321
 ZMIR.cxx:322
 ZMIR.cxx:323
 ZMIR.cxx:324
 ZMIR.cxx:325
 ZMIR.cxx:326
 ZMIR.cxx:327
 ZMIR.cxx:328
 ZMIR.cxx:329
 ZMIR.cxx:330
 ZMIR.cxx:331
 ZMIR.cxx:332
 ZMIR.cxx:333
 ZMIR.cxx:334
 ZMIR.cxx:335
 ZMIR.cxx:336
 ZMIR.cxx:337
 ZMIR.cxx:338
 ZMIR.cxx:339
 ZMIR.cxx:340
 ZMIR.cxx:341
 ZMIR.cxx:342
 ZMIR.cxx:343
 ZMIR.cxx:344
 ZMIR.cxx:345
 ZMIR.cxx:346
 ZMIR.cxx:347
 ZMIR.cxx:348
 ZMIR.cxx:349
 ZMIR.cxx:350
 ZMIR.cxx:351
 ZMIR.cxx:352
 ZMIR.cxx:353
 ZMIR.cxx:354
 ZMIR.cxx:355
 ZMIR.cxx:356
 ZMIR.cxx:357
 ZMIR.cxx:358
 ZMIR.cxx:359
 ZMIR.cxx:360
 ZMIR.cxx:361
 ZMIR.cxx:362
 ZMIR.cxx:363
 ZMIR.cxx:364
 ZMIR.cxx:365
 ZMIR.cxx:366
 ZMIR.cxx:367
 ZMIR.cxx:368
 ZMIR.cxx:369
 ZMIR.cxx:370
 ZMIR.cxx:371
 ZMIR.cxx:372
 ZMIR.cxx:373
 ZMIR.cxx:374
 ZMIR.cxx:375
 ZMIR.cxx:376
 ZMIR.cxx:377
 ZMIR.cxx:378
 ZMIR.cxx:379
 ZMIR.cxx:380
 ZMIR.cxx:381
 ZMIR.cxx:382
 ZMIR.cxx:383
 ZMIR.cxx:384
 ZMIR.cxx:385