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