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