parseStab.C

Go to the documentation of this file.
00001 /*
00002  * See the dyninst/COPYRIGHT file for copyright information.
00003  * 
00004  * We provide the Paradyn Tools (below described as "Paradyn")
00005  * on an AS IS basis, and do not warrant its validity or performance.
00006  * We reserve the right to update, modify, or discontinue this
00007  * software at any time.  We shall have no obligation to supply such
00008  * updates or modifications or any other form of support to you.
00009  * 
00010  * By your use of Paradyn, you understand and agree that we (or any
00011  * other person or entity with proprietary rights in Paradyn) are
00012  * under no obligation to provide either maintenance services,
00013  * update services, notices of latent defects, or correction of
00014  * defects for Paradyn.
00015  * 
00016  * This library is free software; you can redistribute it and/or
00017  * modify it under the terms of the GNU Lesser General Public
00018  * License as published by the Free Software Foundation; either
00019  * version 2.1 of the License, or (at your option) any later version.
00020  * 
00021  * This library is distributed in the hope that it will be useful,
00022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00024  * Lesser General Public License for more details.
00025  * 
00026  * You should have received a copy of the GNU Lesser General Public
00027  * License along with this library; if not, write to the Free Software
00028  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00029  */
00030 
00031 #include <ctype.h>
00032 #include <iostream>
00033 // from libiberty's demangle.h
00034 #define DMGL_PARAMS   (1 << 0) 
00035 #define DMGL_ANSI     (1 << 1) 
00036 #define DMGL_VERBOSE  (1 << 3) 
00037 
00038 #include "symutil.h"
00039 #include "Symtab.h" // For looking up compiler type
00040 #include "Symbol.h" 
00041 #include "Function.h"
00042 #include "Variable.h"
00043 #include "Module.h" 
00044 #include "Collections.h"
00045 #include "annotations.h"
00046 #include "common/h/headers.h"
00047 #include "Type-mem.h"
00048 
00049 #include "debug.h"
00050 
00051 using namespace Dyninst;
00052 using namespace Dyninst::SymtabAPI;
00053 
00054 /*
00055 #include "BPatch.h"
00056 #include "debug.h"
00057 */
00058 
00059 extern std::string symt_current_func_name;
00060 extern std::string symt_current_mangled_func_name;
00061 extern Function *symt_current_func;
00062 namespace Dyninst{
00063 namespace SymtabAPI{
00064     std::string parseStabString(Module *mod, int linenum, char *stabstr, 
00065               int framePtr, typeCommon *commonBlock = NULL);
00066 }
00067 }
00068 
00069 // Forward references for parsing routines
00070 static int parseSymDesc(char *stabstr, int &cnt);
00071 static Type *parseConstantUse(Module *, char *stabstr, int &cnt);
00072 static char *parseTypeDef(Module *, char *stabstr, 
00073                           const char *name, int ID, unsigned int sizeHint = 0);
00074 static int parseTypeUse(Module*, char *&stabstr, int &cnt,
00075                         const char *name);
00076 static inline bool isSymId(char ch);
00077 static std::string getIdentifier(char *stabstr, int &cnt, bool stopOnSpace=false);
00078 
00079 static std::string currentRawSymbolName;
00080 
00081 std::string convertCharToString(const char *ptr){
00082     if(ptr)
00083         return ptr;
00084     else
00085         return "";
00086 }
00087 
00088 //
00089 // Start of code to parse Stab information.
00090 //    The structure of this code is a recursive decent parser that parses
00091 //    information in stab records and builds up the corresponding BPatch_types.
00092 //    
00093 //    Each non-terminal in the grammer has a function of the form parse<NT>.
00094 //  
00095 //    The grammar for a non-terminal appears in the comments just before
00096 //    the non-terminal parsing function
00097 //  
00098 
00099 void vectorNameMatchKLUDGE(Module *mod, char *demangled_sym, std::vector<Function *> &bpfv, std::vector<int> &matches)
00100 {
00101   // iterate through all matches and demangle names with extra parameters, compare
00102   for (unsigned int i = 0; i < bpfv.size(); ++i) {
00103     std::string l_mangled;
00104     std::vector<Symbol *> syms;
00105     bpfv[i]->getSymbols(syms);
00106     if (syms.size()) {
00107         l_mangled = syms[0]->getMangledName();
00108         
00109         char * l_demangled_raw = P_cplus_demangle(l_mangled.c_str(), mod->exec()->isNativeCompiler());
00110         if( l_demangled_raw == NULL ) {
00111             l_demangled_raw = strdup(l_mangled.c_str());
00112         }
00113         
00114         if (!strcmp(l_demangled_raw, demangled_sym)) {
00115            matches.push_back(i);
00116         }
00117         free(l_demangled_raw);
00118     }
00119   } /* end iteration over function vector */
00120 }
00121 
00122 Function *mangledNameMatchKLUDGE(const char *pretty, const char *mangled, 
00123                     Module *mod)
00124 {
00125 
00126   std::vector<Function *> bpfv;
00127   if (!mod->exec()->findFunctionsByName(bpfv, pretty)) {
00128      //cerr << __FILE__ << __LINE__ << ":  KLUDGE Cannot find " << pretty << endl;
00129      return NULL;  // no pretty name hits, expecting multiple
00130   }
00131 
00132   //cerr << __FILE__ << __LINE__ << ":  mangledNameMatchKLUDGE: language = " 
00133   //<< mod->getLanguageStr() << endl;
00134 
00135   if (lang_Fortran_with_pretty_debug == mod->language()) {
00136       // debug function symbols are presented in "demangled" style.
00137       if (bpfv.size() == 1)
00138     return bpfv[0];
00139       else {
00140     cerr << __FILE__ << __LINE__ << ":  FIXME!" << endl;
00141     return NULL;
00142       }
00143     }
00144 
00145   // demangle name with extra parameters
00146   char * demangled_sym = P_cplus_demangle( mangled, mod->exec()->isNativeCompiler(), true );
00147   if( demangled_sym == NULL ) {
00148     demangled_sym = strdup( mangled );
00149     assert( demangled_sym != NULL );
00150   }
00151 
00152   std::vector<int> matches;
00153 
00154   vectorNameMatchKLUDGE(mod, demangled_sym, bpfv, matches);
00155 
00156   Function *ret = NULL;
00157 
00158   if (matches.size() == 1) {ret = bpfv[matches[0]]; goto clean_up;}
00159   if (matches.size() > 1) goto clean_up;
00160   
00161   // check in the uninstrumentable pile
00162   bpfv.clear();
00163   matches.clear();
00164 
00165   vectorNameMatchKLUDGE(mod, demangled_sym, bpfv, matches);
00166   if (matches.size() == 1) {ret = bpfv[matches[0]]; goto clean_up;}
00167   if (matches.size() > 1) goto clean_up;
00168 
00169  clean_up:
00170   free( demangled_sym );
00171   return ret;
00172 }
00173 
00174 // This function takes the stab stabstring and parses it to create a new 
00175 // type or variable object.  This function only defines the type/variable 
00176 // name and ID.
00177 //
00178 // <stabString> = <ident>:<symDesc>             |
00179 //        <ident>:c<constantUse>        |
00180 //        <ident>:f<symDesc>            |
00181 //        <ident>:f<syymDesc>,<ident>,<ident>   |
00182 //        <ident>:F<typeUse><paramList>     |
00183 //        <ident>:G<typeUse>            |
00184 //        <ident>:r<int>            |
00185 //        <ident>:S<typeUse>            |
00186 //        <ident>:[pPr]<typeUse>        |
00187 //        <ident>::T<typeUse>           |
00188 //        <ident>:t<typeUse>            |
00189 //        <ident>:T<typeUse>            |
00190 //        <ident>:v<typeUse>            |
00191 //        <ident>:V<symDesc>            |
00192 //        <indet>:Y[Tc|Ts]
00193 //
00194 // <paramList> = | <typeUse>;<paramList> 
00195 //
00196 
00197 std::string Dyninst::SymtabAPI::parseStabString(Module *mod, int linenum, char *stabstr, 
00198       int framePtr, typeCommon *commonBlock)
00199 {
00200     typeCollection *tc = typeCollection::getModTypeCollection(mod);
00201    int cnt;
00202    int ID = 0;
00203    int symdescID = 0;
00204    int funcReturnID = 0;
00205    Function  *fp = NULL;
00206    Type * ptrType = NULL;
00207    Type * newType = NULL; // For new types to add to the collection
00208    localVar *locVar = NULL;
00209    cnt= 0;
00210 
00211    types_printf("parseStabString, mod %p/%s, linenum %d, stabstr %s\n",
00212         mod,
00213         (mod != NULL) ? mod->fileName().c_str() : "NULL",
00214         linenum, 
00215         stabstr);
00216 
00217    std::string fName = mod->fileName();
00218 
00219    /* get type or variable name */
00220    std::string mangledname = getIdentifier( stabstr, cnt );
00221 
00222    currentRawSymbolName = mangledname;
00223    char * demangled = P_cplus_demangle( mangledname.c_str(), mod->exec()->isNativeCompiler() );
00224    std::string name;
00225 
00226    if ( demangled == NULL ) 
00227    {
00228       name = mangledname;
00229    } 
00230    else 
00231    {
00232       name = demangled;
00233    }
00234 
00235    if ( name[0] != '\0' && stabstr[cnt] != ':' ) 
00236    {
00237      types_printf("\t returning name %s\n", name.c_str());
00238       return name;
00239    }
00240 
00241    if (stabstr[cnt] == ':') 
00242    {
00243       // skip to type part
00244       cnt++;
00245    }
00246 
00247    if (isSymId(stabstr[cnt])) 
00248    {
00249       /* instance of a predefined type */
00250 
00251       ID = parseSymDesc(stabstr, cnt);
00252 
00253       if (stabstr[cnt] == '=') 
00254       {
00255          /* More Stuff to parse, call parseTypeDef */
00256 
00257           stabstr = parseTypeDef(mod, (&stabstr[cnt+1]), name.c_str(), ID);
00258          cnt = 0;
00259          ptrType = tc->findOrCreateType(ID);
00260          if (!symt_current_func) 
00261          {
00262             // XXX-may want to use N_LBRAC and N_RBRAC to set function scope 
00263             // -- jdd 5/13/99
00264             // Still need to add to local variable list if in a function
00265 
00266             std::string modName = mod->fileName();
00267             //bperr("%s[%d] Can't find function %s in module %s\n", __FILE__, __LINE__,
00268             //     symt_current_mangled_func_name.c_str(), modName);
00269             //bperr("Unable to add %s to local variable list in %s\n",
00270             //     name.c_str(), symt_current_func_name.c_str());
00271          } 
00272          else 
00273          {
00274             locVar = new localVar(name, ptrType, fName, linenum, symt_current_func);
00275             VariableLocation loc;
00276             loc.stClass = storageRegOffset;
00277             loc.refClass = storageNoRef;
00278             loc.frameOffset = framePtr;
00279             locVar->addLocation(loc);
00280             if (!ptrType) {
00281                //bperr("adding local var with missing type %s, type = %d\n",
00282                //      name, ID);
00283             }
00284 
00285             localVarCollection *lvs = NULL;
00286 
00287             if (!symt_current_func->getAnnotation(lvs, FunctionLocalVariablesAnno)) 
00288             {
00289                lvs = new localVarCollection();
00290                if (!symt_current_func->addAnnotation(lvs, FunctionLocalVariablesAnno)) 
00291                {
00292                   fprintf(stderr, "%s[%d]: failed to add annotation here\n", FILE__, __LINE__);
00293                }
00294             }
00295 
00296             if (!lvs)
00297             {
00298                fprintf(stderr, "%s[%d]: failed to get annotation here\n", FILE__, __LINE__);
00299             }
00300 
00301             lvs->addLocalVar(locVar);
00302          }
00303       } 
00304       else if (symt_current_func) 
00305       {
00306          // Try to find the BPatch_Function
00307          ptrType = tc->findOrCreateType( ID);
00308 
00309          locVar = new localVar(name, ptrType, fName, linenum, symt_current_func);
00310          VariableLocation loc;
00311          loc.stClass = storageRegOffset;
00312          loc.refClass = storageNoRef;
00313          loc.frameOffset = framePtr;
00314          locVar->addLocation(loc);
00315 
00316          if (!ptrType) 
00317          {
00318             ////bperr("adding local var with missing type %s, type = %d\n",
00319             //       name, ID);
00320          }
00321 
00322          if (!symt_current_func->addLocalVar(locVar)) 
00323          {
00324             fprintf(stderr, "%s[%d]:  FIXME\n", FILE__, __LINE__);
00325          }
00326 
00327       }
00328    } 
00329    else if (stabstr[cnt]) 
00330    {
00331       std::vector<Function *> bpfv;
00332 
00333       switch (stabstr[cnt]) {
00334          case 'f': /*Local Function*/ 
00335             {
00336                std::string scopeName;
00337                std::string lfuncName;
00338                cnt++;
00339 
00340                symt_current_func_name = name;
00341                symt_current_mangled_func_name = mangledname;
00342 
00343                funcReturnID = parseTypeUse(mod, stabstr, cnt, name.c_str());
00344 
00345                if (stabstr[cnt]==',') 
00346                {
00347                   cnt++;    /*skip the comma*/
00348 
00349                   /* Local Function Name */
00350                   lfuncName = getIdentifier(stabstr, cnt);
00351 
00352                   assert(stabstr[cnt] == ',');
00353                   cnt++;    /*skip the comma*/
00354 
00355                   /* Scope Name of Local Function */
00356                   scopeName = getIdentifier(stabstr, cnt);
00357 
00358                   if (stabstr[cnt]) 
00359                   {
00360                      //bperr("Extra: %s\n", &stabstr[cnt]);
00361                   }
00362                }
00363 
00364                if (!scopeName.length()) 
00365                { 
00366                   // Not an embeded function
00367 
00368                   ptrType = tc->findOrCreateType(funcReturnID);
00369                   /*
00370                     The shared_ptr type_Untyped is static, so this
00371                     otherwise unsafe operation is safe.
00372                   */
00373                   if ( !ptrType) ptrType = Symtab::type_Untyped().get();
00374 
00375                   if (!(mod->exec()->findFunctionsByName(bpfv, name)))
00376                   {
00377                       //showInfoCallback(string("missing local function ") +
00378                       //                         name + "\n");
00379                       // It's very possible that we might not find a function
00380                       // that's a weak reference, and defined in multiple places
00381                       // as we only store an object from the last definition
00382                       //
00383                       // 12/08 - not sure this is necessary anymore
00384                       // due to the Function abstraction
00385                       fp = NULL;
00386                   } 
00387                   else 
00388                   {
00389                      if (bpfv.size() > 1) 
00390                      {
00391                         // warn if we find more than one function with current_func_name
00392                         char msg[1024];
00393                         sprintf(msg, "%s[%d]:  found %d functions with name %s, using the first",
00394                               __FILE__, __LINE__, (int)bpfv.size(), name.c_str());
00395                         // BPatch::bpatch->reportError(BPatchWarning, 0, msg);
00396 
00397                      }
00398                      else if (!bpfv.size()) 
00399                      {
00400                         //bperr("%s[%d]:  SERIOUS: found 0 functions with name %s",
00401                         //       __FILE__, __LINE__, name.c_str());
00402                         break;
00403                      }
00404 
00405                      fp = bpfv[0];
00406                      // set return type.
00407                      fp->setReturnType(ptrType);
00408                   }
00409                } 
00410                else 
00411                {
00412                   //bperr("%s is an embedded function in %s\n",name.c_str(), scopeName.c_str());
00413                }
00414 
00415                symt_current_func = fp;
00416                // skip to end - SunPro Compilers output extra info here - jkh 6/9/3
00417                cnt = strlen(stabstr);
00418 
00419                break;
00420             }  
00421 
00422          case 'F':/* Global Function */
00423             {
00424                cnt++; /*skipping 'F' */
00425 
00426                funcReturnID = parseTypeUse(mod, stabstr, cnt, name.c_str());
00427 
00428                symt_current_func_name = name;
00429                symt_current_mangled_func_name = mangledname;
00430 
00431                //
00432                // For SunPro compilers there may be a parameter list after 
00433                //   the return
00434                //
00435 
00436                while (stabstr[cnt] == ';') 
00437                {
00438                   cnt++;    // skip ';'
00439                   (void) parseTypeUse(mod, stabstr, cnt, "");
00440                }
00441 
00442                // skip to end - SunPro Compilers output extra info here - jkh 6/9/3
00443                cnt = strlen(stabstr);
00444 
00445                ptrType = tc->findOrCreateType(funcReturnID);
00446                if (!ptrType) ptrType = Symtab::type_Untyped().get();
00447 
00448                std::vector<Function *>fpv;
00449                if (!mod->exec()->findFunctionsByName(fpv, symt_current_mangled_func_name))
00450                //if (!mod->findSymbol(fpv, symt_current_mangled_func_name, Symbol::ST_FUNCTION, true)) 
00451                {
00452                   std::string modName = mod->fileName();
00453 
00454                   if (NULL == (fp = mangledNameMatchKLUDGE(symt_current_func_name.c_str(), 
00455                               symt_current_mangled_func_name.c_str(), mod)))
00456                   {
00457                      //bpwarn("%s L%d - Cannot find global function with mangled name '%s' or pretty name '%s' with return type '%s' in module '%s', possibly extern\n",
00458                      //       __FILE__, __LINE__,
00459                      //       symt_current_mangled_func_name.c_str(), current_func_name.c_str(),
00460                      //       ((ptrType->getMangledName() == NULL) ? "" : ptrType->getMangledName()), 
00461                      //       modName);
00462                      //char prefix[5];
00463                      //strncpy(prefix, current_mangled_func_name, 4);
00464                      //prefix[4] = '\0';
00465                      // mod->dumpMangled(prefix);
00466                      break;
00467                   }
00468                }
00469                fp = fpv[0];
00470 
00471                fp->setReturnType(ptrType);
00472                symt_current_func = fp;
00473                fpv.clear();
00474             }    
00475             break;
00476 
00477          case 'U':/* Class Declaration - for Sun Compilers - jkh 6/6/03 */
00478          case 'E':/* Extern'd Global ??? - undocumented type for Sun Compilers - jkh 6/6/03 */
00479          case 'G':/* Global Varaible */
00480             cnt++; /* skip the 'G' */
00481 
00482             /* Get variable type number */
00483             symdescID = parseTypeUse(mod, stabstr, cnt, name.c_str());
00484             Type *BPtype;
00485 
00486             BPtype = tc->findOrCreateType(symdescID);
00487             if (BPtype) 
00488             {
00489           Module *toUse = mod;
00490                std::vector<Variable *> ret;
00491            bool result = mod->findVariablesByName(ret, name);
00492            if (!result) {
00493          // Might be in a different module...
00494          if (mod->exec()->getDefaultModule()->findVariablesByName(ret, name))
00495            toUse = mod->exec()->getDefaultModule();
00496            }
00497            for (unsigned i=0; i<ret.size(); i++) {
00498          ret[i]->setType(BPtype);
00499            }
00500 
00501            typeCollection *tc_to_use = typeCollection::getModTypeCollection(toUse);
00502                tc_to_use->addGlobalVariable(name, BPtype);
00503             }
00504             else 
00505             break;
00506 
00507          case 'P':  // function parameter passed in a register (GNU/Solaris)
00508          case 'R':  // function parameter passed in a register (AIX style)
00509          case 'v':  // Fortran Local Variable
00510          case 'X':  // Fortran function return Variable (e.g. function name)
00511          case 'p': 
00512             {   
00513                // Function Parameter
00514                cnt++; /* skip the 'p' */
00515 
00516                /* Get variable type number */
00517                symdescID = parseTypeUse(mod, stabstr, cnt, name.c_str());
00518 
00519                if (stabstr[cnt] == ';') 
00520                {
00521                   // parameter type information, not used for now
00522                   cnt = strlen(stabstr);
00523                } 
00524               // else if (stabstr[cnt]) 
00525               // {
00526                   //bperr( "\tMore to parse func param %s\n", &stabstr[cnt]);
00527                   //bperr( "\tFull String: %s\n", stabstr);
00528                //}
00529 
00530                ptrType = tc->findOrCreateType(symdescID);
00531                if (!ptrType) ptrType = Symtab::type_Untyped().get();
00532 
00533                localVar *param;
00534 
00535                param = new localVar(name, ptrType, fName, linenum, symt_current_func);
00536                VariableLocation loc;
00537                loc.stClass = storageRegOffset;
00538                loc.refClass = storageNoRef;
00539                loc.frameOffset = framePtr;
00540                param->addLocation(loc);
00541 
00542                if (symt_current_func) 
00543                {
00544                   if (!symt_current_func->addParam(param)) 
00545                   {
00546                      fprintf(stderr, "%s[%d]:  FIXME\n", FILE__, __LINE__);
00547                   }
00548                } 
00549 
00550                break;
00551             }
00552 
00553          case 'c': /* constant */
00554             {
00555                cnt++; /*move past the 'c' */
00556                if (symt_current_mangled_func_name.length()) 
00557                {
00558                   std::vector<Function *>fpv;
00559                   if (mod->exec()->findFunctionsByName(fpv, symt_current_mangled_func_name))
00560                   { 
00561                      // found function, add parameter
00562                      fp = fpv[0];   
00563                      symt_current_func = fp;
00564                   }
00565                   fpv.clear();
00566                } 
00567 
00568                ptrType = parseConstantUse(mod, stabstr, cnt);
00569 
00570                if (!ptrType) ptrType = Symtab::type_Untyped().get();
00571 
00572                localVar *var;
00573                var = new localVar(name, ptrType, fName, linenum, symt_current_func);
00574                VariableLocation loc;
00575                loc.stClass = storageRegOffset;
00576                loc.refClass = storageNoRef;
00577                loc.frameOffset = 0;
00578                var->addLocation(loc);
00579                if (symt_current_func) {
00580                      if (!symt_current_func->addParam(var)) 
00581                      {
00582                         fprintf(stderr, "%s[%d]:  FIXME\n", FILE__, __LINE__);
00583                      }
00584                   }
00585             }
00586             break;
00587 
00588          case 'r':/* Register Variable */
00589             cnt++; /*move past the 'r'*/
00590             /* get type reference */
00591 
00592             symdescID = parseSymDesc(stabstr, cnt);
00593             break;
00594 
00595          case 'S':/* Global Static Variable */ 
00596             {
00597                cnt++; /*move past the 'S'*/
00598 
00599                /* get type reference */
00600                symdescID = parseTypeUse(mod, stabstr, cnt, name.c_str());
00601 
00602                // lookup symbol and set type
00603                Type *BPtype;
00604 
00605                std::string nameTrailer;
00606                if (name.find(".") < name.length()) 
00607                {
00608                   std::string defaultNameSpace;
00609                   defaultNameSpace = name.substr(0,name.find("."));
00610                   nameTrailer = name.substr(name.find(".")+1,name.length()-name.find(".")-1);
00611                   mod->setDefaultNamespacePrefix(defaultNameSpace);
00612                } 
00613                else
00614                {
00615                   nameTrailer = name;
00616                }
00617 
00618                BPtype = tc->findOrCreateType(symdescID);
00619 
00620                if (BPtype) 
00621                {
00622                   Symtab *img = mod->exec();
00623                   std::vector<Symbol *>syms;
00624                   if (img->findSymbol(syms, 
00625                                             nameTrailer,
00626                                             Symbol::ST_OBJECT,
00627                                             mangledName) ||
00628               img->findSymbol(syms, 
00629                                             nameTrailer,
00630                                             Symbol::ST_OBJECT, 
00631                                             mangledName,
00632                                             true)) 
00633                   {
00634              
00635                      tc->addGlobalVariable(nameTrailer, BPtype);
00636                   }
00637                }
00638 
00639                //else 
00640                //{
00641                   //bperr("ERROR: unable to find type #%d for variable %s\n", 
00642                   // symdescID, nameTrailer.c_str());
00643                //} 
00644 
00645                break;
00646             }
00647 
00648          case 't':  // Type Name 
00649             cnt++; /*move past the 't'*/
00650 
00651             /* get type reference */
00652             symdescID = parseSymDesc(stabstr, cnt);
00653 
00654             //Create Type.
00655             if (stabstr[cnt] == '=') 
00656             {
00657                /* More Stuff to parse, call parseTypeDef */
00658                //char *oldstabstr = stabstr;
00659                 stabstr = parseTypeDef(mod, (&stabstr[cnt+1]), name.c_str(), symdescID);
00660                cnt = 0;
00661 
00662 
00663                // AIX seems to append an semi at the end of these
00664                if (stabstr[0] && strcmp(stabstr, ";")) 
00665                {
00666                   //bperr("\tMore to parse creating type %s\n", stabstr);
00667                   //bperr( "\tFull String: %s\n", oldStr);
00668                }
00669             } 
00670             else 
00671             {
00672                //Create Type defined as a pre-exisitng type.
00673 
00674                ptrType = tc->findOrCreateType(symdescID);
00675                if (!ptrType)
00676                {
00677                   ptrType = Symtab::type_Untyped().get();
00678                }
00679 
00680                // We assume that IDs are unique per type. Instead of reusing the 
00681                // underlying base ID, use a SymtabAPI-generated ID.
00682 
00683                typeTypedef *newType = new typeTypedef(ptrType, name);
00684 
00685                if (newType) 
00686                {
00687                    tc->addOrUpdateType(newType);
00688                }
00689             }
00690             break;
00691 
00692          case ':':  // :T... - skip ":" and parse 'T'
00693             if ((stabstr[cnt+1] == 't') || (stabstr[cnt+1] == 'T')) 
00694             {
00695                // parse as a normal typedef
00696                parseStabString(mod, linenum, &stabstr[cnt+1], framePtr);
00697             } 
00698 
00699             // else 
00700             //{
00701             //bperr("Unknown type seen %s\n", stabstr);
00702             //}
00703 
00704             break;
00705 
00706          case 'T':/* Aggregate type tag -struct, union, enum */
00707             cnt++; /*move past the 'T'*/
00708 
00709             if (stabstr[cnt] == 't') 
00710             {
00711                //C++ struct  tag "T" and type def "t"
00712                ////bperr("SKipping C++ Identifier t of Tt\n");
00713                cnt++;  //skip it
00714             }
00715 
00716             /* get type reference */
00717             symdescID = parseSymDesc(stabstr, cnt);
00718 
00719             //Create Type.
00720             if (stabstr[cnt] == '=') 
00721             {
00722                /* More Stuff to parse, call parseTypeDef */
00723                stabstr = parseTypeDef(mod,(&stabstr[cnt+1]),name.c_str(),symdescID);
00724                cnt = 0;
00725 
00726                //if (stabstr[0]) 
00727                //{
00728                   //bperr( "\tMore to parse aggregate type %s\n", (&stabstr[cnt]));
00729                   //bperr("\tFull String: %s\n", stabstr);
00730                //}
00731 
00732             } 
00733             else 
00734             {
00735                //Create Type defined as a pre-exisitng type.
00736 
00737                newType = Type::createPlaceholder(symdescID, name);
00738             }
00739 
00740             break;
00741 
00742          case 'V':/* Local Static Variable (common block vars too) */
00743             cnt++; /*move past the 'V'*/
00744 
00745             // //bperr("parsing 'v' type of %s\n", stabstr);
00746             /* Get variable type number */
00747 
00748             symdescID = parseTypeUse(mod, stabstr, cnt, name.c_str());
00749 
00750             // lookup symbol and set type
00751             BPtype = tc->findOrCreateType(symdescID);
00752 
00753             if (!BPtype) 
00754             {
00755                //bperr("ERROR: unable to find type #%d for variable %s\n", 
00756                // symdescID, name.c_str());
00757                break;
00758             }
00759 
00760             if (commonBlock) 
00761             {
00762                /* This variable is in a common block */
00763                /* add it only if not already there, common block
00764                   are re-defined for each subroutine but subroutines
00765                   define only the member they care about
00766                 */
00767 
00768                bool found = false;
00769                const std::vector<Field *> *fields;
00770                fields = commonBlock->getFields();
00771                if (fields) 
00772                {
00773                   for (unsigned int i=0; i < fields->size(); i++) 
00774                   {
00775                      if (name == (*fields)[i]->getName()) 
00776                      {
00777                         found = true;
00778                         break;
00779                      }
00780 
00781                      int start1, start2, end1, end2;
00782                      start1 = (*fields)[i]->getOffset();
00783                      end1 = start1 + (*fields)[i]->getSize();
00784                      start2 = framePtr;
00785                      end2 = framePtr + BPtype->getSize();
00786                      if ( ((start2 >= start1) && (start2 < end1)) 
00787                          || ((start1 >= start2) && (start1 < end2)) ) 
00788                      {
00789                         /* common block aliasing detected */
00790                         //bpwarn("WARN: EQUIVALENCE used in %s: %s and %s\n",
00791                         //  current_func_name.c_str(), name.c_str(), (*fields)[i]->getName());
00792 
00793                         found = true;
00794                         break;
00795                      }
00796                   }
00797                }
00798 
00799                if (!found) 
00800                {
00801                   commonBlock->addField(name, BPtype, framePtr);
00802                }
00803             } 
00804             else 
00805             {
00806                // put it into the local variable scope
00807                if (symt_current_func) 
00808                {
00809                   locVar = new localVar(name, BPtype, fName, linenum, symt_current_func);
00810                   VariableLocation loc;
00811                   loc.stClass = storageAddr;
00812                   loc.refClass = storageNoRef;
00813                   loc.frameOffset = framePtr;
00814                   locVar->addLocation(loc);
00815 
00816                   if (!symt_current_func->addLocalVar(locVar)) 
00817                   {
00818                      fprintf(stderr, "%s[%d]:  FIXME\n", FILE__, __LINE__);
00819                   }
00820                }
00821 
00822                //else 
00823                //{
00824                   //bperr("Unable to add %s to local variable list in %s\n",
00825                   //     name.c_str(),current_func_name.c_str());
00826                //} 
00827             }
00828             break;
00829          case 'l':
00830             // These are string literals, of the form 
00831             // name:l(type);value
00832             // where type must be predefined, and value of of type type.
00833             // It should be safe to ignore these. 
00834 
00835             cnt = strlen(stabstr);
00836             break;
00837 
00838          case 'Y':  // C++ specific stuff
00839             cnt++; // Skip past the 'Y'
00840             if (stabstr[cnt] == 'I') 
00841             {
00842                /* Template instantiation */
00843                cnt++; // skip past the I;
00844                if (stabstr[cnt] == 'f') /* Template function */ 
00845                {
00846                   while (stabstr[cnt] != '@') cnt++;
00847                   cnt++; // Skip past '@'
00848                   cnt++; // Skip past ';'
00849                   cnt++; // Skip past ';'
00850                   while (stabstr[cnt] != ':') cnt++;
00851                   // Create fake stab string that cuts out template garbage
00852                   char *dupstring = strdup(stabstr);
00853                   strcpy(dupstring, mangledname.c_str());
00854                   strcat(dupstring, stabstr+cnt);
00855                   parseStabString(mod, linenum, dupstring, framePtr, commonBlock);
00856                   free(dupstring);
00857               }
00858           } 
00859           cnt = strlen(stabstr);
00860           break;
00861 
00862       default:
00863           //bperr( "Unknown symbol descriptor: %c\n", stabstr[cnt]);
00864           //bperr( " : %s\n", stabstr);
00865           break;
00866       }   
00867     }
00868 
00869     return(&stabstr[cnt]);
00870 } /* end of parseStabString */
00871 
00872 
00873 //
00874 // Is the current character a valid prefix for a symDesc non-terminal?
00875 //
00876 inline bool isSymId(char ch)
00877 {
00878     return ((ch == '(') || isdigit(ch) || (ch == '-'));
00879 }
00880 
00881 //
00882 // parse a Symbol Descriptor ID
00883 //  symDesc = <int> | (<int>,<int>)
00884 //
00885 int parseSymDesc(char *stabstr, int &cnt)
00886 {
00887     int id;
00888     int lid;
00889     int hid;
00890     int sign = 1;
00891     bool newForm = false;
00892 
00893     hid = 0; //file-number
00894     // parse both an int and (int,int) format (file-number, type ID)
00895     if (stabstr[cnt] == '(') {
00896     cnt++;
00897     while (isdigit(stabstr[cnt])) {
00898         hid = hid * 10 + stabstr[cnt] - '0';
00899         cnt++;
00900     }
00901 
00902     // skip ","
00903     if (stabstr[cnt] == ',') cnt++;
00904     newForm = true;
00905     }
00906        
00907     if (stabstr[cnt] == '-') {
00908     sign = -1;
00909     cnt++;
00910     }
00911 
00912     lid = 0; //type ID
00913     while (isdigit(stabstr[cnt])) {
00914         lid = lid * 10 + stabstr[cnt] - '0';
00915         cnt++;
00916     }
00917     if( hid != 0 )
00918       assert(lid < 65536);
00919     
00920     // skip closing ')'
00921     if (newForm) cnt++;
00922 
00923     id = hid * 65536 + lid;
00924     id = id * sign;
00925     
00926     return id;
00927 }
00928 
00929 //
00930 // parse an identifier up to a ":" or "," or ";"
00931 //
00932 std::string getIdentifier( char *stabstr, int &cnt, bool stopOnSpace ) {
00933     int i = 0;
00934     int brCnt = 0;
00935     bool idChar = true;
00936 
00937     while( idChar ) {
00938         switch( stabstr[ cnt + i ] ) {
00939             case '<':
00940             case '(':
00941                 brCnt++;
00942                 i++;
00943                 break;
00944 
00945             case '>':
00946             case ')':
00947                 brCnt--;
00948                 i++;
00949                 break;
00950 
00951             case ' ':
00952                 if ( !stopOnSpace ) {
00953                     i++;
00954                     break;
00955                     } // else fall through
00956             case '\0':
00957             case ':':
00958             case ',':
00959             case ';':
00960                                 /* Handle case of '::' */
00961                                 if ( stabstr[ cnt + i ] == ':' && stabstr[ cnt + i + 1 ] == ':' &&
00962                                      (stabstr[ cnt + i + 2 ] == '_' || isalpha(stabstr[ cnt + i + 2 ])) ) {
00963                                    i+=3;
00964                                    break;
00965                                 }
00966                 /* If we're inside a bracket and we haven't reached
00967                    the end of the string, continue. */
00968                 if( brCnt != 0 && stabstr[ cnt + i ] != '\0' ) {
00969                     i++;
00970                     }
00971                 else if( brCnt ) {
00972                     //bperr( "Failed to find identifier in stabstring '%s;\n", stabstr );
00973                     idChar = false;
00974                     }
00975                 else {
00976                     idChar = false;
00977                     }
00978                 break;
00979                 
00980             default:
00981                 i++;
00982                 break;
00983             } /* end switch */
00984     } /* end while */
00985 
00986     char * identifier = (char *)malloc( i + 1 );
00987     assert( identifier );
00988     
00989     strncpy( identifier, & stabstr[cnt], i );
00990     identifier[i] = '\0';
00991     cnt += i;
00992     
00993         std::string pd_identifier = identifier;
00994         free(identifier);
00995     return pd_identifier;
00996     } /* end getIdentifier() */
00997 
00998 //
00999 // getFieldName
01000 //
01001 // A simplified version of getIdentifier, it only cares about finding a ':'
01002 //
01003 
01004 char * getFieldName( char *stabstr, int &cnt) {
01005    int i = 0;
01006    bool idChar = true;
01007 
01008    while ( idChar ) {
01009       switch( stabstr[ cnt + i ] ) {
01010       case ':':
01011          idChar = false;
01012          break;
01013       default:
01014          i++;
01015       }
01016    }
01017 
01018    char * identifier = (char *) malloc(i + 1);
01019    assert(identifier);
01020 
01021    strncpy(identifier, &stabstr[cnt], i);
01022    identifier[i] = '\0';
01023    cnt += i;
01024 
01025    return identifier;
01026 }
01027 
01028 //
01029 // Parse a use of a type.  
01030 //
01031 //  <typeUse> = <symDesc> | <symDesc>=<typeDef>
01032 //
01033 static int parseTypeUse(Module *mod,char *&stabstr, int &cnt, 
01034                         const char *name)
01035 {
01036     int ret = parseSymDesc(stabstr, cnt);
01037 
01038     if (stabstr[cnt] == '=') {
01039     /* More Stuff to parse, call parseTypeDef */
01040     stabstr = parseTypeDef(mod, (&stabstr[cnt+1]), name, ret);
01041     cnt = 0;
01042     }
01043     return ret;
01044 }
01045 
01046 //
01047 // parseCrossRef - internal struct/union pointer
01048 //
01049 //  <crossRef>  = [s|u|e]<ident>
01050 //
01051 static char *parseCrossRef(typeCollection *moduleTypes,const char * /*name*/,
01052                            int ID, char *stabstr, int &cnt)
01053 {
01054     std::string temp;
01055     Type *newType = NULL;
01056     char xreftype;
01057     cnt++; /* skip 'x'*/
01058 
01059     if ((stabstr[cnt] == 's') ||    // struct 
01060             (stabstr[cnt] == 'u') ||    // union
01061             (stabstr[cnt] == 'e')) {    // enum
01062         xreftype = stabstr[cnt++];
01063 
01064         temp = getIdentifier(stabstr, cnt);
01065         cnt++; /*skip ':' */
01066 
01067         // Find type that this one points to.
01068         Type *ptrType = moduleTypes->findType(temp.c_str());
01069         if (!ptrType) {
01070             // This type name hasn't been seen before.  Create the
01071             // skeleton for it, and we'll update it later when we actually see
01072             // it
01073             if (xreftype == 'e') {
01074                 newType = new typeEnum(ID, temp);
01075         newType = moduleTypes->addOrUpdateType((typeEnum *) newType);
01076             } else if (xreftype == 'u') {
01077                 newType = new typeUnion(ID, temp);
01078         newType = moduleTypes->addOrUpdateType((typeEnum *) newType);
01079             } else {
01080                 newType = new typeStruct(ID, temp);
01081         newType = moduleTypes->addOrUpdateType((typeEnum *) newType);
01082             }
01083         assert(newType);
01084         }         
01085     } else {
01086         /* don't know what it is?? */
01087 
01088         temp = getIdentifier(stabstr, cnt);
01089         cnt++; /*skip ':' */
01090     }
01091 
01092     return( &(stabstr[cnt]));
01093 }
01094         
01095 //
01096 // parse the definition of an array.
01097 //  arrayDef = ar<symDesc>;<symDesc>;<symDesc>;<symDesc> |
01098 //         ar<symDesc>;<symDesc>;<symDesc>;<arrayDef> |
01099 //                 A<arrayDef>
01100 //
01101 static Type *parseArrayDef(Module *mod, const char *name,
01102              int ID, char *&stabstr, int &cnt, unsigned int sizeHint)
01103 {
01104     typeCollection *tc = typeCollection::getModTypeCollection(mod);
01105     char *symdesc;
01106     int symdescID;
01107     int elementType;
01108     Type *newType = NULL;
01109     Type *ptrType = NULL;
01110     int lowbound, hibound;
01111 
01112     // format is ar<indexType>;<lowBound>;<highBound>;<elementType>
01113 
01114     assert(stabstr[cnt] == 'a' || stabstr[cnt] == 'A');
01115 
01116     if (stabstr[cnt ++] == 'A') {
01117        // Open array
01118        lowbound = 1;
01119        hibound = 0;
01120        elementType = parseSymDesc(stabstr, cnt);
01121        ptrType = tc->findOrCreateType(elementType);
01122     } else {
01123        // Regular (maybe) array
01124 
01125        if (stabstr[cnt] != 'r') {
01126           //bperr("unknown array definition seen %s\n", &stabstr[cnt]);
01127           return(NULL);
01128        }
01129        
01130        /* array with range */
01131        symdesc = &(stabstr[cnt]);
01132        
01133        cnt++;   /* skip 'r' */
01134        
01135        symdescID = parseTypeUse(mod, stabstr, cnt, name);
01136        
01137        cnt++; /* skip semicolon */
01138        lowbound = parseSymDesc(stabstr, cnt);
01139        
01140        cnt++; /* skip semicolon */
01141        if (stabstr[cnt] == 'J') {
01142           /* Fortran unbounded array */
01143           hibound = 0;
01144           cnt++;
01145        } else if (stabstr[cnt] == 'T') {
01146           /* Fortran runtime bound array - Txx is the form (xx=digits)*/
01147           hibound = 0;
01148           cnt++;
01149           while (isdigit(stabstr[cnt])) cnt++;
01150        } else {
01151           hibound = parseSymDesc(stabstr, cnt);
01152        }
01153        
01154        cnt++; /* skip semicolon */
01155        elementType = parseSymDesc(stabstr, cnt);
01156        
01157        if (stabstr[cnt] == 'a') 
01158        {
01159            /* multi dimensional array - Fortran style */
01160            /* it has no valid id, so we give it a known duplicate */
01161            //fprintf(stderr, "%s[%d]:  parseArrayDef(...'%s'...)\n", FILE__, __LINE__, stabstr);
01162            ptrType = parseArrayDef(mod, name, 0, stabstr, cnt, sizeHint);
01163        } 
01164        else 
01165        { 
01166            if (stabstr[cnt] == '=') 
01167            {
01168                /* multi dimensional array */
01169                char *temp;
01170                temp = parseTypeDef(mod, &(stabstr[cnt+1]), NULL, elementType);
01171                /* parseTypeDef uses old style of returning updated stabstr,
01172                   but parseArrayDef function needs to return an updated cnt.  
01173                   This simple hack updates cnt based on how far parseTypDef 
01174                   advances it.  jkh 12/4/00 */
01175                cnt = temp-stabstr;
01176                if (stabstr[cnt] == ':') {
01177                    //C++ stuff
01178                    ////bperr("Skipping C++ rest of array def:  %s\n",name );
01179                    while (stabstr[cnt] != ';') cnt++;
01180                }
01181            }
01182            ptrType = tc->findOrCreateType(elementType);
01183        }
01184     }
01185 
01186     //  //bperr("Symbol Desriptor: %s Descriptor ID: %d Type: %d, Low Bound: %d, Hi Bound: %d,\n", symdesc, symdescID, elementType, lowbound, hibound);
01187 
01188 
01189     if (ptrType) {
01190         // Create new type - field in a struct or union
01191         std::string tName = convertCharToString(name);
01192 
01193         typeArray *newAType = new typeArray(ID, ptrType, lowbound, hibound, tName, sizeHint);
01194         // Add to Collection
01195         newType = tc->addOrUpdateType((typeArray *) newAType);
01196 
01197         return newAType;
01198     }
01199         
01200     // //bperr( "parsed array def to %d, remaining %s\n", cnt, &stabstr[cnt]);
01201     return newType;
01202 }
01203 
01204 int guessSize(const char *low, const char *hi) 
01205 {
01206    long long l, h;
01207 
01208    if (low[0] == '0')
01209       sscanf(low, "%llo", &l);
01210    else
01211       sscanf(low, "%lld", &l);
01212    if (hi[0] == '0')
01213       sscanf(hi, "%llo", &h);
01214    else
01215       sscanf(hi, "%lld", &h);
01216 
01217    /*   
01218    if (( low[0]=='-' && l < -2147483648LL )
01219        || ( l > || ( h > 2147483647LL))
01220       return 8;
01221    else if (( l < -32768 ) || ( h > 32767 ))
01222       return 4;
01223    else if (( l < -128 ) || ( h > 127 ))
01224       return 2;
01225    else
01226       return 1;
01227    */
01228    if (l < 0) { // Must be signed
01229       if (l < -2147483648LL || h > 0x7fffffffLL)
01230          return 8;
01231       else if (l < 0xffff8000 || h > 0x7fff)
01232          return 4;
01233       else if (l < 0xffffff80 || h > 0x7f)
01234          return 2;
01235       else
01236          return 1;
01237    } else {
01238       if (h > 0xffffffffLL)
01239          return 8;
01240       else if (h > 0xffff)
01241          return 4;
01242       else if (h > 0xff)
01243          return 2;
01244       else
01245          return 1;
01246    }
01247 }
01248 
01249 #if defined(i386_unknown_linux2_0) \
01250  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */ 
01251 //
01252 // parse range type of the form:    
01253 //
01254 //  <rangeType> = r<typeNum>;<low>;<high>;
01255 //
01256 static char *parseRangeType(Module *mod, const char *name, int ID, 
01257                             char *stabstr, unsigned int sizeHint = 0)
01258 {
01259    int cnt, i, symdescID;
01260    //int sign = 1;
01261    Type *baseType;
01262 
01263    cnt = i = 0;
01264 
01265    assert(stabstr[0] == 'r');
01266    cnt++;
01267 
01268    // range index type - not used
01269    symdescID = parseSymDesc(stabstr, cnt);
01270 
01271    typeCollection *tc = typeCollection::getModTypeCollection(mod);
01272    if (!mod || !tc) 
01273    {
01274       fprintf(stderr, "%s[%d]: FIXME\n", FILE__, __LINE__);
01275       return NULL;
01276    }
01277    else 
01278    {
01279       baseType = tc->findType(symdescID);
01280    }
01281 
01282    // //bperr("\tSymbol Descriptor: %c and Value: %d\n",tmpchar, symdescID);
01283 
01284    cnt++; /* Discarding the ';' */
01285    i=0;
01286    if (stabstr[cnt] == '-' ) {
01287       i++;
01288    }
01289 
01290    /* Getting type range or size */
01291 
01292    while (isdigit(stabstr[cnt+i])) i++;
01293 
01294    char *low = (char *)malloc(sizeof(char)*(i+1));
01295    if(!strncpy(low, &(stabstr[cnt]), i))
01296       /* Error copying size/range*/
01297       exit(1);
01298    low[i] = '\0';
01299 
01300    cnt = cnt + i + 1; /* Discard other Semicolon */
01301    i = 0;
01302    if((stabstr[cnt]) == '-') {
01303       i++; /* discard '-' for (long) unsigned int */
01304    }
01305    //Find high bound
01306    while (isdigit(stabstr[cnt+i])) i++;
01307    char *hi = (char *)malloc(sizeof(char)*(i+1));
01308    if(!strncpy(hi, &(stabstr[cnt]), i))
01309       /* Error copying upper range */
01310       exit(1);
01311    hi[i] = '\0';
01312 
01313    int j = atol(hi);
01314     
01315    if (j == 0) {
01316        //Size
01317        int size = atol(low);
01318 
01319        //Create new type
01320        Type *newType = new typeScalar(ID, size, name);
01321        //Add to Collection
01322        newType = tc->addOrUpdateType((typeScalar *) newType);
01323    }
01324    else {
01325        //Range
01326        //Create new type
01327        Type *newType;
01328        std::string tName = convertCharToString(name);
01329 
01330        errno = 0;
01331        long low_conv = strtol(low, NULL, 10);
01332        if (errno)
01333        {
01334            low_conv = LONG_MIN;
01335        }
01336 
01337        errno = 0;
01338        long hi_conv = strtol(hi, NULL, 10);
01339        if (errno)
01340        {
01341            hi_conv = LONG_MAX;
01342        }
01343 
01344        if (baseType == NULL)
01345            newType = new typeSubrange(ID, sizeHint ? sizeHint / 8 : guessSize(low,hi), 
01346                    low_conv, hi_conv, tName);
01347        else
01348            newType = new typeSubrange(ID, sizeHint ? sizeHint / 8 : baseType->getSize(), 
01349                    low_conv, hi_conv, tName);
01350        //Add to Collection
01351        tc->addOrUpdateType((typeSubrange *) newType);
01352    }
01353    free(low);
01354    free(hi);
01355    hi=low=NULL;
01356 
01357    cnt = cnt + i;
01358    if( stabstr[cnt] == ';')
01359       cnt++;
01360 
01361    return(&(stabstr[cnt]));
01362 }
01363 
01364 #else
01365 //
01366 // parse range type of the form:    
01367 //
01368 //  <rangeType> = r<typeNum>;<low>;<high>;
01369 //
01370 static char *parseRangeType(Module *mod, const char *name, int ID,
01371                             char *stabstr, unsigned int sizeHint = 0)
01372 {
01373     int cnt, i, symdescID;
01374     Type *baseType;
01375     Type *newType;
01376 
01377     cnt = i = 0;
01378 
01379     assert(stabstr[0] == 'r');
01380     cnt++;
01381 
01382     // range index type
01383     symdescID = parseSymDesc(stabstr, cnt);
01384 
01385     typeCollection *tc = typeCollection::getModTypeCollection(mod);
01386     baseType = tc->findType(symdescID);
01387 
01388     // //bperr("\tSymbol Descriptor: %c and Value: %d\n",tmpchar, symdescID);
01389 
01390     cnt++; /* Discarding the ';' */
01391     i=0;
01392     if (stabstr[cnt] == '-' ) {
01393        i++;
01394     }
01395 
01396     /* Getting type range or size */
01397     while (isdigit(stabstr[cnt+i])) i++;
01398 
01399     char *temp = (char *)malloc(sizeof(char)*(i+1));
01400     if(!strncpy(temp, &(stabstr[cnt]), i))
01401       /* Error copying size/range*/
01402       exit(1);
01403     temp[i] = '\0';
01404     int j = atol(temp);
01405     
01406     char *low = temp;
01407     cnt = cnt + i + 1; /* Discard other Semicolon */
01408     i = 0;
01409     if((stabstr[cnt]) == '-') {
01410        i++; /* discard '-' for (long) unsigned int */
01411     }
01412     
01413     while(isdigit(stabstr[cnt+i]))
01414        i++;
01415     
01416     char *hi = (char *)malloc(sizeof(char)*(i+1));
01417     if(!strncpy(hi, &(stabstr[cnt]), i))
01418        /* Error copying upper range */
01419        exit(1);
01420     hi[i] = '\0';
01421 
01422     std::string tname = convertCharToString(name);
01423     if ( j <= 0 )
01424     {
01425         /* range */
01426 
01427         // //bperr("\tLower limit: %s and Upper limit: %s\n", low, hi);
01428         //Create new type
01429         errno = 0;
01430         long low_conv = strtol(low, NULL, 10);
01431         if (errno)
01432         {
01433         //  fprintf(stderr, "%s[%d]:  error converting range limit '%s' to long: %s\n", 
01434         //          FILE__, __LINE__, low, strerror(errno));
01435             low_conv = LONG_MIN;
01436         }
01437 
01438         if (low_conv < LONG_MIN)
01439         {
01440             fprintf(stderr, "%s[%d]:  signed variable saturation...\n", FILE__, __LINE__);
01441             low_conv = LONG_MIN;
01442         }
01443 
01444         errno = 0;
01445         long hi_conv = strtol(hi, NULL, 10);
01446         if (errno)
01447         {
01448             //fprintf(stderr, "%s[%d]:  error converting range limit '%s' to long: %s\n", 
01449         //          FILE__, __LINE__, hi, strerror(errno));
01450             hi_conv = LONG_MAX;
01451         }
01452 
01453         if (hi_conv > LONG_MAX)
01454         {
01455             fprintf(stderr, "%s[%d]:  signed variable saturation...\n", FILE__, __LINE__);
01456             hi_conv = LONG_MAX;
01457         }
01458 
01459         if (baseType == NULL) 
01460         {
01461             newType = new typeSubrange(ID, sizeHint ? sizeHint / 8 : guessSize(low,hi), 
01462                     low_conv, hi_conv, tname);
01463         }
01464         else 
01465         {
01466             newType = new typeSubrange(ID, sizeHint ? sizeHint / 8 : baseType->getSize(), 
01467                     low_conv, hi_conv, tname);
01468         }
01469         newType = tc->addOrUpdateType((typeSubrange *) newType);
01470     } 
01471     else if( j > 0)
01472     {
01473         j = atol(hi);
01474         if (j == 0)
01475         {
01476             /*size */
01477             int size = (int)j;
01478 
01479             // //bperr("\tSize of Type : %d bytes\n",size);
01480             //Create new type
01481 
01482             newType = new typeScalar(ID, size, convertCharToString(name));
01483             //Add to Collection
01484             newType = tc->addOrUpdateType((typeScalar *) newType);
01485         } 
01486         else 
01487         {
01488             /* range */
01489             // //bperr("Type RANGE: ERROR!!\n");
01490             errno = 0;
01491             long low_conv = strtol(low, NULL, 10);
01492             if (errno)
01493             {
01494                 fprintf(stderr, "%s[%d]:  error converting range limit '%s' to long: %s\n", 
01495                         FILE__, __LINE__, low, strerror(errno));
01496                 low_conv = LONG_MIN;
01497             }
01498 
01499             errno = 0;
01500             long hi_conv = strtol(hi, NULL, 10);
01501             if (errno)
01502             {
01503                 fprintf(stderr, "%s[%d]:  error converting range limit '%s' to long: %s\n", 
01504                         FILE__, __LINE__, hi, strerror(errno));
01505                 hi_conv = LONG_MAX;
01506             }
01507 
01508             if (baseType == NULL)
01509                 newType = new typeSubrange(ID, sizeHint ? sizeHint / 8 : sizeof(long), 
01510                         low_conv, hi_conv, tname);
01511             else
01512                 newType = new typeSubrange(ID, sizeHint ? sizeHint / 8 : baseType->getSize(), 
01513                         low_conv, hi_conv, tname);
01514             newType = tc->addOrUpdateType((typeSubrange *) newType);
01515         }   
01516     }
01517     free(low);
01518     free(hi);
01519 
01520     cnt = cnt + i;
01521     if( stabstr[cnt] == ';')
01522       cnt++;
01523     
01524     return(&(stabstr[cnt]));
01525 }
01526 
01527 #endif
01528 
01529 //
01530 //  <attrType> = @s<int>;<int>
01531 //  <attrType> = @s<int>;(<int>,<int>)
01532 //  <attrType> = @s<int>;r(<int>,<int>);<int>;<int>;
01533 //
01534 
01535 //
01536 //   This may in fact be much simpler than first anticipated
01537 //   AIX stabs use attributes only as hints, and dbx only
01538 //   understands @s (size) and @P (packed) types.  We only 
01539 //   parse the size attribute, and should be able to get away
01540 //   with simply passing the remainder to the rest of our parser
01541 //
01542 static char *parseAttrType(Module *mod, const char *name,
01543              int ID, char *stabstr, int &cnt)
01544 {
01545     assert(stabstr[cnt] == '@');
01546     cnt++; // skip the @
01547    
01548     if (stabstr[cnt] == 's') {
01549       cnt++;
01550       
01551       int size = parseSymDesc(stabstr, cnt);
01552       cnt++;  // skip ';'
01553 
01554       char *newstr =  parseTypeDef(mod, stabstr+cnt, name, ID, size);
01555       if (newstr[0] == ';')
01556          return newstr+1;
01557       else
01558          return newstr;
01559     } else {
01560     ////bperr(" Unable to parse Type Attribute: %s ID %d : %s\n", 
01561     // name,ID, &(stabstr[cnt]));
01562        while (stabstr[cnt] != ';') cnt++;
01563        cnt++;
01564        return parseTypeDef(mod, stabstr+cnt, name, ID);
01565     }
01566 }
01567 /*
01568 static void parseAttrType(Module *mod, const char *name,
01569              int ID, char *stabstr, int &cnt)
01570 {
01571     bool includesRange = false;
01572     char *low = NULL, *high = NULL;
01573 
01574     // format @s(size in bits); negative type number;
01575     dataClass typdescr = dataTypeAttrib;
01576 
01577     assert(stabstr[cnt] == '@');
01578     cnt++; // skip the @
01579 
01580     if (stabstr[cnt] == 's') {
01581       cnt++;
01582       
01583       int size = parseSymDesc(stabstr, cnt);
01584       cnt++;  // skip ';'
01585 
01586       if (stabstr[cnt] == 'r') {
01587       // include range at end
01588       cnt++;
01589       includesRange = true;
01590       }
01591 
01592       int type = parseSymDesc(stabstr, cnt);
01593       // skip ';' end of stab record ??? (at least for bool)
01594       cnt++;
01595 
01596       if (includesRange) {
01597       int len;
01598 
01599       // Parse out low range string.
01600       len = 0;
01601       if (stabstr[cnt] == '-' ) cnt++, len++;
01602       while (isdigit(stabstr[cnt])) cnt++, len++;
01603       cnt++;    // skip ';'
01604 
01605       // Store the low range string.
01606       low = (char *)malloc(sizeof(char) * (len + 1));
01607       assert(low);
01608       strncpy(low, &stabstr[cnt - (len + 1)], len);
01609       low[len] = '\0';
01610 
01611       // Parse out high range string.
01612       len = 0;
01613       if (stabstr[cnt] == '-' ) cnt++, len++;
01614       while (isdigit(stabstr[cnt])) cnt++, len++;
01615       cnt++;    // skip ';'
01616 
01617       // Store the high range string.
01618       high = (char *)malloc(sizeof(char) * (len + 1));
01619           assert(high);
01620           strncpy(high, &stabstr[cnt - (len + 1)], len);
01621           high[len] = '\0';
01622       }
01623 
01624       // Create a new B_type that points to a builtInTypes
01625       Type *ptrType =BPatch::bpatch->builtInTypes->findBuiltInType(type);
01626       
01627       if (!ptrType) ptrType = BPatch::bpatch->type_Untyped;
01628       
01629       Type *newType = new Type(name, ID, typdescr, size/8, ptrType);
01630       if(!newType) {
01631         //bperr(" Can't Allocate new type ");
01632         exit(-1);
01633       }
01634 
01635       if (includesRange) {
01636       newType->setLow(low);
01637       newType->setHigh(high);
01638       free(low);
01639       free(high);
01640       }
01641 
01642       // Add type to collection
01643       newType2 = tc->addOrUpdateType(newType);
01644 
01645       if (stabstr[cnt]) {
01646       //bperr("More Type Attribute to Parse: %s ID %d : %s\n", name,
01647            ID, &(stabstr[cnt]));
01648       //bperr("got type = %d\n", type);
01649       //bperr("full string = %s\n", stabstr);
01650       }
01651     } else {
01652     ////bperr(" Unable to parse Type Attribute: %s ID %d : %s\n", 
01653     // name,ID, &(stabstr[cnt]));
01654     }
01655 }
01656 */
01657 //
01658 //  <refType> = &<typeUse>
01659 //
01660 static char *parseRefType(Module *mod, const char *name,
01661            int ID, char *stabstr, int &cnt)
01662 {
01663     /* reference to another type */
01664     assert(stabstr[cnt] == '&');
01665     cnt++;
01666     
01667     int refID = parseTypeUse(mod, stabstr, cnt, name);
01668     
01669     // Create a new B_type that points to a structure
01670     typeCollection *tc = typeCollection::getModTypeCollection(mod);
01671     Type *ptrType = tc->findOrCreateType(refID);
01672     if (!ptrType) ptrType = Symtab::type_Untyped().get();
01673     std::string tName = convertCharToString(name); 
01674     typeRef *newType = new typeRef(ID, ptrType, tName);
01675 
01676     // Add to typeCollection
01677     newType = tc->addOrUpdateType(newType);
01678     
01679     return(&(stabstr[cnt]));
01680 }
01681 
01682 //
01683 // Given a base class and a new type, add all visible fields to the new class
01684 //
01685 void addBaseClassToClass(Module *mod, int baseID, 
01686                          fieldListType *newType, int /*offset*/)
01687 {
01688 
01689     typeCollection *tc = typeCollection::getModTypeCollection(mod);
01690 
01691     //Find base class
01692     fieldListType *baseCl = dynamic_cast<fieldListType *>(tc->findType(baseID));
01693     if( ! baseCl ) {
01694         std::string modName = mod->fileName();
01695         //bpwarn( "can't find base class id %d in module %s\n", baseID, modName);
01696         baseCl = new typeStruct(baseID);
01697         fieldListType *baseCl2 = dynamic_cast<typeStruct *>(tc->addOrUpdateType( (typeStruct *)baseCl ));
01698         std::string fName = "{superclass}";
01699         newType->addField( fName, baseCl2, -1, visUnknown );
01700         baseCl->decrRefCount();
01701         return;
01702     }
01703     std::string fName = "{superclass}";
01704     newType->addField( fName, baseCl, -1, visUnknown );
01705 
01706     //Get field descriptions of the base type
01707     /*
01708     const std::vector<Field *> *baseClFields = baseCl->getComponents();
01709     for (unsigned int fieldNum=0; fieldNum < baseClFields->size(); fieldNum++) {
01710     Field *field = (*baseClFields)[fieldNum];
01711 
01712     if (field->getVisibility() == visPrivate)
01713         continue; //Can not add this member
01714 
01715     newType->addField(field->getName(), field->getTypeDesc(), field->getType(), field->getOffset()+offset, field->getVisibility());
01716     }
01717     */
01718 }
01719 
01720 //
01721 // parse a list of fields.
01722 //    Format is [A|B|C-M|N|O][c][G]<fieldName>:<type-desc>;offset;size;
01723 //
01724 static char *parseFieldList(Module *mod, fieldListType *newType, 
01725         char *stabstr, bool sunCPlusPlus)
01726 {
01727     int cnt = 0;
01728     int size = 0;
01729     char *compname;
01730     int comptype= 0;
01731     int beg_offset=0;
01732     visibility_t _vis = visUnknown;
01733     dataClass typedescr;
01734     bool hasVirtuals = false;
01735     typeCollection *tc = typeCollection::getModTypeCollection(mod);
01736     assert(tc);
01737 
01738     if (stabstr[cnt] == '!') 
01739     {
01740         //Inheritance definition, Add base class field list to the current one
01741         //according to visibility rules.
01742 
01743         cnt++; //Skip '!'
01744 
01745         //Get # of base classes
01746         int baseClNum = atoi(getIdentifier(stabstr, cnt).c_str());
01747         cnt++; //Skip ','
01748 
01749         typeStruct *newStructType = dynamic_cast<typeStruct *>(newType);
01750         //Skip information for each base class
01751         for (int i=0; i<baseClNum; ++i) 
01752         {
01753             //Skip virtual inheritance flag, base visibility flag and base offset
01754             getIdentifier(stabstr, cnt);
01755             cnt++; //Skip ','
01756 
01757             //Find base class type identifier
01758             int baseID = parseSymDesc(stabstr, cnt);
01759 
01760             cnt++; //Skip ';'
01761 
01762             addBaseClassToClass(mod, baseID, newStructType, 0);
01763         }
01764     }
01765 
01766     while (stabstr[cnt] && (stabstr[cnt] != ';')) 
01767     {
01768         typedescr = dataScalar;
01769 
01770         if (stabstr[cnt] == '~') 
01771         {
01772             //End of virtual class
01773             while (stabstr[cnt] != ';') cnt++;
01774             break; //End of class is reached
01775         }
01776 
01777         // skip <letter>cG
01778         if (sunCPlusPlus) cnt += 3;
01779 
01780         if ((stabstr[cnt] == 'u') && (stabstr[cnt+1] == ':') && (!isdigit(stabstr[cnt+2]))) 
01781         {
01782             cnt += 2;
01783         }
01784 
01785         compname = getFieldName(stabstr, cnt);
01786 
01787         /*
01788            if (strlen(compname) == 0) {
01789         //Something wrong! Most probably unhandled C++ type
01790         //Skip the rest of the structure
01791         while(stabstr[cnt]) cnt++;
01792         return(&stabstr[cnt]);
01793         }
01794          */
01795         cnt++;  // Skip ":"
01796 
01797         if ((stabstr[cnt]) == ':') 
01798         {
01799             //Method definition
01800             typedescr = dataFunction;
01801             cnt++;
01802         }
01803 
01804         if ((stabstr[cnt]) == '/') 
01805         { // visibility C++
01806             cnt++; /* get '/' */
01807             switch (stabstr[cnt]) {
01808                 case '0':
01809                     _vis = visPrivate;
01810                     break;
01811                 case '1':
01812                     _vis = visProtected;
01813                     break;
01814                 case '2':
01815                     _vis = visPublic;
01816                     break;
01817                 default:
01818                     _vis = visUnknown;
01819             }
01820             cnt++; // get visibility value
01821         }
01822 
01823         // should be a typeDescriptor
01824         comptype = parseTypeUse(mod, stabstr, cnt, "");
01825 
01826         if (stabstr[cnt] == ':') 
01827         {
01828             while (stabstr[cnt] == ':') 
01829             {
01830                 cnt++; //Discard ':'
01831                 beg_offset = 0;
01832                 size = 0;
01833                 std::string varName = getIdentifier(stabstr, cnt);
01834 
01835                 if (typedescr == dataFunction) 
01836                 {
01837                     // Additional qualifiers for methods
01838                     cnt++; //Skip ';'
01839                     cnt++; //Skip visibility
01840                     cnt++; //Skip method modifier
01841                     if (stabstr[cnt] == '*') 
01842                     {
01843                         //Virtual fcn definition
01844                         hasVirtuals = true;
01845                         cnt++; //Skip '*'
01846                         while(stabstr[cnt] != ';') cnt++; //Skip vtable index
01847                         cnt++; //Skip ';'
01848                         if (stabstr[cnt] != ';') 
01849                         {
01850                             parseTypeUse(mod, stabstr, cnt, ""); //Skip type number to the base class
01851                         }
01852                         cnt++; //Skip ';'
01853                         if (isSymId(stabstr[cnt])) 
01854                         {
01855                             parseTypeUse(mod, stabstr, cnt, "");
01856                         }
01857                     } else if (   (stabstr[cnt] == '.') 
01858                                || (stabstr[cnt] == '?') ) 
01859                     {
01860                         cnt++; //Skip '.' or '?'
01861                         if (isSymId(stabstr[cnt])) 
01862                         {
01863                             parseTypeUse(mod, stabstr, cnt, "");
01864                         }
01865                     }
01866                 }
01867 
01868                 if (stabstr[cnt] == ';')
01869                     cnt++; //Skip ';'
01870             }
01871         } 
01872         else if (stabstr[cnt] == ',') 
01873         {
01874             cnt++;  // skip ','
01875             beg_offset = parseSymDesc(stabstr, cnt);
01876 
01877             if (stabstr[cnt] == ',') 
01878             {
01879                 cnt++;  // skip ','
01880                 size = parseSymDesc(stabstr, cnt);
01881             }
01882             else
01883                 size = 0;
01884         }
01885 
01886         if (stabstr[cnt] == ';') // jaw 03/15/02-- major kludge here for DPCL compat
01887             cnt++;  // needs further examination
01888 
01889         // //bperr("\tType: %d, Starting Offset: %d (bits), Size: %d (bits)\n", comptype, beg_offset, size);
01890         // Add struct field to type
01891 
01892         Type *fieldType = tc->findOrCreateType( comptype );
01893         if (fieldType == NULL) 
01894         {
01895             //C++ compilers may add extra fields whose types might not available.
01896             //Assign void type to these kind of fields. --Mehmet
01897             fieldType = tc->findType("void");
01898         }
01899         std::string fName = convertCharToString(compname);
01900         if (_vis == visUnknown) 
01901         {
01902             newType->addField(fName, fieldType, beg_offset);
01903         } 
01904         else 
01905         {
01906             // //bperr( "Adding field '%s' to type '%s' @ 0x%x\n", compname, newType->getName(), newType );
01907             newType->addField(fName, fieldType, beg_offset, _vis);
01908             ////bperr("Adding Component with VISIBILITY STRUCT\n");
01909         }
01910         free(compname);
01911     }
01912 
01913     if (hasVirtuals && 
01914             stabstr[cnt] == ';' &&
01915             stabstr[cnt+1] == '~' &&
01916             stabstr[cnt+2] == '%') 
01917     {
01918         cnt+=3;
01919         while (stabstr[cnt] != ';') cnt++;
01920     }         
01921 
01922     // should end with a ';'
01923     if (stabstr[cnt] == ';') 
01924     {
01925         return &stabstr[cnt+1];
01926     } 
01927     else if (stabstr[cnt] == '\0') 
01928     {
01929         return &stabstr[cnt];
01930     } 
01931     else 
01932     {
01933         //bperr("invalid stab record: %s\n", &stabstr[cnt]);
01934         abort();
01935         return NULL; // should not get here
01936     }
01937 }
01938 
01939 
01940 //
01941 //  Y<type><size><className>;<Bases>;<DataMembers>;<MemberFunctions>;<StaticDataMembers>;
01942 //      <Friends>;<VirtualFunctionInfo>;<NestedClassList>;<AccessAdjustments>;
01943 //      <VirtualBaseClassOffsets>;<TemplatmentMembers>;<PassMethod>;
01944 //
01945 static char *parseCPlusPlusInfo(Module *mod,
01946         char *stabstr, const char *mangledName, int ID)
01947 {
01948     typeCollection *tc = typeCollection::getModTypeCollection(mod);
01949     int cnt;
01950     char *name;
01951     int structsize;
01952     bool sunStyle = true;
01953     bool nestedType = false;
01954     dataClass typdescr;
01955     fieldListType * newType = NULL, *newType2 = NULL;
01956 
01957     assert(stabstr[0] == 'Y');
01958     cnt = 1;
01959 
01960     // size on AIX 
01961     if (isdigit(stabstr[cnt])) {
01962     structsize = parseSymDesc(stabstr, cnt);
01963     sunStyle = false;
01964     }
01965 
01966     switch(stabstr[cnt]) {
01967     case 'C':
01968     case 'c':
01969         typdescr = dataTypeClass;
01970         break;
01971 
01972     case 'S':
01973         nestedType = true;
01974     case 's':
01975         typdescr = dataStructure;
01976         break;
01977 
01978     case 'U':
01979         nestedType = true;
01980     case 'u':
01981         typdescr = dataUnion;
01982         break;
01983 
01984         case 'n':   // namespace - ignored
01985         cnt = strlen(stabstr);
01986         return(&(stabstr[cnt]));
01987         break;
01988 
01989     default:
01990         //bperr( "ERROR: Unrecognized C++ str = %s\n", stabstr);
01991         cnt = strlen(stabstr);
01992         return(&(stabstr[cnt]));
01993         break;
01994     }
01995 
01996     cnt++;      // skip to size
01997     if (isdigit(stabstr[cnt])) {
01998     structsize = parseSymDesc(stabstr, cnt);
01999     }
02000     
02001     if (stabstr[cnt] == 'V') cnt++;
02002     if (stabstr[cnt] == '(') cnt++;
02003 
02004     if (sunStyle && (stabstr[cnt] != ';')) {
02005     int len;
02006     char *n;
02007 
02008     // Class or Type Name
02009     n = &stabstr[cnt];
02010     while (stabstr[cnt] != ';') cnt++;
02011     len = &stabstr[cnt] - n;
02012     name = (char *) calloc(len + 1, sizeof(char));
02013     strncpy(name, n, len);
02014     } else {
02015     name = const_cast< char * >( mangledName );
02016     }
02017 
02018     std::string tName = convertCharToString(name);
02019     //Create new type
02020     switch (typdescr) {
02021     case dataTypeClass:
02022     case dataStructure:
02023        newType = new typeStruct(ID, tName);
02024        newType2 = dynamic_cast<fieldListType *>(tc->addOrUpdateType((typeStruct *) newType));
02025        break;
02026     case dataUnion:
02027        newType = new typeUnion(ID, tName);
02028        newType2 = dynamic_cast<fieldListType *>(tc->addOrUpdateType((typeUnion *) newType));
02029        break;
02030     default:
02031        assert(0);
02032     }
02033     //add to type collection
02034 
02035     if(newType2 != newType)
02036         newType->decrRefCount();
02037 
02038     if (sunStyle) {
02039     cnt++;
02040     // base class(es) 
02041     while (stabstr[cnt] != ';') {
02042         // skip visibility flag
02043         cnt++;
02044 
02045         int offset = parseSymDesc(stabstr, cnt);
02046 
02047         // Find base class type identifier
02048             int baseID = parseSymDesc(stabstr, cnt);
02049         addBaseClassToClass(mod, baseID, newType2, offset);
02050     }
02051 
02052     cnt++;  // skip ;
02053     }
02054 
02055     // parse dataMembers
02056     stabstr = parseFieldList(mod, newType2, &stabstr[cnt], sunStyle);
02057     cnt = 0;
02058 
02059     if (stabstr[0]) {
02060     // parse member functions
02061     cnt++;
02062     while (stabstr[cnt] && (stabstr[cnt] != ';')) {
02063         std::string pd_funcName = getIdentifier(stabstr, cnt, true);
02064             const char *funcName = pd_funcName.c_str();
02065 
02066         funcName++; // skip ppp-code
02067 
02068         if (*funcName == '-') funcName++; // it's a pure vitual
02069 
02070         while (isdigit(*funcName)) funcName++; // skip virtual function index
02071         funcName++;
02072 
02073         char *className = strdup(currentRawSymbolName.c_str());
02074         className[3] = 'c';
02075         className[strlen(className)-1] = '\0';  // remove tailing "_"
02076         std::string methodName = std::string(className) + std::string(funcName) + std::string("_");
02077         char * name = P_cplus_demangle( methodName.c_str(), mod->exec()->isNativeCompiler() );
02078         if( name != NULL ) {
02079             funcName = strrchr( name, ':' );
02080             if( funcName ) { funcName++; }
02081             else { funcName = name; }
02082             }
02083 
02084         // should include position for virtual methods
02085         Type *fieldType = tc->findType("void");
02086 
02087         std::string fName = convertCharToString(funcName);
02088 
02089         typeFunction *funcType = new typeFunction( ID, fieldType, fName);
02090             newType2->addField( fName, funcType);
02091                         
02092         free(name);
02093         free(className);
02094         if (stabstr[cnt] == ' ') cnt++;
02095     }
02096     }
02097 
02098     cnt = strlen(stabstr);
02099     return(&(stabstr[cnt]));
02100 }
02101 
02102 //
02103 // This function takes a <typeDef> and parses it 
02104 //
02105 //  <typeDef> = <symDesc>   |
02106 //      <crossRef>  |   
02107 //      *<typeUse>  |   Pointer to a type
02108 //      <arrayDef>  |
02109 //      f<typeUse>  |   function type
02110 //      R<int>,<int>    |   Real type 
02111 //      b[u|s][c|]<int>;<int>;<int> |   Builtin
02112 //      <rangeType> |
02113 //      e<enumType> |
02114 //      <attrType>  |
02115 //      <refType>   |
02116 //      k<typeDef>  |   SunPro constant
02117 //      B<typeDef>  |   SunPro volatile
02118 //      M<symDesc>;<int>|   Fortran CHARACTER array
02119 //      s<int><fields>  |   Structure <int> is size
02120 //      u<int><fields>  |   Union <int> is size
02121 //      V<typeUse>
02122 //
02123 //  <enumType> = <ident>:<int> | <ident>:<int>,<enumType>
02124 //
02125 // It adds the typeDef to the type definition with the name name, and id ID.
02126 //
02127 static char *parseTypeDef(Module *mod, char *stabstr, 
02128                           const char *name, int ID, unsigned int sizeHint)
02129 {
02130     typeCollection *tc = typeCollection::getModTypeCollection(mod);
02131     Type * newType = NULL;
02132     fieldListType * newFieldType = NULL, *newFieldType2 = NULL;
02133     Type * ptrType = NULL;
02134   
02135     std::string compsymdesc;
02136   
02137     dataClass typdescr;
02138     int ptrID=0;
02139     
02140     int value;
02141     int cnt,i,j,k;
02142     int structsize;
02143     int type;
02144     cnt = i = j = k = 0;
02145 
02146     assert (stabstr[0] != '=');
02147 
02148     // //bperr( "parsing %s\n", stabstr);
02149     if (isSymId(stabstr[0])) 
02150     {
02151     typdescr = dataScalar;
02152     type = parseSymDesc(stabstr, cnt);
02153             
02154     if (ID == type) 
02155     {
02156         // Type:tFOO = FOO
02157         // as far as I can tell, this only happens when defining an empty
02158         // type (i.e. void)
02159 
02160         std::string tName = convertCharToString(name);
02161         newType = new typeScalar(ID, 0, tName);
02162         newType = tc->addOrUpdateType((typeScalar *) newType); 
02163     } 
02164     else if (stabstr[cnt] == '=') 
02165     {
02166         // XXX - in the new type t(0,1)=(0,2)=s... is possible
02167         //       skip the second id for now -- jkh 3/21/99
02168         stabstr = parseTypeDef(mod, &(stabstr[cnt+i+1]), name, type);
02169         cnt = 0;
02170         Type *oldType;
02171 
02172         oldType = tc->findOrCreateType(type);
02173         if (!oldType) oldType = Symtab::type_Untyped().get();
02174         std::string tName = convertCharToString(name);
02175         newType = new typeTypedef(ID, oldType, tName, sizeHint);
02176         tc->addOrUpdateType((typeTypedef *) newType);
02177 
02178     } 
02179     else 
02180     {
02181         Type *oldType;
02182         std::string tName = convertCharToString(name);
02183         oldType = tc->findOrCreateType(type);
02184         newType = new typeTypedef(ID, oldType, tName, sizeHint);
02185         newType = tc->addOrUpdateType((typeTypedef *) newType);
02186     }
02187     } else {
02188       switch (stabstr[0]) {
02189       case 'x':  //cross reference 
02190       {
02191         parseCrossRef(tc, name, ID, stabstr, cnt);
02192         break;
02193       }   
02194       case '*':
02195       {
02196         /* pointer to another type */
02197         cnt++;
02198         ptrID = parseTypeUse(mod, stabstr, cnt, NULL);
02199 
02200         // Create a new B_type that points to a structure
02201         ptrType = tc->findOrCreateType(ptrID);
02202         if (!ptrType) ptrType = Symtab::type_Untyped().get();
02203 
02204             newType = new typePointer(ID, ptrType);
02205         // Add to typeCollection
02206         newType = tc->addOrUpdateType((typePointer *) newType);
02207         return(&(stabstr[cnt]));
02208         break;
02209       }
02210       case 'a':
02211       case 'A':
02212       {
02213           (void) parseArrayDef(mod, name, ID, stabstr, cnt, sizeHint);
02214           return (&stabstr[cnt]);
02215           break;
02216       }
02217       case 'g':  
02218       {
02219         /* function with return type and prototype */
02220 
02221         // g<typeUse>[<typeUse>]*#
02222         typdescr = dataFunction;
02223 
02224         cnt++; /* skip the g */
02225             type = parseTypeUse(mod, stabstr, cnt, name);
02226                 ptrType = tc->findOrCreateType(type);
02227 
02228                 {
02229            std::string tName = convertCharToString(name);
02230                    typeFunction *newFunction = 
02231                       new typeFunction(ID, ptrType, tName);
02232                    typeFunction *newFunction2 = NULL;
02233                    
02234                    if (newFunction) { 
02235                       newFunction2 = dynamic_cast<typeFunction*>(tc->addOrUpdateType(newFunction)); 
02236                       if(newFunction2 != newFunction)
02237                           newFunction->decrRefCount();
02238                    }
02239                    if (!newFunction2) {
02240                       //bpfatal(" Can't Allocate new type ");
02241                             types_printf("%s[%d]: parseTypeDef: unable to allocate newType\n", FILE__, __LINE__);
02242                             //exit(-1);
02243                    }
02244                    
02245                    while ((stabstr[cnt] != '#') &&  (stabstr[cnt])) {
02246                       int paramType;
02247                       paramType = parseTypeUse(mod, stabstr, cnt, name);
02248                       newType = tc->findOrCreateType(paramType);
02249               newFunction2->addParam(newType);
02250                       //newFunction2->addField(buffer, newType->getDataClass(), newType, curOffset, newType->getSize());
02251                    }
02252                 }
02253 
02254         // skip #
02255         if (stabstr[cnt] == '#') cnt++;
02256         break;
02257       }
02258       case 'f':
02259       {
02260             /* function type */
02261         typdescr = dataFunction;
02262 
02263         cnt++; /* skip the f */
02264             type = parseTypeUse(mod, stabstr, cnt, name);
02265                 ptrType = tc->findOrCreateType(type);
02266 
02267         
02268                 std::string tName = convertCharToString(name);
02269         newType = new typeFunction(ID, ptrType, tName);
02270         newType = tc->addOrUpdateType((typeFunction *) newType);
02271 
02272         // skip to end - SunPro Compilers output extra info here - jkh 6/9/3
02273         // cnt = strlen(stabstr);
02274         break;
02275      }
02276 
02277      case 'M': 
02278      {
02279         /* CHARACTER ??? */
02280         cnt++; // skip  'M'
02281 
02282         int baseType = parseSymDesc(stabstr, cnt);
02283         if (baseType != -2 || (stabstr[cnt] != ';')) {
02284             //bperr("unexpected non character array %s\n", stabstr);
02285         } else {
02286             cnt++; // skip ';'
02287             int size;
02288             if (stabstr[cnt] == 'T') {
02289               /* Fortran stack-based array bounds */
02290               size = 0;
02291               cnt++; // skip 'T'
02292               (void) parseSymDesc(stabstr, cnt);
02293             } else if (stabstr[cnt] == 'J') {
02294                       /* Unbounded range */
02295                       size = 0;
02296                       cnt++; // skip 'J';
02297               (void) parseSymDesc(stabstr, cnt);
02298                     } else
02299               size = parseSymDesc(stabstr, cnt);
02300 
02301             ptrType = tc->findOrCreateType(baseType);
02302             std::string tName = convertCharToString(name);
02303 
02304             Type *newAType = new typeArray(ID, ptrType, 1, size, tName);
02305             newType = tc->addOrUpdateType((typeArray* ) newAType);
02306         }
02307         break;
02308 
02309      }
02310      case 'R': 
02311      {
02312         // Define a floating point type - R fp-type; bytes;
02313         cnt++;
02314         (void) parseSymDesc(stabstr, cnt);
02315         cnt ++;
02316 
02317         int bytes = parseSymDesc(stabstr, cnt);
02318 
02319         newType = new typeScalar(ID, bytes, name);
02320         newType = tc->addOrUpdateType((typeScalar *) newType);
02321 
02322         if (stabstr[cnt] == ';') cnt++; // skip the final ';'
02323 
02324         // gcc 3.0 adds an extra field that is always 0 (no indication in the code why)
02325         if (stabstr[cnt] == '0') cnt += 2;  // skip the final '0;'
02326 
02327         break;
02328       }
02329 
02330       case 'b': 
02331       {
02332         // builtin type b  - signed char-flag width; offset; nbits
02333         int limit = strlen(&stabstr[cnt]);
02334 
02335         // skip to width
02336         while (!isdigit(stabstr[cnt+i]) && (i < limit)) i++;    
02337         if (i >= limit) return(&(stabstr[cnt]));
02338 
02339                 cnt += i;
02340                 int size = parseSymDesc(stabstr,cnt);
02341                 cnt -= i;
02342         i++;    // skip the ';'
02343 
02344         // skip to bits
02345         while (stabstr[cnt+i] != ';' && (i < limit)) i++;   
02346         if (i >= limit) return(&(stabstr[cnt]));
02347         i++;
02348 
02349         cnt += i;
02350         parseSymDesc(stabstr, cnt);
02351         
02352         if (stabstr[cnt]) cnt++;    // skip the final ';'
02353 
02354         newType = new typeScalar(ID, size, name);
02355         //Add to Collection
02356         newType = tc->addOrUpdateType((typeScalar *) newType);
02357 
02358         return &stabstr[cnt];
02359         break;
02360     }
02361     case 'r':       // range type
02362     {    
02363         return parseRangeType(mod, name, ID, stabstr, sizeHint);
02364         break;
02365     }
02366     case 'e':       // Enumerated type
02367     {
02368         cnt++;  /* skip the 'e' */
02369 
02370         // Create new Enum type
02371         std::string tName = convertCharToString(name);
02372         typeEnum *newEnumType = new typeEnum(ID, tName);
02373         // Add type to collection
02374         newEnumType = dynamic_cast<typeEnum *>(tc->addOrUpdateType(newEnumType));
02375         
02376         while (stabstr[cnt]) {
02377         /* Get enum component value */
02378         compsymdesc = getIdentifier(stabstr, cnt);
02379         cnt++; /* skip colon */
02380 
02381 #ifdef IBM_BPATCH_COMPAT_STAB_DEBUG
02382         //bperr( "%s[%d]:  before parseSymDesc -- enumerated type \n", 
02383         //      __FILE__, __LINE__);
02384 #endif        
02385         value = parseSymDesc(stabstr, cnt);
02386 
02387         // add enum field to type
02388         newEnumType->addConstant(compsymdesc, value);
02389           
02390         cnt++; /* skip trailing comma */
02391         if ((stabstr[cnt]) == ';') cnt++; /* End of enum stab record */
02392         }
02393         break;
02394     }    
02395         case '@':  // type attribute, defines size and type (negative num)
02396     {
02397         return parseAttrType(mod, name, ID, stabstr, cnt);
02398         break;
02399     }
02400         case '&': //XXX- Need to complete, may be more to parse jdd 4/22/99
02401     {    
02402         return parseRefType(mod, name, ID, stabstr, cnt);
02403         break;
02404     }
02405         case 'k':   // Sun constant type s<typeDef> - parse as <typeDef>
02406     {
02407         return parseTypeDef(mod, &stabstr[cnt+1], name, ID);
02408         break;
02409     }
02410     case 'V':   // AIX colatile ? type V<typeDef> - parse as <typeDef>
02411         case 'B':   // Sun volatile type B<typeDef> - parse as <typeDef>
02412         return parseTypeDef(mod, &stabstr[cnt+1], name, ID);
02413         break;
02414 
02415     case 's':   // struct
02416     case 'u':   // union
02417     case 'T':   // Fortran TYPE
02418     {    
02419         /* Type descriptor */
02420         if (stabstr[cnt] == 's' || stabstr[cnt] == 'T') {
02421             typdescr = dataStructure;
02422         } else {
02423             typdescr = dataUnion;
02424         }
02425 
02426         cnt++;      // skip to size
02427         structsize = parseSymDesc(stabstr, cnt);
02428        
02429         std::string tName = convertCharToString(name);
02430         //Create new type
02431             if (typdescr == dataStructure) {
02432                newFieldType = new typeStruct(ID, tName);
02433            newFieldType2 = dynamic_cast<fieldListType *>(tc->addOrUpdateType((typeStruct *) newFieldType));
02434         }
02435             else {
02436                newFieldType = new typeUnion(ID, tName);
02437            newFieldType2 = dynamic_cast<fieldListType *>(tc->addOrUpdateType((typeUnion *) newFieldType));
02438         }
02439         //add to type collection
02440 
02441         //TODO What if two different files have the same structure?? // on AIX
02442         if(!newFieldType2)
02443             newFieldType2 = dynamic_cast<fieldListType *>(newFieldType);
02444         if(newFieldType2 != newFieldType)
02445             newFieldType->decrRefCount();
02446         char *ret = parseFieldList(mod, newFieldType2, &stabstr[cnt], false);
02447         return ret;
02448 
02449         break;
02450     }
02451     case 'Y':
02452     {
02453         // C++ specific stabs (Sun compiler)
02454         return parseCPlusPlusInfo(mod, stabstr, name, ID);
02455         break;
02456     }
02457     case 'Z':  // What is this ??? - jkh 10/14/99 (xlc compiler uses it)
02458     {    
02459         return (&stabstr[1]);
02460         break;
02461     }
02462     case '#':
02463     {
02464         //Class method definition
02465         cnt++; //Skip '#'
02466         if (stabstr[cnt] == '#') {
02467         //Get return type
02468             cnt++; //Skip '#'
02469         parseTypeUse(mod, stabstr, cnt, name);
02470         }
02471         else {
02472             while(1) {
02473             //Skip class type, return typ and arg types
02474             parseTypeUse(mod, stabstr, cnt, name);
02475             if (stabstr[cnt] == ',')
02476                 cnt++;
02477             else if (stabstr[cnt] == ';')
02478                 break;
02479         }
02480         }
02481 
02482         cnt++; //Skip ';'
02483             return(&(stabstr[cnt]));
02484         break;
02485     }
02486     default:
02487         //bperr( "ERROR: Unrecognized str = %s\n", &stabstr[cnt]);
02488         //      return NULL;
02489         // Null probably isn't the right choice here.
02490         cnt = strlen(stabstr);
02491         break;
02492       }
02493     }
02494 
02495     return(&(stabstr[cnt]));
02496 } /* end of parseTypeDef*/
02497 
02498 //
02499 // parseConstantUse - parse a constant (used by Fortran PARAMETERS)
02500 //
02501 // <constantUse> = =i<int> |
02502 //         =r <float>
02503 //
02504 //
02505 static Type *parseConstantUse(Module *mod, char *stabstr, int &cnt)
02506 {
02507     typeCollection *tc = typeCollection::getModTypeCollection(mod);
02508     // skip =
02509     cnt++;
02510 
02511     Type *ret;
02512 
02513     if (stabstr[cnt] == 'i') {
02514     ret = tc->findType("integer*4");
02515     } else if (stabstr[cnt] == 'r') {
02516     ret = tc->findType("double");
02517     } else if (stabstr[cnt] == 's') {
02518         ret = tc->findType("char *");
02519     } else {
02520     //bperr("unknown constant type %s\n", &stabstr[cnt]);
02521     ret = NULL;
02522     }
02523 
02524     cnt = strlen(stabstr);
02525 
02526     return ret;
02527 }
02528 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1