Detecting endianess of platform at runtime and generating warning if not on a little...
[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 #include <cstdlib>
40 #include <cassert>
41 #include <new>
42 #include <fstream>
43
44 #include <iostream>
45 using std::cout;
46 using std::cerr;
47 using std::endl;
48 using std::showbase;
49 using std::noshowbase;
50 using std::hex;
51 using std::dec;
52
53 #include <iomanip>
54 using std::setw;
55 using std::left;
56 using std::internal;
57
58
59 #define CMDLINE_ERROR 1
60 #define PARSE_ERROR 2
61 #define SYSTEM_ERROR 3
62 #define FATAL_ERROR 4
63
64
65 void PrintRubbishData(AliHLTUInt32_t offset, const char* padByte, AliHLTUInt32_t padCount)
66 {
67         if (padCount == 0) return;
68         
69         cerr << "ERROR: Found the following unexpected rubbish data at the"
70                 " end of the data block:" << endl;
71         cerr << "Byte #\tValue\tCharacter" << endl;
72         for (AliHLTUInt32_t i = 0; i < padCount; i++)
73         {
74                 short value = short(padByte[i]) & 0xFF;
75                 char character = padByte[i];
76                 cerr << offset + i + 1 << "\t"
77                         << noshowbase << hex << "0x" << value << dec << "\t"
78                         << character << endl;
79         }
80 }
81
82
83 template <typename FieldType>
84 int CheckHeaderField(
85                 FieldType& field, const char* buffer, unsigned long bufferSize,
86                 bool continueParse
87         )
88 {
89         const char* fieldptr = reinterpret_cast<const char*>(&field);
90         const char* endptr = buffer + bufferSize;
91         AliHLTUInt32_t bufferRemaining = endptr > fieldptr ? endptr - fieldptr : 0;
92         
93         if (bufferRemaining < sizeof(field))
94         {
95                 cout << "..." << endl; // We may be half way through printing a line so end it.
96                 cerr << "ERROR: The data block is too short. The header is corrupt." << endl;
97                 if (continueParse)
98                 {
99                         AliHLTUInt32_t offset = fieldptr - buffer;
100                         PrintRubbishData(offset, fieldptr, bufferRemaining);
101                 }
102                 return PARSE_ERROR;
103         }
104         return EXIT_SUCCESS;
105 }
106
107
108 template <typename FieldType>
109 int CheckField(
110                 FieldType& field, const char* buffer, unsigned long bufferSize,
111                 bool continueParse
112         )
113 {
114         const char* fieldptr = reinterpret_cast<const char*>(&field);
115         const char* endptr = buffer + bufferSize;
116         AliHLTUInt32_t bufferRemaining = endptr > fieldptr ? endptr - fieldptr : 0;
117         
118         if (bufferRemaining < sizeof(field))
119         {
120                 cout << "..." << endl; // We may be half way through printing a line so end it.
121                 cerr << "ERROR: The data block is too short. The data is corrupt." << endl;
122                 if (continueParse)
123                 {
124                         AliHLTUInt32_t offset = fieldptr - buffer;
125                         PrintRubbishData(offset, fieldptr, bufferRemaining);
126                 }
127                 return PARSE_ERROR;
128         }
129         return EXIT_SUCCESS;
130 }
131
132
133 template <typename BlockType>
134 int CheckCommonHeader(
135                 BlockType& block, const char* /*buffer*/, unsigned long bufferSize,
136                 bool continueParse
137         )
138 {
139         int result = EXIT_SUCCESS;
140
141         // Check the fRecordWidth field in the common header.
142         if (block.CommonBlockHeader().fRecordWidth !=
143                 sizeof(typename BlockType::ElementType))
144         {
145                 cerr << "ERROR: The record width found in the header is incorrect."
146                         " Found a record width of "
147                         << block.CommonBlockHeader().fRecordWidth << " bytes, but expected"
148                         " a value of " << sizeof(typename BlockType::ElementType)
149                         << " bytes." << endl;
150                 result = PARSE_ERROR;
151                 if (not continueParse) return result;
152         }
153         
154         if (not block.BufferSizeOk())
155         {
156                 cerr << "ERROR: The size of the file is incorrect. It is "
157                         << bufferSize << " bytes big, but according"
158                         " to the data block header it should be " << block.BytesUsed()
159                         << " bytes." << endl;
160                 result = PARSE_ERROR;
161                 if (not continueParse) return result;
162         }
163         
164         return result;
165 }
166
167
168 template <typename BlockType>
169 AliHLTUInt32_t CalculateNEntries(BlockType& block, unsigned long bufferSize)
170 {
171         // Calculate how many entries we can display. If the buffer size is correct
172         // we just use the number of entries the block specifies. Otherwise we need
173         // to calculate it from the buffer size.
174         AliHLTUInt32_t nentries;
175         if (block.BytesUsed() == bufferSize)
176         {
177                 nentries = block.Nentries();
178         }
179         else
180         {
181                 AliHLTInt32_t dataSize = bufferSize
182                         - sizeof(typename BlockType::HeaderType);
183                 nentries = dataSize / sizeof(typename BlockType::ElementType);
184                 if (dataSize % sizeof(typename BlockType::ElementType) > 0)
185                         nentries++;
186         }
187         return nentries;
188 }
189
190
191 int DumpRecHitStruct(
192                 const char* buffer, unsigned long bufferSize,
193                 const AliHLTMUONRecHitStruct* hit,
194                 bool continueParse
195         )
196 {
197         // Step through the fields trying to print them.
198         // At each step check if we have not overflowed the buffer. If we have
199         // not, then we can print the field, otherwise we print the left over
200         // bytes assumed to be corrupted rubbish.
201         int result = CheckField(hit->fX, buffer, bufferSize, continueParse);
202         if (result != EXIT_SUCCESS) return result;
203         cout << setw(13) << left << hit->fX << setw(0);
204
205         result = CheckField(hit->fY, buffer, bufferSize, continueParse);
206         if (result != EXIT_SUCCESS) return result;
207         cout << setw(13) << left << hit->fY << setw(0);
208
209         result = CheckField(hit->fZ, buffer, bufferSize, continueParse);
210         if (result != EXIT_SUCCESS) return result;
211         cout << hit->fZ << setw(0) << endl;
212
213         return result;
214 }
215
216
217 int DumpRecHitsBlock(
218                 const char* buffer, unsigned long bufferSize,
219                 bool continueParse
220         )
221 {
222         int result = EXIT_SUCCESS;
223         AliHLTMUONRecHitsBlockReader block(buffer, bufferSize);
224         
225         result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
226         if (result != EXIT_SUCCESS and not continueParse) return result;
227         
228         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
229         
230         // Print the data block record entries.
231         cout << " X (cm)     | Y (cm)     | Z (cm)" << endl;
232         cout << "---------------------------------------" << endl;
233         const AliHLTMUONRecHitStruct* entry = block.GetArray();
234         for(AliHLTUInt32_t i = 0; i < nentries; i++)
235         {
236                 int subResult = DumpRecHitStruct(buffer, bufferSize, entry++, continueParse);
237                 if (subResult != EXIT_SUCCESS) return subResult;
238         }
239         
240         return result;
241 }
242
243
244 int DumpTriggerRecordStruct(
245                const char* buffer, unsigned long bufferSize, 
246                const AliHLTMUONTriggerRecordStruct* record,
247                bool continueParse
248        )
249 {
250         // Step through the fields trying to print them.
251         // At each step check if we have not overflowed the buffer. If we have
252         // not, then we can print the field, otherwise we print the left over
253         // bytes assumed to be corrupted rubbish.
254         int result = CheckField(record->fId, buffer, bufferSize, continueParse);
255         if (result != EXIT_SUCCESS) return result;
256         cout << "Trigger Record ID: " << record->fId <<endl;
257         
258         result = CheckField(record->fFlags, buffer, bufferSize, continueParse);
259         if (result != EXIT_SUCCESS) return result;
260         cout << "Flags: " << showbase << hex << record->fFlags << dec;
261                 
262         // Print the individual trigger bits.
263         AliHLTMUONParticleSign sign;
264         bool hitset[4];
265         AliHLTMUONUtils::UnpackTriggerRecordFlags(record->fFlags, sign, hitset);
266         cout << " [Sign: " << sign << ", Hits set on chambers: ";
267         bool first = true;
268         for (AliHLTUInt32_t i = 0; i < 4; i++)
269         {
270                 if (hitset[i])
271                 {
272                         cout << (first ? "" : ", ") << i+11;
273                         first = false;
274                 }
275         }
276         cout << (first ? "none]" : "]") << endl;
277
278         result = CheckField(record->fPx, buffer, bufferSize, continueParse);
279         if (result != EXIT_SUCCESS) return result;
280         cout << "Momentum: (px = " << record->fPx << ", ";
281
282         result = CheckField(record->fPy, buffer, bufferSize, continueParse);
283         if (result != EXIT_SUCCESS) return result;
284         cout << "py = " << record->fPy << ", ";
285
286         result = CheckField(record->fPz, buffer, bufferSize, continueParse);
287         if (result != EXIT_SUCCESS) return result;
288         cout << "pz = " << record->fPz << ") GeV/c"<<endl;
289         
290         cout << "Track hits:" << endl;
291         cout << "Chamber | X (cm)     | Y (cm)     | Z (cm)" << endl;
292         cout << "------------------------------------------------" << endl;
293         const AliHLTMUONRecHitStruct* hit = &record->fHit[0];
294         for(AliHLTUInt32_t ch = 0; ch < 4; ch++)
295         {
296                 cout << setw(10) << left << ch + 11 << setw(0);
297                 result = DumpRecHitStruct(buffer, bufferSize, hit++, continueParse);
298                 if (result != EXIT_SUCCESS) return result;
299         }
300
301         return result;
302
303 }
304
305
306 int DumpTriggerRecordsBlock(
307                 const char* buffer, unsigned long bufferSize,
308                 bool continueParse
309         )
310 {
311         AliHLTMUONTriggerRecordsBlockReader block(buffer, bufferSize);
312         
313         int result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
314         if (result != EXIT_SUCCESS and not continueParse) return result;
315         
316         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
317         
318         // Print the data block record entries.
319         const AliHLTMUONTriggerRecordStruct* entry = block.GetArray();
320         for(AliHLTUInt32_t i = 0; i < nentries; i++)
321         {
322                 cout << "============================== Trigger Record number " << i+1
323                         << " of " << nentries << " ==============================" << endl;
324                 int subResult = DumpTriggerRecordStruct(buffer, bufferSize, entry++, continueParse);
325                 if (subResult != EXIT_SUCCESS) return subResult;
326         }
327         
328         return EXIT_SUCCESS;
329 }
330
331
332 int DumpTrigRecInfoStruct(const char* buffer, unsigned long bufferSize, 
333                           const AliHLTMUONTrigRecInfoStruct* debuginfo, 
334                           bool continueParse
335                           )
336 {
337         // Step through the fields trying to print them.
338         // At each step check if we have not overflowed the buffer. If we have
339         // not, then we can print the field, otherwise we print the left over
340         // bytes assumed to be corrupted rubbish.
341         int result = CheckField(debuginfo->fTrigRecId, buffer, bufferSize, continueParse);
342         if (result != EXIT_SUCCESS) return result;
343         cout << setw(22) << left << debuginfo->fTrigRecId << setw(0);
344
345         result = CheckField(debuginfo->fDetElemId, buffer, bufferSize, continueParse);
346         if (result != EXIT_SUCCESS) return result;
347         cout << setw(20) << left << debuginfo->fDetElemId << setw(0);
348         
349         result = CheckField(debuginfo->fZmiddle, buffer, bufferSize, continueParse);
350         if(result != EXIT_SUCCESS) return result;
351         cout << setw(30) << left << debuginfo->fZmiddle << setw(0);
352
353         result = CheckField(debuginfo->fBl, buffer, bufferSize, continueParse);
354         if (result != EXIT_SUCCESS) return result;
355         cout <<debuginfo->fBl << setw(0) << endl;
356
357         return result;
358 }
359
360
361 int DumpTrigRecsDebugBlock(
362                 const char* buffer, unsigned long bufferSize,
363                 bool continueParse
364         )
365 {
366         AliHLTMUONTrigRecsDebugBlockReader block(buffer, bufferSize);
367         
368         int result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
369         if (result != EXIT_SUCCESS and not continueParse) return result;
370         
371         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
372         
373         // Print the data block record entries.
374         cout << "Trigger Record ID  | Detector ID  | Momentum X Component (Gev/c) | Integrated Magnetic Field (T.m)" << endl;
375         cout << "--------------------------------------------------------------------------------------------------" << endl;
376         const AliHLTMUONTrigRecInfoStruct* entry = block.GetArray();
377         for(AliHLTUInt32_t i = 0; i < nentries; i++)
378         {
379                 int subResult = DumpTrigRecInfoStruct(buffer, bufferSize, entry++, continueParse);
380                 if (subResult != EXIT_SUCCESS) return subResult;
381         }
382         
383         return EXIT_SUCCESS;
384 }
385
386
387 int DumpTriggerChannelStruct(const char* buffer, unsigned long bufferSize, 
388                       const AliHLTMUONTriggerChannelStruct* triggerchannel, 
389                       bool continueParse
390                       )
391 {
392         // Step through the fields trying to print them.
393         // At each step check if we have not overflowed the buffer. If we have
394         // not, then we can print the field, otherwise we print the left over
395         // bytes assumed to be corrupted rubbish.
396         int result = CheckField(triggerchannel->fTrigRecId, buffer, bufferSize, continueParse);
397         if (result != EXIT_SUCCESS) return result;
398         cout << setw(25) << left << triggerchannel->fTrigRecId << setw(0);
399
400         result = CheckField(triggerchannel->fChamber, buffer, bufferSize, continueParse);
401         if (result != EXIT_SUCCESS) return result;
402         cout << setw(13) << left << triggerchannel->fChamber << setw(0);
403
404         result = CheckField(triggerchannel->fSignal, buffer, bufferSize, continueParse);
405         if (result != EXIT_SUCCESS) return result;
406         cout << setw(10) << left << triggerchannel->fSignal << setw(0);
407
408         result = CheckField(triggerchannel->fRawDataWord, buffer, bufferSize, continueParse);
409         if(result != EXIT_SUCCESS) return result;
410         cout << showbase << hex << triggerchannel->fRawDataWord << dec << setw(0) << endl;
411         return result;
412 }
413
414
415 int DumpTriggerChannelsBlock(
416                 const char* buffer, unsigned long bufferSize,
417                 bool continueParse
418         )
419 {
420         int result = EXIT_SUCCESS;
421         AliHLTMUONTriggerChannelsBlockReader block(buffer, bufferSize);
422         
423         result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
424         if (result != EXIT_SUCCESS and not continueParse) return result;
425         
426         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
427         
428         // Print the data block record entries.
429         cout << " Trigger Record ID   | Chamber    | Signal   | Raw Data Word " << endl;
430         cout << "--------------------------------------------------------------" << endl;
431         const AliHLTMUONTriggerChannelStruct* entry = block.GetArray();
432         for(AliHLTUInt32_t i = 0; i < nentries; i++)
433         {
434                 int subResult = DumpTriggerChannelStruct(buffer, bufferSize, entry++, continueParse);
435                 if (subResult != EXIT_SUCCESS) return subResult;
436         }
437
438         return result;
439 }
440
441
442 int DumpClusterStruct(
443                       const char* buffer, unsigned long bufferSize,
444                       const AliHLTMUONClusterStruct* cluster,
445                       bool continueParse
446        )
447 {
448         // Step through the fields trying to print them.
449         // At each step check if we have not overflowed the buffer. If we have
450         // not, then we can print the field, otherwise we print the left over
451         // bytes assumed to be corrupted rubbish.
452         int result = CheckField(cluster->fId, buffer, bufferSize, continueParse);
453         if (result != EXIT_SUCCESS) return result;
454         cout << "cluster->fId: " << cluster->fId << "\t";
455
456         result = CheckField(cluster->fDetElemId, buffer, bufferSize, continueParse);
457         if (result != EXIT_SUCCESS) return result;
458         cout << "cluster->fDetElemId: " << cluster->fDetElemId << "\t";
459
460         result = CheckField(cluster->fNchannels, buffer, bufferSize, continueParse);
461         if(result != EXIT_SUCCESS) return result;
462         cout << "cluster->fNchannels: " << cluster->fNchannels <<endl;
463
464         cout << " Corresponding Hit: "<< endl;
465         cout << " X (cm)     | Y (cm)     | Z (cm)" << endl;
466         cout << "---------------------------------------" << endl;
467         const AliHLTMUONRecHitStruct * hit = & cluster->fHit;
468         result = DumpRecHitStruct(buffer, bufferSize, hit, continueParse);
469
470         return result;
471 }
472
473
474 int DumpClustersBlock(
475                 const char* buffer, unsigned long bufferSize,
476                 bool continueParse
477         )
478 {
479         int result = EXIT_SUCCESS;
480         AliHLTMUONClustersBlockReader block(buffer, bufferSize);
481         
482         result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
483         if (result != EXIT_SUCCESS and not continueParse) return result;
484         
485         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
486         
487         // Print the data block record entries.
488         const AliHLTMUONClusterStruct* entry = block.GetArray();
489         for(AliHLTUInt32_t i = 0; i < nentries; i++)
490         {
491                 cout << " ===================================================== Cluster Number "
492                         << i+1 << "==================================================" << endl; 
493                 int subResult = DumpClusterStruct(buffer, bufferSize, entry++, continueParse);
494                 if (subResult != EXIT_SUCCESS) return subResult;
495         }       
496
497         return result;
498 }
499
500
501 int DumpChannelStruct(
502                const char* buffer, unsigned long bufferSize,
503                const AliHLTMUONChannelStruct* channel,
504                bool continueParse                 
505        )
506 {
507         // Step through the fields trying to print them.
508         // At each step check if we have not overflowed the buffer. If we have
509         // not, then we can print the field, otherwise we print the left over
510         // bytes assumed to be corrupted rubbish.
511         int result = CheckField(channel->fClusterId, buffer, bufferSize, continueParse);
512         if (result != EXIT_SUCCESS) return result;
513         cout << setw(16) << left << channel->fClusterId << setw(0);
514
515         result = CheckField(channel->fManu, buffer, bufferSize, continueParse);
516         if (result != EXIT_SUCCESS) return result;
517         cout << setw(16) << left << channel->fManu << setw(0);
518
519         result = CheckField(channel->fChannelAddress, buffer, bufferSize, continueParse);
520         if (result != EXIT_SUCCESS) return result;
521         cout << setw(19) << left << channel->fChannelAddress << setw(0);
522
523         result = CheckField(channel->fSignal, buffer, bufferSize, continueParse);
524         if(result != EXIT_SUCCESS) return result;
525         cout << setw(16) << left << channel->fSignal << setw(0);
526
527         result = CheckField(channel->fRawDataWord, buffer, bufferSize, continueParse);
528         if(result != EXIT_SUCCESS) return result;
529         cout << showbase << hex << channel->fRawDataWord << dec << setw(0) <<endl;
530
531         return result;
532 }
533
534
535 int DumpChannelsBlock(
536                 const char* buffer, unsigned long bufferSize,
537                 bool continueParse
538         )
539 {
540         int result = EXIT_SUCCESS;
541         AliHLTMUONChannelsBlockReader block(buffer, bufferSize);
542         
543         result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
544         if (result != EXIT_SUCCESS and not continueParse) return result;
545         
546         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
547         
548         // Print the data block record entries.
549         cout << "Cluster Id  | Manu Address  | Channel Address  | Signal Value  | Raw Data Word " <<endl;
550         cout << "-------------------------------------------------------------------------------" <<endl;
551         const AliHLTMUONChannelStruct* entry = block.GetArray();
552         for(AliHLTUInt32_t i = 0; i < nentries; i++)
553         { 
554                 int subResult = DumpChannelStruct(buffer, bufferSize, entry++, continueParse);
555                 if (subResult != EXIT_SUCCESS) return subResult;
556         }
557         return EXIT_SUCCESS;
558 }
559
560
561 int DumpMansoTrackStruct(
562                 const char* buffer, unsigned long bufferSize,
563                 const AliHLTMUONMansoTrackStruct* track,
564                 bool continueParse
565         )
566 {
567         // Step through the fields trying to print them.
568         // At each step check if we have not overflowed the buffer. If we have
569         // not, then we can print the field, otherwise we print the left over
570         // bytes assumed to be corrupted rubbish.
571         int result = CheckField(track->fId, buffer, bufferSize, continueParse);
572         if (result != EXIT_SUCCESS) return result;
573         cout << "Track ID: " << track->fId << "\t";
574
575         result = CheckField(track->fTrigRec, buffer, bufferSize, continueParse);
576         if (result != EXIT_SUCCESS) return result;
577         cout << "Trigger Record ID: " << track->fTrigRec << endl;
578         
579         result = CheckField(track->fFlags, buffer, bufferSize, continueParse);
580         if (result != EXIT_SUCCESS) return result;
581         cout << "Flags: " << showbase << hex << track->fFlags << dec;
582         
583         // Print the individual trigger bits.
584         AliHLTMUONParticleSign sign;
585         bool hitset[4];
586         AliHLTMUONUtils::UnpackMansoTrackFlags(track->fFlags, sign, hitset);
587         cout << " [Sign: " << sign << ", Hits set on chambers: ";
588         bool first = true;
589         for (AliHLTUInt32_t i = 0; i < 4; i++)
590         {
591                 if (hitset[i])
592                 {
593                         cout << (first ? "" : ", ") << i+7;
594                         first = false;
595                 }
596         }
597         cout << (first ? "none]" : "]") << endl;
598
599         result = CheckField(track->fPx, buffer, bufferSize, continueParse);
600         if (result != EXIT_SUCCESS) return result;
601         cout << "Momentum: (px = " << track->fPx << ", ";
602
603         result = CheckField(track->fPy, buffer, bufferSize, continueParse);
604         if (result != EXIT_SUCCESS) return result;
605         cout << "py = " << track->fPy << ", ";
606
607         result = CheckField(track->fPz, buffer, bufferSize, continueParse);
608         if (result != EXIT_SUCCESS) return result;
609         cout << "pz = " << track->fPz << ") GeV/c\t";
610
611         result = CheckField(track->fChi2, buffer, bufferSize, continueParse);
612         if (result != EXIT_SUCCESS) return result;
613         cout << "Chi squared fit: " << track->fChi2 << endl;
614         
615         cout << "Track hits:" << endl;
616         cout << "Chamber | X (cm)     | Y (cm)     | Z (cm)" << endl;
617         cout << "------------------------------------------------" << endl;
618         const AliHLTMUONRecHitStruct* hit = &track->fHit[0];
619         for(AliHLTUInt32_t ch = 0; ch < 4; ch++)
620         {
621                 cout << setw(10) << left << ch + 7 << setw(0);
622                 result = DumpRecHitStruct(buffer, bufferSize, hit++, continueParse);
623                 if (result != EXIT_SUCCESS) return result;
624         }
625
626         return result;
627 }
628
629
630 int DumpMansoTracksBlock(
631                 const char* buffer, unsigned long bufferSize,
632                 bool continueParse
633         )
634 {
635         int result = EXIT_SUCCESS;
636         AliHLTMUONMansoTracksBlockReader block(buffer, bufferSize);
637         
638         result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
639         if (result != EXIT_SUCCESS and not continueParse) return result;
640         
641         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
642         
643         // Print the data block record entries.
644         const AliHLTMUONMansoTrackStruct* entry = block.GetArray();
645         for(AliHLTUInt32_t i = 0; i < nentries; i++)
646         {
647                 cout << "============================== Manso track number " << i+1
648                         << " of " << nentries << " ==============================" << endl;
649                 int subResult = DumpMansoTrackStruct(buffer, bufferSize, entry++, continueParse);
650                 if (subResult != EXIT_SUCCESS) return subResult;
651         }
652         
653         return result;
654 }
655
656
657 int DumpMansoRoIStruct(
658                 const char* buffer, unsigned long bufferSize,
659                 const AliHLTMUONMansoRoIStruct* roi,
660                 bool continueParse
661         )
662 {
663         // Step through the fields trying to print them.
664         // At each step check if we have not overflowed the buffer. If we have
665         // not, then we can print the field, otherwise we print the left over
666         // bytes assumed to be corrupted rubbish.
667         int result = CheckField(roi->fX, buffer, bufferSize, continueParse);
668         if (result != EXIT_SUCCESS) return result;
669         cout << setw(13) << left << roi->fX << setw(0);
670
671         result = CheckField(roi->fY, buffer, bufferSize, continueParse);
672         if (result != EXIT_SUCCESS) return result;
673         cout << setw(13) << left << roi->fY << setw(0);
674
675         result = CheckField(roi->fZ, buffer, bufferSize, continueParse);
676         if (result != EXIT_SUCCESS) return result;
677         cout << setw(13) << left << roi->fZ << setw(0);
678
679         result = CheckField(roi->fRadius, buffer, bufferSize, continueParse);
680         if (result != EXIT_SUCCESS) return result;
681         cout << roi->fRadius << setw(0) << endl;
682
683         return result;
684 }
685
686
687 int DumpMansoCandidateStruct(
688                 const char* buffer, unsigned long bufferSize,
689                 const AliHLTMUONMansoCandidateStruct* candidate,
690                 bool continueParse
691         )
692 {
693         int result = DumpMansoTrackStruct(buffer, bufferSize, &candidate->fTrack, continueParse);
694         if (result != EXIT_SUCCESS) return result;
695         
696         cout << "Regions of interest:" << endl;
697         cout << "Chamber | X (cm)     | Y (cm)     | Z (cm)     | Radius (cm)" << endl;
698         cout << "-------------------------------------------------------------" << endl;
699         const AliHLTMUONMansoRoIStruct* roi = &candidate->fRoI[0];
700         for(AliHLTUInt32_t ch = 0; ch < 4; ch++)
701         {
702                 cout << setw(10) << ch + 7;
703                 result = DumpMansoRoIStruct(buffer, bufferSize, roi++, continueParse);
704                 if (result != EXIT_SUCCESS) return result;
705         }
706         return result;
707 }
708
709
710 int DumpMansoCandidatesBlock(
711                 const char* buffer, unsigned long bufferSize,
712                 bool continueParse
713         )
714 {
715         int result = EXIT_SUCCESS;
716         AliHLTMUONMansoCandidatesBlockReader block(buffer, bufferSize);
717         
718         result = CheckCommonHeader(block, buffer, bufferSize, continueParse);
719         if (result != EXIT_SUCCESS and not continueParse) return result;
720         
721         AliHLTUInt32_t nentries = CalculateNEntries(block, bufferSize);
722         
723         // Print the data block record entries.
724         const AliHLTMUONMansoCandidateStruct* entry = block.GetArray();
725         for(AliHLTUInt32_t i = 0; i < nentries; i++)
726         {
727                 cout << "=========================== Manso track candidate number " << i+1
728                         << " of " << nentries << " ===========================" << endl;
729                 int subResult = DumpMansoCandidateStruct(buffer, bufferSize, entry++, continueParse);
730                 if (subResult != EXIT_SUCCESS) return subResult;
731         }
732         
733         return result;
734 }
735
736
737 int DumpSinglesDecisionBlockHeader(
738                 const char* buffer, unsigned long bufferSize,
739                 const AliHLTMUONSinglesDecisionBlockStruct* header,
740                 bool continueParse
741         )
742 {
743         // Step through the header fields trying to print them.
744         // At each step check if we have not overflowed the buffer, if we have
745         // not then we can print the field, otherwise we print the left over
746         // bytes assumed to be corrupted rubbish.
747         int result = CheckHeaderField(header->fNlowPt, buffer, bufferSize, continueParse);
748         if (result != EXIT_SUCCESS) return result;
749         cout << " Number of low pt triggers: " << header->fNlowPt << endl;
750         
751         result = CheckHeaderField(header->fNhighPt, buffer, bufferSize, continueParse);
752         if (result != EXIT_SUCCESS) return result;
753         cout << "Number of high pt triggers: " << header->fNhighPt << endl;
754
755         return result;
756 }
757
758
759 int DumpTrackDecisionStruct(
760                 const char* buffer, unsigned long bufferSize,
761                 const AliHLTMUONTrackDecisionStruct* decision,
762                 bool continueParse
763         )
764 {
765         // Step through the fields trying to print them.
766         // At each step check if we have not overflowed the buffer. If we have
767         // not, then we can print the field, otherwise we print the left over
768         // bytes assumed to be corrupted rubbish.
769         int result = CheckField(decision->fTrackId, buffer, bufferSize, continueParse);
770         if (result != EXIT_SUCCESS) return result;
771         cout << setw(13) << left << decision->fTrackId << setw(0);
772         
773         result = CheckField(decision->fTriggerBits, buffer, bufferSize, continueParse);
774         if (result != EXIT_SUCCESS) return result;
775         cout << setw(12) << left << showbase << hex << decision->fTriggerBits
776                 << setw(0) << dec;
777                 
778         // Print the individual trigger bits.
779         bool highPt, lowPt;
780         AliHLTMUONUtils::UnpackTrackDecisionBits(decision->fTriggerBits, highPt, lowPt);
781         cout << setw(7) << left << (highPt ? "yes" : "no");
782         cout << setw(8) << left << (lowPt ? "yes" : "no");
783         
784         result = CheckField(decision->fPt, buffer, bufferSize, continueParse);
785         if (result != EXIT_SUCCESS) return result;
786         cout << setw(0) << decision->fPt << 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 | pT" << 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(bool asError = true)
1159 {
1160         std::ostream& os = asError ? cerr : cout;
1161         os << "Usage: dHLTdumpraw [-help|-h] [-continue] [-type <typename>] <filename>" << endl;
1162         os << "Where <filename> is the name of a file containing a raw data block." << endl;
1163         os << "Options:" << endl;
1164         os << " -help | -h" << endl;
1165         os << "       Displays this message." << endl;
1166         os << " -continue" << endl;
1167         os << "       If specified, the program will try to continue parsing the data block" << endl;
1168         os << "       as much as possible rather than stopping at the first error." << endl;
1169         os << " -type <typename>" << endl;
1170         os << "       Forces the contents of the subsequent files specified on the command" << endl;
1171         os << "       line to be interpreted as a specific type of data block." << endl;
1172         os << "       Where <typename> can be one of:" << endl;
1173         os << "         trigrecs - trigger records data." << endl;
1174         os << "         trigrecsdebug - debugging information about trigger records." << endl;
1175         os << "         trigchannels - channel debugging in." << endl;
1176         os << "         rechits - reconstructed hits data." << endl;
1177         os << "         channels - channel debugging information from hit reconstruction." << endl;
1178         os << "         clusters - cluster debugging information from hit reconstruction." << endl;
1179         os << "         mansotracks - partial tracks from Manso algorithm." << endl;
1180         os << "         mansocandidates - track candidates considered in the Manso algorithm." << endl;
1181         os << "         singlesdecision - trigger decisions for single tracks." << endl;
1182         os << "         pairsdecision - trigger decisions for track pairs." << endl;
1183         os << "         autodetect - the type of the data block will be automatically" << endl;
1184         os << "                      detected." << endl;
1185 }
1186
1187 /**
1188  * Parse the string passed as the type of the block and return the corresponding
1189  * AliHLTMUONDataBlockType value.
1190  */
1191 AliHLTMUONDataBlockType ParseCommandLineType(const char* type)
1192 {
1193         if (strcmp(type, "trigrecs") == 0)
1194         {
1195                 return kTriggerRecordsDataBlock;
1196         }
1197         else if (strcmp(type, "trigrecsdebug") == 0)
1198         {
1199                 return kTrigRecsDebugDataBlock;
1200         }
1201         else if (strcmp(type, "trigchannels") == 0)
1202         {
1203                 return kTriggerChannelsDataBlock;
1204         }
1205         else if (strcmp(type, "rechits") == 0)
1206         {      
1207                 return kRecHitsDataBlock;
1208         }
1209         else if (strcmp(type,"channels") == 0)
1210         {
1211                 return kChannelsDataBlock;
1212         }
1213         else if (strcmp(type,"clusters") == 0)
1214         {
1215                 return kClustersDataBlock;
1216         }
1217         else if (strcmp(type, "mansotracks") == 0)
1218         {
1219                 return kMansoTracksDataBlock;
1220         }
1221         else if (strcmp(type, "mansocandidates") == 0)
1222         {
1223                 return kMansoCandidatesDataBlock;
1224         }
1225         else if (strcmp(type, "singlesdecision") == 0)
1226         {
1227                 return kSinglesDecisionDataBlock;
1228         }
1229         else if (strcmp(type, "pairsdecision") == 0)
1230         {
1231                 return kPairsDecisionDataBlock;
1232         }
1233         
1234         cerr << "ERROR: Invalid type name '" << type << "' specified for argument -type."
1235                 << endl << endl;
1236         PrintUsage();
1237         return kUnknownDataBlock;
1238 }
1239
1240 /**
1241  * Parses the command line.
1242  * @param argc  Number of arguments as given in main().
1243  * @param argv  Array of arguments as given in main().
1244  * @param filenames  Pointer to buffer storing file name strings.
1245  * @param numOfFiles  Receives the number of file name strings that were found
1246  *                    and added to 'filenames'.
1247  * @param filetypes  Array that receives the type of the data block expected, i.e.
1248  *                   the value of the -type flag for the corresponding file.
1249  * @return  A status flag suitable for returning from main(), containing either
1250  *          EXIT_SUCCESS or CMDLINE_ERROR.
1251  */
1252 int ParseCommandLine(
1253                 int argc,
1254                 const char** argv,
1255                 const char** filenames,
1256                 int& numOfFiles,
1257                 bool& continueParse,
1258                 AliHLTMUONDataBlockType* filetypes
1259         )
1260 {
1261         numOfFiles = 0;
1262         continueParse = false;
1263         AliHLTMUONDataBlockType currentType = kUnknownDataBlock;
1264
1265         // Parse the command line.
1266         for (int i = 1; i < argc; i++)
1267         {
1268                 if (strcmp(argv[i], "-help") == 0 || strcmp(argv[i], "-h") == 0)
1269                 {
1270                         PrintUsage(false);
1271                         return EXIT_SUCCESS;
1272                 }
1273                 else if (strcmp(argv[i], "-continue") == 0)
1274                 {
1275                         continueParse = true;
1276                 }
1277                 else if (strcmp(argv[i], "-type") == 0)
1278                 {
1279                         if (++i >= argc)
1280                         {
1281                                 cerr << "ERROR: Missing a type specifier" << endl;
1282                                 PrintUsage();
1283                                 return CMDLINE_ERROR;
1284                         }
1285                         // Now we need to parse the typename in the command line.
1286                         if (strcmp(argv[i], "autodetect") == 0)
1287                         {
1288                                 currentType = kUnknownDataBlock;
1289                         }
1290                         else
1291                         {
1292                                 currentType = ParseCommandLineType(argv[i]);
1293                                 if (currentType == kUnknownDataBlock) return CMDLINE_ERROR;
1294                         }
1295                 }
1296                 else
1297                 {
1298                         assert( numOfFiles < argc );
1299                         filenames[numOfFiles] = argv[i];
1300                         filetypes[numOfFiles] = currentType;
1301                         numOfFiles++;
1302                 }
1303         }
1304         
1305         // Now check that we have at least one filename and all the flags we need.
1306         if (numOfFiles == 0)
1307         {
1308                 cerr << "ERROR: Missing a file name. You must specify at least one file to process."
1309                         << endl << endl;
1310                 PrintUsage();
1311                 return CMDLINE_ERROR;
1312         }
1313         
1314         return EXIT_SUCCESS;
1315 }
1316
1317
1318 int main(int argc, const char** argv)
1319 {
1320         // Test endianess of this machine during runtime and print warning if it is not
1321         // little endian.
1322         union
1323         {
1324                 int dword;
1325                 char byte[4];
1326         } endianTest;
1327         endianTest.dword = 0x1;
1328         if (endianTest.byte[0] != 0x1)
1329         {
1330                 cerr << "!!!! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !!!!!" << endl;
1331                 cerr << "!!!! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !!!!!" << endl;
1332                 cerr << "!!                                                                     !!" << endl;
1333                 cerr << "!! This is not a little endian machine, but dHLT raw data is normally  !!" << endl;
1334                 cerr << "!! generated in little endian format. Unless you are looking at localy !!" << endl;
1335                 cerr << "!! created simulated data, then this program will not show you correct !!" << endl;
1336                 cerr << "!! output.                                                             !!" << endl;
1337                 cerr << "!!                                                                     !!" << endl;
1338                 cerr << "!!!! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !!!!!" << endl;
1339                 cerr << "!!!! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !! WARNING !!!!!" << endl;
1340                 cerr << endl;
1341         }
1342
1343
1344         int numOfFiles = 0;
1345         bool continueParse = false;
1346         int returnCode = EXIT_SUCCESS;
1347         char* buffer = NULL;
1348
1349         try
1350         {
1351                 // There will be at least 'argc' number of filenames.
1352                 typedef const char* AnsiString;
1353                 const char** filename = new AnsiString[argc];
1354                 AliHLTMUONDataBlockType* filetype = new AliHLTMUONDataBlockType[argc];
1355                 
1356                 returnCode = ParseCommandLine(argc, argv, filename, numOfFiles, continueParse, filetype);
1357
1358                 if (returnCode == EXIT_SUCCESS)
1359                 {
1360                         for (int i = 0; i < numOfFiles; i++)
1361                         {
1362                                 unsigned long bufferSize = 0;
1363                                 returnCode = ReadFile(filename[i], buffer, bufferSize);
1364                                 if (returnCode != EXIT_SUCCESS) break;
1365                                 if (numOfFiles > 1)
1366                                 {
1367                                         cout << "########## Start of dump for file: " << filename[i] << " ##########" << endl;
1368                                 }
1369                                 int result = ParseBuffer(buffer, bufferSize, continueParse, filetype[i]);
1370                                 if (buffer != NULL) delete [] buffer;
1371                                 if (result != EXIT_SUCCESS)
1372                                 {
1373                                         returnCode = result;
1374                                         if (not continueParse) break;
1375                                 }
1376                                 if (numOfFiles > 1)
1377                                 {
1378                                         cout << "##########   End of dump for file: " << filename[i] << " ##########" << endl;
1379                                 }
1380                         }
1381                 }
1382                 
1383                 delete [] filename;
1384                 delete [] filetype;
1385         }
1386         catch (...)
1387         {
1388                 cerr << "FATAL ERROR: An unknown exception occurred!" << endl << endl;
1389                 returnCode = FATAL_ERROR;
1390                 if (buffer != NULL) delete [] buffer;
1391         }
1392         
1393         return returnCode;
1394 }