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