20-apr-2005 NvE Id of owning device added to the output of AliSignal::Data().
[u/mrichter/AliRoot.git] / RALICE / icepack / iceconvert / amanda.c
1 /*
2  * Read/write files in the oncoming Standard AMANDA format - "format 2000"
3  */
4 #if 0 /******* TODO *********/
5 /* skip event gets array as parameter   */
6 /* level 4 event types in mevt  */
7 /*   end of file, tend          */
8 /******************************/        
9 #endif
10
11
12 char *amanda_rdmc_cvsid = 
13 "$Header: /net/local/cvsroot/siegmund/rdmc/amanda.c,v 1.81 2004/02/19 17:10:08 wiebusch Exp $";
14
15 #include <stdlib.h>
16 #include <ctype.h>
17
18 #include "rdmc.h"
19 #ifdef AMANDA_ASCII_F
20
21 #include "rdmc_local.h"
22
23 #include "amanda.h"
24 #include "f2k.h"
25
26 /****************************************************************************/
27 /*       rdmc_nint(double a)                                                 */
28 /* converts a to the nearest integer                                        */
29 /* but also takes care on the sign                                          */
30 /****************************************************************************/
31 long rdmc_nint(double a)
32 { long i;
33   i =  (a >= 0.) ?  (long) (a + 0.5 ) : (long) (a - 0.5);
34  return  i;
35 }
36
37 /*******************************/
38 /* Work around missing isnan() */
39 /*******************************/
40 int isnan(float r)
41 {
42  return 0;
43 }
44
45 /******************************************************/
46 /*** Definitions of f2k blocks struture in memory   ***/
47 /******************************************************/
48
49
50 /* check if line is in  buffer or read a new one */
51 /* returns 0 if OK */
52 static int amanda_readline(mcfile *fp);
53
54 /* dump a line back into the buffer if it is empty */
55 /* returns 0 if OK */
56 static int amanda_unreadline(mcfile *fp);
57
58 /* read the next block according to a list of allowed lines into the buffer */
59 /* returns 0 if OK */
60 static int amanda_read_block(mcfile *fp ,const f2000_event_t *def);
61
62 /* try to decode a given line according to line_def */
63 /* store if OK */
64 /* returns RDMC_IO_OK or RDMC_LINE_EMPTY or RDMC_EVENT_NOT_RECOGNIZED */ 
65 static int amanda_lex_line(mcfile *fp, const f2000_line_t * const line_def[F2K_MAX_LINETYPES] );
66
67 /* compares each byte of key to the first no white exam until lngth of key*/
68 /* -1 if line is empty, 0 on no and 1 on succes */
69 static int tokencmp(const char *key, char *exam);
70
71 /* same with no trailing chars */ 
72 static int tokencmp_notrail(const char *key, char *exam);
73
74 /* checks if the first non-white char in exam is in keys */
75 /* if a line is only whitespace ot empty -1 is returned */
76 /* 0: if the char is not found */
77 /* 1: if the char is not found */
78 static int tokenchr(const char *keys, char *exam);
79 /* same as above but chars are not alnum (ispunct()) */
80 static int tokenchrpunct(const char *keys, char *exam);
81
82 /***************************************************************************/
83 /***************************************************************************/
84 /***                                                                     ***/
85 /*** Read  functions follow                                              ***/
86 /***                                                                     ***/
87 /***************************************************************************/
88
89   
90 /****************************************************************************
91  * read the F2000 "V" line (the first one) and put it into fp
92  ****************************************************************************/
93 /******* This is the only parswer routine, which is different !!! */
94 /* it reads directly from fp, instead of the readline mode */
95 int rdmc_amanda_V(const char *s, mcfile *fp)
96 {
97   int major = 0, minor = 0;
98   if(sscanf(s,"V 2000.%i.%i",&major, &minor) != 2) 
99     return RDMC_LINE_NOT_PARSED;
100   if (rdmc_is_f2000_supported(major, minor) == 0)
101     return  RDMC_UNKNOWN_FORMAT_VERSION;
102   fp->fmajor = major;
103   fp->fminor = minor;
104   return RDMC_IO_OK;
105
106 } /* amanda_rdmc_V() */
107
108 int rdmc_rhd_amanda(mcfile *fp){ 
109   const  f2000_event_t *ev_def;
110   int ret;
111
112   /* get the config def for the right format*/
113   switch( 100*fp->fmajor + fp->fminor ){
114   case 101:
115   case 102:
116   case 200401:
117     ev_def=&f2000_preamble_1x1;
118     break;
119   default:
120     return RDMC_UNKNOWN_FORMAT_VERSION;
121   }
122
123   /* read the block acordng to the def */
124   if ((ret = amanda_read_block(fp, ev_def)) != RDMC_IO_OK)
125     return ret;
126
127   /* use the pointer from  the event definition and scan*/
128   return ev_def->reader(fp, NULL, NULL);
129 }
130
131
132 int rdmc_rarr_amanda(mcfile *fp, array *ar)
133
134   const  f2000_event_t *ev_def;
135   int ret;
136
137   /* get the config def for the right format*/
138   switch( 100*fp->fmajor + fp->fminor ){
139   case 101:
140   case 102:
141   case 200401:
142     ev_def=&f2000_mhead_1x1;
143     break;
144   default:
145     return RDMC_UNKNOWN_FORMAT_VERSION;
146   }
147
148   /* read the block acordng to the def */
149   if ((ret = amanda_read_block(fp, ev_def)) != RDMC_IO_OK)
150     return ret;
151
152   /* use the pointer from  the event definition and scan*/
153   return ev_def->reader(fp, ar, NULL);
154
155 }
156
157 int rdmc_revt_amanda(mcfile *fp, mevt *ev, array *ar){ 
158   const  f2000_event_t **ev_def,*foot_def;
159
160   int ret = RDMC_ILF;
161   int ret2 = RDMC_ILF;
162
163   /* get the config def for the right format*/
164   /* get the config def for the right format*/
165   switch( 100*fp->fmajor + fp->fminor ){
166   case 101:
167     ev_def = f2000_events_1x1;
168     foot_def =  &f2000_mfoot_1x1 ;
169     break;
170   case 102:
171     ev_def =f2000_events_1x2;
172     foot_def =  &f2000_mfoot_1x1 ;
173     break;
174   case 200401:
175     ev_def =f2000_events_2004x1;
176     foot_def =  &f2000_mfoot_1x1 ;
177     break;
178   default:
179     return RDMC_UNKNOWN_FORMAT_VERSION;
180   }
181
182   while( *ev_def !=NULL ){
183     /* read the block acordng to the def */
184     ret = amanda_read_block(fp, *ev_def);
185     if ( ret == RDMC_IO_OK)
186       break;
187     ++ev_def;
188   }
189   if ( ret == RDMC_IO_OK){
190     rdmc_clear_mevt(ev);                           /* reset the event */
191     /* use the pointer from  the event definition and scan*/
192     if (fp->info.f2000.nolex)
193       return RDMC_IO_OK;
194     else
195       return (*ev_def)->reader(fp, ar, ev);
196   }else{  /* test footer */
197     if ( ret == RDMC_EVENT_NOT_RECOGNIZED) {
198       ret2 = amanda_read_block(fp, foot_def);
199       if (ret2 == RDMC_IO_OK)
200         return RDMC_EOF;
201       else
202         return ret2;
203     }else{
204       return ret;
205     }
206   }
207 }
208
209 int rdmc_skipevt_amanda(mcfile *fp)
210
211   int ret;
212 #if 0
213   array ar;
214 #endif
215   mevt ev;
216 #if 0 /* this is the proper, presently slow version */
217   rdmc_init_array(&ar); 
218   rdmc_init_mevt(&ev);
219   fp->info.f2000.nolex=1;
220   ret = rdmc_revt_amanda(fp, &ev, &ar);
221   fp->info.f2000.nolex=0;
222   rdmc_clear_array(&ar);
223   rdmc_clear_mevt(&ev);
224 #else /* presently no array is needed -> dirty patch ! */
225   rdmc_init_mevt(&ev);
226   fp->info.f2000.nolex=1;
227   ret = rdmc_revt_amanda(fp, &ev, NULL);
228   fp->info.f2000.nolex=0;
229   rdmc_clear_mevt(&ev);
230 #endif
231   return ret;
232 }
233
234
235
236 /****************************************************************************
237  * Reads a nonempty line 
238  ****************************************************************************/
239 static int amanda_readline(mcfile *fp){
240
241   char *s = fp->last_line;
242   do {
243     if (fp->info.f2000.unread != 0 ) { /* line in buffer */
244       fp->info.f2000.unread = 0;
245     } else{ /* no line in buffer - read from file */
246       if (fgets(s, RDMC_MAXLINE-1, fp->fp) == NULL)/*fgets includes the '\n'*/
247         return EOF;
248     }
249   } while (*s == '\0');      /* look for a not-empty line */
250   /* increment the counter line */
251   fp->fpos++;
252   return RDMC_IO_OK;
253
254 } /* amanda_readline() */
255
256 /****************************************************************************
257  * "unread" an amanda F2000 format line
258  ****************************************************************************/
259
260 static int amanda_unreadline(mcfile *fp){
261   if (fp->info.f2000.unread != 0) 
262     return EOF; /* only one line allowed */
263   else
264     fp->info.f2000.unread = 1;
265   fp->fpos--;
266   return RDMC_IO_OK;
267 } /* amanda_unreadline() */
268
269
270 static int amanda_read_block(mcfile *fp ,const f2000_event_t *def){
271   int r;
272   int ret=RDMC_ILF;
273   int do_reading;
274   rdmc_clear_f2k_buffer(fp->info.f2000.f2k_buffer);
275   fp->errline = 0;
276
277   /* test if the block starts with the right line */
278   do_reading=1;
279   do {
280     if (def->opener[0]){  /* yes there is one needed ! */
281       if ( (r=amanda_readline(fp)) != RDMC_IO_OK)
282         ret=r;
283       else /* analyse if this line matches and store it then */
284         ret = amanda_lex_line(fp, def->opener);
285     } else{ /* no opener needed  -> OK */
286       ret = RDMC_IO_OK;
287       break;
288     }
289     if( ret != RDMC_LINE_EMPTY ){ /* something happende */
290       do_reading=0;
291       if ( ret == RDMC_EVENT_NOT_RECOGNIZED){
292         amanda_unreadline(fp); /* we have read one line to much  */
293         return ret;
294       }
295     }
296   } while(do_reading);
297
298   /* keep on reading body lines  */
299   do_reading=1;
300   do {
301     /* analyse if this line matches and store it then */
302     if (def->inner[0]){  /* yes there are some  ! */
303       if ( (r=amanda_readline(fp)) != RDMC_IO_OK)
304         ret =r;
305       else
306         ret = amanda_lex_line(fp, def->inner);
307     } else{ 
308       ret = RDMC_IO_OK;
309       do_reading=0;
310       break;
311     }
312
313     if( ret != RDMC_LINE_EMPTY ){ /* something happend */
314       if (ret == RDMC_IO_OK) /* line OK -> next one */
315         continue;
316       else{ /* line is not parsed -> check if an end marker appeared */
317         amanda_unreadline(fp); /* we have read one line to much  */
318         do_reading = 0; /* this is no error since the body may be empty */
319         ret = RDMC_IO_OK; /* this is no error but maybe  the next event */
320         break; /* ok we end here */
321       }
322     }
323   } while(do_reading);
324
325   /* check the end marker   */
326   do_reading=1;
327   do {
328     /* analyse if this line matches and store it then */
329     if (def->closer[0]){  /* yes there are some needed ! */
330       if ( (r=amanda_readline(fp)) != RDMC_IO_OK)
331         ret=r;
332       else
333         ret = amanda_lex_line(fp, def->closer);
334     } else{ 
335       ret = RDMC_IO_OK;
336       do_reading=0;
337       break;
338     }
339
340     if( ret != RDMC_LINE_EMPTY ){ /* something happend */
341       if (ret == RDMC_IO_OK){ /* line OK -> finish */
342         do_reading=0;
343         break;
344       }
345       else{ /* line is not parsed  */
346         amanda_unreadline(fp); /* we have read one line to much  */
347         do_reading = 0; /* this is no error since the body may be empty */
348         break; /* ok we end here */
349       }
350     }
351   } while(do_reading);
352
353   return ret;
354 }
355
356
357 static int amanda_lex_line(mcfile *fp, const f2000_line_t * const line_def[F2K_MAX_LINETYPES] ){
358   int ptindex , cres = 0;
359   const f2000_line_t *opt;
360
361   if ( !(line_def[0]) ) /* no match actually needed */
362     return RDMC_EVENT_NOT_RECOGNIZED;
363
364   for(ptindex=0 , cres=0, opt = line_def[0] 
365         ; opt 
366         ; opt = line_def[++ptindex] 
367       ){
368
369     switch (opt->searchtype){
370     case COMP_STRINGWISE:
371       cres = tokencmp(opt->tag,fp->last_line);
372       break;
373     case COMP_STRINGWISE_NOTRAIL:
374       cres = tokencmp_notrail(opt->tag,fp->last_line);
375       break;
376     case COMP_CHARWISE:
377       cres = tokenchr(opt->tag,fp->last_line);
378       break;
379     case COMP_CHARPUNCT:
380       cres = tokenchrpunct(opt->tag,fp->last_line);
381       break;
382 #if 0
383     case COMP_DUMMY: /* no token is needed so stop parsing */
384       /* trap to finish here */
385       return RDMC_EVENT_NOT_RECOGNIZED;
386       break;
387 #endif
388     default:
389       return RDMC_LIBRARY_ERROR;
390     } /* switch */
391     if (cres < 0){ /* empty line */
392       return RDMC_LINE_EMPTY;
393     } else if(cres == 0){ /* no match found */
394       /* needed but not found -> try the next */
395       continue;
396     }else{ /* ok tag is found */
397       rdmc_push_f2k_buffer(fp->info.f2000.f2k_buffer, fp->last_line,line_def[ptindex]); 
398       return RDMC_IO_OK;
399     } /* check cres */
400   } /*for */
401   return RDMC_EVENT_NOT_RECOGNIZED;
402 }
403
404 /* compares each byte of key to exam until th lngth of key */
405 /* leading whitespaces are ignored */
406 static int tokencmp(const char *key, char *exam){
407   int r = -1;
408   const char *k = key;
409   const char *e = exam;
410   while(*e){
411     if (isspace(*e))
412       ++e;
413     else { /* this is the first non white */
414       r=0;
415       while (*k){ /* now check key */
416         if (!(*e)) /* if e ends before key */ 
417           return r=0;
418         if( *e == *k ) /* stil agreement ? */
419           r=1;
420         else
421           return r=0; /* break if not */
422         ++e; /* next char */
423         ++k;
424       } /* while k */
425       return r; /*  exit here likely with r==1  */
426     } 
427   } /* while e */
428
429   return r;
430 }
431 /* compares each byte of key to exam until the lngth of key */
432 /* trailing chars are ignored */
433 static int tokencmp_notrail(const char *key, char *exam){
434   int r = -1;
435   const char *k = key;
436   const char *e = exam;
437   while(*e){
438     if (isspace(*e))
439       ++e;
440     else { /* this is the first non white */
441       r=0;
442       while (*k){ /* now check key */
443         if (!(*e)) /* if e ends before key */ 
444           return r=0;
445         if( *e == *k ) /* stil agreement ? */
446           r=1;
447         else
448           return r=0; /* break if not */
449         ++e; /* next char */
450         ++k;
451       } /* while k */
452       return r; /*  exit here likely with r==1  */
453     } 
454   } /* while e */
455   return r;
456 }
457
458 /* checks if the first non-white char in exam is in keys */
459 /* if a line is only whitespace ot empty -1 is returned */
460 /* 0: if the char is not found */
461 /* 1: if the char is found */
462 static int tokenchr(const char *keys, char *exam){
463   int r = -1;
464   const char *k=keys;
465   const char *e=exam;
466   while(*e){
467     if (isspace(*e))
468       ++e;
469     else { /* this is the first non white */
470       r=0;
471       while (*k){ /* now check key */
472         if( *e == *k ) /* agreement ? */
473           return r=1;
474         else
475           ++k;
476       } /* while k */
477       return r=0; /*  exit here likely with r==1  */
478     } 
479   } /* while e */
480   return r;
481 }
482
483 static int tokenchrpunct(const char *keys, char *exam){
484   int r = -1;
485   const char *k=keys;
486   const char *e=exam;
487   while(*e){
488     if (isspace(*e))
489       ++e;
490     else if (!ispunct(*e))
491       return r=0;
492     else { /* this is the first non white */
493       r=0;
494       while (*k){ /* now check key */
495         if( *e == *k ) /* agreement ? */
496           return r=1;
497         else
498           ++k;
499       } /* while k */
500       return r=0; /*  exit here likely  */
501     } 
502   } /* while e */
503   return r;
504 }
505
506
507 /***************************************************************************/
508 /***                                                                     ***/
509 /*** Write functions follow                                              ***/
510 /***                                                                     ***/
511 /***************************************************************************/
512 /***************************************************************************/
513
514
515
516
517 /***************************************************************************/
518 /* write end of file (F2000 format)                                        */
519 int rdmc_wrend_amanda(const mcfile *fp)
520 {
521   const  f2000_event_t *ev_def;
522
523   /* get the config def for the right format*/
524   switch( 100*fp->fmajor + fp->fminor ){
525   case 101:
526   case 102:
527   case 200401:
528     ev_def=&f2000_mfoot_1x1;
529     break;
530   default:
531     return RDMC_UNKNOWN_FORMAT_VERSION;
532   }
533
534   /* use the pointer from  the event definition and scan*/
535   return ev_def->writer(fp, NULL, NULL);
536 } /* wrend_amanda() */
537
538 /****************************************************************************
539  * function warr_amanda() writes the array info to a amanda-like file
540  * This function writes out the head of a AMANDA ascii file
541  * opposite to reading the input file it writes not only
542  * the Geometry banks ('G', 'P') , but also the ('V' and 'M' flags)
543  * so the function whd_amanda does not exist
544  ****************************************************************************/
545
546 int rdmc_warr_amanda(const mcfile *fp,const array *geo)
547 {
548   const  f2000_event_t *ev_def;
549
550   /* get the config def for the right format*/
551   switch( 100*fp->fmajor + fp->fminor ){
552   default:
553     ev_def=&f2000_mhead_1x1;
554     break;
555   }
556
557   /* use the pointer from  the event definition and scan*/
558   return ev_def->writer(fp, geo, NULL);
559 }
560
561 /****************************************************************************
562  * function wevt_amanda() writes an event to a amanda-like file
563  ****************************************************************************/
564
565 int rdmc_wevt_amanda(const mcfile *fp,const mevt *event, const array *ar)
566 {
567   const  f2000_event_t *ev_def;
568
569   /* get the config def for the right format*/
570   switch( 100*fp->fmajor + fp->fminor ){
571   case 101:
572     ev_def=f2000_events_1x1[0]; /* take first array element */
573     break;
574   case 102:
575     ev_def=f2000_events_1x2[0]; /* take first array element */
576     break;
577   case 200401:
578     ev_def=f2000_events_2004x1[0]; /* take first array element */
579     break;
580   default:
581     return RDMC_UNKNOWN_FORMAT_VERSION;
582   }
583
584   /* use the pointer from  the event definition and scan*/
585   return ev_def->writer(fp, ar, event);
586
587 }
588
589 #if 0
590 /****************************************************************************
591  * wrhist_amanda() writes history lines to an ASCII file
592  ****************************************************************************/
593
594 int rdmc_wrhist_amanda(const mcfile *fp, const char *s, const char *pre)
595 {
596   return rdmc_wrhist_f2k_1x1(fp, s, pre);
597 }
598
599 /****************************************************************************
600  * wrcomment_amanda() writes a comment line to an ASCII file
601  ****************************************************************************/
602
603 int rdmc_wrcomment_amanda(const mcfile *fp, const char *s)
604 {
605   return rdmc_wrcomment_f2k_1x1(fp, s);
606 }
607 #endif
608
609 #endif /* AMANDA_ASCII_F */
610
611 /****************************************************************************
612  ********************************** E O F ***********************************
613  ****************************************************************************/
614 /* 
615    This is just for EMACS:
616    Local Variables:
617    compile-command: "cd .. ; make -k rdmc" 
618    End: 
619 */
620
621
622
623
624
625
626
627
628
629
630
631