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