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