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