]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/trigger/AliHLTGlobalTriggerComponent.cxx
0c400723e8b016b1edbb91bbb35f8e0d2f10d029
[u/mrichter/AliRoot.git] / HLT / trigger / AliHLTGlobalTriggerComponent.cxx
1 /**************************************************************************
2  * This file is property of and copyright by the ALICE HLT Project        *
3  * ALICE Experiment at CERN, All rights reserved.                         *
4  *                                                                        *
5  * Primary Authors: Artur Szostak <artursz@iafrica.com>                   *
6  *                  for The ALICE HLT Project.                            *
7  *                                                                        *
8  * Permission to use, copy, modify and distribute this software and its   *
9  * documentation strictly for non-commercial purposes is hereby granted   *
10  * without fee, provided that the above copyright notice appears in all   *
11  * copies and that both the copyright notice and this permission notice   *
12  * appear in the supporting documentation. The authors make no claims     *
13  * about the suitability of this software for any purpose. It is          *
14  * provided "as is" without express or implied warranty.                  *
15  **************************************************************************/
16
17 /// @file   AliHLTGlobalTriggerComponent.cxx
18 /// @author Artur Szostak <artursz@iafrica.com>
19 /// @date   26 Nov 2008
20 /// @brief  Implementation of the AliHLTGlobalTriggerComponent component class.
21 ///
22 /// The AliHLTGlobalTriggerComponentComponent class applies the global HLT trigger to all
23 /// trigger information produced by components deriving from AliHLTTrigger.
24
25 #include "AliHLTGlobalTriggerComponent.h"
26 #include "AliHLTGlobalTriggerDecision.h"
27 #include "AliHLTGlobalTrigger.h"
28 #include "AliHLTGlobalTriggerConfig.h"
29 #include "AliHLTTriggerMenu.h"
30 #include "TUUID.h"
31 #include "TROOT.h"
32 #include "TRegexp.h"
33 #include "TClonesArray.h"
34 #include "TObjString.h"
35 #include "TSystem.h"
36 #include "TInterpreter.h"
37 #include <fstream>
38 #include <cerrno>
39
40 ClassImp(AliHLTGlobalTriggerComponent)
41
42
43 AliHLTGlobalTriggerComponent::AliHLTGlobalTriggerComponent() :
44         AliHLTTrigger(),
45         fTrigger(NULL),
46         fDebugMode(false)
47 {
48   // Default constructor.
49   
50   ClearInfoForNewEvent(false);
51 }
52
53
54 AliHLTGlobalTriggerComponent::~AliHLTGlobalTriggerComponent()
55 {
56   // Default destructor.
57   
58   if (fTrigger != NULL) delete fTrigger;
59 }
60
61
62 void AliHLTGlobalTriggerComponent::GetOutputDataSize(unsigned long& constBase, double& inputMultiplier)
63 {
64   // Returns the output data size estimate.
65
66   constBase = sizeof(AliHLTGlobalTriggerDecision);
67   inputMultiplier = 1;
68 }
69
70
71 Int_t AliHLTGlobalTriggerComponent::DoInit(int argc, const char** argv)
72 {
73   // Initialises the global trigger component.
74   
75   fDebugMode = false;
76   const char* configFileName = NULL;
77   const char* codeFileName = NULL;
78   TString classname;
79   TClonesArray includePaths(TObjString::Class());
80   TClonesArray includeFiles(TObjString::Class());
81   
82   for (int i = 0; i < argc; i++)
83   {
84     if (strcmp(argv[i], "-config") == 0)
85     {
86       if (configFileName != NULL)
87       {
88         HLTWarning("Trigger configuration macro was already specified."
89                    " Will replace previous value given by -config."
90         );
91       }
92       if (argc <= i+1)
93       {
94         HLTError("The trigger configuration macro filename was not specified." );
95         return -EINVAL;
96       }
97       configFileName = argv[i+1];
98       i++;
99       continue;
100     }
101     
102     if (strcmp(argv[i], "-includepath") == 0)
103     {
104       if (argc <= i+1)
105       {
106         HLTError("The include path was not specified." );
107         return -EINVAL;
108       }
109       new (includePaths[includePaths.GetEntriesFast()]) TObjString(argv[i+1]);
110       i++;
111       continue;
112     }
113     
114     if (strcmp(argv[i], "-include") == 0)
115     {
116       if (argc <= i+1)
117       {
118         HLTError("The include file name was not specified." );
119         return -EINVAL;
120       }
121       new (includeFiles[includeFiles.GetEntriesFast()]) TObjString(argv[i+1]);
122       i++;
123       continue;
124     }
125     
126     if (strcmp(argv[i], "-debug") == 0)
127     {
128       if (fDebugMode == true)
129       {
130         HLTWarning("The debug flag was already specified. Ignoring this instance.");
131       }
132       fDebugMode = true;
133       i++;
134       continue;
135     }
136     
137     if (strcmp(argv[i], "-usecode") == 0)
138     {
139       if (codeFileName != NULL)
140       {
141         HLTWarning("Custom trigger code file was already specified."
142                    " Will replace previous value given by -usecode."
143         );
144       }
145       if (argc <= i+1)
146       {
147         HLTError("The custom trigger code filename was not specified." );
148         return -EINVAL;
149       }
150       codeFileName = argv[i+1];
151       if (argc <= i+2)
152       {
153         HLTError("The custom trigger class name was not specified." );
154         return -EINVAL;
155       }
156       classname = argv[i+2];
157       i += 2;
158       continue;
159     }
160     
161     HLTError("Unknown option '%s'.", argv[i]);
162     return -EINVAL;
163   } // for loop
164   
165   const AliHLTTriggerMenu* menu = NULL;
166   if (configFileName != NULL)
167   {
168     TString cmd = ".x ";
169     cmd += configFileName;
170     gROOT->ProcessLine(cmd);
171     menu = AliHLTGlobalTriggerConfig::Menu();
172   }
173   
174   if (menu == NULL)
175   {
176     HLTError("No trigger menu configuration found or specified.");
177     return -ENOENT;
178   }
179   
180   int result = 0;
181   if (codeFileName == NULL)
182   {
183     HLTDebug("Generating custom HLT trigger class.");
184     result = GenerateTrigger(menu, classname, includePaths, includeFiles);
185   }
186   else
187   {
188     HLTDebug("Loading HLT trigger class from file '%s'.", codeFileName);
189     result = LoadTriggerClass(codeFileName, includePaths);
190   }
191   if (result != 0) return result;
192   
193   fTrigger = AliHLTGlobalTrigger::CreateNew(classname.Data());
194   if (fTrigger == NULL)
195   {
196     HLTError("Could not create a new instance of '%s'.", classname.Data());
197     return -EIO;
198   }
199   
200   fTrigger->FillFromMenu(*menu);
201   fTrigger->ResetCounters(menu->NumberOfItems());
202   
203   // Set the default values from the trigger menu.
204   SetDescription(menu->DefaultDescription());
205   SetTriggerDomain(menu->DefaultTriggerDomain());
206   
207   return 0;
208 }
209
210
211 Int_t AliHLTGlobalTriggerComponent::DoDeinit()
212 {
213   // Cleans up the global trigger component.
214   
215   if (fTrigger != NULL)
216   {
217     delete fTrigger;
218     fTrigger = NULL;
219   }
220   
221   return 0;
222 }
223
224
225 AliHLTComponent* AliHLTGlobalTriggerComponent::Spawn()
226 {
227   // Creates a new object instance.
228   
229   return new AliHLTGlobalTriggerComponent;
230 }
231
232
233 int AliHLTGlobalTriggerComponent::DoTrigger()
234 {
235   // This method will apply the global trigger decision.
236
237   if (fTrigger == NULL)
238   {
239     HLTFatal("Global trigger implementation object is NULL!");
240     return -EIO;
241   }
242   
243   fTrigger->NewEvent();
244   
245   // Fill in the input data.
246   const TObject* obj = GetFirstInputObject();
247   while (obj != NULL)
248   {
249     fTrigger->Add(obj, GetDataType(), GetSpecification());
250     obj = GetNextInputObject();
251   }
252
253   // Calculate the global trigger result and trigger domain, then create and push
254   // back the new global trigger decision object.
255   TString description;
256   AliHLTTriggerDomain triggerDomain;
257   bool triggerResult = fTrigger->CalculateTriggerDecision(triggerDomain, description);
258   
259   AliHLTGlobalTriggerDecision decision(
260       triggerResult,
261       // The following will cause the decision to be generated with default values
262       // (set in fTriggerDomain and fDescription) if the trigger result is false.
263       (triggerResult == true) ? triggerDomain : GetTriggerDomain(),
264       (triggerResult == true) ? description.Data() : GetDescription()
265     );
266   decision.SetCounters(fTrigger->Counters());
267   
268   // Add the input objects used to the global decision.
269   obj = GetFirstInputObject();
270   while (obj != NULL)
271   {
272     if (obj->IsA() == AliHLTTriggerDecision::Class())
273     {
274       decision.AddTriggerInput( *static_cast<const AliHLTTriggerDecision*>(obj) );
275     }
276     else
277     {
278       decision.AddInputObject(obj);
279     }
280     obj = GetNextInputObject();
281   }
282   
283   TriggerEvent(&decision);
284   return 0;
285 }
286
287
288 int AliHLTGlobalTriggerComponent::GenerateTrigger(
289     const AliHLTTriggerMenu* menu, TString& name,
290     const TClonesArray& includePaths, const TClonesArray& includeFiles
291   )
292 {
293   // Generates the global trigger class that will implement the specified trigger menu.
294   // See header for more details.
295   
296   // Create a new UUID and replace the '-' characters with '_' to make it a valid
297   // C++ symbol name.
298   TUUID uuid;
299   TString uuidstr = uuid.AsString();
300   for (Int_t i = 0; i < uuidstr.Length(); i++)
301   {
302     if (uuidstr[i] == '-') uuidstr[i] = '_';
303   }
304   
305   // Create the name of the new class.
306   name = "AliHLTGlobalTriggerImpl_";
307   name += uuidstr;
308   TString filename = name + ".cxx";
309   
310   // Open a text file to write the code and generate the new class.
311   fstream code(filename.Data(), ios_base::out | ios_base::trunc);
312   if (not code.good())
313   {
314     HLTError("Could not open file '%s' for writing.", filename.Data());
315     return -EIO;
316   }
317   
318   TClonesArray symbols(AliHLTTriggerMenuSymbol::Class());
319   int result = BuildSymbolList(menu, symbols);
320   if (result != 0) return result;
321   
322   code << "#include <cstring>" << endl;
323   code << "#include \"TString.h\"" << endl;
324   code << "#include \"TClonesArray.h\"" << endl;
325   code << "#include \"AliHLTGlobalTrigger.h\"" << endl;
326   code << "#include \"AliHLTGlobalTriggerDecision.h\"" << endl;
327   code << "#include \"AliHLTDomainEntry.h\"" << endl;
328   code << "#include \"AliHLTTriggerDomain.h\"" << endl;
329   code << "#include \"AliHLTReadoutList.h\"" << endl;
330   code << "#include \"AliHLTTriggerMenu.h\"" << endl;
331   code << "#include \"AliHLTTriggerMenuItem.h\"" << endl;
332   code << "#include \"AliHLTTriggerMenuSymbol.h\"" << endl;
333   
334   // Add any include files that were specified on the command line.
335   for (Int_t i = 0; i < includeFiles.GetEntriesFast(); i++)
336   {
337     TString file = static_cast<const TObjString*>(includeFiles.UncheckedAt(i))->String();
338     code << "#include \"" << file.Data() << "\"" << endl;
339   }
340   
341   code << "class " << name << " : public AliHLTGlobalTrigger" << endl;
342   code << "{" << endl;
343   code << "public:" << endl;
344   
345   code << "  " << name << "() : AliHLTGlobalTrigger()";
346   // Write the symbols in the trigger menu in the initialisation list.
347   for (Int_t i = 0; i < symbols.GetEntriesFast(); i++)
348   {
349     code << "," << endl;
350     AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) );
351     code << "    " << symbol->Name() << "()," << endl;
352     if (strcmp(symbol->ObjectClass(), "AliHLTTriggerDecision") == 0)
353     {
354       code << "    " << symbol->Name() << "TriggerDomain()," << endl;
355     }
356     code << "    " << symbol->Name() << "DomainEntry(kAliHLTAnyDataType)";
357   }
358   for (UInt_t i = 0; i < menu->NumberOfItems(); i++)
359   {
360     code << "," << endl << "    fMenuItemDescription" << i << "()";
361   }
362   code << endl << "  {" << endl;
363   if (fDebugMode)
364   {
365     code << "    SetLocalLoggingLevel(kHLTLogAll);" << endl;
366     code << "    HLTInfo(\"Creating new instance at %p.\", this);" << endl;
367   }
368   code << "  }" << endl;
369   
370   code << "  virtual ~" << name << "() {" << endl;
371   if (fDebugMode)
372   {
373     code << "    HLTInfo(\"Deleting instance at %p.\", this);" << endl;
374   }
375   code << "  }" << endl;
376   
377   // Generate the FillFromMenu method.
378   code << "  virtual void FillFromMenu(const AliHLTTriggerMenu& menu) {" << endl;
379   if (fDebugMode)
380   {
381     code << "    HLTDebug(\"Filling description entries from trigger menu for global trigger %p.\", this);" << endl;
382   }
383   for (UInt_t i = 0; i < menu->NumberOfItems(); i++)
384   {
385     code << "    fMenuItemDescription" << i << " = (menu.Item(" << i
386          << ") != NULL) ? menu.Item(" << i << ")->Description() : \"\";" << endl;
387   }
388   if (fDebugMode)
389   {
390     code << "    HLTDebug(\"Finished filling description entries from trigger menu.\");" << endl;
391     code << "    HLTDebug(\"Filling domain entries from trigger menu symbols for global trigger %p.\", this);" << endl;
392   }
393   code << "    for (Int_t i = 0; i < menu.SymbolArray().GetEntriesFast(); i++) {" << endl;
394   code << "      const AliHLTTriggerMenuSymbol* symbol = dynamic_cast<const"
395            " AliHLTTriggerMenuSymbol*>(menu.SymbolArray().UncheckedAt(i));" << endl;
396   code << "      if (symbol == NULL) continue;" << endl;
397   for (Int_t i = 0; i < symbols.GetEntriesFast(); i++)
398   {
399     AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) );
400     code << "      if (strcmp(symbol->Name(), \"" << symbol->Name() << "\") == 0) {" << endl;
401     if (fDebugMode)
402     {
403       code << "        HLTDebug(\"Assinging domain entry value to match for symbol '%s' to '%s'.\","
404               " symbol->Name(), symbol->BlockType().AsString().Data());" << endl;
405     }
406     code << "        " << symbol->Name() << "DomainEntry = symbol->BlockType();" << endl;
407     code << "        continue;" << endl;
408     code << "      }" << endl;
409   }
410   code << "    }" << endl;
411   if (fDebugMode)
412   {
413     code << "    HLTDebug(\"Finished filling domain entries from trigger menu symbols.\");" << endl;
414   }
415   code << "  }" << endl;
416   
417   // Generate the NewEvent method.
418   code << "  virtual void NewEvent() {" << endl;
419   if (fDebugMode)
420   {
421     code << "    HLTDebug(\"New event for global trigger object %p, initialising variables to default values.\", this);" << endl;
422   }
423   // Write code to initialise the symbols in the trigger menu to their default values.
424   for (Int_t i = 0; i < symbols.GetEntriesFast(); i++)
425   {
426     AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) );
427     code << "    " << symbol->Name() << " = " << symbol->DefaultValue() << ";" << endl;
428     if (strcmp(symbol->ObjectClass(), "AliHLTTriggerDecision") == 0)
429     {
430       code << "    " << symbol->Name() << "TriggerDomain.Clear();" << endl;
431     }
432   }
433   if (fDebugMode)
434   {
435     code << "    HLTDebug(\"Finished initialising variables.\");" << endl;
436   }
437   code << "  }" << endl;
438   
439   // Generate the Add method.
440   code << "  virtual void Add(const TObject* _object_, const AliHLTComponentDataType& _type_, AliHLTUInt32_t _spec_) {" << endl;
441   code << "    AliHLTDomainEntry _type_spec_(_type_, _spec_);" << endl;
442   if (fDebugMode)
443   {
444     code << "    HLTDebug(\"Adding TObject %p, with class name '%s' from data block"
445             " '%s', to global trigger object %p\", _object_, _object_->ClassName(),"
446             " _type_spec_.AsString().Data(), this);" << endl;
447     code << "    _object_->Print();" << endl;
448     code << "    bool _object_assigned_ = false;" << endl;
449   }
450   for (Int_t i = 0; i < symbols.GetEntriesFast(); i++)
451   {
452     // Write code to check if the block type, specification and class name is correct.
453     // Then write code to assign the variable from the input object.
454     AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) );
455     TString expr = symbol->AssignExpression();
456     if (expr == "") continue; // Skip entries that have no assignment expression.
457     bool isTrigDecision = strcmp(symbol->ObjectClass(), "AliHLTTriggerDecision") == 0;
458     if (fDebugMode)
459     {
460       if (isTrigDecision)
461       {
462         code << "    HLTDebug(\"Trying to match input object to class '"
463              << symbol->ObjectClass() << "', trigger name '" << symbol->Name()
464              << "' and block type '%s'\", " << symbol->Name()
465              << "DomainEntry.AsString().Data());" << endl;
466       }
467       else
468       {
469         code << "    HLTDebug(\"Trying to match input object to class '"
470              << symbol->ObjectClass() << "' and block type '%s'\", "
471              << symbol->Name() << "DomainEntry.AsString().Data());" << endl;
472       }
473     }
474     code << "    const " << symbol->ObjectClass() << "* " << symbol->Name()
475          << "_object_ = dynamic_cast<const " << symbol->ObjectClass()
476          << "*>(_object_);" << endl;
477     code << "    if (" << symbol->Name() << "_object_ != NULL and ";
478     if (isTrigDecision)
479     {
480       code << "strcmp(" << symbol->Name() << "_object_->Name(), \""
481            << symbol->Name() << "\") == 0 and ";
482     }
483     code << symbol->Name() << "DomainEntry == _type_spec_) {" << endl;
484     TString fullname = symbol->Name();
485     fullname += "_object_";
486     expr.ReplaceAll("this", fullname);
487     code << "      this->" << symbol->Name() << " = " << expr.Data() << ";" << endl;
488     if (isTrigDecision)
489     {
490       code << "      this->" << symbol->Name() << "TriggerDomain = "
491            << fullname.Data() << "->TriggerDomain();" << endl;
492     }
493     if (fDebugMode)
494     {
495       code << "      HLTDebug(\"Added TObject %p with class name '%s' to variable "
496            << symbol->Name() << "\", _object_, _object_->ClassName());" << endl;
497       code << "      _object_assigned_ = true;" << endl;
498     }
499     code << "    }" << endl;
500   }
501   if (fDebugMode)
502   {
503     code << "    if (not _object_assigned_) HLTDebug(\"Did not assign TObject %p"
504             " with class name '%s' to any variable.\", _object_, _object_->ClassName());"
505          << endl;
506   }
507   code << "  }" << endl;
508   
509   // Generate the CalculateTriggerDecision method.
510   code << "  virtual bool CalculateTriggerDecision(AliHLTTriggerDomain& _domain_, TString& _description_) {" << endl;
511   if (fDebugMode)
512   {
513     code << "    HLTDebug(\"Calculating global HLT trigger result with trigger object at %p.\", this);" << endl;
514   }
515   for (UInt_t i = 0; i < menu->NumberOfItems(); i++)
516   {
517     const AliHLTTriggerMenuItem* item = menu->Item(i);
518     TString mergeExpr = item->MergeExpression();
519     for (Int_t j = 0; j < symbols.GetEntriesFast(); j++)
520     {
521       AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(j) );
522       if (strcmp(symbol->ObjectClass(), "AliHLTTriggerDecision") != 0) continue;
523       TString newname = symbol->Name();
524       newname += "TriggerDomain";
525       mergeExpr.ReplaceAll(symbol->Name(), newname);
526     }
527     if (fDebugMode)
528     {
529       code << "    HLTDebug(\"Trying trigger condition " << i
530            << " (Description = '%s').\", fMenuItemDescription" << i << ".Data());"
531            << endl;
532     }
533     code << "    if (" << item->TriggerCondision() << ") {" << endl;
534     code << "      IncrementCounter(" << i << ");" << endl;
535     const char* indentation = "";
536     if (item->PreScalar() != 0)
537     {
538       indentation = "  ";
539       code << "      if ((GetCounter(" << i << ") % " << item->PreScalar() << ") == 1) {" << endl;
540     }
541     code << indentation << "      _domain_ = " << mergeExpr.Data() << ";" << endl;
542     code << indentation << "      _description_ = fMenuItemDescription" << i << ";" << endl;
543     if (fDebugMode)
544     {
545       code << indentation << "      HLTDebug(\"Matched trigger condition " << i
546            << " (Description = '%s').\", fMenuItemDescription" << i << ".Data());" << endl;
547     }
548     code << indentation << "      return true;" << endl;
549     if (item->PreScalar() != 0)
550     {
551       code << "      }" << endl;
552     }
553     code << "    }" << endl;
554   }
555   code << "    return false;" << endl;
556   code << "  }" << endl;
557   
558   // Generate the custom Factory class.
559   code << "  class FactoryImpl : public AliHLTGlobalTrigger::Factory" << endl;
560   code << "  {" << endl;
561   code << "  public:" << endl;
562   code << "    virtual const char* ClassName() const {" << endl;
563   code << "      return \"" << name << "\";" << endl;
564   code << "    }" << endl;
565   code << "    virtual AliHLTGlobalTrigger* New() const {" << endl;
566   code << "      return new " << name << "();" << endl;
567   code << "    }" << endl;
568   code << "  };" << endl;
569   
570   code << "private:" << endl;
571   // Add the symbols in the trigger menu to the list of private variables.
572   for (Int_t i = 0; i < symbols.GetEntriesFast(); i++)
573   {
574     AliHLTTriggerMenuSymbol* symbol = static_cast<AliHLTTriggerMenuSymbol*>( symbols.UncheckedAt(i) );
575     code << "  " << symbol->Type() << " " << symbol->Name() << ";" << endl;
576     if (strcmp(symbol->ObjectClass(), "AliHLTTriggerDecision") == 0)
577     {
578       code << "  AliHLTTriggerDomain " << symbol->Name() << "TriggerDomain;" << endl;
579     }
580     code << "  AliHLTDomainEntry " << symbol->Name() << "DomainEntry;" << endl;
581   }
582   for (UInt_t i = 0; i < menu->NumberOfItems(); i++)
583   {
584     code << "  TString fMenuItemDescription" << i << ";" << endl;
585   }
586   code << "};" << endl;
587   
588   // Write a global object for the Factory class for automatic registration.
589   code << "namespace {" << endl;
590   code << "  const " << name << "::FactoryImpl gkFactoryImpl;" << endl;
591   code << "};" << endl;
592   
593   code.close();
594   
595   // Now we need to compile and load the new class.
596   result = LoadTriggerClass(filename, includePaths);
597   return result;
598 }
599
600
601 int AliHLTGlobalTriggerComponent::LoadTriggerClass(
602     const char* filename, const TClonesArray& includePaths
603   )
604 {
605   // Loads the code for a custom global trigger class implementation on the fly.
606   
607   TString compiler = gSystem->GetBuildCompilerVersion();
608   if (compiler.Contains("gcc") or compiler.Contains("icc"))
609   {
610     TString includePath = "-I${ALICE_ROOT}/include -I${ALICE_ROOT}/HLT/BASE -I${ALICE_ROOT}/HLT/trigger";
611     // Add any include paths that were specified on the command line.
612     for (Int_t i = 0; i < includePaths.GetEntriesFast(); i++)
613     {
614       TString path = static_cast<const TObjString*>(includePaths.UncheckedAt(i))->String();
615       includePath += " ";
616       includePath += path;
617     }
618     gSystem->SetIncludePath(includePath);
619     gSystem->SetFlagsOpt("-O3 -DNDEBUG");
620     gSystem->SetFlagsDebug("-g3 -DDEBUG -D__DEBUG");
621     
622     int result = kTRUE;
623     if (fDebugMode)
624     {
625       result = gSystem->CompileMacro(filename, "g");
626     }
627     else
628     {
629       result = gSystem->CompileMacro(filename, "O");
630     }
631     if (result != kTRUE)
632     {
633       HLTFatal("Could not compile and load global trigger menu implementation.");
634       return -ENOENT;
635     }
636   }
637   else
638   {
639     // If we do not support the compiler then try interpret the class instead.
640     TString cmd = ".L ";
641     cmd += filename;
642     Int_t errorcode = TInterpreter::kNoError;
643     gROOT->ProcessLine(cmd, &errorcode);
644     if (errorcode != TInterpreter::kNoError)
645     {
646       HLTFatal("Could not load interpreted global trigger menu implementation"
647                " (Interpreter error code = %d).",
648                errorcode
649       );
650       return -ENOENT;
651     }
652   }
653   
654   return 0;
655 }
656
657
658 int AliHLTGlobalTriggerComponent::FindSymbol(const char* name, const TClonesArray& list)
659 {
660   // Searches for the named symbol in the given list.
661   // See header for more details.
662   
663   for (int i = 0; i < list.GetEntriesFast(); i++)
664   {
665     const AliHLTTriggerMenuSymbol* symbol = dynamic_cast<const AliHLTTriggerMenuSymbol*>( list.UncheckedAt(i) );
666     if (symbol == NULL) continue;
667     if (strcmp(symbol->Name(), name) == 0) return i;
668   }
669   return -1;
670 }
671
672
673 int AliHLTGlobalTriggerComponent::BuildSymbolList(const AliHLTTriggerMenu* menu, TClonesArray& list)
674 {
675   // Builds the list of symbols to use in the custom global trigger menu
676   // implementation class.
677   // See header for more details.
678   
679   for (UInt_t i = 0; i < menu->NumberOfSymbols(); i++)
680   {
681     const AliHLTTriggerMenuSymbol* symbol = menu->Symbol(i);
682     if (FindSymbol(symbol->Name(), list) != -1)
683     {
684       HLTError("Multiple symbols with the name '%s' defined in the trigger menu.", symbol->Name());
685       return -EIO;
686     }
687     new (list[list.GetEntriesFast()]) AliHLTTriggerMenuSymbol(*symbol);
688   }
689   
690   TRegexp exp("[_a-zA-Z][_a-zA-Z0-9]*");
691   for (UInt_t i = 0; i < menu->NumberOfItems(); i++)
692   {
693     const AliHLTTriggerMenuItem* item = menu->Item(i);
694     TString str = item->TriggerCondision();
695     Ssiz_t start = 0;
696     do
697     {
698       Ssiz_t length = 0;
699       Ssiz_t pos = exp.Index(str, &length, start);
700       if (pos == kNPOS) break;
701       TString s = str(pos, length);
702       start = pos+length;
703       
704       if (s == "and" or s == "and_eq" or s == "bitand" or s == "bitor" or
705           s == "compl" or s == "not" or s == "not_eq" or s == "or" or
706           s == "or_eq" or s == "xor" or s == "xor_eq" or s == "true" or
707           s == "false"
708          )
709       {
710         // Ignore iso646.h and other keywords.
711         continue;
712       }
713       
714       if (FindSymbol(s.Data(), list) == -1)
715       {
716         AliHLTTriggerMenuSymbol newSymbol;
717         newSymbol.Name(s.Data());
718         newSymbol.Type("bool");
719         newSymbol.ObjectClass("AliHLTTriggerDecision");
720         newSymbol.AssignExpression("this->Result()");
721         newSymbol.DefaultValue("false");
722         new (list[list.GetEntriesFast()]) AliHLTTriggerMenuSymbol(newSymbol);
723       }
724     }
725     while (start < str.Length());
726   }
727   
728   return 0;
729 }
730