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