e720c87c961be8162d301e276921e1f9a25ee863
[u/mrichter/AliRoot.git] / HLT / MUON / utils / dHLTdumpraw.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-2007, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author:                                                                *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 /**
19  * @file   dHLTdumpraw.cxx
20  * @author Artur Szostak <artursz@iafrica.com>,
21  *         Seforo Mohlalisi <seforomohlalisi@yahoo.co.uk>
22  * @date   
23  * @brief  Command line utility to dump dHLT's internal raw data blocks.
24  */
25
26 // We define NDEBUG for the AliHLTMUONDataBlockReader.h header file since this
27 // program by definition handles corrupt data. So we do not need the assertions
28 // in the AliHLTMUONDataBlockReader class to be checked.
29 #define NDEBUG
30 #include "AliHLTMUONDataBlockReader.h"
31 #undef NDEBUG
32 #include "AliHLTMUONUtils.h"
33
34 /*TODO: fix this. Need a platform independant way of checking the endian encoding.
35  * This does not want to work on Apple Mac OS compiler: i686-apple-darw
36 #include <endian.h>
37 #ifndef LITTLE_ENDIAN
38 #error Handling of internal data for non little endian machines not yet implemented.
39 #endif
40 */
41
42 #include <cstdlib>
43 #include <cassert>
44 #include <new>
45 #include <fstream>
46
47 #include <iostream>
48 using std::cout;
49 using std::cerr;
50 using std::endl;
51 using std::showbase;
52 using std::noshowbase;
53 using std::hex;
54 using std::dec;
55
56 #include <iomanip>
57 using std::setw;
58 using std::left;
59 using std::internal;
60
61
62 #define CMDLINE_ERROR 1
63 #define PARSE_ERROR 2
64 #define SYSTEM_ERROR 3
65 #define FATAL_ERROR 4
66
67
68 void PrintRubbishData(AliHLTUInt32_t offset, const char* padByte, AliHLTUInt32_t padCount)
69 {
70         if (padCount == 0) return;
71         
72         cerr << "ERROR: Found the following unexpected rubbish data at the"
73                 " end of the data block:" << endl;
74         cerr << "Byte #\tValue\tCharacter" << endl;
75         for (AliHLTUInt32_t i = 0; i < padCount; i++)
76         {
77                 short value = short(padByte[i]) & 0xFF;
78                 char character = padByte[i];
79                 cerr << offset + i + 1 << "\t"
80                         << noshowbase << hex << "0x" << value << dec << "\t"
81                         << character << endl;
82         }
83 }
84
85
86 template <typename FieldType>
87 int CheckHeaderField(
88                 FieldType& field, const char* buffer, unsigned long bufferSize,
89                 bool continueParse
90         )
91 {
92         const char* fieldptr = reinterpret_cast<const char*>(&field);
93         const char* endptr = buffer + bufferSize;
94         AliHLTUInt32_t bufferRemaining = endptr > fieldptr ? endptr - fieldptr : 0;
95         
96         if (bufferRemaining < sizeof(field))
97         {
98                 cout << "..." << endl; // We may be half way through printing a line so end it.
99                 cerr << "ERROR: The data block is too short. The header is corrupt." << endl;
100                 if (continueParse)
101                 {
102                         AliHLTUInt32_t offset = fieldptr - buffer;
103                         PrintRubbishData(offset, fieldptr, bufferRemaining);
104                 }
105                 return PARSE_ERROR;
106         }
107         return EXIT_SUCCESS;
108 }
109
110
111 template <typename FieldType>
112 int CheckField(
113                 FieldType& field, const char* buffer, unsigned long bufferSize,
114                 bool continueParse
115         )
116 {
117         const char* fieldptr = reinterpret_cast<const char*>(&field);
118         const char* endptr = buffer + bufferSize;
119         AliHLTUInt32_t bufferRemaining = endptr > fieldptr ? endptr - fieldptr : 0;
120         
121         if (bufferRemaining < sizeof(field))
122         {
123                 cout << "..." << endl; // We may be half way through printing a line so end it.
124                 cerr << "ERROR: The data block is too short. The data is corrupt." << endl;
125                 if (continueParse)
126                 {
127                         AliHLTUInt32_t offset = fieldptr - buffer;
128                         PrintRubbishData(offset, fieldptr, bufferRemaining);
129                 }
130                 return PARSE_ERROR;
131         }
132         return EXIT_SUCCESS;
133 }
134
135
136 template <typename BlockType>
137 int CheckCommonHeader(
138                 BlockType& block, const char* buffer, unsigned long bufferSize,
139                 bool continueParse
140         )
141 {
142         int result = EXIT_SUCCESS;
143
144         // Check the fRecordWidth field in the common header.
145         if (block.CommonBlockHeader().fRecordWidth !=
146                 sizeof(typename BlockType::ElementType))
147         {
148                 cerr << "ERROR: The record width found in the header is incorrect."
149                         " Found a record width of "
150                         << block.CommonBlockHeader().fRecordWidth << " bytes, but expected"
151                         " a value of " << sizeof(typename BlockType::ElementType)
152                         << " bytes." << endl;
153                 result = PARSE_ERROR;
154                 if (not continueParse) return result;
155         }
156         
157         if (not block.BufferSizeOk())
158         {
159                 cerr << "ERROR: The size of the file is incorrect. It is "
160                         << bufferSize << " bytes big, but according"
161                         " to the data block header it should be " << block.BytesUsed()
162                         << " bytes." << endl;
163                 result = PARSE_ERROR;
164                 if (not continueParse) return result;
165         }
166         
167         return result;
168 }
169
170
171 template <typename BlockType>
172 AliHLTUInt32_t CalculateNEntries(BlockType& block, unsigned long bufferSize)
173 {
174         // Calculate how many entries we can display. If the buffer size is correct
175         // we just use the number of entries the block specifies. Otherwise we need
176         // to calculate it from the buffer size.
177         AliHLTUInt32_t nentries;
178         if (block.BytesUsed() == bufferSize)
179         {
180                 nentries = block.Nentries();
181         }
182         else
183         {
184                 AliHLTInt32_t dataSize = bufferSize
185                         - sizeof(typename BlockType::HeaderType);
186                 nentries = dataSize / sizeof(typename BlockType::ElementType);
187                 if (dataSize % sizeof(typename BlockType::ElementType) > 0)
188                         nentries++;
189         }
190         return nentries;
191 }
192
193
194 int DumpRecHitStruct(
195                 const char* buffer, unsigned long bufferSize,
196                 const AliHLTMUONRecHitStruct* hit,
197                 bool continueParse
198         )
199 {
200         // Step through the fields trying to print them.
201         // At each step check if we have not overflowed the buffer. If we have
202         // not, then we can print the field, otherwise we print the left over
203         // bytes assumed to be corrupted rubbish.
204         int result = CheckField(hit->fX, buffer, bufferSize, continueParse);
205         if (result != EXIT_SUCCESS) return result;
206         cout << setw(13) << left << hit->fX << setw(0);
207
208         result = CheckField(hit->fY, buffer, bufferSize, continueParse);
209         if (result != EXIT_SUCCESS) return result;
210         cout << setw(13) << left << hit->fY << setw(0);
211
212         result = CheckField(hit->fZ, buffer, bufferSize, continueParse);
213         if (result != EXIT_SUCCESS) return result;
214         cout << hit->fZ << setw(0) << endl;
215
216         return result;
217 }
218
219
220 int DumpRecHitsBlock(
221                 const char* buffer, unsigned long bufferSize,
222                 bool continueParse
223         )
224 {
225         int result = EXIT_SUCCESS;
226         AliHLTMUONRecHitsBlockReader block(buffer, bufferSize);
227         
228         result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
229         if (result != EXIT_SUCCESS and not continueParse) return result;
230         
231         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
232         
233         // Print the data block record entries.
234         cout << " X (cm)     | Y (cm)     | Z (cm)" << endl;
235         cout << "---------------------------------------" << endl;
236         const AliHLTMUONRecHitStruct* entry = block.GetArray();
237         for(AliHLTUInt32_t i = 0; i < nentries; i++)
238         {
239                 int subResult = DumpRecHitStruct(buffer, bufferSize, entry++, continueParse);
240                 if (subResult != EXIT_SUCCESS) return subResult;
241         }
242         
243         return result;
244 }
245
246
247 int DumpTriggerRecordStruct(
248                const char* buffer, unsigned long bufferSize, 
249                const AliHLTMUONTriggerRecordStruct* record,
250                bool continueParse
251        )
252 {
253         // Step through the fields trying to print them.
254         // At each step check if we have not overflowed the buffer. If we have
255         // not, then we can print the field, otherwise we print the left over
256         // bytes assumed to be corrupted rubbish.
257         int result = CheckField(record->fId, buffer, bufferSize, continueParse);
258         if (result != EXIT_SUCCESS) return result;
259         cout << "Trigger Record ID: " << record->fId <<endl;
260         
261         result = CheckField(record->fFlags, buffer, bufferSize, continueParse);
262         if (result != EXIT_SUCCESS) return result;
263         cout << "Flags: " << showbase << hex << record->fFlags << dec;
264                 
265         // Print the individual trigger bits.
266         AliHLTMUONParticleSign sign;
267         bool hitset[4];
268         AliHLTMUONUtils::UnpackTriggerRecordFlags(record->fFlags, sign, hitset);
269         cout << " [Sign: " << sign << ", Hits set on chambers: ";
270         bool first = true;
271         for (AliHLTUInt32_t i = 0; i < 4; i++)
272         {
273                 if (hitset[i])
274                 {
275                         cout << (first ? "" : ", ") << i+11;
276                         first = false;
277                 }
278         }
279         cout << (first ? "none]" : "]") << endl;
280
281         result = CheckField(record->fPx, buffer, bufferSize, continueParse);
282         if (result != EXIT_SUCCESS) return result;
283         cout << "Momentum: (px = " << record->fPx << ", ";
284
285         result = CheckField(record->fPy, buffer, bufferSize, continueParse);
286         if (result != EXIT_SUCCESS) return result;
287         cout << "py = " << record->fPy << ", ";
288
289         result = CheckField(record->fPz, buffer, bufferSize, continueParse);
290         if (result != EXIT_SUCCESS) return result;
291         cout << "pz = " << record->fPz << ") GeV/c"<<endl;
292         
293         cout << "Track hits:" << endl;
294         cout << "Chamber | X (cm)     | Y (cm)     | Z (cm)" << endl;
295         cout << "------------------------------------------------" << endl;
296         const AliHLTMUONRecHitStruct* hit = &record->fHit[0];
297         for(AliHLTUInt32_t ch = 0; ch < 4; ch++)
298         {
299                 cout << setw(10) << left << ch + 11 << setw(0);
300                 result = DumpRecHitStruct(buffer, bufferSize, hit++, continueParse);
301                 if (result != EXIT_SUCCESS) return result;
302         }
303
304         return result;
305
306 }
307
308
309 int DumpTriggerRecordsBlock(
310                 const char* buffer, unsigned long bufferSize,
311                 bool continueParse
312         )
313 {
314         AliHLTMUONTriggerRecordsBlockReader block(buffer, bufferSize);
315         
316         int result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
317         if (result != EXIT_SUCCESS and not continueParse) return result;
318         
319         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
320         
321         // Print the data block record entries.
322         const AliHLTMUONTriggerRecordStruct* entry = block.GetArray();
323         for(AliHLTUInt32_t i = 0; i < nentries; i++)
324         {
325                 cout << "============================== Trigger Record number " << i+1
326                         << " of " << nentries << " ==============================" << endl;
327                 int subResult = DumpTriggerRecordStruct(buffer, bufferSize, entry++, continueParse);
328                 if (subResult != EXIT_SUCCESS) return subResult;
329         }
330         
331         return EXIT_SUCCESS;
332 }
333
334
335 int DumpTrigRecInfoStruct(const char* buffer, unsigned long bufferSize, 
336                           const AliHLTMUONTrigRecInfoStruct* debuginfo, 
337                           bool continueParse
338                           )
339 {
340         // Step through the fields trying to print them.
341         // At each step check if we have not overflowed the buffer. If we have
342         // not, then we can print the field, otherwise we print the left over
343         // bytes assumed to be corrupted rubbish.
344         int result = CheckField(debuginfo->fTrigRecId, buffer, bufferSize, continueParse);
345         if (result != EXIT_SUCCESS) return result;
346         cout << setw(22) << left << debuginfo->fTrigRecId << setw(0);
347
348         result = CheckField(debuginfo->fDetElemId, buffer, bufferSize, continueParse);
349         if (result != EXIT_SUCCESS) return result;
350         cout << setw(20) << left << debuginfo->fDetElemId << setw(0);
351         
352         result = CheckField(debuginfo->fZmiddle, buffer, bufferSize, continueParse);
353         if(result != EXIT_SUCCESS) return result;
354         cout << setw(30) << left << debuginfo->fZmiddle << setw(0);
355
356         result = CheckField(debuginfo->fBl, buffer, bufferSize, continueParse);
357         if (result != EXIT_SUCCESS) return result;
358         cout <<debuginfo->fBl << setw(0) << endl;
359
360         return result;
361 }
362
363
364 int DumpTrigRecsDebugBlock(
365                 const char* buffer, unsigned long bufferSize,
366                 bool continueParse
367         )
368 {
369         AliHLTMUONTrigRecsDebugBlockReader block(buffer, bufferSize);
370         
371         int result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
372         if (result != EXIT_SUCCESS and not continueParse) return result;
373         
374         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
375         
376         // Print the data block record entries.
377         cout << "Trigger Record ID  | Detector ID  | Momentum X Component (Gev/c) | Integrated Magnetic Field (T.m)" << endl;
378         cout << "--------------------------------------------------------------------------------------------------" << endl;
379         const AliHLTMUONTrigRecInfoStruct* entry = block.GetArray();
380         for(AliHLTUInt32_t i = 0; i < nentries; i++)
381         {
382                 int subResult = DumpTrigRecInfoStruct(buffer, bufferSize, entry++, continueParse);
383                 if (subResult != EXIT_SUCCESS) return subResult;
384         }
385         
386         return EXIT_SUCCESS;
387 }
388
389
390 int DumpTriggerChannelStruct(const char* buffer, unsigned long bufferSize, 
391                       const AliHLTMUONTriggerChannelStruct* triggerchannel, 
392                       bool continueParse
393                       )
394 {
395         // Step through the fields trying to print them.
396         // At each step check if we have not overflowed the buffer. If we have
397         // not, then we can print the field, otherwise we print the left over
398         // bytes assumed to be corrupted rubbish.
399         int result = CheckField(triggerchannel->fTrigRecId, buffer, bufferSize, continueParse);
400         if (result != EXIT_SUCCESS) return result;
401         cout << setw(25) << left << triggerchannel->fTrigRecId << setw(0);
402
403         result = CheckField(triggerchannel->fChamber, buffer, bufferSize, continueParse);
404         if (result != EXIT_SUCCESS) return result;
405         cout << setw(13) << left << triggerchannel->fChamber << setw(0);
406
407         result = CheckField(triggerchannel->fSignal, buffer, bufferSize, continueParse);
408         if (result != EXIT_SUCCESS) return result;
409         cout << setw(10) << left << triggerchannel->fSignal << setw(0);
410
411         result = CheckField(triggerchannel->fRawDataWord, buffer, bufferSize, continueParse);
412         if(result != EXIT_SUCCESS) return result;
413         cout << showbase << hex << triggerchannel->fRawDataWord << dec << setw(0) << endl;
414         return result;
415 }
416
417
418 int DumpTriggerChannelsBlock(
419                 const char* buffer, unsigned long bufferSize,
420                 bool continueParse
421         )
422 {
423         int result = EXIT_SUCCESS;
424         AliHLTMUONTriggerChannelsBlockReader block(buffer, bufferSize);
425         
426         result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
427         if (result != EXIT_SUCCESS and not continueParse) return result;
428         
429         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
430         
431         // Print the data block record entries.
432         cout << " Trigger Record ID   | Chamber    | Signal   | Raw Data Word " << endl;
433         cout << "--------------------------------------------------------------" << endl;
434         const AliHLTMUONTriggerChannelStruct* entry = block.GetArray();
435         for(AliHLTUInt32_t i = 0; i < nentries; i++)
436         {
437                 int subResult = DumpTriggerChannelStruct(buffer, bufferSize, entry++, continueParse);
438                 if (subResult != EXIT_SUCCESS) return subResult;
439         }
440
441         return result;
442 }
443
444
445 int DumpClusterStruct(
446                       const char* buffer, unsigned long bufferSize,
447                       const AliHLTMUONClusterStruct* cluster,
448                       bool continueParse
449        )
450 {
451         // Step through the fields trying to print them.
452         // At each step check if we have not overflowed the buffer. If we have
453         // not, then we can print the field, otherwise we print the left over
454         // bytes assumed to be corrupted rubbish.
455         int result = CheckField(cluster->fId, buffer, bufferSize, continueParse);
456         if (result != EXIT_SUCCESS) return result;
457         cout << "cluster->fId: " << cluster->fId << "\t";
458
459         result = CheckField(cluster->fDetElemId, buffer, bufferSize, continueParse);
460         if (result != EXIT_SUCCESS) return result;
461         cout << "cluster->fDetElemId: " << cluster->fDetElemId << "\t";
462
463         result = CheckField(cluster->fNchannels, buffer, bufferSize, continueParse);
464         if(result != EXIT_SUCCESS) return result;
465         cout << "cluster->fNchannels: " << cluster->fNchannels <<endl;
466
467         cout << " Corresponding Hit: "<< endl;
468         cout << " X (cm)     | Y (cm)     | Z (cm)" << endl;
469         cout << "---------------------------------------" << endl;
470         const AliHLTMUONRecHitStruct * hit = & cluster->fHit;
471         result = DumpRecHitStruct(buffer, bufferSize, hit, continueParse);
472
473         return result;
474 }
475
476
477 int DumpClustersBlock(
478                 const char* buffer, unsigned long bufferSize,
479                 bool continueParse
480         )
481 {
482         int result = EXIT_SUCCESS;
483         AliHLTMUONClustersBlockReader block(buffer, bufferSize);
484         
485         result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
486         if (result != EXIT_SUCCESS and not continueParse) return result;
487         
488         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
489         
490         // Print the data block record entries.
491         const AliHLTMUONClusterStruct* entry = block.GetArray();
492         for(AliHLTUInt32_t i = 0; i < nentries; i++)
493         {
494                 cout << " ===================================================== Cluster Number "
495                         << i+1 << "==================================================" << endl; 
496                 int subResult = DumpClusterStruct(buffer, bufferSize, entry++, continueParse);
497                 if (subResult != EXIT_SUCCESS) return subResult;
498         }       
499
500         return result;
501 }
502
503
504 int DumpChannelStruct(
505                const char* buffer, unsigned long bufferSize,
506                const AliHLTMUONChannelStruct* channel,
507                bool continueParse                 
508        )
509 {
510         // Step through the fields trying to print them.
511         // At each step check if we have not overflowed the buffer. If we have
512         // not, then we can print the field, otherwise we print the left over
513         // bytes assumed to be corrupted rubbish.
514         int result = CheckField(channel->fClusterId, buffer, bufferSize, continueParse);
515         if (result != EXIT_SUCCESS) return result;
516         cout << setw(16) << left << channel->fClusterId << setw(0);
517
518         result = CheckField(channel->fManu, buffer, bufferSize, continueParse);
519         if (result != EXIT_SUCCESS) return result;
520         cout << setw(16) << left << channel->fManu << setw(0);
521
522         result = CheckField(channel->fChannelAddress, buffer, bufferSize, continueParse);
523         if (result != EXIT_SUCCESS) return result;
524         cout << setw(19) << left << channel->fChannelAddress << setw(0);
525
526         result = CheckField(channel->fSignal, buffer, bufferSize, continueParse);
527         if(result != EXIT_SUCCESS) return result;
528         cout << setw(16) << left << channel->fSignal << setw(0);
529
530         result = CheckField(channel->fRawDataWord, buffer, bufferSize, continueParse);
531         if(result != EXIT_SUCCESS) return result;
532         cout << showbase << hex << channel->fRawDataWord << dec << setw(0) <<endl;
533
534         return result;
535 }
536
537
538 int DumpChannelsBlock(
539                 const char* buffer, unsigned long bufferSize,
540                 bool continueParse
541         )
542 {
543         int result = EXIT_SUCCESS;
544         AliHLTMUONChannelsBlockReader block(buffer, bufferSize);
545         
546         result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
547         if (result != EXIT_SUCCESS and not continueParse) return result;
548         
549         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
550         
551         // Print the data block record entries.
552         cout << "Cluster Id  | Manu Address  | Channel Address  | Signal Value  | Raw Data Word " <<endl;
553         cout << "-------------------------------------------------------------------------------" <<endl;
554         const AliHLTMUONChannelStruct* entry = block.GetArray();
555         for(AliHLTUInt32_t i = 0; i < nentries; i++)
556         { 
557                 int subResult = DumpChannelStruct(buffer, bufferSize, entry++, continueParse);
558                 if (subResult != EXIT_SUCCESS) return subResult;
559         }
560         return EXIT_SUCCESS;
561 }
562
563
564 int DumpMansoTrackStruct(
565                 const char* buffer, unsigned long bufferSize,
566                 const AliHLTMUONMansoTrackStruct* track,
567                 bool continueParse
568         )
569 {
570         // Step through the fields trying to print them.
571         // At each step check if we have not overflowed the buffer. If we have
572         // not, then we can print the field, otherwise we print the left over
573         // bytes assumed to be corrupted rubbish.
574         int result = CheckField(track->fId, buffer, bufferSize, continueParse);
575         if (result != EXIT_SUCCESS) return result;
576         cout << "Track ID: " << track->fId << "\t";
577
578         result = CheckField(track->fTrigRec, buffer, bufferSize, continueParse);
579         if (result != EXIT_SUCCESS) return result;
580         cout << "Trigger Record ID: " << track->fTrigRec << endl;
581         
582         result = CheckField(track->fFlags, buffer, bufferSize, continueParse);
583         if (result != EXIT_SUCCESS) return result;
584         cout << "Flags: " << showbase << hex << track->fFlags << dec;
585         
586         // Print the individual trigger bits.
587         AliHLTMUONParticleSign sign;
588         bool hitset[4];
589         AliHLTMUONUtils::UnpackMansoTrackFlags(track->fFlags, sign, hitset);
590         cout << " [Sign: " << sign << ", Hits set on chambers: ";
591         bool first = true;
592         for (AliHLTUInt32_t i = 0; i < 4; i++)
593         {
594                 if (hitset[i])
595                 {
596                         cout << (first ? "" : ", ") << i+7;
597                         first = false;
598                 }
599         }
600         cout << (first ? "none]" : "]") << endl;
601
602         result = CheckField(track->fPx, buffer, bufferSize, continueParse);
603         if (result != EXIT_SUCCESS) return result;
604         cout << "Momentum: (px = " << track->fPx << ", ";
605
606         result = CheckField(track->fPy, buffer, bufferSize, continueParse);
607         if (result != EXIT_SUCCESS) return result;
608         cout << "py = " << track->fPy << ", ";
609
610         result = CheckField(track->fPz, buffer, bufferSize, continueParse);
611         if (result != EXIT_SUCCESS) return result;
612         cout << "pz = " << track->fPz << ") GeV/c\t";
613
614         result = CheckField(track->fChi2, buffer, bufferSize, continueParse);
615         if (result != EXIT_SUCCESS) return result;
616         cout << "Chi squared fit: " << track->fChi2 << endl;
617         
618         cout << "Track hits:" << endl;
619         cout << "Chamber | X (cm)     | Y (cm)     | Z (cm)" << endl;
620         cout << "------------------------------------------------" << endl;
621         const AliHLTMUONRecHitStruct* hit = &track->fHit[0];
622         for(AliHLTUInt32_t ch = 0; ch < 4; ch++)
623         {
624                 cout << setw(10) << left << ch + 7 << setw(0);
625                 result = DumpRecHitStruct(buffer, bufferSize, hit++, continueParse);
626                 if (result != EXIT_SUCCESS) return result;
627         }
628
629         return result;
630 }
631
632
633 int DumpMansoTracksBlock(
634                 const char* buffer, unsigned long bufferSize,
635                 bool continueParse
636         )
637 {
638         int result = EXIT_SUCCESS;
639         AliHLTMUONMansoTracksBlockReader block(buffer, bufferSize);
640         
641         result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
642         if (result != EXIT_SUCCESS and not continueParse) return result;
643         
644         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
645         
646         // Print the data block record entries.
647         const AliHLTMUONMansoTrackStruct* entry = block.GetArray();
648         for(AliHLTUInt32_t i = 0; i < nentries; i++)
649         {
650                 cout << "============================== Manso track number " << i+1
651                         << " of " << nentries << " ==============================" << endl;
652                 int subResult = DumpMansoTrackStruct(buffer, bufferSize, entry++, continueParse);
653                 if (subResult != EXIT_SUCCESS) return subResult;
654         }
655         
656         return result;
657 }
658
659
660 int DumpMansoRoIStruct(
661                 const char* buffer, unsigned long bufferSize,
662                 const AliHLTMUONMansoRoIStruct* roi,
663                 bool continueParse
664         )
665 {
666         // Step through the fields trying to print them.
667         // At each step check if we have not overflowed the buffer. If we have
668         // not, then we can print the field, otherwise we print the left over
669         // bytes assumed to be corrupted rubbish.
670         int result = CheckField(roi->fX, buffer, bufferSize, continueParse);
671         if (result != EXIT_SUCCESS) return result;
672         cout << setw(13) << left << roi->fX << setw(0);
673
674         result = CheckField(roi->fY, buffer, bufferSize, continueParse);
675         if (result != EXIT_SUCCESS) return result;
676         cout << setw(13) << left << roi->fY << setw(0);
677
678         result = CheckField(roi->fZ, buffer, bufferSize, continueParse);
679         if (result != EXIT_SUCCESS) return result;
680         cout << setw(13) << left << roi->fZ << setw(0);
681
682         result = CheckField(roi->fRadius, buffer, bufferSize, continueParse);
683         if (result != EXIT_SUCCESS) return result;
684         cout << roi->fRadius << setw(0) << endl;
685
686         return result;
687 }
688
689
690 int DumpMansoCandidateStruct(
691                 const char* buffer, unsigned long bufferSize,
692                 const AliHLTMUONMansoCandidateStruct* candidate,
693                 bool continueParse
694         )
695 {
696         int result = DumpMansoTrackStruct(buffer, bufferSize, &candidate->fTrack, continueParse);
697         if (result != EXIT_SUCCESS) return result;
698         
699         cout << "Regions of interest:" << endl;
700         cout << "Chamber | X (cm)     | Y (cm)     | Z (cm)     | Radius (cm)" << endl;
701         cout << "-------------------------------------------------------------" << endl;
702         const AliHLTMUONMansoRoIStruct* roi = &candidate->fRoI[0];
703         for(AliHLTUInt32_t ch = 0; ch < 4; ch++)
704         {
705                 cout << setw(10) << ch + 7;
706                 result = DumpMansoRoIStruct(buffer, bufferSize, roi++, continueParse);
707                 if (result != EXIT_SUCCESS) return result;
708         }
709         return result;
710 }
711
712
713 int DumpMansoCandidatesBlock(
714                 const char* buffer, unsigned long bufferSize,
715                 bool continueParse
716         )
717 {
718         int result = EXIT_SUCCESS;
719         AliHLTMUONMansoCandidatesBlockReader block(buffer, bufferSize);
720         
721         result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
722         if (result != EXIT_SUCCESS and not continueParse) return result;
723         
724         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
725         
726         // Print the data block record entries.
727         const AliHLTMUONMansoCandidateStruct* entry = block.GetArray();
728         for(AliHLTUInt32_t i = 0; i < nentries; i++)
729         {
730                 cout << "=========================== Manso track candidate number " << i+1
731                         << " of " << nentries << " ===========================" << endl;
732                 int subResult = DumpMansoCandidateStruct(buffer, bufferSize, entry++, continueParse);
733                 if (subResult != EXIT_SUCCESS) return subResult;
734         }
735         
736         return result;
737 }
738
739
740 int DumpSinglesDecisionBlockHeader(
741                 const char* buffer, unsigned long bufferSize,
742                 const AliHLTMUONSinglesDecisionBlockStruct* header,
743                 bool continueParse
744         )
745 {
746         // Step through the header fields trying to print them.
747         // At each step check if we have not overflowed the buffer, if we have
748         // not then we can print the field, otherwise we print the left over
749         // bytes assumed to be corrupted rubbish.
750         int result = CheckHeaderField(header->fNlowPt, buffer, bufferSize, continueParse);
751         if (result != EXIT_SUCCESS) return result;
752         cout << " Number of low pt triggers: " << header->fNlowPt << endl;
753         
754         result = CheckHeaderField(header->fNhighPt, buffer, bufferSize, continueParse);
755         if (result != EXIT_SUCCESS) return result;
756         cout << "Number of high pt triggers: " << header->fNhighPt << endl;
757
758         return result;
759 }
760
761
762 int DumpTrackDecisionStruct(
763                 const char* buffer, unsigned long bufferSize,
764                 const AliHLTMUONTrackDecisionStruct* decision,
765                 bool continueParse
766         )
767 {
768         // Step through the fields trying to print them.
769         // At each step check if we have not overflowed the buffer. If we have
770         // not, then we can print the field, otherwise we print the left over
771         // bytes assumed to be corrupted rubbish.
772         int result = CheckField(decision->fTrackId, buffer, bufferSize, continueParse);
773         if (result != EXIT_SUCCESS) return result;
774         cout << setw(13) << left << decision->fTrackId << setw(0);
775         
776         result = CheckField(decision->fTriggerBits, buffer, bufferSize, continueParse);
777         if (result != EXIT_SUCCESS) return result;
778         cout << setw(12) << left << showbase << hex << decision->fTriggerBits
779                 << setw(0) << dec;
780                 
781         // Print the individual trigger bits.
782         bool highPt, lowPt;
783         AliHLTMUONUtils::UnpackTrackDecisionBits(decision->fTriggerBits, highPt, lowPt);
784         cout << setw(7) << left << (highPt ? "yes" : "no");
785         cout << setw(8) << left << (lowPt ? "yes" : "no");
786         cout << setw(0) << endl;
787
788         return result;
789 }
790
791
792 int DumpSinglesDecisionBlock(
793                 const char* buffer, unsigned long bufferSize,
794                 bool continueParse
795         )
796 {
797         int result = EXIT_SUCCESS;
798         AliHLTMUONSinglesDecisionBlockReader block(buffer, bufferSize);
799         
800         result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
801         if (result != EXIT_SUCCESS and not continueParse) return result;
802         
803         // Dump the rest of the block header.
804         const AliHLTMUONSinglesDecisionBlockStruct* header = &block.BlockHeader();
805         int subResult = DumpSinglesDecisionBlockHeader(buffer, bufferSize, header, continueParse);
806         if (subResult != EXIT_SUCCESS) return subResult;
807         
808         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
809         
810         // Print the data block record entries.
811         cout << "           |        Trigger Bits" << endl;
812         cout << "Track ID   | Raw         HighPt LowPt" << endl;
813         cout << "--------------------------------------" << endl;
814         const AliHLTMUONTrackDecisionStruct* entry = block.GetArray();
815         for(AliHLTUInt32_t i = 0; i < nentries; i++)
816         {
817                 subResult = DumpTrackDecisionStruct(buffer, bufferSize, entry++, continueParse);
818                 if (subResult != EXIT_SUCCESS) return subResult;
819         }
820         
821         return result;
822 }
823
824
825 int DumpPairsDecisionBlockHeader(
826                 const char* buffer, unsigned long bufferSize,
827                 const AliHLTMUONPairsDecisionBlockStruct* header,
828                 bool continueParse
829         )
830 {
831         // Step through the header fields trying to print them.
832         // At each step check if we have not overflowed the buffer, if we have
833         // not then we can print the field, otherwise we print the left over
834         // bytes assumed to be corrupted rubbish.
835         int result = CheckHeaderField(header->fNunlikeAnyPt, buffer, bufferSize, continueParse);
836         if (result != EXIT_SUCCESS) return result;
837         cout << "      Number of unlike all pt triggers: " << header->fNunlikeAnyPt << endl;
838         
839         result = CheckHeaderField(header->fNunlikeLowPt, buffer, bufferSize, continueParse);
840         if (result != EXIT_SUCCESS) return result;
841         cout << "      Number of unlike low pt triggers: " << header->fNunlikeLowPt << endl;
842         
843         result = CheckHeaderField(header->fNunlikeHighPt, buffer, bufferSize, continueParse);
844         if (result != EXIT_SUCCESS) return result;
845         cout << "     Number of unlike high pt triggers: " << header->fNunlikeHighPt << endl;
846         
847         result = CheckHeaderField(header->fNlikeAnyPt, buffer, bufferSize, continueParse);
848         if (result != EXIT_SUCCESS) return result;
849         cout << "        Number of like any pt triggers: " << header->fNlikeAnyPt << endl;
850         
851         result = CheckHeaderField(header->fNlikeLowPt, buffer, bufferSize, continueParse);
852         if (result != EXIT_SUCCESS) return result;
853         cout << "        Number of like low pt triggers: " << header->fNlikeLowPt << endl;
854         
855         result = CheckHeaderField(header->fNlikeHighPt, buffer, bufferSize, continueParse);
856         if (result != EXIT_SUCCESS) return result;
857         cout << "       Number of like high pt triggers: " << header->fNlikeHighPt << endl;
858         
859         result = CheckHeaderField(header->fNmassAny, buffer, bufferSize, continueParse);
860         if (result != EXIT_SUCCESS) return result;
861         cout << " Number of all invariant mass triggers: " << header->fNmassAny << endl;
862         
863         result = CheckHeaderField(header->fNmassLow, buffer, bufferSize, continueParse);
864         if (result != EXIT_SUCCESS) return result;
865         cout << " Number of low invariant mass triggers: " << header->fNmassLow << endl;
866         
867         result = CheckHeaderField(header->fNmassHigh, buffer, bufferSize, continueParse);
868         if (result != EXIT_SUCCESS) return result;
869         cout << "Number of high invariant mass triggers: " << header->fNmassHigh << endl;
870         
871         return result;
872 }
873
874
875 int DumpPairDecisionStruct(
876                 const char* buffer, unsigned long bufferSize,
877                 const AliHLTMUONPairDecisionStruct* decision,
878                 bool continueParse
879         )
880 {
881         // Step through the fields trying to print them.
882         // At each step check if we have not overflowed the buffer. If we have
883         // not, then we can print the field, otherwise we print the left over
884         // bytes assumed to be corrupted rubbish.
885         int result = CheckField(decision->fTrackAId, buffer, bufferSize, continueParse);
886         if (result != EXIT_SUCCESS) return result;
887         cout << setw(13) << left << decision->fTrackAId << setw(0);
888         
889         result = CheckField(decision->fTrackBId, buffer, bufferSize, continueParse);
890         if (result != EXIT_SUCCESS) return result;
891         cout << setw(13) << left << decision->fTrackBId << setw(0);
892         
893         result = CheckField(decision->fTriggerBits, buffer, bufferSize, continueParse);
894         if (result != EXIT_SUCCESS) return result;
895         cout << setw(12) << left << showbase << hex << decision->fTriggerBits
896                 << setw(0) << dec;
897                 
898         // Print the individual trigger bits.
899         bool highMass, lowMass, unlike;
900         AliHLTUInt8_t highPtCount, lowPtCount;
901         AliHLTMUONUtils::UnpackPairDecisionBits(
902                         decision->fTriggerBits,
903                         highMass, lowMass, unlike, highPtCount, lowPtCount
904                 );
905         cout << setw(7) << left << (highMass ? "yes" : "no");
906         cout << setw(7) << left << (lowMass ? "yes" : "no");
907         cout << setw(7) << left << (unlike ? "yes" : "no");
908         cout << setw(6) << left << AliHLTUInt16_t(highPtCount);
909         cout << setw(8) << left << AliHLTUInt16_t(lowPtCount);
910         cout << setw(0);
911         
912         result = CheckField(decision->fInvMass, buffer, bufferSize, continueParse);
913         if (result != EXIT_SUCCESS) return result;
914         cout << decision->fInvMass << endl;
915         
916         return EXIT_SUCCESS;
917 }
918
919
920 int DumpPairsDecisionBlock(
921                 const char* buffer, unsigned long bufferSize,
922                 bool continueParse
923         )
924 {
925         int result = EXIT_SUCCESS;
926         AliHLTMUONPairsDecisionBlockReader block(buffer, bufferSize);
927         
928         result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
929         if (result != EXIT_SUCCESS and not continueParse) return result;
930         
931         // Dump the rest of the block header.
932         const AliHLTMUONPairsDecisionBlockStruct* header = &block.BlockHeader();
933         int subResult = DumpPairsDecisionBlockHeader(buffer, bufferSize, header, continueParse);
934         if (subResult != EXIT_SUCCESS) return subResult;
935         
936         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
937         
938         // Print the data block record entries.
939         cout << "           |            |                Trigger Bits                  |" << endl;
940         cout << "Track A ID | Track B ID | Raw         HiMass LoMass Unlike HiPt# LoPt# | Invariant mass" << endl;
941         cout << "----------------------------------------------------------------------------------------" << endl;
942         const AliHLTMUONPairDecisionStruct* entry = block.GetArray();
943         for(AliHLTUInt32_t i = 0; i < nentries; i++)
944         {
945                 subResult = DumpPairDecisionStruct(buffer, bufferSize, entry++, continueParse);
946                 if (subResult != EXIT_SUCCESS) return subResult;
947         }
948         
949         return result;
950 }
951
952
953 int DumpCommonHeader(
954                 const char* buffer, unsigned long bufferSize,
955                 const AliHLTMUONDataBlockHeader* header, bool continueParse
956         )
957 {
958         // Step through the header fields trying to print them.
959         // At each step check if we have not overflowed the buffer, if we have
960         // not then we can print the field, otherwise we print the left over
961         // bytes assumed to be corrupted rubbish.
962         int result = CheckHeaderField(header->fType, buffer, bufferSize, continueParse);
963         if (result != EXIT_SUCCESS) return result;
964         AliHLTMUONDataBlockType type = AliHLTMUONDataBlockType(header->fType);
965         cout << "       Block type: " << type << endl;
966         
967         result = CheckHeaderField(header->fRecordWidth, buffer, bufferSize, continueParse);
968         if (result != EXIT_SUCCESS) return result;
969         cout << "     Record width: " << header->fRecordWidth << endl;
970         
971         result = CheckHeaderField(header->fNrecords, buffer, bufferSize, continueParse);
972         if (result != EXIT_SUCCESS) return result;
973         cout << "Number of entries: " << header->fNrecords << endl;
974         
975         return result;
976 }
977
978
979 int ParseBuffer(
980                 const char* buffer, unsigned long bufferSize,
981                 bool continueParse, AliHLTMUONDataBlockType type
982         )
983 {
984         assert( buffer != NULL );
985         int result = EXIT_SUCCESS;
986         
987         if (bufferSize < sizeof(AliHLTMUONDataBlockHeader))
988         {
989                 cerr << "ERROR: The size of the file is too small to contain a"
990                         " valid data block." << endl;
991                 result = PARSE_ERROR;
992                 if (not continueParse) return result;
993         }
994         const AliHLTMUONDataBlockHeader* header =
995                 reinterpret_cast<const AliHLTMUONDataBlockHeader*>(buffer);
996
997         int subResult = DumpCommonHeader(buffer, bufferSize, header, continueParse);
998         if (subResult != EXIT_SUCCESS) return subResult;
999
1000         
1001         // Check if the block type in the header corresponds to the type given
1002         // by the '-type' command line parameter. If they do not then print an
1003         // error or big fat warning message and force interpretation of the data
1004         // block with the type given by '-type'.
1005         AliHLTMUONDataBlockType headerType = AliHLTMUONDataBlockType(header->fType);
1006         
1007         if (type == kUnknownDataBlock)
1008         {
1009                 // -type not used in the command line so just use what is given
1010                 // by the data block header.
1011                 type = headerType;
1012         }
1013         else if (type != headerType)
1014         {
1015                 cerr << "WARNING: The data block header indicates a type"
1016                         " different from what was specified on the command line."
1017                         " The data could be corrupt."
1018                         << endl;
1019                 cerr << "WARNING: The type value in the file is "
1020                         << showbase << hex << header->fType
1021                         << " (" << headerType << "), but on the command line it is "
1022                         << showbase << hex << int(type) << dec
1023                         << " (" << type << ")."
1024                         << endl;
1025                 cerr << "WARNING: Will force the interpretation of the data block"
1026                         " with a type of " << type << "." << endl;
1027         }
1028         
1029         // Now we know what type the data block is supposed to be so we can
1030         // dump it to screen with the appropriate dump routine.
1031         switch (type)
1032         {
1033         case kTriggerRecordsDataBlock:
1034                 subResult = DumpTriggerRecordsBlock(buffer, bufferSize, continueParse);
1035                 if (subResult != EXIT_SUCCESS) result = subResult;
1036                 break;
1037         case kTrigRecsDebugDataBlock:
1038                 subResult = DumpTrigRecsDebugBlock(buffer, bufferSize, continueParse);
1039                 if (subResult != EXIT_SUCCESS) result = subResult;
1040                 break;
1041         case kTriggerChannelsDataBlock:
1042                 subResult = DumpTriggerChannelsBlock(buffer, bufferSize, continueParse);
1043                 if (subResult != EXIT_SUCCESS) result = subResult;
1044                 break;
1045         case kRecHitsDataBlock:
1046                 subResult = DumpRecHitsBlock(buffer, bufferSize, continueParse);
1047                 if (subResult != EXIT_SUCCESS) result = subResult;
1048                 break;
1049         case kClustersDataBlock:
1050                 subResult = DumpClustersBlock(buffer, bufferSize, continueParse);
1051                 if (subResult != EXIT_SUCCESS) result = subResult;
1052                 break;
1053         case kChannelsDataBlock:
1054                 return DumpChannelsBlock(buffer, bufferSize, continueParse);
1055                 if (subResult != EXIT_SUCCESS) result = subResult;
1056                 break;
1057         case kMansoTracksDataBlock:
1058                 subResult = DumpMansoTracksBlock(buffer, bufferSize, continueParse);
1059                 if (subResult != EXIT_SUCCESS) result = subResult;
1060                 break;
1061         case kMansoCandidatesDataBlock:
1062                 subResult = DumpMansoCandidatesBlock(buffer, bufferSize, continueParse);
1063                 if (subResult != EXIT_SUCCESS) result = subResult;
1064                 break;
1065         case kSinglesDecisionDataBlock:
1066                 subResult = DumpSinglesDecisionBlock(buffer, bufferSize, continueParse);
1067                 if (subResult != EXIT_SUCCESS) result = subResult;
1068                 break;
1069         case kPairsDecisionDataBlock:
1070                 return DumpPairsDecisionBlock(buffer, bufferSize, continueParse);
1071                 if (subResult != EXIT_SUCCESS) result = subResult;
1072                 break;
1073         default :
1074                 cout << "ERROR: Unknown data block type. Found a type number of "
1075                         << showbase << hex << int(type) << dec
1076                         << " (" << int(type) << ")." << endl;
1077                 result = PARSE_ERROR;
1078         }
1079         
1080         return result;
1081 }
1082
1083
1084 /**
1085  * The caller is responsible for freeing memory allocated for buffer with a call
1086  * to delete [] buffer.
1087  */
1088 int ReadFile(const char* filename, char*& buffer, unsigned long& bufferSize)
1089 {
1090         assert( filename != NULL );
1091         
1092         // Open the file and find its size.
1093         fstream file;
1094         file.open(filename, ios::in);
1095         if (not file)
1096         {
1097                 cerr << "ERROR: Could not open the file: " << filename << endl;
1098                 return SYSTEM_ERROR;
1099         }
1100         file.seekg(0, ios::end);
1101         if (not file)
1102         {
1103                 cerr << "ERROR: Could not seek in the file: " << filename << endl;
1104                 return SYSTEM_ERROR;
1105         }
1106         bufferSize = file.tellg();
1107         if (not file)
1108         {
1109                 cerr << "ERROR: Could not get file size for the file: " <<
1110                         filename << endl;
1111                 return SYSTEM_ERROR;
1112         }
1113         file.seekg(0, ios::beg);
1114         if (not file)
1115         {
1116                 cerr << "ERROR: Could not seek in the file: " << filename << endl;
1117                 return SYSTEM_ERROR;
1118         }
1119         
1120         // Allocate the memory for the file.
1121         try
1122         {
1123                 buffer = new char[bufferSize];
1124         }
1125         catch (const std::bad_alloc&)
1126         {
1127                 cerr << "ERROR: Out of memory. Tried to allocate " << bufferSize
1128                         << " bytes." << endl;
1129                 return SYSTEM_ERROR;
1130         }
1131         
1132         file.read(buffer, bufferSize);
1133         if (not file)
1134         {
1135                 delete [] buffer;
1136                 buffer = NULL;
1137                 bufferSize = 0;
1138                 cerr << "ERROR: Could not read from file: " << filename << endl;
1139                 return SYSTEM_ERROR;
1140         }
1141         
1142         file.close();
1143         if (not file)
1144         {
1145                 delete [] buffer;
1146                 buffer = NULL;
1147                 bufferSize = 0;
1148                 cerr << "ERROR: Could not close the file: " << filename << endl;
1149                 return SYSTEM_ERROR;
1150         }
1151         
1152         return EXIT_SUCCESS;
1153 }
1154
1155 /**
1156  * Prints the command line usage of this program to standard error.
1157  */
1158 void PrintUsage()
1159 {
1160         cerr << "Usage: dHLTdumpraw [-help|-h] [-continue] [-type <typename>] <filename>" << endl;
1161         cerr << "Where <filename> is the name of a file containing a raw data block." << endl;
1162         cerr << "Options:" << endl;
1163         cerr << " -help | -h" << endl;
1164         cerr << "       Displays this message." << endl;
1165         cerr << " -continue" << endl;
1166         cerr << "       If specified, the program will try to continue parsing the data block" << endl;
1167         cerr << "       as much as possible rather than stopping at the first error." << endl;
1168         cerr << " -type <typename>" << endl;
1169         cerr << "       Forces the contents of the file to be interpreted as a specific" << endl;
1170         cerr << "       type of data block. Where <typename> can be one of:" << endl;
1171         cerr << "         trigrecs - trigger records data." << endl;
1172         cerr << "         trigrecsdebug - debugging information about trigger records." << endl;
1173         cerr << "         trigchannels - channel debugging in." << endl;
1174         cerr << "         rechits - reconstructed hits data." << endl;
1175         cerr << "         channels - channel debugging information from hit reconstruction." << endl;
1176         cerr << "         clusters - cluster debugging information from hit reconstruction." << endl;
1177         cerr << "         mansotracks - partial tracks from Manso algorithm." << endl;
1178         cerr << "         mansocandidates - track candidates considered in the Manso algorithm." << endl;
1179         cerr << "         singlesdecision - trigger decisions for single tracks." << endl;
1180         cerr << "         pairsdecision - trigger decisions for track pairs." << endl;
1181 }
1182
1183 /**
1184  * Parse the string passed as the type of the block and return the corresponding
1185  * AliHLTMUONDataBlockType value.
1186  */
1187 AliHLTMUONDataBlockType ParseCommandLineType(const char* type)
1188 {
1189         if (strcmp(type, "trigrecs") == 0)
1190         {
1191                 return kTriggerRecordsDataBlock;
1192         }
1193         else if (strcmp(type, "trigrecsdebug") == 0)
1194         {
1195                 return kTrigRecsDebugDataBlock;
1196         }
1197         else if (strcmp(type, "trigchannels") == 0)
1198         {
1199                 return kTriggerChannelsDataBlock;
1200         }
1201         else if (strcmp(type, "rechits") == 0)
1202         {      
1203                 return kRecHitsDataBlock;
1204         }
1205         else if (strcmp(type,"channels") == 0)
1206         {
1207                 return kChannelsDataBlock;
1208         }
1209         else if (strcmp(type,"clusters") == 0)
1210         {
1211                 return kClustersDataBlock;
1212         }
1213         else if (strcmp(type, "mansotracks") == 0)
1214         {
1215                 return kMansoTracksDataBlock;
1216         }
1217         else if (strcmp(type, "mansocandidates") == 0)
1218         {
1219                 return kMansoCandidatesDataBlock;
1220         }
1221         else if (strcmp(type, "singlesdecision") == 0)
1222         {
1223                 return kSinglesDecisionDataBlock;
1224         }
1225         else if (strcmp(type, "pairsdecision") == 0)
1226         {
1227                 return kPairsDecisionDataBlock;
1228         }
1229         
1230         cerr << "ERROR: Invalid type name '" << type << "' specified for argument -type."
1231                 << endl << endl;
1232         PrintUsage();
1233         return kUnknownDataBlock;
1234 }
1235
1236 /**
1237  * Parses the command line.
1238  * @param argc  Number of arguments as given in main().
1239  * @param argv  Array of arguments as given in main().
1240  * @param filename  Receives the pointer to the file name string.
1241  * @param type      Receives the type of the data block expected, i.e. the
1242  *                  value of the -type flag.
1243  * @return  A status flag suitable for returning from main(), containing either
1244  *          EXIT_SUCCESS or CMDLINE_ERROR.
1245  */
1246 int ParseCommandLine(
1247                 int argc, const char** argv,
1248                 const char*& filename, bool& continueParse,
1249                 AliHLTMUONDataBlockType& type
1250         )
1251 {
1252         filename = NULL;
1253         continueParse = false;
1254
1255         // Parse the command line.
1256         for (int i = 1; i < argc; i++)
1257         {
1258                 if (strcmp(argv[i], "-help") == 0 || strcmp(argv[i], "-h") == 0)
1259                 {
1260                         PrintUsage();
1261                         return EXIT_SUCCESS;
1262                 }
1263                 else if (strcmp(argv[i], "-continue") == 0)
1264                 {
1265                         continueParse = true;
1266                 }
1267                 else if (strcmp(argv[i], "-type") == 0)
1268                 {
1269                         // Now we need to parse the typename in the command line.
1270                         type = ParseCommandLineType(argv[++i]);
1271                         if (type == kUnknownDataBlock) return CMDLINE_ERROR;
1272                 }
1273                 else
1274                 {
1275                         if (filename != NULL)
1276                         {
1277                                 cerr << "ERROR: Only one file can be specified, but got '"
1278                                         << argv[i] << "', with '" << filename
1279                                         << "' specified earlier." << endl << endl;
1280                                 PrintUsage();
1281                                 return CMDLINE_ERROR;
1282                         }
1283                         else
1284                                 filename = argv[i];
1285                 }
1286         }
1287         
1288         // Now check that we have the filename and all the flags we need.
1289         if (filename == NULL)
1290         {
1291                 cerr << "ERROR: Missing a file name. You must specify a file to process."
1292                         << endl << endl;
1293                 PrintUsage();
1294                 return CMDLINE_ERROR;
1295         }
1296         
1297         return EXIT_SUCCESS;
1298 }
1299
1300
1301 int main(int argc, const char** argv)
1302 {
1303         const char* filename = NULL;
1304         bool continueParse = false;
1305         int returnCode = EXIT_SUCCESS;
1306         AliHLTMUONDataBlockType type = kUnknownDataBlock;
1307         char* buffer = NULL;
1308
1309         try
1310         {
1311                 returnCode = ParseCommandLine(argc, argv, filename, continueParse, type);
1312
1313                 if (returnCode == EXIT_SUCCESS and filename != NULL)
1314                 {
1315                         unsigned long bufferSize = 0;
1316                         returnCode = ReadFile(filename, buffer, bufferSize);
1317                         if (returnCode == EXIT_SUCCESS)
1318                                 returnCode = ParseBuffer(buffer, bufferSize, continueParse, type);
1319                         if (buffer != NULL) delete [] buffer;
1320                 }
1321                 
1322         }
1323         catch (...)
1324         {
1325                 cerr << "FATAL ERROR: An unknown exception occurred!" << endl << endl;
1326                 returnCode = FATAL_ERROR;
1327                 if (buffer != NULL) delete [] buffer;
1328         }
1329
1330         return returnCode;
1331 }