mhdump.cxx

Go to the documentation of this file.
00001 //
00002 // mhdump: midas history explorer
00003 //
00004 // Author: Konstantin Olchanski, 20-NOV-2007
00005 //
00006 // Compile: 
00007 //   g++ -o mhdump.o -c mhdump.cxx -O2 -g -Wall -Wuninitialized
00008 //   g++ -o mhdump -g -O2 mhdump.o
00009 //
00010 // $Id$
00011 //
00012 
00013 #include <stdio.h>
00014 #include <stdlib.h>
00015 #include <stdint.h>
00016 #include <string.h>
00017 #include <assert.h>
00018 #include <errno.h>
00019 
00020 #include <string>
00021 #include <map>
00022 #include <vector>
00023 
00024 ////////////////////////////////////////
00025 // Definitions extracted from midas.h //
00026 ////////////////////////////////////////
00027 
00028 #define DWORD uint32_t
00029 
00030 #define NAME_LENGTH            32            /**< length of names, mult.of 8! */
00031 
00032 typedef struct {
00033    DWORD record_type;           /* RT_DATA or RT_DEF */
00034    DWORD event_id;
00035    DWORD time;
00036    DWORD def_offset;            /* place of definition */
00037    DWORD data_size;             /* data following this header in bytes */
00038 } HIST_RECORD;
00039 
00040 typedef struct {
00041    char name[NAME_LENGTH];             /**< - */
00042    DWORD type;                         /**< - */
00043    DWORD n_data;                       /**< - */
00044 } TAG;
00045 
00046 ////////////////////////////////////////
00047 // Definitions extracted from midas.c //
00048 ////////////////////////////////////////
00049 
00050 /********************************************************************/
00051 /* data type sizes */
00052 int tid_size[] = {
00053    0,                           /* tid == 0 not defined                               */
00054    1,                           /* TID_BYTE      unsigned byte         0       255    */
00055    1,                           /* TID_SBYTE     signed byte         -128      127    */
00056    1,                           /* TID_CHAR      single character      0       255    */
00057    2,                           /* TID_WORD      two bytes             0      65535   */
00058    2,                           /* TID_SHORT     signed word        -32768    32767   */
00059    4,                           /* TID_DWORD     four bytes            0      2^32-1  */
00060    4,                           /* TID_INT       signed dword        -2^31    2^31-1  */
00061    4,                           /* TID_BOOL      four bytes bool       0        1     */
00062    4,                           /* TID_FLOAT     4 Byte float format                  */
00063    8,                           /* TID_DOUBLE    8 Byte float format                  */
00064    1,                           /* TID_BITFIELD  8 Bits Bitfield    00000000 11111111 */
00065    0,                           /* TID_STRING    zero terminated string               */
00066    0,                           /* TID_ARRAY     variable length array of unkown type */
00067    0,                           /* TID_STRUCT    C structure                          */
00068    0,                           /* TID_KEY       key in online database               */
00069    0                            /* TID_LINK      link in online database              */
00070 };
00071 
00072 /* data type names */
00073 char *tid_name[] = {
00074    "NULL",
00075    "BYTE",
00076    "SBYTE",
00077    "CHAR",
00078    "WORD",
00079    "SHORT",
00080    "DWORD",
00081    "INT",
00082    "BOOL",
00083    "FLOAT",
00084    "DOUBLE",
00085    "BITFIELD",
00086    "STRING",
00087    "ARRAY",
00088    "STRUCT",
00089    "KEY",
00090    "LINK"
00091 };
00092 
00093 ////////////////////////////////////////
00094 
00095 struct Tag
00096 {
00097   int event_id;
00098   std::string name;
00099   int offset;
00100   int arraySize;
00101   int typeSize;
00102   int typeCode;
00103 };
00104 
00105 struct Event
00106 {
00107   bool printAllTags;
00108   int size;
00109   std::map<std::string,Tag*> tags;
00110   std::vector<std::string> tagNames;
00111   std::vector<int> tagIndexes;
00112 };
00113 
00114 std::map<int,Event*> gTags;
00115 
00116 bool doPrintTags  = true;
00117 bool doPrintNames = true;
00118 bool doPrintData  = true;
00119 bool doAll        = false;
00120 
00121 int readHstFile(FILE*f)
00122 {
00123   bool doRead = true;
00124 
00125   assert(f!=NULL);
00126 
00127   while (1)
00128     {
00129       HIST_RECORD rec;
00130 
00131       if (doRead)
00132         {
00133           int rd = fread(&rec, sizeof(rec), 1, f);
00134           if (!rd)
00135             break;
00136         }
00137 
00138       doRead = true;
00139 #if 0
00140       printf("HIST_RECORD:\n");
00141       printf("  Record type: 0x%x\n", rec.record_type);
00142       printf("  Event ID: %d\n", rec.event_id);
00143       printf("  Time: %d\n", rec.time);
00144       printf("  Offset: 0x%x\n", rec.def_offset);
00145       printf("  Size: 0x%x\n", rec.data_size);
00146 #endif
00147 
00148       switch (rec.record_type)
00149         {
00150         default:
00151           printf("Unexpected record type: 0x%08x, trying to recover by skipping bad data.\n", rec.record_type);
00152           while (1)
00153             {
00154               int c = fgetc(f);
00155               //printf("read 0x%02x\n", c);
00156               if (c==EOF)
00157                 return 0;
00158               if (c!=0x48)
00159                 continue;
00160 
00161               c = fgetc(f);
00162               if (c==EOF)
00163                 return 0;
00164               if (c!=0x53)
00165                 continue;
00166 
00167               c = fgetc(f);
00168               if (c==EOF)
00169                 return 0;
00170               if (c!=0x44)
00171                 continue;
00172 
00173               printf("Maybe recovered - see what looks like valid history record header.\n");
00174 
00175               ((char*)(&rec))[0] = 0x48;
00176               ((char*)(&rec))[1] = 0x53;
00177               ((char*)(&rec))[2] = 0x44;
00178 
00179               int rd = fread(((char*)(&rec))+3, sizeof(rec)-3, 1, f);
00180               if (!rd)
00181                 return 0;
00182 
00183               doRead = false;
00184               break;
00185             }
00186           break;
00187 
00188         case 0x46445348: // RT_DEF:
00189           {
00190             char event_name[NAME_LENGTH];
00191             int rd = fread(event_name, 1, NAME_LENGTH, f);
00192             assert(rd == NAME_LENGTH);
00193             
00194             int size = rec.data_size;
00195             int ntags = size/sizeof(TAG);
00196 
00197             if (doPrintTags)
00198               printf("Event %d, \"%s\", size %d, %d tags.\n", rec.event_id, event_name, size, ntags);
00199 
00200             assert(size > 0);
00201             assert(size < 1*1024*1024);
00202             assert(size == ntags*(int)sizeof(TAG));
00203             
00204             TAG *tags = new TAG[ntags];
00205             rd = fread(tags, 1, size, f);
00206             assert(rd == size);
00207 
00208             Event* e = gTags[rec.event_id];
00209             if (!e)
00210               {
00211                 gTags[rec.event_id] = new Event;
00212                 e = gTags[rec.event_id];
00213                 e->printAllTags = false;
00214                 if (doAll)
00215                   e->printAllTags = true;
00216               }
00217             else
00218               {
00219                 e->tagNames.clear();
00220                 e->tagIndexes.clear();
00221               }
00222 
00223             e->size = 0;
00224 
00225             int offset = 0;
00226 
00227             for (int itag=0; itag<ntags; itag++)
00228               {
00229                 int tsize = tid_size[tags[itag].type];
00230 
00231                 if (tsize == 0)
00232                   tsize = 1;
00233 
00234                 int size = tags[itag].n_data * tsize;
00235 
00236                 if (offset%tsize != 0)
00237                   offset += tsize-offset%tsize;
00238 
00239                 assert(offset%tsize == 0);
00240 
00241                 Tag* t = new Tag;
00242                 t->event_id  = rec.event_id;
00243                 t->name      = tags[itag].name;
00244                 t->offset    = offset;
00245                 t->arraySize = tags[itag].n_data;
00246                 t->typeSize  = tid_size[tags[itag].type];
00247                 t->typeCode  = tags[itag].type;
00248 
00249                 e->tags[t->name] = t;
00250 
00251                 if (e->printAllTags)
00252                   {
00253                     e->tagNames.push_back(t->name);
00254                     e->tagIndexes.push_back(-1);
00255                   }
00256 
00257                 if (doPrintTags)
00258                   printf("  Tag %d: \"%s\"[%d], type \"%s\" (%d), type size %d, offset %d+%d\n", itag, tags[itag].name, tags[itag].n_data, tid_name[tags[itag].type], tags[itag].type, tid_size[tags[itag].type], offset, size);
00259 
00260                 offset += size;
00261               }
00262 
00263             e->size = offset;
00264 
00265             delete tags;
00266             break;
00267           }
00268 
00269         case 0x41445348: // RT_DATA:
00270           {
00271             int size = rec.data_size;
00272 
00273             if (0)
00274               printf("Data record, size %d.\n", size);
00275 
00276             if (size <= 1 || size > 1*1024*1024)
00277               {
00278                 printf("Invalid data record: event %d, size %d is invalid\n", rec.event_id, rec.data_size);
00279                 continue;
00280               }
00281             
00282             char *buf = new char[size];
00283             int rd = fread(buf, 1, size, f);
00284             assert(rd == size);
00285 
00286             time_t t = (time_t)rec.time;
00287 
00288             Event* e = gTags[rec.event_id];
00289             if (e && doPrintData)
00290               {
00291                 if (size != e->size)
00292                   {
00293                     printf("event %d, size mismatch should be %d, got %d bytes\n", rec.event_id, e->size, size);
00294                   }
00295 
00296                 //printf("event %d, time %s", rec.event_id, ctime(&t));
00297 
00298                 int n  = e->tagNames.size();
00299 
00300                 if (n>0)
00301                   printf("%d %d ", rec.event_id, rec.time);
00302 
00303                 for (int i=0; i<n; i++)
00304                   {
00305                     Tag*t = e->tags[e->tagNames[i]];
00306                     int index = e->tagIndexes[i];
00307 
00308                     //printf(" dump %s[%d] (%p)\n", e->tagNames[i].c_str(), e->tagIndexes[i], t);
00309 
00310                     if (t)
00311                       {
00312                         int offset = t->offset;
00313                         void* ptr = (void*)(buf+offset);
00314 
00315                         if (doPrintNames)
00316                           {
00317                             if (index < 0)
00318                               printf(" %s=", t->name.c_str());
00319                             else
00320                               printf(" %s[%d]=", t->name.c_str(), index);
00321                           }
00322 
00323                         for (int j=0; j<t->arraySize; j++)
00324                           {
00325                             if (index >= 0)
00326                               j = index;
00327 
00328                             switch (t->typeCode)
00329                               {
00330                               default:
00331                                 printf("unknownType%d ",t->typeCode);
00332                                 break;
00333                               case 1: /* BYTE */
00334                                 printf("%u ",((uint8_t*)ptr)[j]);
00335                                 break;
00336                               case 2: /* SBYTE */
00337                                 printf("%d ",((int8_t*)ptr)[j]);
00338                                 break;
00339                               case 3: /* CHAR */
00340                                 printf("\'%c\' ",((char*)ptr)[j]);
00341                                 break;
00342                               case 4: /* WORD */
00343                                 printf("%u ",((uint16_t*)ptr)[j]);
00344                                 break;
00345                               case 5: /* SHORT */
00346                                 printf("%d ",((int16_t*)ptr)[j]);
00347                                 break;
00348                               case 6: /* DWORD */
00349                                 printf("%u ",((uint32_t*)ptr)[j]);
00350                                 break;
00351                               case 7: /* INT */
00352                                 printf("%d ",((int32_t*)ptr)[j]);
00353                                 break;
00354                               case 8: /* BOOL */
00355                                 printf("%u ",((uint32_t*)ptr)[j]);
00356                                 break;
00357                               case 9: /* FLOAT */
00358                                 printf("%.8g ",((float*)ptr)[j]);
00359                                 break;
00360                               case 10: /* DOUBLE */
00361                                 printf("%.16g ",((double*)ptr)[j]);
00362                                 break;
00363                               }
00364 
00365                             if (index >= 0)
00366                               break;
00367                           }
00368                       }
00369                   }
00370 
00371                 if (n>0)
00372                   printf(" %s", ctime(&t));
00373               }
00374 
00375             delete buf;
00376             break;
00377           }
00378         }
00379     }
00380 
00381   return 0;
00382 }
00383 
00384 int readHst(const char* name)
00385 {
00386   FILE* f = fopen(name,"r");
00387   if (!f)
00388     {
00389       fprintf(stderr,"Error: Cannot open \'%s\', errno %d (%s)\n", name, errno, strerror(errno));
00390       exit(1);
00391     }
00392 
00393   readHstFile(f);
00394   fclose(f);
00395   return 0;
00396 }
00397 
00398 void help()
00399 {
00400   fprintf(stderr,"Usage: mhdump [-h] [-L] [-n] [-t] [-E event_id] [-T tag_name] file1.hst file2.hst ...\n");
00401   fprintf(stderr,"\n");
00402   fprintf(stderr,"Switches:\n");
00403   fprintf(stderr,"  -h --- print this help message\n");
00404   fprintf(stderr,"  -L --- list tag definitions only\n");
00405   fprintf(stderr,"  -t --- omit tag definitions\n");
00406   fprintf(stderr,"  -n --- omit variable names\n");
00407   fprintf(stderr,"\n");
00408   fprintf(stderr,"Examples:\n");
00409   fprintf(stderr,"  To list all existing tags: mhdump -L file1.hst file2.hst ...\n");
00410   fprintf(stderr,"  To show data for all events, all tags: mhdump file1.hst file2.hst ...\n");
00411   fprintf(stderr,"  To show all data for event 0: mhdump -E 0 file1.hst file2.hst ...\n");
00412   fprintf(stderr,"  To show data for event 0, tag \"State\": mhdump -n -E 0 -T State file1.hst file2.hst ...\n");
00413   fprintf(stderr,"  To show data for event 3, tag \"MCRT\", array index 5: mhdump -n -E 3 -T MCRT[5] file1.hst file2.hst ...\n");
00414   exit(1);
00415 }
00416 
00417 int main(int argc,char*argv[])
00418 {
00419   int event_id = -1;
00420 
00421   if (argc <= 1)
00422     help(); // DOES NOT RETURN
00423 
00424   for (int iarg=1; iarg<argc; iarg++)
00425     if (strcmp(argv[iarg], "-h")==0)
00426       {
00427         help(); // DOES NOT RETURN
00428       }
00429     else if (strcmp(argv[iarg], "-E")==0)
00430       {
00431         iarg++;
00432         event_id = atoi(argv[iarg]);
00433         if (!gTags[event_id])
00434           gTags[event_id] = new Event;
00435         gTags[event_id]->printAllTags = true;
00436       }
00437     else if (strcmp(argv[iarg], "-T")==0)
00438       {
00439         iarg++;
00440         char *s = strchr(argv[iarg],'[');
00441         int index = -1;
00442         if (s)
00443           {
00444             index = atoi(s+1);
00445             *s = 0;
00446           }
00447 
00448         std::string name = argv[iarg];
00449 
00450         Event* e = gTags[event_id];
00451 
00452         if ((event_id<0) || !e)
00453           {
00454             fprintf(stderr,"Error: expected \"-E event_id\" before \"-T ...\"\n");
00455             exit(1);
00456           }
00457 
00458         e->printAllTags = false;
00459         e->tagNames.push_back(name);
00460         e->tagIndexes.push_back(index);
00461       }
00462     else if (strcmp(argv[iarg], "-t")==0)
00463       doPrintTags = false;
00464     else if (strcmp(argv[iarg], "-L")==0)
00465       {
00466         doPrintTags = true;
00467         doPrintData = false;
00468       }
00469     else if (strcmp(argv[iarg], "-A")==0)
00470       doAll = true;
00471     else if (strcmp(argv[iarg], "-n")==0)
00472       doPrintNames = false;
00473     else
00474       {
00475         if (gTags.size() == 0)
00476           doAll = true;
00477         readHst(argv[iarg]);
00478       }
00479 
00480   return 0;
00481 }
00482 
00483 // end

Midas DOC Version 3.0.0 ---- PSI Stefan Ritt ----
Contributions: Pierre-Andre Amaudruz - Sergio Ballestrero - Suzannah Daviel - Doxygen - Peter Green - Qing Gu - Greg Hackman - Gertjan Hofman - Paul Knowles - Exaos Lee - Rudi Meier - Glenn Moloney - Dave Morris - John M O'Donnell - Konstantin Olchanski - Renee Poutissou - Tamsen Schurman - Andreas Suter - Jan M.Wouters - Piotr Adam Zolnierczuk