# Macro to generate a Tree skeleton function

    Int_t MakeCode(TTree *t, const char *filename=0)
    {
    //_________________________________________________________________________
    //   generate skeleton function for a TNtuple or TTree pointed by t
    //   The function code is written on filename
    //   if filename is NULL, filename will be nameoftree.C
    //
    //   The generated code includes the following:
    //      - Identification of the original Tree and Input file name
    //      - Connection of the Tree file
    //      - Declaration of Tree variables
    //      - Declaration of pointers to leaves and setting of leaves addresses
    //      - a skeleton for the event loop
    //
    //   To use this function:
    //      - connect your Tree file (eg: TFile f("myfile.root");)
    //      - .L MakeCode.C
    //      - MakeCode(T,"anal.C")
    //    where T is the name of the Tree in file myfile.root
    //    and anal.C the name of the file created by this function.
    //
    //   Use this macro with ROOT version 0.90
    //   In ROOT version 1.0 the TTree class includes a new function
    //       TTree::MakeCode(const char *filename)
    //   that generates the skeleton code for a TTree object.
    //
    //          Author: Rene Brun
    //_________________________________________________________________________

    // Check against an invalid Tree pointer
       if (!t) return 1;
       if (!t->IsA()->InheritsFrom("TTree")) {
          printf("Attempt to makecode for a non-TTree object\n");
          return 2;
       }
    // Connect output file
       char tfile[64];
       if (filename) strcpy(tfile,filename);
       else          sprintf(tfile,"%s.C",t->GetName());
       FILE *fp = fopen(tfile,"w");
       if (!fp) {
          printf("Cannot open output file:%s\n",tfile);
          return 3;
       }
    // Print header
       TObjArray *leaves = t->GetListOfLeaves();
       Int_t nleaves = leaves->GetEntriesFast();
       TDatime td;
       fprintf(fp,"{\n");
       fprintf(fp,"//////////////////////////////////////////////////////////\n");
       fprintf(fp,"//   This file has been automatically generated \n");
       fprintf(fp,"//     (%s by ROOT version%s)\n",td.AsString(),gROOT->GetVersion());
       fprintf(fp,"//   from TTree %s/%s\n",t->GetName(),t->GetTitle());
       fprintf(fp,"//   found on file: %s\n",gFile->GetName());
       fprintf(fp,"//////////////////////////////////////////////////////////\n");
       fprintf(fp,"\n");
       fprintf(fp,"\n");

    // Reset and file connect
       fprintf(fp,"//Reset ROOT and connect tree file\n");
       fprintf(fp,"   gROOT->Reset();\n");
       fprintf(fp,"   TFile *f = new TFile(\"%s\");\n\n",gFile->GetName());

    // First loop on all leaves to generate type declarations
       fprintf(fp,"//Declaration of leaves types\n");
       Int_t len, nl, l;
       TLeaf *leafcount;
       char *bname;
       char branchname[64];
       for (l=0;l<nleaves;l++) {
          TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
          TBranch *branch = leaf->GetBranch();
          nl = branch->GetListOfLeaves()->GetEntriesFast();
          if (nl > 1) strcpy(branchname,leaf->GetName());
          else        strcpy(branchname,branch->GetName());
          bname = branchname;
          while (*bname) {if (*bname == '.') *bname='_'; bname++;}
          if (!strcmp(branch->ClassName(),"TBranchObject")) {
             TLeafObject *leafobj = (TLeafObject*)leaf;
             fprintf(fp,"   %-15s *%s;\n",leafobj->GetTypeName(), leafobj->GetName());
             continue;
          }
          len = leaf->GetLen();
          leafcount =leaf->GetLeafCount();
          if (leafcount) len = leafcount->GetMaximum()+1;
          if (len > 1) fprintf(fp,"   %-15s %s[%d];\n",leaf->GetTypeName(), branchname,len);
          else         fprintf(fp,"   %-15s %s;\n",leaf->GetTypeName(), branchname);
       }

    // Second loop on all leaves to set the leaf addresses
       fprintf(fp,"\n//Get a pointer to individual leaves and set their addresses\n");
       fprintf(fp,"   TObjArray *leaves = %s->GetListOfLeaves();\n",t->GetName());
       for (l=0;l<nleaves;l++) {
          TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
          TBranch *branch = leaf->GetBranch();
          nl = branch->GetListOfLeaves()->GetEntriesFast();
          if (nl > 1) strcpy(branchname,leaf->GetName());
          else        strcpy(branchname,branch->GetName());
          bname = branchname;
          while (*bname) {if (*bname == '.') *bname='_'; bname++;}
          if (!strcmp(branch->ClassName(),"TBranchObject")) {
             fprintf(fp,"   TLeaf *l_%-15s = (TLeaf*)leaves->At(%d);\n",branchname,l);
          } else {
             len = leaf->GetLen();
             leafcount =leaf->GetLeafCount();
             if (leafcount) len = leafcount->GetMaximum()+1;
             if (len > 1) fprintf(fp,"   TLeaf *l_%-15s = (TLeaf*)leaves->At(%d);   l_%s->SetAddress(&%s[0]);\n",branchname,l,branchname,branchname);
             else         fprintf(fp,"   TLeaf *l_%-15s = (TLeaf*)leaves->At(%d);   l_%s->SetAddress(&%s);\n",branchname,l,branchname,branchname);
          }
       }

    //Generate instructions to make the loop on events
       fprintf(fp,"\n//This is the loop skeleton\n");
       fprintf(fp,"//To read only selected branches, Insert a statement like:\n");
       fprintf(fp,"//          leafname->GetBranch()->GetEvent(i); instead of %s->GetEvent(i);\n",t->GetName());
       fprintf(fp,"\n   Int_t nentries = %s->GetEntries();\n",t->GetName());
       fprintf(fp,"   for (Int_t i=0; i<nentries;i++) {\n");
       fprintf(fp,"      %s->GetEvent(i);\n",t->GetName());
       fprintf(fp,"   }\n");
       fprintf(fp,"}\n");

       fclose(fp);
       printf("Macro: %s generated from Tree: %s\n",tfile,t->GetName());

       return 0;
    }