]> git.uio.no Git - u/mrichter/AliRoot.git/blob - RAW/dateStream.cxx
Adding possibility to use custom Gain map for dEdx calculation (Marian)
[u/mrichter/AliRoot.git] / RAW / dateStream.cxx
1 /*
2                              dateStream.c
3                              ============
4
5    Utility to simulate a DATE raw data stream using a given set of raw
6    data files and a configuration file.
7
8    Revision history:
9
10    V01.00  4/05/2004  RD  Created
11    V01.01 25/10/2005  RD  Support added for timestamp
12    V01.02  4/04/2006  RD  Support for CDH
13    V01.03 24/05/2006  RD  Added "Direct disk access" option
14 */
15 #define VID "1.03"
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <errno.h>
20 #include <assert.h>
21 #include <ctype.h>
22 #include <time.h>
23 #include <cassert>
24 #include "event.h"
25
26 #define DESCRIPTION "DATE raw data stream simulator"
27 #ifdef AIX
28 static
29 #endif
30 char fileHandlerIdent[]= "@(#)""" __FILE__ """: """ DESCRIPTION \
31                          """ """ VID """ """ \
32                          """ compiled """ __DATE__ """ """ __TIME__;
33
34 #define DBG_BASE     if ( debug > 0 )
35 #define DBG_DETAILED if ( debug > 1 )
36 #define DBG_VERBOSE  if ( debug > 2 )
37
38 #ifndef TRUE
39 # define TRUE (0 == 0)
40 #endif
41 #ifndef FALSE
42 # define FALSE (0 == 1)
43 #endif
44
45 const char *myName;
46 int debug;
47 FILE *outF;
48 typedef enum { unknown, ldc, gdc } workingAsType;
49 typedef enum { collider, fixedTarget } workingModeType;
50 workingAsType workingAs;
51 workingModeType workingMode;
52 struct ldcDescriptorStruct {
53   eventLdcIdType id;
54   struct ldcDescriptorStruct *next;
55 } *ldcsHead, *ldcsTail;
56 void *eventsHead, *eventsTail;
57 struct gdcEventDescriptorStruct {
58   struct ldcEventDescriptorStruct *head;
59   struct ldcEventDescriptorStruct *tail;
60   struct gdcEventDescriptorStruct *next;
61   struct eventHeaderStruct header;
62   int loaded;
63 } *currGdc;
64 struct ldcEventDescriptorStruct {
65   struct equipmentEventDescriptorStruct *head;
66   struct equipmentEventDescriptorStruct *tail;
67   struct ldcEventDescriptorStruct *next;
68   eventLdcIdType id;
69   struct eventHeaderStruct header;
70   int loaded;
71 } *currLdc;
72 struct equipmentEventDescriptorStruct {
73   struct equipmentEventDescriptorStruct *next;
74   equipmentIdType id;
75   struct payloadDescriptorStruct *payload;
76   struct equipmentHeaderStruct header;
77 } *currEvent;
78 struct payloadDescriptorStruct {
79   struct payloadDescriptorStruct *next;
80   char *fileName;
81   int fileSize;
82   int size;
83   void *data;
84 } *payloadsHead, *payloadsTail;
85 int lineNo;
86 eventGdcIdType currGdcId;
87 eventLdcIdType currLdcId;
88 equipmentIdType currEquipmentId;
89 int currRunNb;
90 int numOfLdcs;
91 int numOfEvents;
92 int createSorEor;
93 int handleCDH;
94 eventIdType oneEventDelta;
95 eventIdType currEventId;
96 int gotAliceTrigger;
97 int bufferData;
98
99 struct commonDataHeaderStruct *cdhRef = NULL;
100
101 void dumpPayload( const struct payloadDescriptorStruct *p ) {
102   char *c;
103   int i;
104   int printable;
105           
106   if ( p->data != NULL ) {
107     for ( i = 0, c = (char *)p->data, printable = TRUE;
108           printable && i != p->size;
109           c++, i++ )
110       printable = isascii( *c );
111     if ( printable ) {
112       printf( "       \"" );
113       for ( i = 0, c = (char *)p->data; i != p->size; c++, i++ ) {
114         if ( *c == '\n' )
115           printf( "\"\n       \"" );
116         else
117           putchar( *c );
118       }
119       if ( *c != '\n' ) printf( "\"\n" );
120     } else {
121       long32 *v;
122       for ( i = 0, v = (long32 *)p->data;
123             i+4 <= p->size;
124             v++, i += 4 ) {
125         if ( i % (4*8) == 0 ) {
126           if ( i != 0 ) printf( "\n" );
127           printf( "       " );
128         }
129         printf( "%08x ", *v );
130       }
131       if ( i < p->size ) {
132         int j = 0;
133
134         printf( "\n       " );
135         while ( i != p->size ) {
136           printf( "%02x ", *((char *)p->data + p->size - j - 1) & 0xff );
137           j++;
138           i++;
139         }
140       }
141     }
142     printf( "\n" );
143   }
144 } /* End of dumpPayload */
145
146 void dumpEvents() {
147   assert( workingAs == ldc || workingAs == gdc );
148   if ( eventsHead != NULL ) {
149     printf( "Events:\n" );
150     if ( workingAs == gdc ) {
151       struct gdcEventDescriptorStruct *gdc;
152
153       for ( gdc = (struct gdcEventDescriptorStruct *)eventsHead;
154             gdc != NULL;
155             gdc = gdc->next ) {
156         struct ldcEventDescriptorStruct *ldc;
157
158         printf( " GDC (%p)\n", gdc );
159         for ( ldc = gdc->head; ldc != NULL; ldc = ldc->next ) {
160           struct equipmentEventDescriptorStruct *eq;
161             
162           printf( "   LDC (%p): %d\n", ldc, ldc->id );
163           for ( eq = ldc->head; eq != NULL; eq = eq->next ) {
164             printf( "     EQUIPMENT (%p): %d PAYLOAD (%p):",
165                     eq,
166                     eq->id,
167                     eq->payload );
168             fflush( stdout );
169             printf( "\"%s\" (%d bytes)\n",
170                     eq->payload->fileName,
171                     eq->payload->size );
172             dumpPayload( eq->payload );
173           }
174         }
175       }
176     }
177     if ( workingAs == ldc ) {
178       struct ldcEventDescriptorStruct *ldc;
179
180       for ( ldc = (struct ldcEventDescriptorStruct *)eventsHead;
181             ldc != NULL;
182             ldc = ldc->next ) {
183         struct equipmentEventDescriptorStruct *eq;
184             
185         printf( "   LDC\n" );
186         for ( eq = ldc->head; eq != NULL; eq = eq->next ) {
187           printf( "     EQUIPMENT (%p): %d PAYLOAD (%p):",
188                   eq,
189                   eq->id,
190                   eq->payload );
191           fflush( stdout );
192           printf( "\"%s\" (%d bytes)\n",
193                   eq->payload->fileName,
194                   eq->payload->size );
195           dumpPayload( eq->payload );
196         }
197       }
198     }
199   } else {
200     printf( "Events: EMPTY\n" );
201   }
202 } /* End of dumpEvents */
203
204 void getLine( char *line, const int maxSize ) {
205   int read;
206   int c;
207
208   for ( read = 0; !feof( stdin ) && !ferror( stdin ) && read != maxSize; read++ ) {
209     if ( (line[read] = getchar()) == '\n' ) break;
210   }
211   if ( ferror( stdin ) ) {
212     fprintf( stderr,
213              "%s: failed to read configuration input errno:%d ",
214              myName, errno );
215     perror( "" );
216     exit( 1 );
217   }
218   if ( feof( stdin ) ) read--;
219   if ( read == maxSize && line[read] != '\n' ) {
220     fprintf( stderr,
221              "%s: Input line # %d too long (%d chars max)\n",
222              myName, lineNo, maxSize-1 );
223     exit( 1 );
224   }
225   line[ read ] = 0;
226   DBG_VERBOSE {
227     if ( !( read == 0 && feof( stdin ) ) ) {
228       printf( "%d) [%3d] \"%s\"", lineNo, read, line );
229     }
230   }
231   for ( c = 0; c != read; c++ ) {
232     if ( line[c] == '#' ) {
233       line[c] = 0;
234       break;
235     }
236   }
237   DBG_VERBOSE {
238     if ( read != c ) {
239       printf( " => \"%s\"", line );
240     }
241     if ( feof( stdin ) ) printf( "<<< EOF >>>" );
242     if ( ferror( stdin ) ) printf( "<<< FERROR >>>" );
243     printf( "\n" );
244   }
245 } /* End of getLine */
246
247 void handleLdc( eventLdcIdType ldcId ) {
248   struct ldcDescriptorStruct *ldc;
249
250   if ( ldcsHead != NULL ) {
251     for ( ldc = ldcsHead; ldc != NULL; ldc = ldc->next ) {
252       if ( ldc->id == ldcId ) {
253         return;
254       }
255     }
256   }
257   if ( (ldc = (struct ldcDescriptorStruct *)malloc( sizeof( *ldc ) )) == NULL ) {
258     fprintf( stderr,
259              "%s: Failed to malloc for %d bytes (struct ldcDescriptorStruct)\n",
260              myName, (int)sizeof( *ldc ) );
261     exit( 1 );
262   }
263   ldc->id = ldcId;
264   ldc->next = NULL;
265   if ( ldcsHead == NULL ) {
266     ldcsHead = ldcsTail = ldc;
267   } else {
268     ldcsTail->next = ldc;
269     ldcsTail = ldc;
270   }
271   numOfLdcs++;
272 } /* End of handleLdc */
273
274 void createNewEvent() {
275   assert( workingAs == ldc || workingAs == gdc );
276   if ( workingAs == ldc ) {
277     struct ldcEventDescriptorStruct *p;
278
279     if ( (p = (struct ldcEventDescriptorStruct *)malloc( sizeof( *p ) ))
280            == NULL ) {
281       fprintf( stderr,
282                "%s: failed to malloc for %d bytes (createNewEvent: struct ldcEventDescriptorStruct)",
283                myName, (int)sizeof( *p ) );
284       perror( "" );
285       exit( 1 );
286     }
287     p->loaded = FALSE;
288     p->head = p->tail = NULL;
289     p->next = NULL;
290     currLdc = p;
291     if ( eventsHead == NULL ) {
292       eventsHead = eventsTail = p;
293     } else {
294       struct ldcEventDescriptorStruct *q =
295         (struct ldcEventDescriptorStruct *)eventsTail;
296
297       q->next = p;
298       eventsTail = p;
299     }
300     p->id = currLdcId;
301   } else if ( workingAs == gdc ) {
302     struct gdcEventDescriptorStruct *p;
303
304     if ( (p = (struct gdcEventDescriptorStruct *)malloc( sizeof( *p ) ))
305            == NULL ) {
306       fprintf( stderr,
307                "%s: failed to malloc for %d bytes (createNewEvent: struct gdcEventDescriptorStruct)",
308                myName, (int)sizeof( *p ) );
309       perror( "" );
310       exit( 1 );
311     }
312     p->loaded = FALSE;
313     p->next = NULL;
314     p->head = p->tail = NULL;
315     currGdc = p;
316     if ( eventsHead == NULL ) {
317       eventsHead = eventsTail = p;
318     } else {
319       struct gdcEventDescriptorStruct *q =
320         (struct gdcEventDescriptorStruct *)eventsTail;
321
322       q->next = p;
323       eventsTail = p;
324     }
325   }
326 } /* End of createNewEvent */
327
328 void createNewLdcEvent() {
329   struct gdcEventDescriptorStruct *gdcDesc;
330   struct ldcEventDescriptorStruct *p;
331
332   if ( (p = (struct ldcEventDescriptorStruct *)malloc( sizeof( *p ) ))
333          == NULL ) {
334     fprintf( stderr,
335              "%s: failed to malloc for %d bytes (createNewLdcEvent: struct ldcEventDescriptorStruct)",
336              myName, (int)sizeof( *p ) );
337     perror( "" );
338     exit( 1 );
339   }
340   p->id = currLdcId;
341   p->head = p->tail = NULL;
342   p->next = NULL;
343   gdcDesc = (struct gdcEventDescriptorStruct *)eventsTail;
344   if ( gdcDesc->head == NULL ) {
345     gdcDesc->head = gdcDesc->tail = p;
346   } else {
347     gdcDesc->tail->next = p;
348     gdcDesc->tail = p;
349   }
350   currLdc = p;
351 } /* End of createNewLdcEvent */
352
353 void loadBuffer( struct payloadDescriptorStruct * const payload ) {
354   FILE *f;
355   int bytesRead;
356
357   if ( (f = fopen( payload->fileName, "r" )) == NULL ) {
358     fprintf( stderr,
359              "%s: line:%d payload file \"%s\" not found or not readable, errno:%d. ",
360              myName,
361              lineNo,
362              payload->fileName,
363              errno );
364     perror( "System-dependent error " );
365     exit( 1 );
366   }
367   if ( (payload->data = malloc( payload->size )) == NULL ) {
368     fprintf( stderr,
369              "%s: line:%d Failed to malloc for payload file \"%s\" size:%d errno:%d ",
370              myName,
371              lineNo,
372              payload->fileName,
373              payload->size,
374              errno );
375     perror( "System-dependent status " );
376     exit( 1 );
377   }
378   if ( (bytesRead = fread( payload->data, payload->fileSize, 1, f )) != 1 ) {
379     fprintf( stderr,
380              "%s: line:%d Failed to read payload file \"%s\" size:%d requested:1 got:%d feof:%s ferror:%s errno:%d ",
381              myName,
382              lineNo,
383              payload->fileName,
384              payload->size,
385              bytesRead,
386              feof(f) ? "TRUE" : "false",
387              ferror(f) ? "TRUE" : "false",
388              errno );
389     perror( "System-dependent status " );
390     exit( 1 );
391   }
392   fclose(f);
393   if ( payload->size != payload->fileSize ) {
394     memset( (char *)payload->data + payload->fileSize,
395             0,
396             payload->size - payload->fileSize );
397   }
398 } /* End of loadBuffer */
399
400 void unloadBuffer( struct payloadDescriptorStruct * const payload ) {
401   if ( payload->data != NULL ) {
402     free( payload->data );
403     payload->data = NULL;
404   }
405 } /* End of unloadBuffer */
406
407 void unloadAllBuffers() {
408   struct payloadDescriptorStruct *payload;
409
410   for ( payload = payloadsHead; payload != NULL; payload = payload->next ) {
411     unloadBuffer( payload );
412   }
413 } /* End of unloadAllBuffers */
414
415 void loadPayload( const char *fileName ) {
416   struct payloadDescriptorStruct *payload;
417
418   for ( payload = payloadsHead; payload != NULL; payload = payload->next ) {
419     if ( strcmp( fileName, payload->fileName ) == 0 )
420       break;
421   }
422   if ( payload == NULL ) {
423     FILE *f;
424
425     if ( (payload = (struct payloadDescriptorStruct *)malloc( sizeof( *payload ) ))
426            == NULL ) {
427       fprintf( stderr,
428                "%s: failed to malloc for %d bytes (loadPayload/payloadDescriptorStruct)\n",
429                myName,
430                (int)sizeof( *payload ) );
431       exit( 1 );
432     }
433     if ( (payload->fileName = strdup( fileName )) == NULL ) {
434       fprintf( stderr,
435                "%s: failed to duplicate string \"%s\" (loadPaload/fileName)\n",
436                myName,
437                fileName );
438       exit( 1 );
439     }
440     if ( (f = fopen( fileName, "r" )) == NULL ) {
441       fprintf( stderr,
442                "%s: line:%d payload file \"%s\" not found or not readable, errno:%d. ",
443                myName,
444                lineNo,
445                fileName,
446                errno );
447       perror( "System-dependent error " );
448       exit( 1 );
449     }
450     if ( fseek( f, 0L, SEEK_END ) != 0 ) {
451       fprintf( stderr,
452                "%s: line:%d Failed to seek payload file \"%s\" errno:%d ",
453                myName,
454                lineNo,
455                fileName,
456                errno );
457       perror( "System-dependent error " );
458       exit( 1 );
459     }
460     if ( (payload->size = ftell( f )) <= 0 ) {
461       fprintf( stderr,
462                "%s: line:%d Failed to get file \"%s\" size size:%d errno:%d ",
463                myName,
464                lineNo,
465                fileName,
466                payload->size,
467                errno );
468       perror( "System-dependent status " );
469       exit( 1 );
470     }
471     payload->fileSize = payload->size;
472     while ( (payload->size & 3) != 0 ) payload->size++;
473     fclose( f );
474
475     if ( bufferData ) {
476       loadBuffer( payload );
477     } else {
478       payload->data = NULL;
479     }
480
481     payload->next = NULL;
482     if ( payloadsHead == NULL ) {
483       payloadsHead = payloadsTail = payload;
484     } else {
485       payloadsTail->next = payload;
486       payloadsTail = payload;
487     }
488     DBG_VERBOSE {
489       int b, n;
490
491       printf( "%d)       Payload \"%s\" loaded at %p\n",
492               lineNo,
493               fileName,
494               payload );
495       if ( bufferData ) {
496         if ( handleCDH &&
497              strncmp(fileName,"TRG_",4) != 0 ) {
498           struct commonDataHeaderStruct *cdh =
499             (struct commonDataHeaderStruct *)payload->data;
500
501           printf( " CDH: blockLenght:%d=0x%08x ",
502                   cdh->cdhBlockLength, cdh->cdhBlockLength );
503           if ( cdh->cdhBlockLength < sizeof( *cdh ) ) {
504             printf( "TOO SMALL (minimum:%ld=0x%08lx)\n",
505                    (unsigned long)sizeof( *cdh ),
506                    (unsigned long)sizeof( *cdh ) );
507           } else {
508             printf( "version:%d=0x%x ", cdh->cdhVersion, cdh->cdhVersion );
509             if ( cdh->cdhVersion != CDH_VERSION ) {
510               printf( "EXPECTED:%d=%x (decoding may be inaccurate) ",
511                       CDH_VERSION, CDH_VERSION );
512             }
513           }
514           printf( "L1TriggerMessage:0x%x", cdh->cdhL1TriggerMessage );
515           if (  cdh->cdhL1TriggerMessage != 0 ) {
516             for ( b = 0, n = 0; b != 10; b++ ) {
517               if ( (cdh->cdhL1TriggerMessage & (1<<b)) != 0 ) {
518                 if ( n++ != 0 )printf( "+" );
519                 switch (b) {
520                 case 0: printf( "L1SwC" ); break;
521                 case 1: printf( "ESR" ); break;
522                 case 2: printf( "RoC1" ); break;
523                 case 3: printf( "RoC2" ); break;
524                 case 4: printf( "RoC3" ); break;
525                 case 5: printf( "RoC4" ); break;
526                 case 6: printf( "ClT" ); break;
527                 default: printf( "spare %d", b+14 );
528                 }
529               }
530             }
531             printf( ">" );
532           }
533           printf( " " );
534           if ( cdh->cdhMBZ0 != 0 )
535             printf( "MBZ0:0x%x ",
536                     cdh->cdhMBZ0 );
537           printf( "\n" );
538           
539           printf( "      " );
540           printf( "EventId2(orbit):%d=0x%x ",
541                   cdh->cdhEventId2, cdh->cdhEventId2 );
542           printf( "EventId1(bunchCrossing):%d=0x%x ",
543                   cdh->cdhEventId1, cdh->cdhEventId1 );
544           printf( "\n" );
545           
546           printf( "      " );
547           if ( cdh->cdhMBZ1 != 0 )
548             printf( "MBZ1:0x%x ",
549                     cdh->cdhMBZ1 );
550           printf( "BlockAttributes:0x%x",
551                   cdh->cdhBlockAttributes );
552           if ( cdh->cdhBlockAttributes != 0 ) {
553             printf( "=<" );
554             for ( b = 0, n = 0; b != 8; b++ ) {
555               if ( (cdh->cdhBlockAttributes & (1<<b)) != 0 ) {
556                 if ( n++ != 0 )
557                   printf( "+" );
558                 printf( "%d", b );
559               }
560             }
561             printf( ">" );
562           }
563           printf( " " );
564           printf( "ParticipatingSubDetectors:0x%x ",
565                   cdh->cdhParticipatingSubDetectors );
566           printf( "\n" );
567           printf( "      " );
568           
569           if ( cdh->cdhMBZ2 != 0 )
570             printf( "MBZ2:0x%x ",
571                     cdh->cdhMBZ2 );
572           printf( "Status/Error:0x%x", cdh->cdhStatusErrorBits );
573           if ( cdh->cdhStatusErrorBits != 0 ) {
574             printf( "=<" );
575             for ( b = 0,n = 0; b != 16; b++ ) {
576               if ( (cdh->cdhStatusErrorBits & (1<<b)) != 0 ) {
577                 if ( n++ != 0 ) printf( "+" );
578                 switch (b) {
579                 case 0: printf( "TriggerOverLapError" ); break;
580                 case 1: printf( "TriggerMissingError" ); break;
581                 case 2: printf( "DataParityError" ); break;
582                 case 3: printf( "ControlParityError" ); break;
583                 case 4: printf( "TriggerInformationUnavailable" ); break;
584                 case 5: printf( "FEEError" ); break;
585                 case 6: printf( "HLTDecision" ); break;
586                 case 7: printf( "HLTPayload" ); break;
587                 case 8: printf( "DDGPayload" ); break;
588                 default: printf( "spare %d", b );
589                 }
590               }
591             }
592             printf( ">" );
593           }
594           printf( " " );
595           printf( "MiniEventId(bunchCrossing):%d=0x%x ",
596                   cdh->cdhMiniEventId, cdh->cdhMiniEventId );
597           printf( "\n" );
598           
599           printf( "      " );
600           printf( "Trigger classes: 0x(%05x-%08x)",
601                   cdh->cdhTriggerClassesHigh,
602                   cdh->cdhTriggerClassesLow );
603           if ( cdh->cdhTriggerClassesHigh != 0
604                || cdh->cdhTriggerClassesLow != 0 ) {
605             printf( "=<" );
606             for ( b=0, n=0; b != 32; b++ ) {
607               if ( (cdh->cdhTriggerClassesLow & (1<<b)) != 0 ) {
608                 if ( n++ != 0 ) printf( "+" );
609                 printf( "%d", b );
610               }
611             }
612             for ( b=0; b != 18; b++ ) {
613               if ( (cdh->cdhTriggerClassesHigh & (1<<b)) != 0 ) {
614                 if ( n++ != 0 ) printf( "+" );
615                 printf( "%d", b+32 );
616               }
617             }
618             printf( ">" );
619           }
620           printf( "\n" );
621           
622           printf( "      " );
623           if ( cdh->cdhMBZ3 != 0 ) {
624             printf( "MBZ3:0x%x ",
625                     cdh->cdhMBZ3 );
626           }
627           printf( "ROI:0x(%08x-%01x)", cdh->cdhRoiHigh, cdh->cdhRoiLow );
628           if ( cdh->cdhRoiHigh != 0
629                || cdh->cdhRoiLow != 0 ) {
630             printf( "=<" );
631             for ( b=0, n=0; b != 5; b++ ) {
632               if ( (cdh->cdhRoiLow & (1<<b)) != 0 ) {
633                 if ( n++ != 0 ) printf( "+" );
634                 printf( "%d", b );
635               }
636             }
637             for ( b=0; b != 32; b++ ) {
638               if ( (cdh->cdhRoiHigh & (1<<b)) != 0 ) {
639                 if ( n++ != 0 ) printf( "+" );
640                 printf( "%d", b+4 );
641               }
642             }
643             printf( ">" );
644           }
645           printf( "\n" );
646         }
647       }
648     }
649   } else {
650     DBG_VERBOSE
651       printf( "%d)       Payload \"%s\" already loaded at %p\n",
652               lineNo,
653               fileName,
654               payload );
655   }
656
657   currEvent->payload = payload;
658 } /* End of loadPayload */
659
660 void parseEquipment( char * const line ) {
661   struct equipmentEventDescriptorStruct *equipment;
662   int payloadFound = FALSE;
663   char *p;
664   char *keyword;
665
666   if ( (equipment =
667          (struct equipmentEventDescriptorStruct *)malloc( sizeof( *equipment ) )) == NULL ) {
668     fprintf( stderr,
669              "%s: filed to malloc for %d bytes (parseEquipment/equipmentEventDescriptorStruct) errno:%d ",
670              myName,
671              (int)sizeof( *equipment ),
672              errno );
673     perror( "" );
674     exit( 1 );
675   }
676   currEvent = equipment;
677
678   p = line;
679   while ( (keyword = strtok_r( p, " \t", &p )) != NULL ) {
680     DBG_VERBOSE printf( "%d)     Equipment - Keyword:\"%s\"\n",
681                         lineNo,
682                         keyword );
683     if ( strcasecmp( "id", keyword ) == 0 ) {
684       char *idNum;
685
686       if ( (idNum = strtok_r( p, " \t", &p )) == NULL ) {
687         fprintf( stderr,
688                  "%s: line:%d EQUIPMENT declaration, ID needed",
689                  myName,
690                  lineNo );
691         exit( 1 );
692       }
693       if ( sscanf( idNum, "%d", &currEquipmentId ) != 1 ) {
694         fprintf( stderr,
695                  "%s: line:%d EQUIPMENT declaration, numeric ID needed (%s)",
696                  myName,
697                  lineNo,
698                  idNum );
699         exit( 1 );
700       }
701       DBG_VERBOSE printf( "%d)     EQUIPMENT - ID:%d\n",
702                           lineNo,
703                           currEquipmentId );
704     } else if ( strncasecmp( "pay", keyword, 3 ) == 0 ) {
705       char *fileName;
706
707       if ( (fileName = strtok_r( p, " \t", &p )) == NULL ) {
708         fprintf( stderr,
709                  "%s line:%d Payload without filename found\n",
710                  myName,
711                  lineNo );
712         exit( 1 );
713       }
714       DBG_VERBOSE printf( "%d)     Equipment - Payload:\"%s\"\n",
715                           lineNo,
716                           fileName );
717       if ( payloadFound ) {
718         fprintf( stderr,
719                  "%s line:%d Payload with multiple filenames found\n",
720                  myName,
721                  lineNo );
722         exit( 1 );
723       }
724       loadPayload( fileName );
725       payloadFound = TRUE;
726     } else {
727       fprintf( stderr,
728                "%s: line:%d Equipment declaration, unknown keyword \"%s\"\n",
729                myName,
730                lineNo,
731                keyword );
732       exit( 1 );
733     }
734   }
735   if ( !payloadFound ) {
736     fprintf( stderr,
737              "%s: line:%d Equipment without payload found\n",
738              myName,
739              lineNo );
740     exit( 1 );
741   }
742
743   equipment->id = currEquipmentId;
744   equipment->next = NULL;
745   if ( currLdc->head == NULL ) {
746     currLdc->head = currLdc->tail = equipment;
747   } else {
748     currLdc->tail->next = equipment;
749     currLdc->tail = equipment;
750   }
751 } /* End of parseEquipment */
752
753 void parseGdc( char * const line ) {
754   char *p;
755   char *keyword;
756
757   p = line;
758   while ( (keyword = strtok_r( p, " \t", &p )) != NULL ) {
759     if ( strcasecmp( "id", keyword ) == 0 ) {
760       char *idNum;
761
762       if ( (idNum = strtok_r( p, " \t", &p )) == NULL ) {
763         fprintf( stderr,
764                  "%s: line:%d GDC declaration, ID needed",
765                  myName,
766                  lineNo );
767         exit( 1 );
768       }
769       if ( sscanf( idNum, "%d", &currGdcId ) != 1 ) {
770         fprintf( stderr,
771                  "%s: line:%d GDC declaration, numeric ID needed (%s)",
772                  myName,
773                  lineNo,
774                  idNum );
775         exit( 1 );
776       }
777       DBG_VERBOSE printf( "%d)     GDC - ID:%d\n",
778                           lineNo,
779                           currGdcId );
780     } else {
781       fprintf( stderr,
782                "%s: line:%d GDC declaration, unknown keyword \"%s\"\n",
783                myName,
784                lineNo,
785                keyword );
786       exit( 1 );
787     }  
788   }
789 } /* End of parseGdc */
790
791 void parseLdc( char * const line ) {
792   char *p;
793   char *keyword;
794
795   p = line;
796   while ( (keyword = strtok_r( p, " \t", &p )) != NULL ) {
797     if ( strcasecmp( "id", keyword ) == 0 ) {
798       char *idNum;
799
800       if ( (idNum = strtok_r( p, " \t", &p )) == NULL ) {
801         fprintf( stderr,
802                  "%s: line:%d LDC declaration, ID needed",
803                  myName,
804                  lineNo );
805         exit( 1 );
806       }
807       if ( sscanf( idNum, "%d", &currLdcId ) != 1 ) {
808         fprintf( stderr,
809                  "%s: line:%d LDC declaration, numeric ID needed (%s)",
810                  myName,
811                  lineNo,
812                  idNum );
813         exit( 1 );
814       }
815       DBG_VERBOSE printf( "%d)     LDC - ID:%d\n",
816                           lineNo,
817                           currLdcId );
818     } else {
819       fprintf( stderr,
820                "%s: line:%d LDC declaration, unknown keyword \"%s\"\n",
821                myName,
822                lineNo,
823                keyword );
824       exit( 1 );
825     }  
826   }
827 } /* End of parseLdc */
828
829 void parseRules() {
830   char line[ 1025 ];
831
832   currLdcId = HOST_ID_MIN;
833   currGdcId = HOST_ID_MIN;
834
835   for ( lineNo = 1; !feof( stdin ); lineNo++ ) {
836     getLine( line, sizeof(line) );
837     if ( strlen(line) != 0 ) {
838       char *p;
839       char *keyword;
840
841       if ( (keyword = strtok_r( line, " \t", &p )) != NULL ) {
842         DBG_VERBOSE printf( "%d)   Keyword:\"%s\"\n", lineNo, keyword );
843         if ( strcasecmp( "gdc", keyword ) == 0 ) {
844           if ( workingAs != gdc && workingAs != unknown ) {
845             fprintf( stderr,
846                      "%s: line:%d GDC found when working in non-GDC mode (e.g. as a LDC)\n",
847                      myName, lineNo );
848             exit( 1 );
849           }
850           workingAs = gdc;
851           parseGdc( p );
852           createNewEvent();
853           currLdcId = HOST_ID_MIN;
854           currLdc = NULL;
855           currEquipmentId = 0;
856         } else if ( strcasecmp( "ldc", keyword ) == 0 ) {
857           if ( workingAs != gdc && workingAs != ldc && workingAs != unknown ) {
858             fprintf( stderr,
859                      "%s: line:%d LDC found when working in non-LDC/GDC mode\n",
860                      myName, lineNo );
861             exit( 1 );
862           }
863           if ( workingAs == unknown ) workingAs = ldc;
864           parseLdc( p );
865           if ( workingAs == ldc ) {
866             createNewEvent();
867             currEquipmentId = 0;
868           } else {
869             createNewLdcEvent();
870             handleLdc( currLdcId );
871             currLdcId++;
872           }
873           currEvent = NULL;
874         } else if ( strncasecmp( "equ", keyword, 3 ) == 0 ) {
875           if ( workingAs == unknown
876             || (workingAs == ldc && currLdc == NULL )
877             || (workingAs == gdc && currGdc == NULL ) ) {
878             fprintf( stderr,
879                      "%s: line:%d Unexpected EQUIPMENT declaration (LDC or GDC needed first)\n",
880                      myName,
881                      lineNo );
882             exit( 1 );
883           }
884           parseEquipment( p );
885           currEquipmentId++;
886         } else {
887           fprintf( stderr,
888                    "%s: line:%d Parse error in \"%s\" unknown keyword\n",
889                    myName,
890                    lineNo,
891                    keyword );
892           exit( 1 );
893         }
894       }
895     }
896   } while ( !feof( stdin ) );
897   lineNo -= 2;
898
899   DBG_VERBOSE {
900     printf( "End of parse: %d line%s found\n",
901             lineNo,
902             lineNo != 1 ? "s" : "" );
903     printf( "Working as %s\n",
904             workingAs == gdc ? "GDC" :
905              workingAs == ldc ? "LDC" :
906               "UNKNOWN" );
907     if ( workingAs == gdc ) {
908       struct ldcDescriptorStruct *ldc;
909
910       printf( "LDCs (%d):", numOfLdcs );
911       for ( ldc = ldcsHead; ldc != NULL; ldc = ldc->next ) {
912         printf( " %d", ldc->id );
913       }
914       printf( "\n" );
915     }
916     dumpEvents();
917   }
918
919   if ( workingAs == ldc ) {
920     assert( ldcsHead == ldcsTail );
921     assert( ldcsTail == NULL );
922   }
923
924   if ( workingAs == gdc ) {
925     struct ldcDescriptorStruct *ldc;
926
927     assert( ldcsHead != NULL );
928     assert( ldcsTail != NULL );
929     assert( ldcsTail->next == NULL );
930     for ( ldc = ldcsHead; ldc->next != NULL; ldc = ldc->next );
931     assert ( ldc == ldcsTail );
932   }
933
934   if ( workingAs == unknown ) {
935     DBG_VERBOSE printf( "Empty configuration: nothing to do!\n" );
936     exit( 0 );
937   }
938
939   assert( (eventsHead == NULL && eventsTail == NULL)
940        || (eventsHead != NULL && eventsTail != NULL) );
941 } /* End of parseRules */
942
943 void loadTimestamp( struct eventHeaderStruct * const ev ) {
944   time_t t;
945
946   if ( time( &t ) == (time_t)-1 ) {
947     fprintf( stderr,
948              "%s: failed to get system time errno:%d (%s)\n",
949              myName, errno, strerror( errno ) );
950     exit( 1 );
951   }
952   ev->eventTimestamp = (eventTimestampType)t;
953 } /* End of loadTimestamp */
954
955 void initEvent( struct eventHeaderStruct * const ev ) {
956   memset( ev, 0, sizeof( *ev ) );
957
958   ev->eventMagic = EVENT_MAGIC_NUMBER;
959   ev->eventHeadSize = EVENT_HEAD_BASE_SIZE;
960   ev->eventVersion = EVENT_CURRENT_VERSION;
961   ev->eventRunNb = currRunNb;
962   ZERO_EVENT_ID( ev->eventId );
963   ZERO_TRIGGER_PATTERN( ev->eventTriggerPattern );
964   ZERO_DETECTOR_PATTERN( ev->eventDetectorPattern );
965   RESET_ATTRIBUTES( ev->eventTypeAttribute );
966   if ( workingMode == collider )
967     SET_SYSTEM_ATTRIBUTE( ev->eventTypeAttribute, ATTR_ORBIT_BC );
968   ev->eventLdcId = VOID_ID;
969   ev->eventGdcId = VOID_ID;
970   loadTimestamp( ev );
971 } /* End of initEvent */
972
973 int Swap(int x)
974 {
975    // Swap the endianess of the integer value 'x'
976
977    return (((x & 0x000000ffU) << 24) | ((x & 0x0000ff00U) <<  8) |
978            ((x & 0x00ff0000U) >>  8) | ((x & 0xff000000U) >> 24));
979 }
980
981 void outputEvent( const void * const ev,
982                   const int size ) {
983   int done;
984
985   DBG_VERBOSE {
986     const long32 * const v = (long32 *)ev; 
987     printf( "Writing %d bytes @ %p (%d)\n", size, ev, *v );
988   }
989
990   // .............................Test endianess..............................
991   int temp = 1;
992   char* ptemp = (char*) &temp;
993
994   if (ptemp[0]!=1) { // Mac platform: ptemp != 1..............................................................................
995      int  bufSize= size; if (bufSize > (int) sizeof(eventHeaderStruct)) { bufSize = sizeof(eventHeaderStruct); }
996      char* evTemp = (char*) malloc (bufSize);
997      memcpy(evTemp, ev, bufSize);
998
999      if ((bufSize % sizeof(int)) != 0) {
1000             fprintf( stderr, "%s: size of the input buffer ev is not multiple of 4 (size = %d)\n", myName, bufSize);
1001             exit( 1 );
1002           }
1003      else {
1004             // Invert header to evTemp.....................................................
1005             int* buf = (int*) evTemp; 
1006             for (int i=0; i < (int) (bufSize / sizeof(int)); i++, buf++) {
1007                  int value = Swap(*buf); 
1008                  memcpy(evTemp + (i * sizeof(int)), &value, sizeof(int)); 
1009             }
1010
1011             // Write inverted header to file...............................................
1012             if ((done = fwrite( evTemp, bufSize, 1, outF )) != 1 ) {
1013                  fprintf( stderr, "%s: failed to write inverted header. event size:%d bytes, errno:%d (%s)\n", myName, size, errno, strerror( errno ) );
1014                  exit( 1 );
1015             }
1016
1017             if (size > bufSize) {  // Still theraw-data payload to write (but not inverted, since it is inverted eariler).............
1018                 if ((done = fwrite( (char*)ev + bufSize, size - bufSize, 1, outF )) != 1 ) {
1019                     fprintf( stderr, "%s: failed to write additional event size:%d bytes, errno:%d (%s)\n", myName, size, errno, strerror( errno ) );
1020                     exit( 1 );
1021                }
1022             }
1023      }
1024      free(evTemp);
1025   }
1026   else {             // Intel platform: ptemp == 1............................................................................
1027      if ((done = fwrite( ev, size, 1, outF )) != 1 ) {
1028           fprintf( stderr, "%s: failed to write event size:%d bytes, errno:%d (%s)\n", myName, size, errno, strerror( errno ) );
1029           exit( 1 );
1030      }
1031   }
1032 } /* End of outputEvent */
1033
1034 void createSorAndEor( const int sor ) {
1035   unsigned char event[ 1000 ];
1036   struct eventHeaderStruct *ev;
1037   struct eventHeaderStruct sev;
1038
1039   assert( workingAs == ldc || workingAs == gdc );
1040
1041   if ( !createSorEor ) return;
1042   ev = (struct eventHeaderStruct *)event;
1043   initEvent( ev );
1044   ev->eventSize = sizeof( event );
1045   ev->eventType = sor ? START_OF_RUN : END_OF_RUN;
1046   if ( workingMode == fixedTarget )
1047     LOAD_RAW_EVENT_ID( ev->eventId, 0, 0, 0 );
1048   else
1049     LOAD_EVENT_ID( ev->eventId, 0, 0, 0 );
1050   SET_SYSTEM_ATTRIBUTE( ev->eventTypeAttribute, ATTR_P_START );
1051
1052   if ( workingAs == ldc ) {
1053     currLdc = (struct ldcEventDescriptorStruct *)eventsHead;
1054   }
1055   if ( workingAs == gdc ) {
1056     initEvent( &sev );
1057     sev.eventGdcId = currGdcId;
1058     ev->eventGdcId = currGdcId;
1059     currGdc = (struct gdcEventDescriptorStruct *)eventsHead;
1060     currLdc = currGdc->head;
1061   }
1062   ev->eventLdcId = currLdc->id;
1063
1064   if ( workingAs == ldc ) {
1065     loadTimestamp( ev );
1066     outputEvent( ev, ev->eventSize );
1067   }
1068   if ( workingAs == gdc ) {
1069     struct ldcDescriptorStruct *ldc;
1070
1071     loadTimestamp( ev );
1072
1073     sev.eventSize = sizeof( sev ) + numOfLdcs * ev->eventSize;
1074     sev.eventType = sor ? START_OF_RUN : END_OF_RUN ;
1075     COPY_EVENT_ID( ev->eventId, sev.eventId );
1076     COPY_SYSTEM_ATTRIBUTES( ev->eventTypeAttribute, sev.eventTypeAttribute );
1077     SET_SYSTEM_ATTRIBUTE( sev.eventTypeAttribute, ATTR_SUPER_EVENT );
1078     loadTimestamp( &sev );
1079     outputEvent( &sev, sizeof( sev ) );
1080
1081     ev->eventGdcId = currGdcId;
1082     for ( ldc = ldcsHead; ldc != NULL; ldc = ldc->next ) {
1083       ev->eventLdcId = ldc->id;
1084       outputEvent( ev, ev->eventSize );
1085     }
1086   }
1087
1088   ADD_EVENT_ID( ev->eventId, oneEventDelta );
1089   ev->eventSize = ev->eventSize / 2;
1090   ev->eventType = sor ? START_OF_RUN_FILES : END_OF_RUN_FILES;
1091   CLEAR_SYSTEM_ATTRIBUTE( ev->eventTypeAttribute, ATTR_P_START );
1092   if ( workingAs == ldc ) {
1093     loadTimestamp( ev );
1094     outputEvent( ev, ev->eventSize );
1095   }
1096   if ( workingAs == gdc ) {
1097     struct ldcDescriptorStruct *ldc;
1098
1099     loadTimestamp( ev );
1100
1101     sev.eventSize = ev->eventSize;
1102     sev.eventType = sor ? START_OF_RUN_FILES : END_OF_RUN_FILES;
1103     COPY_EVENT_ID( ev->eventId, sev.eventId );
1104     COPY_SYSTEM_ATTRIBUTES( ev->eventTypeAttribute, sev.eventTypeAttribute );
1105     CLEAR_SYSTEM_ATTRIBUTE( sev.eventTypeAttribute, ATTR_SUPER_EVENT );
1106     outputEvent( &sev, sizeof( sev ) );
1107     outputEvent( ev, ev->eventSize - sizeof( sev ) );
1108
1109     sev.eventSize = sizeof( sev ) + ev->eventSize;
1110     sev.eventType = sor ? START_OF_RUN_FILES : END_OF_RUN_FILES;
1111     COPY_EVENT_ID( ev->eventId, sev.eventId );
1112     COPY_SYSTEM_ATTRIBUTES( ev->eventTypeAttribute, sev.eventTypeAttribute );
1113     SET_SYSTEM_ATTRIBUTE( sev.eventTypeAttribute, ATTR_SUPER_EVENT );
1114
1115     loadTimestamp( &sev );
1116
1117     ev->eventGdcId = currGdcId;
1118     for ( ldc = ldcsHead; ldc != NULL; ldc = ldc->next ) {
1119       loadTimestamp( &sev );
1120       outputEvent( &sev, sizeof( sev ) );
1121       ev->eventLdcId = ldc->id;
1122       outputEvent( ev, ev->eventSize );
1123     }
1124   }
1125
1126   ADD_EVENT_ID( ev->eventId, oneEventDelta );
1127   ev->eventSize = sizeof( *ev );
1128   ev->eventType = sor ? START_OF_RUN : END_OF_RUN;
1129   SET_SYSTEM_ATTRIBUTE( ev->eventTypeAttribute, ATTR_P_END );
1130   if ( workingAs == ldc ) {
1131     loadTimestamp( ev );
1132     outputEvent( ev, ev->eventSize );
1133   }
1134   if ( workingAs == gdc ) {
1135     struct ldcDescriptorStruct *ldc;
1136
1137     loadTimestamp( ev );
1138
1139     sev.eventSize = sizeof( sev ) + numOfLdcs * ev->eventSize;
1140     sev.eventType = sor ? START_OF_RUN : END_OF_RUN;
1141     COPY_EVENT_ID( ev->eventId, sev.eventId );
1142     COPY_SYSTEM_ATTRIBUTES( ev->eventTypeAttribute, sev.eventTypeAttribute );
1143     SET_SYSTEM_ATTRIBUTE( sev.eventTypeAttribute, ATTR_SUPER_EVENT );
1144     loadTimestamp( &sev );
1145
1146     outputEvent( &sev, sizeof( sev ) );
1147
1148     for ( ldc = ldcsHead; ldc != NULL; ldc = ldc->next ) {
1149       ev->eventLdcId = ldc->id;
1150       outputEvent( ev, ev->eventSize );
1151     }
1152   }
1153 } /* End of createSorEor */
1154
1155 void createSor() {
1156   createSorAndEor( TRUE );
1157 } /* End of createSor */
1158
1159 void createEor() {
1160   createSorAndEor( FALSE );
1161 } /* End of createEor */
1162
1163 void loadCdh( struct commonDataHeaderStruct * const cdh,
1164                      eventIdType            * const eventId,
1165                      equipmentIdType id ) {
1166   if ( !handleCDH ) return;
1167
1168   // CTP raw-data does not contain CDH
1169   if ( id == 4352) return;
1170
1171   if ( gotAliceTrigger ) {
1172     cdh->cdhEventId1 = EVENT_ID_GET_BUNCH_CROSSING( *eventId );
1173     cdh->cdhEventId2 = EVENT_ID_GET_ORBIT( *eventId );
1174   } else {
1175     cdh->cdhEventId1 = 0;
1176     cdh->cdhEventId2 = EVENT_ID_GET_NB_IN_RUN( *eventId );
1177   }
1178   cdh->cdhMiniEventId = cdh->cdhEventId1;
1179 }
1180 void decodeCDH( struct ldcEventDescriptorStruct       * const ldc,
1181                 const struct payloadDescriptorStruct  * const payloadDesc,
1182                 equipmentIdType id );
1183
1184 void createEvent( void ) {
1185   assert( workingAs == ldc || workingAs == gdc );
1186
1187   /* Step 1: load all buffers (if needed) and compose the GDC/LDC headers */
1188   if ( workingAs == gdc ) {
1189     struct ldcEventDescriptorStruct *ldc;
1190
1191     for( ldc = currGdc->head; ldc != NULL; ldc = ldc->next ) {
1192       COPY_EVENT_ID( currEventId, ldc->header.eventId );
1193       loadTimestamp( &ldc->header );
1194     }
1195     COPY_EVENT_ID( currEventId, currGdc->header.eventId );
1196     loadTimestamp( &currGdc->header );
1197
1198     for( ldc = currGdc->head; ldc != NULL; ldc = ldc->next ) {
1199       struct equipmentEventDescriptorStruct *eq;
1200       int n;
1201
1202       for ( eq = ldc->head; eq != NULL; eq = eq->next ) {
1203         if ( !bufferData ) {
1204           loadBuffer( eq->payload );
1205           decodeCDH( ldc, eq->payload, eq->id );
1206         }
1207         loadCdh( (struct commonDataHeaderStruct*)eq->payload->data,
1208                  &currEventId,
1209                  eq->id);
1210       }
1211
1212       if ( !currGdc->loaded ) {
1213         for ( n = 0; n != EVENT_TRIGGER_PATTERN_WORDS; n++ )
1214           currGdc->header.eventTriggerPattern[n] |= ldc->header.eventTriggerPattern[n];
1215         for ( n = 0; n != EVENT_DETECTOR_PATTERN_WORDS; n++ )
1216           currGdc->header.eventDetectorPattern[n] |= ldc->header.eventDetectorPattern[n];
1217         for ( n = 0; n != ALL_ATTRIBUTE_WORDS; n++ )
1218           currGdc->header.eventTypeAttribute[n] |= ldc->header.eventTypeAttribute[n];
1219         currGdc->loaded = TRUE;
1220       }
1221     }
1222     cdhRef = NULL;
1223   } else if ( workingAs == ldc ) {
1224     struct equipmentEventDescriptorStruct *eq;
1225
1226     COPY_EVENT_ID( currEventId, currLdc->header.eventId );
1227     loadTimestamp( &currLdc->header );
1228
1229     for ( eq = currLdc->head; eq != NULL; eq = eq->next ) {
1230       if ( !bufferData ) {
1231         loadBuffer( eq->payload );
1232         decodeCDH( currLdc, eq->payload, eq->id );
1233       }
1234       loadCdh( (struct commonDataHeaderStruct*)eq->payload->data,
1235                &currEventId,
1236                eq->id);
1237       currLdc->loaded = TRUE;
1238     }
1239     cdhRef = NULL;
1240   }
1241   ADD_EVENT_ID( currEventId, oneEventDelta );
1242
1243   /* Step 2: output the event */
1244   if ( workingAs == gdc ) {
1245     struct ldcEventDescriptorStruct *ldc;
1246
1247     outputEvent( &currGdc->header, sizeof( currGdc->header ) );
1248
1249     for( ldc = currGdc->head; ldc != NULL; ldc = ldc->next ) {
1250       struct equipmentEventDescriptorStruct *eq;
1251
1252       outputEvent( &ldc->header, sizeof( ldc->header ) );
1253
1254       for ( eq = ldc->head; eq != NULL; eq = eq->next ) {
1255         outputEvent( &eq->header, sizeof( eq->header ) );
1256         outputEvent( eq->payload->data, eq->payload->size );
1257         if ( !bufferData ) unloadBuffer( eq->payload );
1258       }
1259     }
1260     if ( (currGdc = currGdc->next) == NULL )
1261       currGdc = (struct gdcEventDescriptorStruct *)eventsHead;
1262   } else if ( workingAs == ldc ) {
1263     struct equipmentEventDescriptorStruct *eq;
1264
1265     outputEvent( &currLdc->header, sizeof( currLdc->header ) );
1266
1267     for ( eq = currLdc->head; eq != NULL; eq = eq->next ) {
1268       outputEvent( &eq->header, sizeof( eq->header ) );
1269       outputEvent( eq->payload->data, eq->payload->size );
1270       if ( !bufferData ) unloadBuffer( eq->payload );
1271     }
1272     if ( (currLdc = currLdc->next) == NULL )
1273       currLdc = (struct ldcEventDescriptorStruct *)eventsHead;
1274   }
1275 } /* End of createEvent */
1276
1277 void createEvents() {
1278   int eventNum = 0;
1279
1280   currGdc = (struct gdcEventDescriptorStruct *)eventsHead;
1281   currLdc = (struct ldcEventDescriptorStruct *)eventsHead;
1282   currEvent = NULL;
1283
1284   createSor();
1285   for ( eventNum = 0;
1286         eventNum != numOfEvents && numOfEvents != 0;
1287         eventNum++ ) {
1288     createEvent();
1289   }
1290   createEor();
1291 } /* End of createEvents */
1292
1293 int usage() {
1294   fprintf( stderr,
1295            "Usage: %s [-?][-d][-i definitionFile][-o outputFile][-# numOfEvents][-s][-F|-C]\n\
1296    -?                  This text\n\
1297    -v                  Print version ID and exit\n\
1298    -d                  Enable debug (repeat for more verbosity)\n\
1299    -i definitionFile   File with the description of the events to create (default: stdin)\n\
1300    -o outputFile       File used to store events (default: stdout)\n\
1301    -# numOfEvents      Number of events to generate (default: 1 event)\n\
1302    -s                  Do not generate SOR/EOR files (valid only for GDCs)\n\
1303    -F/-C               Working in Fixed Target (F) or Collider (C) mode\n\
1304    -c                  Handles CDH\n\
1305    -D                  Direct disc access (no buffering)\n",
1306            myName );
1307   return 1;
1308 } /* End of usage */
1309
1310 void parseArgs( int argc, char **argv ) {
1311   int arg = 1;
1312   int inFileName = -1;
1313   int outFileName = -1;
1314
1315   myName = argv[0] ;
1316   while ( arg < argc ) {
1317     if ( strcmp( "-?", argv[ arg ] ) == 0 ) {
1318       usage();
1319       exit( 0 );
1320     }
1321     if ( strcmp( "-i", argv[ arg ] ) == 0 ) {
1322       if ( ++arg == argc ) exit( usage() );
1323       inFileName = arg;
1324       if ( freopen( argv[arg], "r", stdin ) == NULL ){
1325         fprintf( stderr,
1326                  "%s: failed to open input definition \"%s\" errno:%d ",
1327                  myName, argv[arg], errno );
1328         perror( "" );
1329         exit( 1 );
1330       }
1331     } else if ( strcmp( "-v", argv[ arg ] ) == 0 ) {
1332       printf( "%s\n", fileHandlerIdent );
1333       exit( 0 );
1334     } else if ( strcmp( "-o", argv[ arg ] ) == 0 ) {
1335       if ( ++arg == argc ) exit( usage() );
1336       outFileName = arg;
1337     } else if ( strcmp( "-#", argv[ arg ] ) == 0 ) {
1338       int n;
1339
1340       if ( ++arg == argc ) exit( usage() );
1341       if ( sscanf( argv[ arg ], "%d", &n ) != 1 ) exit( usage() );
1342       if ( n < 0 ) exit( usage() );
1343       numOfEvents = n;
1344     } else if ( strcmp( "-s", argv[ arg ] ) == 0 ) {
1345       createSorEor = FALSE;
1346     } else if ( strcmp( "-F", argv[ arg ] ) == 0 ) {
1347       workingMode = fixedTarget;
1348     } else if ( strcmp( "-C", argv[ arg ] ) == 0 ) {
1349       workingMode = collider;
1350     } else if ( strcmp( "-d", argv[ arg ] ) == 0 ) {
1351       debug++;
1352     } else if ( strcmp( "-c", argv[ arg ] ) == 0 ) {
1353       handleCDH = TRUE;
1354     } else if ( strcmp( "-D", argv[ arg ] ) == 0 ) {
1355       bufferData = FALSE;
1356     } else if ( strcmp( "-run", argv[ arg ] ) == 0 ) {
1357       int runnumber;
1358       if ( ++arg == argc ) exit( usage() );
1359       if ( sscanf( argv[ arg ], "%d", &runnumber ) != 1 ) exit( usage() );
1360       if ( runnumber < 0 ) exit( usage() );
1361       currRunNb = runnumber;
1362     } else {
1363       fprintf( stderr, "%s: Unknown switch \"%s\"\n", myName, argv[argc] );
1364       exit( usage() );
1365     }
1366     arg++;
1367   }
1368
1369   if ( workingMode == fixedTarget )
1370     LOAD_RAW_EVENT_ID( oneEventDelta, 1, 0, 1 );
1371   else
1372     LOAD_EVENT_ID( oneEventDelta, 0, 0, 1 );
1373   ZERO_EVENT_ID( currEventId );
1374
1375   DBG_VERBOSE {
1376     printf( "Configuration:\n" );
1377     printf( "  Debug level: %d\n", debug );
1378     printf( "  Configuration: %s\n",
1379             inFileName == -1 ? "stdin" : argv[ inFileName ] );
1380     printf( "  Output: %s\n",
1381             outFileName == -1 ? "stdout" : argv[ outFileName ] );
1382     printf( "  Working mode: %s\n",
1383             workingMode == fixedTarget ? "fixed target" : "collider" );
1384     printf( "  Number of events: %d\n", numOfEvents );
1385     printf( "  %s SOR/EOR files\n",
1386             createSorEor ? "Create" : "Do not create" );
1387     printf( "  CDH handling: %s\n",
1388             handleCDH ? "enabled" : "disabled" );
1389     printf( "  data buffering: %s\n",
1390             bufferData ? "enabled" : "DISABLED" );
1391   }
1392
1393   if ( outFileName == -1 ) {
1394     DBG_BASE
1395       printf( "No more trace information from this point...\n" );
1396     debug = 0;
1397     outF = stdout;
1398   } else {
1399     if ( ( outF = fopen( argv[ outFileName ], "w" ) ) == NULL ) {
1400       fprintf( stderr,
1401                "%s: failed to open output file \"%s\" for writing, errno:%d (%s)\n",
1402                myName,
1403                argv[ outFileName ],
1404                errno,
1405                strerror( errno ) );
1406       exit( 1 );
1407     }
1408     DBG_DETAILED
1409       printf( "Output file \"%s\" opened OK for writing\n",
1410               argv[ outFileName ] );
1411   }
1412 } /* End of parseArgs */
1413 void initEquipment( struct equipmentHeaderStruct * const eq ) {
1414   memset( eq, 0, sizeof( *eq ) );
1415   RESET_ATTRIBUTES( eq->equipmentTypeAttribute );
1416   eq->equipmentBasicElementSize = 4;
1417 } /* End of initEquipment */
1418
1419 void decodeCDH(       struct ldcEventDescriptorStruct * const ldc,
1420                 const struct payloadDescriptorStruct  * const payloadDesc,
1421                       equipmentIdType id ) {
1422   if ( handleCDH && 
1423        id != 4352 ) {
1424     struct commonDataHeaderStruct *cdh;
1425     static int softwareTriggerIndicator = FALSE;
1426     int attr;
1427     int trig;
1428
1429     if ( payloadDesc->size < CDH_SIZE ) {
1430       fprintf( stderr,
1431                "%s: payload too small got:%d CDH:%d\n",
1432                myName,
1433                payloadDesc->size,
1434                CDH_SIZE );
1435       exit( 1 );
1436     }
1437     if ( (cdh = (struct commonDataHeaderStruct *)payloadDesc->data) != NULL ) {
1438       if ( cdh->cdhVersion != CDH_VERSION ) {
1439         fprintf( stderr,
1440                  "%s: CDH version mismatch expected:%d got:%d\n",
1441                  myName,
1442                  CDH_VERSION,
1443                  cdh->cdhVersion );
1444         exit( 1 );
1445       }
1446       if ( cdhRef == NULL ) {
1447         cdhRef = cdh;
1448 #define CDH_TRIGGER_INFORMATION_UNAVAILABLE_MASK (1<<CDH_TRIGGER_INFORMATION_UNAVAILABLE_BIT)
1449         gotAliceTrigger = (cdhRef->cdhStatusErrorBits & CDH_TRIGGER_INFORMATION_UNAVAILABLE_MASK) == 0;
1450         if ( gotAliceTrigger && workingMode == fixedTarget ) {
1451           fprintf( stderr,
1452                    "%s: ALICE trigger and fixed target mode are not compatible.\n\
1453 Either work in Collider mode or set the trigger unavailable status bit in the CDH.\n",
1454                    myName );
1455           exit( 1 );
1456         }
1457         if ( gotAliceTrigger ) {
1458           if ( (cdh->cdhL1TriggerMessage & 0x40) != 0 ) {
1459             fprintf( stderr,
1460                      "%s: CDH is a calibration trigger (unsupported) L1TriggerMessage:0x%x\n",
1461                      myName, cdh->cdhL1TriggerMessage );
1462             exit( 1 );
1463           }
1464           if ( (cdh->cdhL1TriggerMessage & 0x01) != 0 ) {
1465             softwareTriggerIndicator = TRUE;
1466           }
1467           if ( softwareTriggerIndicator ) {
1468             switch ((cdh->cdhL1TriggerMessage >> 2) & 0xF) {
1469             case 0xD:
1470             case 0xC:
1471             case 0xB:
1472             case 0xA:
1473             case 0x9:
1474               break;
1475             case 0xF:
1476               /* L1SwC bit = on, Clt bit = off, RoC[4..1] = 0xF --> END_OF_DATA */ 
1477             case 0xE:
1478               /* L1SwC bit = on, Clt bit = off, RoC[4..1] = 0xE0 --> START_OF_DATA */
1479             case 0x8:
1480               /*  L1SwC bit = on, Clt bit = off, RoC[4] = 1, but not 0xE or 0xF
1481                   --> SYSTEM_SOFTWARE_TRIGGER_EVENT */
1482             default:
1483               /*  L1SwC bit = on, Clt bit = off, RoC[4] = 0
1484                   --> DETECTOR_SOFTWARE_TRIGGER_EVENT */
1485               fprintf( stderr,
1486                        "%s: CDH trigger SOD/EOD/SST/DST (unsupported) \
1487 L1TriggerMessage:0x%x ALICETrigger:%s\n",
1488                        myName,
1489                        cdh->cdhL1TriggerMessage,
1490                        gotAliceTrigger ? "yes" : "no" );
1491               exit( 1 );
1492             }
1493           }
1494         }
1495       } else {
1496         if ( (cdh->cdhStatusErrorBits & CDH_TRIGGER_INFORMATION_UNAVAILABLE_MASK) !=
1497              (cdhRef->cdhStatusErrorBits & CDH_TRIGGER_INFORMATION_UNAVAILABLE_MASK) ) {
1498           fprintf( stderr,
1499                    "%s: CDH coherency check failed. \
1500 Trigger information reference:%savailable current:%savailable\n",
1501                    myName,
1502                    (cdhRef->cdhStatusErrorBits & CDH_TRIGGER_INFORMATION_UNAVAILABLE_MASK) == 0 ? "UN" : "",
1503                    (cdh->cdhStatusErrorBits & CDH_TRIGGER_INFORMATION_UNAVAILABLE_MASK) == 0 ? "UN" : "" );
1504           exit( 1 );
1505         }
1506         if ( gotAliceTrigger ) {
1507           if ( cdhRef->cdhL1TriggerMessage != cdh->cdhL1TriggerMessage ) {
1508             fprintf( stderr,
1509                      "%s: CDH coherency check failed. \
1510 L1 trigger message reference:0x%x current:0x%x\n",
1511                      myName,
1512                      cdhRef->cdhL1TriggerMessage,
1513                      cdh->cdhL1TriggerMessage );
1514             exit( 1 );
1515           }
1516           if ( cdh->cdhParticipatingSubDetectors != cdhRef->cdhParticipatingSubDetectors ) {
1517             fprintf( stderr,
1518                      "%s: CDH coherency check failed. \
1519 ParticipatingSubDetectors reference:0x%x current:0x%x\n",
1520                      myName,
1521                      cdhRef->cdhParticipatingSubDetectors,
1522                      cdh->cdhParticipatingSubDetectors );
1523             exit( 1 );
1524           }
1525           if ( cdh->cdhTriggerClassesLow  != cdhRef->cdhTriggerClassesLow
1526                || cdh->cdhTriggerClassesHigh != cdhRef->cdhTriggerClassesHigh ) {
1527             fprintf( stderr,
1528                      "%s: CDH coherency check failed. \
1529 TriggerClassesHigh/Low reference:0x%x-%x current:0x%x-%x\n",
1530                      myName,
1531                      cdhRef->cdhTriggerClassesHigh, cdhRef->cdhTriggerClassesLow,
1532                      cdh   ->cdhTriggerClassesHigh, cdh   ->cdhTriggerClassesLow  );
1533             exit( 1 );
1534           }
1535           if ( cdh->cdhBlockLength != 0xffffffff ) {
1536             if ( (unsigned)payloadDesc->size !=  cdh->cdhBlockLength ) {
1537               fprintf( stderr,
1538                        "%s: CDH coherency check failed. \
1539 Payload size:%d (0x%08x) CDH block length:%d (0x%08x)\n",
1540                        myName,
1541                        payloadDesc->size, payloadDesc->size,
1542                        cdh->cdhBlockLength, cdh->cdhBlockLength );
1543               exit( 1 );
1544             }
1545           }
1546           if ( cdh->cdhRoiLow  != cdhRef->cdhRoiLow
1547                || cdh->cdhRoiHigh != cdhRef->cdhRoiHigh ) {
1548             fprintf( stderr,
1549                      "%s: CDH coherency check failed. \
1550 RoiHigh/Low reference:0x%x-%x current:0x%x-%x\n",
1551                      myName,
1552                      cdhRef->cdhRoiHigh, cdhRef->cdhRoiLow,
1553                      cdh   ->cdhRoiHigh, cdh   ->cdhRoiLow  );
1554             exit( 1 );
1555           }
1556         }
1557         if ( cdh->cdhMBZ0 != 0
1558              || cdh->cdhMBZ1 != 0
1559              || cdh->cdhMBZ2 != 0
1560              || cdh->cdhMBZ3 != 0 ) {
1561           fprintf( stderr,
1562                    "%s: CDH check failed. MBZ0:0x%x MBZ1:0x%x MBZ2:0x%x MBZ3:0x%x\n",
1563                    myName,
1564                    cdh->cdhMBZ0, cdh->cdhMBZ1, cdh->cdhMBZ2, cdh->cdhMBZ3 );
1565           exit( 1 );
1566         }
1567       }
1568       for ( attr = 0; attr != 8; attr++ ) {
1569         if ( (cdh->cdhBlockAttributes & (1<<attr)) != 0 ) {
1570           SET_USER_ATTRIBUTE( ldc->header.eventTypeAttribute, attr );
1571         }
1572       }
1573       for ( trig = 0; trig != 32; trig++ ) {
1574         if ( (cdh->cdhTriggerClassesLow & (1<<trig)) != 0 ) {
1575           SET_TRIGGER_IN_PATTERN( ldc->header.eventTriggerPattern,
1576                                   trig );
1577         }
1578       }
1579       for ( trig = 0; trig != 18; trig++ ) {
1580         if ( (cdh->cdhTriggerClassesHigh & (1<<trig)) != 0 ) {
1581           SET_TRIGGER_IN_PATTERN( ldc->header.eventTriggerPattern,
1582                                   32+trig );
1583         }
1584       }
1585       if ( gotAliceTrigger )
1586         VALIDATE_TRIGGER_PATTERN( ldc->header.eventTriggerPattern );
1587     }
1588   }
1589 } /* End of decodeCDH */
1590
1591 void initEvents() {
1592   assert( workingAs == ldc || workingAs == gdc );
1593
1594   if ( workingAs == gdc ) {
1595     struct gdcEventDescriptorStruct *gdc;
1596
1597     for ( gdc = (struct gdcEventDescriptorStruct *)eventsHead;
1598           gdc != NULL;
1599           gdc = gdc->next ) {
1600       struct ldcEventDescriptorStruct *ldc;
1601
1602       initEvent( &gdc->header );
1603       gdc->header.eventSize = gdc->header.eventHeadSize;
1604       gdc->header.eventType = PHYSICS_EVENT;
1605       SET_SYSTEM_ATTRIBUTE( gdc->header.eventTypeAttribute, ATTR_SUPER_EVENT );
1606       gdc->header.eventGdcId = currGdcId;
1607       for ( ldc = gdc->head; ldc != NULL; ldc = ldc->next ) {
1608         struct equipmentEventDescriptorStruct *eq;
1609
1610         initEvent( &ldc->header );
1611         ldc->header.eventSize = ldc->header.eventHeadSize;
1612         ldc->header.eventType = PHYSICS_EVENT;
1613         ldc->header.eventGdcId = currGdcId;
1614         ldc->header.eventLdcId = ldc->id;
1615         for ( eq = ldc->head; eq != NULL; eq = eq->next ) {
1616           initEquipment( &eq->header );
1617           eq->header.equipmentId = eq->id;
1618           if ( workingMode == collider )
1619             SET_SYSTEM_ATTRIBUTE( eq->header.equipmentTypeAttribute,
1620                                   ATTR_ORBIT_BC );
1621           eq->header.equipmentSize = eq->payload->size + sizeof( eq->header );
1622           ldc->header.eventSize += eq->header.equipmentSize;
1623           decodeCDH( ldc, eq->payload, eq->id );
1624           OR_ALL_ATTRIBUTES( eq->header.equipmentTypeAttribute,
1625                              ldc->header.eventTypeAttribute );
1626           OR_ALL_ATTRIBUTES( eq->header.equipmentTypeAttribute,
1627                              gdc->header.eventTypeAttribute );
1628         }
1629         gdc->header.eventSize += ldc->header.eventSize;
1630       }
1631       cdhRef = NULL;
1632     }
1633
1634     DBG_VERBOSE {
1635       printf( "Headers:\n" );
1636       for ( gdc = (struct gdcEventDescriptorStruct *)eventsHead;
1637             gdc != NULL;
1638             gdc = gdc->next ) {
1639         struct ldcEventDescriptorStruct *ldc;
1640         
1641         printf( "   GDC:%d size:%d vers:%08x\n",
1642                 currGdcId,
1643                 gdc->header.eventSize,
1644                 gdc->header.eventVersion);
1645         for ( ldc = gdc->head; ldc != NULL; ldc = ldc->next ) {
1646           struct equipmentEventDescriptorStruct *eq;
1647
1648           printf( "      LDC:%d size:%d vers:%08x\n",
1649                   ldc->id,
1650                   ldc->header.eventSize,
1651                   ldc->header.eventVersion );
1652           for ( eq = ldc->head; eq != NULL; eq = eq->next ) {
1653             printf( "         EQ:%d size:%d %spayload:%d\n",
1654                     eq->id,
1655                     eq->header.equipmentSize,
1656                     eq->header.equipmentSize - sizeof( struct equipmentHeaderStruct ) == (unsigned)eq->payload->size ? "" : "-ERROR",
1657                     eq->payload->size );
1658           }
1659         }
1660       }
1661     }
1662   } else if ( workingAs == ldc ) {
1663     struct ldcEventDescriptorStruct *ldc;
1664
1665     for ( ldc = (struct ldcEventDescriptorStruct *)eventsHead;
1666           ldc != NULL;
1667           ldc = ldc->next ) {
1668       struct equipmentEventDescriptorStruct *eq;
1669
1670       initEvent( &ldc->header );
1671       ldc->header.eventSize = ldc->header.eventHeadSize;
1672       ldc->header.eventType = PHYSICS_EVENT;
1673       ldc->header.eventGdcId = VOID_ID;
1674       ldc->header.eventLdcId = ldc->id;
1675       for ( eq = ldc->head; eq != NULL; eq = eq->next ) {
1676         initEquipment( &eq->header );
1677         eq->header.equipmentId = eq->id;
1678         if ( workingMode == collider )
1679           SET_SYSTEM_ATTRIBUTE( eq->header.equipmentTypeAttribute,
1680                                 ATTR_ORBIT_BC );
1681         eq->header.equipmentSize = eq->payload->size + sizeof( eq->header );
1682         ldc->header.eventSize += eq->header.equipmentSize;
1683         decodeCDH( ldc, eq->payload, eq->id );
1684         OR_ALL_ATTRIBUTES( eq->header.equipmentTypeAttribute,
1685                            ldc->header.eventTypeAttribute );
1686       }
1687       cdhRef = NULL;
1688     }
1689     DBG_VERBOSE {
1690       printf( "Headers:\n" );
1691       for ( ldc = (struct ldcEventDescriptorStruct *)eventsHead;
1692             ldc != NULL;
1693             ldc = ldc->next ) {
1694         struct equipmentEventDescriptorStruct *eq;
1695
1696         printf( "      LDC:%d size:%d vers:%08x\n",
1697                 ldc->id,
1698                 ldc->header.eventSize,
1699                 ldc->header.eventVersion );
1700         for ( eq = ldc->head; eq != NULL; eq = eq->next ) {
1701           printf( "         EQ:%d size:%d %spayload:%d\n",
1702                   eq->id,
1703                   eq->header.equipmentSize,
1704                   eq->header.equipmentSize - sizeof( struct equipmentHeaderStruct ) == (unsigned)eq->payload->size ? "" : "-ERROR",
1705                   eq->payload->size );
1706         }
1707       }
1708     }
1709   }
1710 } /* End of initEvents */
1711
1712 void initVars() {
1713   debug = 0;
1714   workingAs = unknown;
1715   workingMode = fixedTarget;
1716   ldcsHead = ldcsTail = NULL;
1717   eventsHead = eventsTail = NULL;
1718   currGdc = NULL;
1719   currLdc = NULL;
1720   currEvent = NULL;
1721   payloadsHead = payloadsTail = NULL;
1722   currRunNb = -1;
1723   numOfLdcs = 0;
1724   numOfEvents = 1;
1725   createSorEor = TRUE;
1726   handleCDH = FALSE;
1727   gotAliceTrigger = TRUE;
1728   bufferData=TRUE;
1729 } /* End of initVars */
1730
1731 int main( int argc, char **argv ) {
1732   initVars();
1733   parseArgs( argc, argv );
1734   parseRules();
1735   initEvents();
1736   createEvents();
1737   return 0;
1738 } /* End of main */