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