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