windows build fixes and some more work on symtab serialization
[dyninst.git] / symtabAPI / src / parseStab.C
1 /*
2  * Copyright (c) 1996-2007 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
30  */
31
32 #include <ctype.h>
33 #include <iostream>
34 // from libiberty's demangle.h
35 #define DMGL_PARAMS   (1 << 0) 
36 #define DMGL_ANSI     (1 << 1) 
37 #define DMGL_VERBOSE  (1 << 3) 
38
39 #include "symutil.h"
40 #include "Symtab.h" // For looking up compiler type
41 #include "Symbol.h" 
42 #include "Function.h"
43 #include "Variable.h"
44 #include "Module.h" 
45 #include "Collections.h"
46 #include "common/h/headers.h"
47 #include "Type-mem.h"
48
49 #include "debug.h"
50
51 using namespace Dyninst;
52 using namespace Dyninst::SymtabAPI;
53
54 /*
55 #include "BPatch.h"
56 #include "debug.h"
57 */
58
59 extern std::string symt_current_func_name;
60 extern std::string symt_current_mangled_func_name;
61 extern Function *symt_current_func;
62 namespace Dyninst{
63 namespace SymtabAPI{
64     std::string parseStabString(Module *mod, int linenum, char *stabstr, 
65                       int framePtr, typeCommon *commonBlock = NULL);
66 }
67 }
68
69 // Forward references for parsing routines
70 static int parseSymDesc(char *stabstr, int &cnt);
71 static Type *parseConstantUse(Module *, char *stabstr, int &cnt);
72 static char *parseTypeDef(Module *, char *stabstr, 
73                           const char *name, int ID, unsigned int sizeHint = 0);
74 static int parseTypeUse(Module*, char *&stabstr, int &cnt,
75                         const char *name);
76 static inline bool isSymId(char ch);
77 static std::string getIdentifier(char *stabstr, int &cnt, bool stopOnSpace=false);
78
79 static std::string currentRawSymbolName;
80
81 std::string convertCharToString(const char *ptr){
82     if(ptr)
83         return ptr;
84     else
85         return "";
86 }
87
88 //
89 // Start of code to parse Stab information.
90 //    The structure of this code is a recursive decent parser that parses
91 //    information in stab records and builds up the corresponding BPatch_types.
92 //    
93 //    Each non-terminal in the grammer has a function of the form parse<NT>.
94 //      
95 //    The grammar for a non-terminal appears in the comments just before
96 //    the non-terminal parsing function
97 //      
98
99 void vectorNameMatchKLUDGE(Module *mod, char *demangled_sym, std::vector<Function *> &bpfv, std::vector<int> &matches)
100 {
101   // iterate through all matches and demangle names with extra parameters, compare
102   for (unsigned int i = 0; i < bpfv.size(); ++i) {
103     std::string l_mangled;
104     std::vector<Symbol *> syms;
105     bpfv[i]->getSymbols(syms);
106     if (syms.size()) {
107         l_mangled = syms[0]->getMangledName();
108         
109         char * l_demangled_raw = P_cplus_demangle(l_mangled.c_str(), mod->exec()->isNativeCompiler());
110         if( l_demangled_raw == NULL ) {
111             l_demangled_raw = strdup(l_mangled.c_str());
112         }
113         
114         if (!strcmp(l_demangled_raw, demangled_sym)) {
115            matches.push_back(i);
116         }
117         free(l_demangled_raw);
118     }
119   } /* end iteration over function vector */
120 }
121
122 Function *mangledNameMatchKLUDGE(const char *pretty, const char *mangled, 
123                                         Module *mod)
124 {
125
126   std::vector<Function *> bpfv;
127   if (!mod->exec()->findFunctionsByName(bpfv, pretty)) {
128      //cerr << __FILE__ << __LINE__ << ":  KLUDGE Cannot find " << pretty << endl;
129      return NULL;  // no pretty name hits, expecting multiple
130   }
131
132   //cerr << __FILE__ << __LINE__ << ":  mangledNameMatchKLUDGE: language = " 
133   //<< mod->getLanguageStr() << endl;
134
135   if (lang_Fortran_with_pretty_debug == mod->language()) {
136       // debug function symbols are presented in "demangled" style.
137       if (bpfv.size() == 1)
138         return bpfv[0];
139       else {
140         cerr << __FILE__ << __LINE__ << ":  FIXME!" << endl;
141         return NULL;
142       }
143     }
144
145   // demangle name with extra parameters
146   char * demangled_sym = P_cplus_demangle( mangled, mod->exec()->isNativeCompiler(), true );
147   if( demangled_sym == NULL ) {
148         demangled_sym = strdup( mangled );
149         assert( demangled_sym != NULL );
150   }
151
152   std::vector<int> matches;
153
154   vectorNameMatchKLUDGE(mod, demangled_sym, bpfv, matches);
155
156   Function *ret = NULL;
157
158   if (matches.size() == 1) {ret = bpfv[matches[0]]; goto clean_up;}
159   if (matches.size() > 1) goto clean_up;
160   
161   // check in the uninstrumentable pile
162   bpfv.clear();
163   matches.clear();
164
165   vectorNameMatchKLUDGE(mod, demangled_sym, bpfv, matches);
166   if (matches.size() == 1) {ret = bpfv[matches[0]]; goto clean_up;}
167   if (matches.size() > 1) goto clean_up;
168
169  clean_up:
170   free( demangled_sym );
171   return ret;
172 }
173
174 // This function takes the stab stabstring and parses it to create a new 
175 // type or variable object.  This function only defines the type/variable 
176 // name and ID.
177 //
178 // <stabString> = <ident>:<symDesc>                     |
179 //                <ident>:c<constantUse>                |
180 //                <ident>:f<symDesc>                    |
181 //                <ident>:f<syymDesc>,<ident>,<ident>   |
182 //                <ident>:F<typeUse><paramList>         |
183 //                <ident>:G<typeUse>                    |
184 //                <ident>:r<int>                        |
185 //                <ident>:S<typeUse>                    |
186 //                <ident>:[pPr]<typeUse>                |
187 //                <ident>::T<typeUse>                   |
188 //                <ident>:t<typeUse>                    |
189 //                <ident>:T<typeUse>                    |
190 //                <ident>:v<typeUse>                    |
191 //                <ident>:V<symDesc>                    |
192 //                <indet>:Y[Tc|Ts]
193 //
194 // <paramList> = | <typeUse>;<paramList> 
195 //
196
197 std::string Dyninst::SymtabAPI::parseStabString(Module *mod, int linenum, char *stabstr, 
198       int framePtr, typeCommon *commonBlock)
199 {
200    int cnt;
201    int ID = 0;
202    int symdescID = 0;
203    int funcReturnID = 0;
204    Function  *fp = NULL;
205    Type * ptrType = NULL;
206    Type * newType = NULL; // For new types to add to the collection
207    localVar *locVar = NULL;
208    cnt= 0;
209
210    types_printf("parseStabString, mod %p/%s, linenum %d, stabstr %s\n",
211                 mod,
212                 (mod != NULL) ? mod->fileName().c_str() : "NULL",
213                 linenum, 
214                 stabstr);
215
216    std::string fName = mod->fileName();
217
218    /* get type or variable name */
219    std::string mangledname = getIdentifier( stabstr, cnt );
220
221    currentRawSymbolName = mangledname;
222    char * demangled = P_cplus_demangle( mangledname.c_str(), mod->exec()->isNativeCompiler() );
223    std::string name;
224
225    if ( demangled == NULL ) 
226    {
227       name = mangledname;
228    } 
229    else 
230    {
231       name = demangled;
232    }
233
234    if ( name[0] != '\0' && stabstr[cnt] != ':' ) 
235    {
236      types_printf("\t returning name %s\n", name.c_str());
237       return name;
238    }
239
240    if (stabstr[cnt] == ':') 
241    {
242       // skip to type part
243       cnt++;
244    }
245
246    if (isSymId(stabstr[cnt])) 
247    {
248       /* instance of a predefined type */
249
250       ID = parseSymDesc(stabstr, cnt);
251
252       if (stabstr[cnt] == '=') 
253       {
254          /* More Stuff to parse, call parseTypeDef */
255
256          stabstr = parseTypeDef(mod, (&stabstr[cnt+1]), name.c_str(), ID);
257          cnt = 0;
258          ptrType = mod->getModuleTypes()->findOrCreateType(ID);
259          if (!symt_current_func) 
260          {
261             // XXX-may want to use N_LBRAC and N_RBRAC to set function scope 
262             // -- jdd 5/13/99
263             // Still need to add to local variable list if in a function
264
265             std::string modName = mod->fileName();
266             //bperr("%s[%d] Can't find function %s in module %s\n", __FILE__, __LINE__,
267             //     symt_current_mangled_func_name.c_str(), modName);
268             //bperr("Unable to add %s to local variable list in %s\n",
269             //     name.c_str(), symt_current_func_name.c_str());
270          } 
271          else 
272          {
273             locVar = new localVar(name, ptrType, fName, linenum);
274             VariableLocation *loc = (VariableLocation *)malloc(sizeof(VariableLocation));
275             loc->stClass = storageRegOffset;
276             loc->refClass = storageNoRef;
277             loc->frameOffset = framePtr;
278             loc->reg = -1;
279             locVar->addLocation(loc);
280             if (!ptrType) {
281                //bperr("adding local var with missing type %s, type = %d\n",
282                //      name, ID);
283             }
284
285             localVarCollection *lvs = NULL;
286             extern AnnotationClass<localVarCollection> FunctionLocalVariablesAnno;
287
288             if (!symt_current_func->getAnnotation(lvs, FunctionLocalVariablesAnno)) 
289             {
290                lvs = new localVarCollection();
291                if (!symt_current_func->addAnnotation(lvs, FunctionLocalVariablesAnno)) 
292                {
293                   fprintf(stderr, "%s[%d]: failed to add annotation here\n", FILE__, __LINE__);
294                }
295             }
296
297             if (!lvs)
298             {
299                fprintf(stderr, "%s[%d]: failed to get annotation here\n", FILE__, __LINE__);
300             }
301
302             lvs->addLocalVar(locVar);
303          }
304       } 
305       else if (symt_current_func) 
306       {
307          // Try to find the BPatch_Function
308          ptrType = mod->getModuleTypes()->findOrCreateType( ID);
309
310          locVar = new localVar(name, ptrType, fName, linenum);
311          VariableLocation *loc = (VariableLocation *)malloc(sizeof(VariableLocation));
312          loc->stClass = storageRegOffset;
313          loc->refClass = storageNoRef;
314          loc->frameOffset = framePtr;
315          loc->reg = -1;
316          locVar->addLocation(loc);
317
318          if (!ptrType) 
319          {
320             ////bperr("adding local var with missing type %s, type = %d\n",
321             //       name, ID);
322          }
323
324          if (!symt_current_func->addLocalVar(locVar)) 
325          {
326             fprintf(stderr, "%s[%d]:  FIXME\n", FILE__, __LINE__);
327          }
328
329       }
330    } 
331    else if (stabstr[cnt]) 
332    {
333       std::vector<Function *> bpfv;
334
335       switch (stabstr[cnt]) {
336          case 'f': /*Local Function*/ 
337             {
338                std::string scopeName;
339                std::string lfuncName;
340                cnt++;
341
342                symt_current_func_name = name;
343                symt_current_mangled_func_name = mangledname;
344
345                funcReturnID = parseTypeUse(mod, stabstr, cnt, name.c_str());
346
347                if (stabstr[cnt]==',') 
348                {
349                   cnt++;        /*skip the comma*/
350
351                   /* Local Function Name */
352                   lfuncName = getIdentifier(stabstr, cnt);
353
354                   assert(stabstr[cnt] == ',');
355                   cnt++;        /*skip the comma*/
356
357                   /* Scope Name of Local Function */
358                   scopeName = getIdentifier(stabstr, cnt);
359
360                   if (stabstr[cnt]) 
361                   {
362                      //bperr("Extra: %s\n", &stabstr[cnt]);
363                   }
364                }
365
366                if (!scopeName.length()) 
367                { 
368                   // Not an embeded function
369
370                   ptrType = mod->getModuleTypes()->findOrCreateType(funcReturnID);
371                   if ( !ptrType) ptrType = mod->exec()->type_Untyped;
372
373                   if (!(mod->exec()->findFunctionsByName(bpfv, name)))
374                   {
375                       //showInfoCallback(string("missing local function ") +
376                       //                                             name + "\n");
377                       // It's very possible that we might not find a function
378                       // that's a weak reference, and defined in multiple places
379                       // as we only store an object from the last definition
380                       //
381                       // 12/08 - not sure this is necessary anymore
382                       // due to the Function abstraction
383                       fp = NULL;
384                   } 
385                   else 
386                   {
387                      if (bpfv.size() > 1) 
388                      {
389                         // warn if we find more than one function with current_func_name
390                         char msg[1024];
391                         sprintf(msg, "%s[%d]:  found %d functions with name %s, using the first",
392                               __FILE__, __LINE__, (int)bpfv.size(), name.c_str());
393                         // BPatch::bpatch->reportError(BPatchWarning, 0, msg);
394
395                      }
396                      else if (!bpfv.size()) 
397                      {
398                         //bperr("%s[%d]:  SERIOUS: found 0 functions with name %s",
399                         //       __FILE__, __LINE__, name.c_str());
400                         break;
401                      }
402
403                      fp = bpfv[0];
404                      // set return type.
405                      fp->setReturnType(ptrType);
406                   }
407                } 
408                else 
409                {
410                   //bperr("%s is an embedded function in %s\n",name.c_str(), scopeName.c_str());
411                }
412
413                symt_current_func = fp;
414                // skip to end - SunPro Compilers output extra info here - jkh 6/9/3
415                cnt = strlen(stabstr);
416
417                break;
418             }  
419
420          case 'F':/* Global Function */
421             {
422                cnt++; /*skipping 'F' */
423
424                funcReturnID = parseTypeUse(mod, stabstr, cnt, name.c_str());
425
426                symt_current_func_name = name;
427                symt_current_mangled_func_name = mangledname;
428
429                //
430                // For SunPro compilers there may be a parameter list after 
431                //   the return
432                //
433
434                while (stabstr[cnt] == ';') 
435                {
436                   cnt++;        // skip ';'
437                   (void) parseTypeUse(mod, stabstr, cnt, "");
438                }
439
440                // skip to end - SunPro Compilers output extra info here - jkh 6/9/3
441                cnt = strlen(stabstr);
442
443                ptrType = mod->getModuleTypes()->findOrCreateType(funcReturnID);
444                if (!ptrType) ptrType = mod->exec()->type_Untyped;
445
446                std::vector<Function *>fpv;
447                if (!mod->exec()->findFunctionsByName(fpv, symt_current_mangled_func_name))
448                //if (!mod->findSymbolByType(fpv, symt_current_mangled_func_name, Symbol::ST_FUNCTION, true)) 
449                {
450                   std::string modName = mod->fileName();
451
452                   if (NULL == (fp = mangledNameMatchKLUDGE(symt_current_func_name.c_str(), 
453                               symt_current_mangled_func_name.c_str(), mod)))
454                   {
455                      //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",
456                      //       __FILE__, __LINE__,
457                      //       symt_current_mangled_func_name.c_str(), current_func_name.c_str(),
458                      //       ((ptrType->getMangledName() == NULL) ? "" : ptrType->getMangledName()), 
459                      //       modName);
460                      //char prefix[5];
461                      //strncpy(prefix, current_mangled_func_name, 4);
462                      //prefix[4] = '\0';
463                      // mod->dumpMangled(prefix);
464                      break;
465                   }
466                }
467                fp = fpv[0];
468
469                fp->setReturnType(ptrType);
470                symt_current_func = fp;
471                fpv.clear();
472             }    
473             break;
474
475          case 'U':/* Class Declaration - for Sun Compilers - jkh 6/6/03 */
476          case 'E':/* Extern'd Global ??? - undocumented type for Sun Compilers - jkh 6/6/03 */
477          case 'G':/* Global Varaible */
478             cnt++; /* skip the 'G' */
479
480             /* Get variable type number */
481             symdescID = parseTypeUse(mod, stabstr, cnt, name.c_str());
482             Type *BPtype;
483
484             BPtype = mod->getModuleTypes()->findOrCreateType(symdescID);
485             if (BPtype) 
486             {
487               Module *toUse = mod;
488                std::vector<Variable *> ret;
489                bool result = mod->findVariablesByName(ret, name);
490                if (!result) {
491                  // Might be in a different module...
492                  if (mod->exec()->getDefaultModule()->findVariablesByName(ret, name))
493                    toUse = mod->exec()->getDefaultModule();
494                }
495                for (unsigned i=0; i<ret.size(); i++) {
496                  ret[i]->setType(BPtype);
497                }
498
499                toUse->getModuleTypes()->addGlobalVariable(name, BPtype);
500             }
501             else 
502             break;
503
504          case 'P':      // function parameter passed in a register (GNU/Solaris)
505          case 'R':      // function parameter passed in a register (AIX style)
506          case 'v':      // Fortran Local Variable
507          case 'X':      // Fortran function return Variable (e.g. function name)
508          case 'p': 
509             {   
510                // Function Parameter
511                cnt++; /* skip the 'p' */
512
513                /* Get variable type number */
514                symdescID = parseTypeUse(mod, stabstr, cnt, name.c_str());
515
516                if (stabstr[cnt] == ';') 
517                {
518                   // parameter type information, not used for now
519                   cnt = strlen(stabstr);
520                } 
521               // else if (stabstr[cnt]) 
522               // {
523                   //bperr( "\tMore to parse func param %s\n", &stabstr[cnt]);
524                   //bperr( "\tFull String: %s\n", stabstr);
525                //}
526
527                ptrType = mod->getModuleTypes()->findOrCreateType(symdescID);
528                if (!ptrType) ptrType = mod->exec()->type_Untyped;
529
530                localVar *param;
531
532                param = new localVar(name, ptrType, fName, linenum);
533                VariableLocation *loc = (VariableLocation *)malloc(sizeof(VariableLocation));
534                loc->stClass = storageRegOffset;
535                loc->refClass = storageNoRef;
536                loc->frameOffset = framePtr;
537                loc->reg = -1;
538                param->addLocation(loc);
539
540                if (symt_current_func) 
541                {
542                   if (!symt_current_func->addParam(param)) 
543                   {
544                      fprintf(stderr, "%s[%d]:  FIXME\n", FILE__, __LINE__);
545                   }
546                } 
547
548                break;
549             }
550
551          case 'c': /* constant */
552             {
553                cnt++; /*move past the 'c' */
554
555                ptrType = parseConstantUse(mod, stabstr, cnt);
556
557                if (!ptrType) ptrType = mod->exec()->type_Untyped;
558
559                localVar *var;
560                var = new localVar(name, ptrType, fName, linenum);
561                VariableLocation *loc = (VariableLocation *)malloc(sizeof(VariableLocation));
562                loc->stClass = storageRegOffset;
563                loc->refClass = storageNoRef;
564                loc->frameOffset = 0;
565                loc->reg = -1;
566                var->addLocation(loc);
567
568                if (symt_current_mangled_func_name.length()) 
569                {
570                   std::vector<Function *>fpv;
571                   if (!mod->exec()->findFunctionsByName(fpv, symt_current_mangled_func_name))
572                   {
573                      //showInfoCallback(string("missing local function ") + 
574                      //                     symt_current_func_name + "\n");
575                   } 
576                   else 
577                   { 
578                      // found function, add parameter
579                      fp = fpv[0];       
580                      symt_current_func = fp;
581                      if (!symt_current_func->addParam(var)) 
582                      {
583                         fprintf(stderr, "%s[%d]:  FIXME\n", FILE__, __LINE__);
584                      }
585                   }
586                   fpv.clear();
587                } 
588             }
589             break;
590
591          case 'r':/* Register Variable */
592             cnt++; /*move past the 'r'*/
593             /* get type reference */
594
595             symdescID = parseSymDesc(stabstr, cnt);
596             break;
597
598          case 'S':/* Global Static Variable */ 
599             {
600                cnt++; /*move past the 'S'*/
601
602                /* get type reference */
603                symdescID = parseTypeUse(mod, stabstr, cnt, name.c_str());
604
605                // lookup symbol and set type
606                Type *BPtype;
607
608                std::string nameTrailer;
609                if (name.find(".") < name.length()) 
610                {
611                   std::string defaultNameSpace;
612                   defaultNameSpace = name.substr(0,name.find("."));
613                   nameTrailer = name.substr(name.find(".")+1,name.length()-name.find(".")-1);
614                   mod->setDefaultNamespacePrefix(defaultNameSpace);
615                } 
616                else
617                {
618                   nameTrailer = name;
619                }
620
621                BPtype = mod->getModuleTypes()->findOrCreateType(symdescID);
622
623                if (BPtype) 
624                {
625                   Symtab *img = mod->exec();
626                   std::vector<Symbol *>syms;
627                   if (img->findSymbolByType(syms, 
628                                             nameTrailer,
629                                             Symbol::ST_OBJECT,
630                                             mangledName) ||
631                       img->findSymbolByType(syms, 
632                                             nameTrailer,
633                                             Symbol::ST_OBJECT, 
634                                             mangledName,
635                                             true)) 
636                   {
637                      
638                      mod->getModuleTypes()->addGlobalVariable(nameTrailer, BPtype);
639                   }
640                }
641
642                //else 
643                //{
644                   //bperr("ERROR: unable to find type #%d for variable %s\n", 
645                   // symdescID, nameTrailer.c_str());
646                //} 
647
648                break;
649             }
650
651          case 't':      // Type Name 
652             cnt++; /*move past the 't'*/
653
654             /* get type reference */
655             symdescID = parseSymDesc(stabstr, cnt);
656
657             //Create Type.
658             if (stabstr[cnt] == '=') 
659             {
660                /* More Stuff to parse, call parseTypeDef */
661                //char *oldStr = stabstr;
662                stabstr = parseTypeDef(mod, (&stabstr[cnt+1]), name.c_str(), symdescID);
663                cnt = 0;
664                // AIX seems to append an semi at the end of these
665                if (stabstr[0] && strcmp(stabstr, ";")) 
666                {
667                   //bperr("\tMore to parse creating type %s\n", stabstr);
668                   //bperr( "\tFull String: %s\n", oldStr);
669                }
670             } 
671             else 
672             {
673                //Create Type defined as a pre-exisitng type.
674
675                ptrType = mod->getModuleTypes()->findOrCreateType(symdescID);
676                if (!ptrType)
677                {
678                   ptrType = mod->exec()->type_Untyped;
679                }
680
681                // We assume that IDs are unique per type. Instead of reusing the 
682                // underlying base ID, use a SymtabAPI-generated ID.
683
684                typeTypedef *newType = new typeTypedef(ptrType, name);
685
686                if (newType) 
687                {
688                   mod->getModuleTypes()->addOrUpdateType(newType);
689                }
690             }
691             break;
692
693          case ':':      // :T... - skip ":" and parse 'T'
694             if ((stabstr[cnt+1] == 't') || (stabstr[cnt+1] == 'T')) 
695             {
696                // parse as a normal typedef
697                parseStabString(mod, linenum, &stabstr[cnt+1], framePtr);
698             } 
699
700             // else 
701             //{
702             //bperr("Unknown type seen %s\n", stabstr);
703             //}
704
705             break;
706
707          case 'T':/* Aggregate type tag -struct, union, enum */
708             cnt++; /*move past the 'T'*/
709
710             if (stabstr[cnt] == 't') 
711             {
712                //C++ struct  tag "T" and type def "t"
713                ////bperr("SKipping C++ Identifier t of Tt\n");
714                cnt++;  //skip it
715             }
716
717             /* get type reference */
718             symdescID = parseSymDesc(stabstr, cnt);
719
720             //Create Type.
721             if (stabstr[cnt] == '=') 
722             {
723                /* More Stuff to parse, call parseTypeDef */
724                stabstr = parseTypeDef(mod,(&stabstr[cnt+1]),name.c_str(),symdescID);
725                cnt = 0;
726
727                //if (stabstr[0]) 
728                //{
729                   //bperr( "\tMore to parse aggregate type %s\n", (&stabstr[cnt]));
730                   //bperr("\tFull String: %s\n", stabstr);
731                //}
732
733             } 
734             else 
735             {
736                //Create Type defined as a pre-exisitng type.
737
738                newType = Type::createPlaceholder(symdescID, name);
739             }
740
741             break;
742
743          case 'V':/* Local Static Variable (common block vars too) */
744             cnt++; /*move past the 'V'*/
745
746             // //bperr("parsing 'v' type of %s\n", stabstr);
747             /* Get variable type number */
748
749             symdescID = parseTypeUse(mod, stabstr, cnt, name.c_str());
750
751             // lookup symbol and set type
752             BPtype = mod->getModuleTypes()->findOrCreateType(symdescID);
753
754             if (!BPtype) 
755             {
756                //bperr("ERROR: unable to find type #%d for variable %s\n", 
757                // symdescID, name.c_str());
758                break;
759             }
760
761             if (commonBlock) 
762             {
763                /* This variable is in a common block */
764                /* add it only if not already there, common block
765                   are re-defined for each subroutine but subroutines
766                   define only the member they care about
767                 */
768
769                bool found = false;
770                const std::vector<Field *> *fields;
771                fields = commonBlock->getFields();
772                if (fields) 
773                {
774                   for (unsigned int i=0; i < fields->size(); i++) 
775                   {
776                      if (name == (*fields)[i]->getName()) 
777                      {
778                         found = true;
779                         break;
780                      }
781
782                      int start1, start2, end1, end2;
783                      start1 = (*fields)[i]->getOffset();
784                      end1 = start1 + (*fields)[i]->getSize();
785                      start2 = framePtr;
786                      end2 = framePtr + BPtype->getSize();
787                      if ( ((start2 >= start1) && (start2 < end1)) 
788                          || ((start1 >= start2) && (start1 < end2)) ) 
789                      {
790                         /* common block aliasing detected */
791                         //bpwarn("WARN: EQUIVALENCE used in %s: %s and %s\n",
792                         //  current_func_name.c_str(), name.c_str(), (*fields)[i]->getName());
793
794                         found = true;
795                         break;
796                      }
797                   }
798                }
799
800                if (!found) 
801                {
802                   commonBlock->addField(name, BPtype, framePtr);
803                }
804             } 
805             else 
806             {
807                // put it into the local variable scope
808                if (symt_current_func) 
809                {
810                   locVar = new localVar(name, BPtype, fName, linenum);
811                   VariableLocation *loc = (VariableLocation *)malloc(sizeof(VariableLocation));
812                   loc->stClass = storageAddr;
813                   loc->refClass = storageNoRef;
814                   loc->frameOffset = framePtr;
815                   loc->reg = -1;
816                   locVar->addLocation(loc);
817
818                   if (!symt_current_func->addLocalVar(locVar)) 
819                   {
820                      fprintf(stderr, "%s[%d]:  FIXME\n", FILE__, __LINE__);
821                   }
822                }
823
824                //else 
825                //{
826                   //bperr("Unable to add %s to local variable list in %s\n",
827                   //     name.c_str(),current_func_name.c_str());
828                //} 
829             }
830             break;
831          case 'l':
832             // These are string literals, of the form 
833             // name:l(type);value
834             // where type must be predefined, and value of of type type.
835             // It should be safe to ignore these. 
836
837             cnt = strlen(stabstr);
838             break;
839
840          case 'Y':      // C++ specific stuff
841             cnt++; // Skip past the 'Y'
842             if (stabstr[cnt] == 'I') 
843             {
844                /* Template instantiation */
845                cnt++; // skip past the I;
846                if (stabstr[cnt] == 'f') /* Template function */ 
847                {
848                   while (stabstr[cnt] != '@') cnt++;
849                   cnt++; // Skip past '@'
850                   cnt++; // Skip past ';'
851                   cnt++; // Skip past ';'
852                   while (stabstr[cnt] != ':') cnt++;
853                   // Create fake stab string that cuts out template garbage
854                   char *dupstring = strdup(stabstr);
855                   strcpy(dupstring, mangledname.c_str());
856                   strcat(dupstring, stabstr+cnt);
857                   parseStabString(mod, linenum, dupstring, framePtr, commonBlock);
858                   free(dupstring);
859               }
860           } 
861           cnt = strlen(stabstr);
862           break;
863
864           default:
865           //bperr( "Unknown symbol descriptor: %c\n", stabstr[cnt]);
866           //bperr( " : %s\n", stabstr);
867           break;
868       }   
869     }
870
871     return(&stabstr[cnt]);
872 } /* end of parseStabString */
873
874
875 //
876 // Is the current character a valid prefix for a symDesc non-terminal?
877 //
878 inline bool isSymId(char ch)
879 {
880     return ((ch == '(') || isdigit(ch) || (ch == '-'));
881 }
882
883 //
884 // parse a Symbol Descriptor ID
885 //      symDesc = <int> | (<int>,<int>)
886 //
887 int parseSymDesc(char *stabstr, int &cnt)
888 {
889     int id;
890     int lid;
891     int hid;
892     int sign = 1;
893     bool newForm = false;
894
895     hid = 0; //file-number
896     // parse both an int and (int,int) format (file-number, type ID)
897     if (stabstr[cnt] == '(') {
898         cnt++;
899         while (isdigit(stabstr[cnt])) {
900             hid = hid * 10 + stabstr[cnt] - '0';
901             cnt++;
902         }
903
904         // skip ","
905         if (stabstr[cnt] == ',') cnt++;
906         newForm = true;
907     }
908        
909     if (stabstr[cnt] == '-') {
910         sign = -1;
911         cnt++;
912     }
913
914     lid = 0; //type ID
915     while (isdigit(stabstr[cnt])) {
916         lid = lid * 10 + stabstr[cnt] - '0';
917         cnt++;
918     }
919     if( hid != 0 )
920       assert(lid < 65536);
921     
922     // skip closing ')'
923     if (newForm) cnt++;
924
925     id = hid * 65536 + lid;
926     id = id * sign;
927     
928     return id;
929 }
930
931 //
932 // parse an identifier up to a ":" or "," or ";"
933 //
934 std::string getIdentifier( char *stabstr, int &cnt, bool stopOnSpace ) {
935         int i = 0;
936         int brCnt = 0;
937         bool idChar = true;
938
939         while( idChar ) {
940                 switch( stabstr[ cnt + i ] ) {
941                         case '<':
942                         case '(':
943                                 brCnt++;
944                                 i++;
945                                 break;
946
947                         case '>':
948                         case ')':
949                                 brCnt--;
950                                 i++;
951                                 break;
952
953                 case ' ':
954                                 if ( !stopOnSpace ) {
955                                     i++;
956                                     break;
957                                         } // else fall through
958                         case '\0':
959                         case ':':
960                         case ',':
961                         case ';':
962                                 /* Handle case of '::' */
963                                 if ( stabstr[ cnt + i ] == ':' && stabstr[ cnt + i + 1 ] == ':' &&
964                                      (stabstr[ cnt + i + 2 ] == '_' || isalpha(stabstr[ cnt + i + 2 ])) ) {
965                                    i+=3;
966                                    break;
967                                 }
968                                 /* If we're inside a bracket and we haven't reached
969                                    the end of the string, continue. */
970                                 if( brCnt != 0 && stabstr[ cnt + i ] != '\0' ) {
971                                         i++;
972                                         }
973                                 else if( brCnt ) {
974                                         //bperr( "Failed to find identifier in stabstring '%s;\n", stabstr );
975                                         idChar = false;
976                                         }
977                                 else {
978                                         idChar = false;
979                                         }
980                                 break;
981                                 
982                         default:
983                                 i++;
984                                 break;
985                         } /* end switch */
986     } /* end while */
987
988         char * identifier = (char *)malloc( i + 1 );
989         assert( identifier );
990         
991         strncpy( identifier, & stabstr[cnt], i );
992         identifier[i] = '\0';
993         cnt += i;
994         
995         std::string pd_identifier = identifier;
996         free(identifier);
997         return pd_identifier;
998         } /* end getIdentifier() */
999
1000 //
1001 // getFieldName
1002 //
1003 // A simplified version of getIdentifier, it only cares about finding a ':'
1004 //
1005
1006 char * getFieldName( char *stabstr, int &cnt) {
1007    int i = 0;
1008    bool idChar = true;
1009
1010    while ( idChar ) {
1011       switch( stabstr[ cnt + i ] ) {
1012       case ':':
1013          idChar = false;
1014          break;
1015       default:
1016          i++;
1017       }
1018    }
1019
1020    char * identifier = (char *) malloc(i + 1);
1021    assert(identifier);
1022
1023    strncpy(identifier, &stabstr[cnt], i);
1024    identifier[i] = '\0';
1025    cnt += i;
1026
1027    return identifier;
1028 }
1029
1030 //
1031 // Parse a use of a type.  
1032 //
1033 //      <typeUse> = <symDesc> | <symDesc>=<typeDef>
1034 //
1035 static int parseTypeUse(Module *mod,char *&stabstr, int &cnt, 
1036                         const char *name)
1037 {
1038     int ret = parseSymDesc(stabstr, cnt);
1039
1040     if (stabstr[cnt] == '=') {
1041         /* More Stuff to parse, call parseTypeDef */
1042         stabstr = parseTypeDef(mod, (&stabstr[cnt+1]), name, ret);
1043         cnt = 0;
1044     }
1045     return ret;
1046 }
1047
1048 //
1049 // parseCrossRef - internal struct/union pointer
1050 //
1051 //      <crossRef>      = [s|u|e]<ident>
1052 //
1053 static char *parseCrossRef(typeCollection *moduleTypes,const char * /*name*/,
1054                            int ID, char *stabstr, int &cnt)
1055 {
1056     std::string temp;
1057     Type *newType = NULL;
1058     char xreftype;
1059     cnt++; /* skip 'x'*/
1060
1061     if ((stabstr[cnt] == 's') ||        // struct 
1062             (stabstr[cnt] == 'u') ||    // union
1063             (stabstr[cnt] == 'e')) {    // enum
1064         xreftype = stabstr[cnt++];
1065
1066         temp = getIdentifier(stabstr, cnt);
1067         cnt++; /*skip ':' */
1068
1069         // Find type that this one points to.
1070         Type *ptrType = moduleTypes->findType(temp.c_str());
1071         if (!ptrType) {
1072             // This type name hasn't been seen before.  Create the
1073             // skeleton for it, and we'll update it later when we actually see
1074             // it
1075             if (xreftype == 'e') {
1076                 newType = new typeEnum(ID, temp);
1077                 newType = moduleTypes->addOrUpdateType((typeEnum *) newType);
1078             } else if (xreftype == 'u') {
1079                 newType = new typeUnion(ID, temp);
1080                 newType = moduleTypes->addOrUpdateType((typeEnum *) newType);
1081             } else {
1082                 newType = new typeStruct(ID, temp);
1083                 newType = moduleTypes->addOrUpdateType((typeEnum *) newType);
1084             }
1085             assert(newType);
1086         }         
1087     } else {
1088         /* don't know what it is?? */
1089
1090         temp = getIdentifier(stabstr, cnt);
1091         cnt++; /*skip ':' */
1092     }
1093
1094     return( &(stabstr[cnt]));
1095 }
1096             
1097 //
1098 // parse the definition of an array.
1099 //      arrayDef = ar<symDesc>;<symDesc>;<symDesc>;<symDesc> |
1100 //                 ar<symDesc>;<symDesc>;<symDesc>;<arrayDef> |
1101 //                 A<arrayDef>
1102 //
1103 static Type *parseArrayDef(Module *mod, const char *name,
1104                      int ID, char *&stabstr, int &cnt, unsigned int sizeHint)
1105 {
1106     char *symdesc;
1107     int symdescID;
1108     int elementType;
1109     Type *newType = NULL;
1110     Type *ptrType = NULL;
1111     int lowbound, hibound;
1112
1113     // format is ar<indexType>;<lowBound>;<highBound>;<elementType>
1114
1115     assert(stabstr[cnt] == 'a' || stabstr[cnt] == 'A');
1116
1117     if (stabstr[cnt ++] == 'A') {
1118        // Open array
1119        lowbound = 1;
1120        hibound = 0;
1121        elementType = parseSymDesc(stabstr, cnt);
1122        ptrType = mod->getModuleTypes()->findOrCreateType(elementType);
1123     } else {
1124        // Regular (maybe) array
1125
1126        if (stabstr[cnt] != 'r') {
1127           //bperr("unknown array definition seen %s\n", &stabstr[cnt]);
1128           return(NULL);
1129        }
1130        
1131        /* array with range */
1132        symdesc = &(stabstr[cnt]);
1133        
1134        cnt++;   /* skip 'r' */
1135        
1136        symdescID = parseTypeUse(mod, stabstr, cnt, name);
1137        
1138        cnt++; /* skip semicolon */
1139        lowbound = parseSymDesc(stabstr, cnt);
1140        
1141        cnt++; /* skip semicolon */
1142        if (stabstr[cnt] == 'J') {
1143           /* Fortran unbounded array */
1144           hibound = 0;
1145           cnt++;
1146        } else if (stabstr[cnt] == 'T') {
1147           /* Fortran runtime bound array - Txx is the form (xx=digits)*/
1148           hibound = 0;
1149           cnt++;
1150           while (isdigit(stabstr[cnt])) cnt++;
1151        } else {
1152           hibound = parseSymDesc(stabstr, cnt);
1153        }
1154        
1155        cnt++; /* skip semicolon */
1156        elementType = parseSymDesc(stabstr, cnt);
1157        
1158        if (stabstr[cnt] == 'a') {
1159           /* multi dimensional array - Fortran style */
1160           /* it has no valid id, so we give it a known duplicate */
1161           ptrType = parseArrayDef(mod, name, 0, stabstr, cnt, sizeHint);
1162        } else { 
1163           if (stabstr[cnt] == '=') {
1164              /* multi dimensional array */
1165              char *temp;
1166              temp = parseTypeDef(mod, &(stabstr[cnt+1]), NULL, elementType);
1167              /* parseTypeDef uses old style of returning updated stabstr,
1168                 but parseArrayDef function needs to return an updated cnt.  
1169                 This simple hack updates cnt based on how far parseTypDef 
1170                 advances it.  jkh 12/4/00 */
1171              cnt = temp-stabstr;
1172              if (stabstr[cnt] == ':') {
1173                 //C++ stuff
1174                 ////bperr("Skipping C++ rest of array def:  %s\n",name );
1175                 while (stabstr[cnt] != ';') cnt++;
1176              }
1177           }
1178           ptrType = mod->getModuleTypes()->findOrCreateType(elementType);
1179        }
1180     }
1181
1182     //  //bperr("Symbol Desriptor: %s Descriptor ID: %d Type: %d, Low Bound: %d, Hi Bound: %d,\n", symdesc, symdescID, elementType, lowbound, hibound);
1183
1184
1185     if (ptrType) {
1186         // Create new type - field in a struct or union
1187         std::string tName = convertCharToString(name);
1188         newType = new typeArray(ID, ptrType, lowbound, hibound, tName, sizeHint);
1189         // Add to Collection
1190         newType = mod->getModuleTypes()->addOrUpdateType((typeArray *) newType);
1191     }
1192             
1193     // //bperr( "parsed array def to %d, remaining %s\n", cnt, &stabstr[cnt]);
1194     return newType;
1195 }
1196
1197 int guessSize(const char *low, const char *hi) {
1198    long long l, h;
1199
1200    if (low[0] == '0')
1201       sscanf(low, "%llo", &l);
1202    else
1203       sscanf(low, "%lld", &l);
1204    if (hi[0] == '0')
1205       sscanf(hi, "%llo", &h);
1206    else
1207       sscanf(hi, "%lld", &h);
1208
1209    /*   
1210    if (( low[0]=='-' && l < -2147483648LL )
1211        || ( l > || ( h > 2147483647LL))
1212       return 8;
1213    else if (( l < -32768 ) || ( h > 32767 ))
1214       return 4;
1215    else if (( l < -128 ) || ( h > 127 ))
1216       return 2;
1217    else
1218       return 1;
1219    */
1220    if (l < 0) { // Must be signed
1221       if (l < -2147483648LL || h > 0x7fffffffLL)
1222          return 8;
1223       else if (l < 0xffff8000 || h > 0x7fff)
1224          return 4;
1225       else if (l < 0xffffff80 || h > 0x7f)
1226          return 2;
1227       else
1228          return 1;
1229    } else {
1230       if (h > 0xffffffffLL)
1231          return 8;
1232       else if (h > 0xffff)
1233          return 4;
1234       else if (h > 0xff)
1235          return 2;
1236       else
1237          return 1;
1238    }
1239 }
1240
1241 #if defined(i386_unknown_linux2_0) \
1242  || defined(x86_64_unknown_linux2_4) /* Blind duplication - Ray */ \
1243  || defined(ia64_unknown_linux2_4) /* temporary duplication - TLM */
1244 //
1245 // parse range type of the form:        
1246 //
1247 //      <rangeType> = r<typeNum>;<low>;<high>;
1248 //
1249 static char *parseRangeType(Module *mod, const char *name, int ID, 
1250                             char *stabstr, unsigned int sizeHint = 0)
1251 {
1252    int cnt, i, symdescID;
1253    //int sign = 1;
1254    Type *baseType;
1255
1256    cnt = i = 0;
1257
1258    assert(stabstr[0] == 'r');
1259    cnt++;
1260
1261    // range index type - not used
1262    symdescID = parseSymDesc(stabstr, cnt);
1263
1264    if (!mod || !mod->getModuleTypes()) 
1265    {
1266       fprintf(stderr, "%s[%d]: FIXME\n", FILE__, __LINE__);
1267       return NULL;
1268    }
1269    else 
1270    {
1271       baseType = mod->getModuleTypes()->findType(symdescID);
1272    }
1273
1274    // //bperr("\tSymbol Descriptor: %c and Value: %d\n",tmpchar, symdescID);
1275
1276    cnt++; /* Discarding the ';' */
1277    i=0;
1278    if (stabstr[cnt] == '-' ) {
1279       i++;
1280    }
1281
1282    /* Getting type range or size */
1283
1284    while (isdigit(stabstr[cnt+i])) i++;
1285
1286    char *low = (char *)malloc(sizeof(char)*(i+1));
1287    if(!strncpy(low, &(stabstr[cnt]), i))
1288       /* Error copying size/range*/
1289       exit(1);
1290    low[i] = '\0';
1291
1292    cnt = cnt + i + 1; /* Discard other Semicolon */
1293    i = 0;
1294    if((stabstr[cnt]) == '-') {
1295       i++; /* discard '-' for (long) unsigned int */
1296    }
1297    //Find high bound
1298    while (isdigit(stabstr[cnt+i])) i++;
1299    char *hi = (char *)malloc(sizeof(char)*(i+1));
1300    if(!strncpy(hi, &(stabstr[cnt]), i))
1301       /* Error copying upper range */
1302       exit(1);
1303    hi[i] = '\0';
1304
1305    int j = atol(hi);
1306     
1307    if (j == 0) {
1308        //Size
1309        int size = atol(low);
1310
1311        //Create new type
1312        Type *newType = new typeScalar(ID, size, name);
1313        //Add to Collection
1314        newType = mod->getModuleTypes()->addOrUpdateType((typeScalar *) newType);
1315    }
1316    else {
1317        //Range
1318        //Create new type
1319        Type *newType;
1320        std::string tName = convertCharToString(name);
1321        if (baseType == NULL)
1322            newType = new typeSubrange(ID, sizeHint ? sizeHint / 8 : guessSize(low,hi), atoi(low), atoi(hi), tName);
1323        else
1324            newType = new typeSubrange(ID, sizeHint ? sizeHint / 8 : baseType->getSize(), atoi(low), atoi(hi), tName);
1325        //Add to Collection
1326        mod->getModuleTypes()->addOrUpdateType((typeSubrange *) newType);
1327    }
1328    free(low);
1329    free(hi);
1330    hi=low=NULL;
1331
1332    cnt = cnt + i;
1333    if( stabstr[cnt] == ';')
1334       cnt++;
1335
1336    return(&(stabstr[cnt]));
1337 }
1338
1339 #else
1340 //
1341 // parse range type of the form:        
1342 //
1343 //      <rangeType> = r<typeNum>;<low>;<high>;
1344 //
1345 static char *parseRangeType(Module *mod, const char *name, int ID,
1346                             char *stabstr, unsigned int sizeHint = 0)
1347 {
1348     int cnt, i, symdescID;
1349     Type *baseType;
1350     Type *newType;
1351
1352     cnt = i = 0;
1353
1354     assert(stabstr[0] == 'r');
1355     cnt++;
1356
1357     // range index type
1358     symdescID = parseSymDesc(stabstr, cnt);
1359
1360     baseType = mod->getModuleTypes()->findType(symdescID);
1361
1362     // //bperr("\tSymbol Descriptor: %c and Value: %d\n",tmpchar, symdescID);
1363
1364     cnt++; /* Discarding the ';' */
1365     i=0;
1366     if (stabstr[cnt] == '-' ) {
1367        i++;
1368     }
1369
1370     /* Getting type range or size */
1371     while (isdigit(stabstr[cnt+i])) i++;
1372
1373     char *temp = (char *)malloc(sizeof(char)*(i+1));
1374     if(!strncpy(temp, &(stabstr[cnt]), i))
1375       /* Error copying size/range*/
1376       exit(1);
1377     temp[i] = '\0';
1378     int j = atol(temp);
1379     
1380     char *low = temp;
1381     cnt = cnt + i + 1; /* Discard other Semicolon */
1382     i = 0;
1383     if((stabstr[cnt]) == '-') {
1384        i++; /* discard '-' for (long) unsigned int */
1385     }
1386     
1387     while(isdigit(stabstr[cnt+i]))
1388        i++;
1389     
1390     char *hi = (char *)malloc(sizeof(char)*(i+1));
1391     if(!strncpy(hi, &(stabstr[cnt]), i))
1392        /* Error copying upper range */
1393        exit(1);
1394     hi[i] = '\0';
1395
1396     std::string tname = convertCharToString(name);
1397     if( j <= 0 ){
1398         /* range */
1399
1400         // //bperr("\tLower limit: %s and Upper limit: %s\n", low, hi);
1401         //Create new type
1402
1403       if (baseType == NULL) {
1404         newType = new typeSubrange(ID, sizeHint ? sizeHint / 8 : guessSize(low,hi), atoi(low), atoi(hi), tname);
1405       }
1406       else {
1407         newType = new typeSubrange(ID, sizeHint ? sizeHint / 8 : baseType->getSize(), atoi(low), atoi(hi), tname);
1408       }
1409       newType = mod->getModuleTypes()->addOrUpdateType((typeSubrange *) newType);
1410     } else if( j > 0){
1411         j = atol(hi);
1412         if(j == 0){
1413             /*size */
1414             int size = (int)j;
1415
1416             // //bperr("\tSize of Type : %d bytes\n",size);
1417             //Create new type
1418
1419             newType = new typeScalar(ID, size, convertCharToString(name));
1420             //Add to Collection
1421             newType = mod->getModuleTypes()->addOrUpdateType((typeScalar *) newType);
1422         } else {
1423             /* range */
1424             // //bperr("Type RANGE: ERROR!!\n");
1425             if (baseType == NULL)
1426                 newType = new typeSubrange(ID, sizeHint ? sizeHint / 8 : sizeof(long), atoi(low), atoi(hi), tname);
1427             else
1428                 newType = new typeSubrange(ID, sizeHint ? sizeHint / 8 : baseType->getSize(), atoi(low), atoi(hi),tname);
1429             newType = mod->getModuleTypes()->addOrUpdateType((typeSubrange *) newType);
1430         }       
1431     }
1432     free(low);
1433     free(hi);
1434
1435     cnt = cnt + i;
1436     if( stabstr[cnt] == ';')
1437       cnt++;
1438     
1439     return(&(stabstr[cnt]));
1440 }
1441
1442 #endif
1443
1444 //
1445 //  <attrType> = @s<int>;<int>
1446 //  <attrType> = @s<int>;(<int>,<int>)
1447 //  <attrType> = @s<int>;r(<int>,<int>);<int>;<int>;
1448 //
1449
1450 //
1451 //   This may in fact be much simpler than first anticipated
1452 //   AIX stabs use attributes only as hints, and dbx only
1453 //   understands @s (size) and @P (packed) types.  We only 
1454 //   parse the size attribute, and should be able to get away
1455 //   with simply passing the remainder to the rest of our parser
1456 //
1457 static char *parseAttrType(Module *mod, const char *name,
1458                          int ID, char *stabstr, int &cnt)
1459 {
1460     assert(stabstr[cnt] == '@');
1461     cnt++; // skip the @
1462    
1463     if (stabstr[cnt] == 's') {
1464       cnt++;
1465       
1466       int size = parseSymDesc(stabstr, cnt);
1467       cnt++;  // skip ';'
1468
1469       char *newstr =  parseTypeDef(mod, stabstr+cnt, name, ID, size);
1470       if (newstr[0] == ';')
1471          return newstr+1;
1472       else
1473          return newstr;
1474     } else {
1475         ////bperr(" Unable to parse Type Attribute: %s ID %d : %s\n", 
1476         // name,ID, &(stabstr[cnt]));
1477        while (stabstr[cnt] != ';') cnt++;
1478        cnt++;
1479        return parseTypeDef(mod, stabstr+cnt, name, ID);
1480     }
1481 }
1482 /*
1483 static void parseAttrType(Module *mod, const char *name,
1484                          int ID, char *stabstr, int &cnt)
1485 {
1486     bool includesRange = false;
1487     char *low = NULL, *high = NULL;
1488
1489     // format @s(size in bits); negative type number;
1490     dataClass typdescr = dataTypeAttrib;
1491
1492     assert(stabstr[cnt] == '@');
1493     cnt++; // skip the @
1494
1495     if (stabstr[cnt] == 's') {
1496       cnt++;
1497       
1498       int size = parseSymDesc(stabstr, cnt);
1499       cnt++;  // skip ';'
1500
1501       if (stabstr[cnt] == 'r') {
1502           // include range at end
1503           cnt++;
1504           includesRange = true;
1505       }
1506
1507       int type = parseSymDesc(stabstr, cnt);
1508       // skip ';' end of stab record ??? (at least for bool)
1509       cnt++;
1510
1511       if (includesRange) {
1512           int len;
1513
1514           // Parse out low range string.
1515           len = 0;
1516           if (stabstr[cnt] == '-' ) cnt++, len++;
1517           while (isdigit(stabstr[cnt])) cnt++, len++;
1518           cnt++;    // skip ';'
1519
1520           // Store the low range string.
1521           low = (char *)malloc(sizeof(char) * (len + 1));
1522           assert(low);
1523           strncpy(low, &stabstr[cnt - (len + 1)], len);
1524           low[len] = '\0';
1525
1526           // Parse out high range string.
1527           len = 0;
1528           if (stabstr[cnt] == '-' ) cnt++, len++;
1529           while (isdigit(stabstr[cnt])) cnt++, len++;
1530           cnt++;    // skip ';'
1531
1532           // Store the high range string.
1533           high = (char *)malloc(sizeof(char) * (len + 1));
1534           assert(high);
1535           strncpy(high, &stabstr[cnt - (len + 1)], len);
1536           high[len] = '\0';
1537       }
1538
1539       // Create a new B_type that points to a builtInTypes
1540       Type *ptrType =BPatch::bpatch->builtInTypes->findBuiltInType(type);
1541       
1542       if (!ptrType) ptrType = BPatch::bpatch->type_Untyped;
1543       
1544       Type *newType = new Type(name, ID, typdescr, size/8, ptrType);
1545       if(!newType) {
1546             //bperr(" Can't Allocate new type ");
1547             exit(-1);
1548       }
1549
1550       if (includesRange) {
1551           newType->setLow(low);
1552           newType->setHigh(high);
1553           free(low);
1554           free(high);
1555       }
1556
1557       // Add type to collection
1558       newType2 = mod->getModuleTypes()->addOrUpdateType(newType);
1559
1560       if (stabstr[cnt]) {
1561           //bperr("More Type Attribute to Parse: %s ID %d : %s\n", name,
1562                ID, &(stabstr[cnt]));
1563           //bperr("got type = %d\n", type);
1564           //bperr("full string = %s\n", stabstr);
1565       }
1566     } else {
1567         ////bperr(" Unable to parse Type Attribute: %s ID %d : %s\n", 
1568         // name,ID, &(stabstr[cnt]));
1569     }
1570 }
1571 */
1572 //
1573 //  <refType> = &<typeUse>
1574 //
1575 static char *parseRefType(Module *mod, const char *name,
1576                    int ID, char *stabstr, int &cnt)
1577 {
1578     /* reference to another type */
1579     assert(stabstr[cnt] == '&');
1580     cnt++;
1581     
1582     int refID = parseTypeUse(mod, stabstr, cnt, name);
1583     
1584     // Create a new B_type that points to a structure
1585     Type *ptrType = mod->getModuleTypes()->findOrCreateType(refID);
1586     if (!ptrType) ptrType = mod->exec()->type_Untyped;
1587     std::string tName = convertCharToString(name); 
1588     typeRef *newType = new typeRef(ID, ptrType, tName);
1589
1590     // Add to typeCollection
1591     newType = mod->getModuleTypes()->addOrUpdateType(newType);
1592     
1593     return(&(stabstr[cnt]));
1594 }
1595
1596 //
1597 // Given a base class and a new type, add all visible fields to the new class
1598 //
1599 void addBaseClassToClass(Module *mod, int baseID, 
1600                          fieldListType *newType, int /*offset*/)
1601 {
1602
1603     //Find base class
1604     fieldListType *baseCl = dynamic_cast<fieldListType *>(mod->getModuleTypes()->findType(baseID));
1605     if( ! baseCl ) {
1606         std::string modName = mod->fileName();
1607         //bpwarn( "can't find base class id %d in module %s\n", baseID, modName);
1608         baseCl = new typeStruct(baseID);
1609         fieldListType *baseCl2 = dynamic_cast<typeStruct *>(mod->getModuleTypes()->addOrUpdateType( (typeStruct *)baseCl ));
1610         std::string fName = "{superclass}";
1611         newType->addField( fName, baseCl2, -1, visUnknown );
1612         baseCl->decrRefCount();
1613         return;
1614     }
1615     std::string fName = "{superclass}";
1616     newType->addField( fName, baseCl, -1, visUnknown );
1617
1618     //Get field descriptions of the base type
1619     /*
1620     const std::vector<Field *> *baseClFields = baseCl->getComponents();
1621     for (unsigned int fieldNum=0; fieldNum < baseClFields->size(); fieldNum++) {
1622         Field *field = (*baseClFields)[fieldNum];
1623
1624         if (field->getVisibility() == visPrivate)
1625             continue; //Can not add this member
1626
1627         newType->addField(field->getName(), field->getTypeDesc(), field->getType(), field->getOffset()+offset, field->getVisibility());
1628     }
1629     */
1630 }
1631
1632 //
1633 // parse a list of fields.
1634 //    Format is [A|B|C-M|N|O][c][G]<fieldName>:<type-desc>;offset;size;
1635 //
1636 static char *parseFieldList(Module *mod, fieldListType *newType, 
1637                             char *stabstr, bool sunCPlusPlus)
1638 {
1639   int cnt = 0;
1640   int size = 0;
1641   char *compname;
1642   int comptype= 0;
1643   int beg_offset=0;
1644   visibility_t _vis = visUnknown;
1645   dataClass typedescr;
1646   bool hasVirtuals = false;
1647   
1648   if (stabstr[cnt] == '!') {
1649     //Inheritance definition, Add base class field list to the current one
1650     //according to visibility rules.
1651     
1652     cnt++; //Skip '!'
1653     
1654     //Get # of base classes
1655     int baseClNum = atoi(getIdentifier(stabstr, cnt).c_str());
1656     cnt++; //Skip ','
1657     
1658     typeStruct *newStructType = dynamic_cast<typeStruct *>(newType);
1659     //Skip information for each base class
1660     for(int i=0; i<baseClNum; ++i) {
1661       //Skip virtual inheritance flag, base visibility flag and base offset
1662       getIdentifier(stabstr, cnt);
1663       cnt++; //Skip ','
1664       
1665       //Find base class type identifier
1666       int baseID = parseSymDesc(stabstr, cnt);
1667       
1668       cnt++; //Skip ';'
1669       
1670       addBaseClassToClass(mod, baseID, newStructType, 0);
1671     }
1672   }
1673   
1674   while (stabstr[cnt] && (stabstr[cnt] != ';')) {
1675     typedescr = dataScalar;
1676     
1677     if (stabstr[cnt] == '~') {
1678       //End of virtual class
1679       while(stabstr[cnt] != ';') cnt++;
1680       break; //End of class is reached
1681     }
1682     
1683     // skip <letter>cG
1684     if (sunCPlusPlus) cnt += 3;
1685     
1686     if ((stabstr[cnt] == 'u') && (stabstr[cnt+1] == ':') && (!isdigit(stabstr[cnt+2]))) {
1687       cnt += 2;
1688     }
1689     
1690     compname = getFieldName(stabstr, cnt);
1691     /*
1692       if (strlen(compname) == 0) {
1693       //Something wrong! Most probably unhandled C++ type
1694       //Skip the rest of the structure
1695       while(stabstr[cnt]) cnt++;
1696       return(&stabstr[cnt]);
1697       }
1698     */
1699     cnt++;      // Skip ":"
1700     
1701     if ((stabstr[cnt]) == ':') {
1702       //Method definition
1703       typedescr = dataFunction;
1704       cnt++;
1705     }
1706     
1707     if ((stabstr[cnt]) == '/') { // visibility C++
1708       cnt++; /* get '/' */
1709       switch (stabstr[cnt]) {
1710       case '0':
1711         _vis = visPrivate;
1712         break;
1713       case '1':
1714         _vis = visProtected;
1715         break;
1716       case '2':
1717         _vis = visPublic;
1718         break;
1719       default:
1720         _vis = visUnknown;
1721       }
1722       cnt++; // get visibility value
1723     }
1724
1725     // should be a typeDescriptor
1726     comptype = parseTypeUse(mod, stabstr, cnt, "");
1727     
1728     if (stabstr[cnt] == ':') {
1729       while (stabstr[cnt] == ':') {
1730         cnt++; //Discard ':'
1731         beg_offset = 0;
1732         size = 0;
1733         std::string varName = getIdentifier(stabstr, cnt);
1734         if (typedescr == dataFunction) {
1735           // Additional qualifiers for methods
1736           cnt++; //Skip ';'
1737           cnt++; //Skip visibility
1738           cnt++; //Skip method modifier
1739           if (stabstr[cnt] == '*') {
1740             //Virtual fcn definition
1741             hasVirtuals = true;
1742             cnt++; //Skip '*'
1743             while(stabstr[cnt] != ';') cnt++; //Skip vtable index
1744             cnt++; //Skip ';'
1745             if (stabstr[cnt] != ';') {
1746               parseTypeUse(mod, stabstr, cnt, ""); //Skip type number to the base class
1747             }
1748             cnt++; //Skip ';'
1749             if (isSymId(stabstr[cnt])) {
1750               parseTypeUse(mod, stabstr, cnt, "");
1751             }
1752           } else if ( (stabstr[cnt] == '.') || 
1753                       (stabstr[cnt] == '?') ) {
1754             cnt++; //Skip '.' or '?'
1755             if (isSymId(stabstr[cnt])) {
1756               parseTypeUse(mod, stabstr, cnt, "");
1757             }
1758           }
1759         }
1760         if (stabstr[cnt] == ';')
1761           cnt++; //Skip ';'
1762       }
1763     } else if (stabstr[cnt] == ',') {
1764       cnt++;    // skip ','
1765       beg_offset = parseSymDesc(stabstr, cnt);
1766       
1767       if (stabstr[cnt] == ',') {
1768         cnt++;  // skip ','
1769         size = parseSymDesc(stabstr, cnt);
1770       }
1771       else
1772         size = 0;
1773     }
1774     
1775     if (stabstr[cnt] == ';') // jaw 03/15/02-- major kludge here for DPCL compat
1776       cnt++;  // needs further examination
1777     // //bperr("\tType: %d, Starting Offset: %d (bits), Size: %d (bits)\n", comptype, beg_offset, size);
1778     // Add struct field to type
1779     Type *fieldType = mod->getModuleTypes()->findOrCreateType( comptype );
1780     if (fieldType == NULL) {
1781       //C++ compilers may add extra fields whose types might not available.
1782       //Assign void type to these kind of fields. --Mehmet
1783       fieldType = mod->getModuleTypes()->findType("void");
1784     }
1785     std::string fName = convertCharToString(compname);
1786     if (_vis == visUnknown) {
1787       newType->addField(fName, fieldType, beg_offset);
1788     } else {
1789       // //bperr( "Adding field '%s' to type '%s' @ 0x%x\n", compname, newType->getName(), newType );
1790       newType->addField(fName, fieldType, beg_offset, _vis);
1791       ////bperr("Adding Component with VISIBILITY STRUCT\n");
1792     }
1793     free(compname);
1794   }
1795   
1796   if (hasVirtuals && 
1797       stabstr[cnt] == ';' &&
1798       stabstr[cnt+1] == '~' &&
1799       stabstr[cnt+2] == '%') {
1800     cnt+=3;
1801     while (stabstr[cnt] != ';') cnt++;
1802   }         
1803   
1804   // should end with a ';'
1805   if (stabstr[cnt] == ';') {
1806     return &stabstr[cnt+1];
1807   } else if (stabstr[cnt] == '\0') {
1808     return &stabstr[cnt];
1809   } else {
1810     //bperr("invalid stab record: %s\n", &stabstr[cnt]);
1811     abort();
1812     return NULL; // should not get here
1813   }
1814 }
1815
1816
1817 //
1818 //      Y<type><size><className>;<Bases>;<DataMembers>;<MemberFunctions>;<StaticDataMembers>;
1819 //              <Friends>;<VirtualFunctionInfo>;<NestedClassList>;<AccessAdjustments>;
1820 //              <VirtualBaseClassOffsets>;<TemplatmentMembers>;<PassMethod>;
1821 //
1822 static char *parseCPlusPlusInfo(Module *mod,
1823              char *stabstr, const char *mangledName, int ID)
1824 {
1825     int cnt;
1826     char *name;
1827     int structsize;
1828     bool sunStyle = true;
1829     bool nestedType = false;
1830     dataClass typdescr;
1831     fieldListType * newType = NULL, *newType2 = NULL;
1832
1833     assert(stabstr[0] == 'Y');
1834     cnt = 1;
1835
1836     // size on AIX 
1837     if (isdigit(stabstr[cnt])) {
1838         structsize = parseSymDesc(stabstr, cnt);
1839         sunStyle = false;
1840     }
1841
1842     switch(stabstr[cnt]) {
1843         case 'C':
1844         case 'c':
1845             typdescr = dataTypeClass;
1846             break;
1847
1848         case 'S':
1849             nestedType = true;
1850         case 's':
1851             typdescr = dataStructure;
1852             break;
1853
1854         case 'U':
1855             nestedType = true;
1856         case 'u':
1857             typdescr = dataUnion;
1858             break;
1859
1860         case 'n':       // namespace - ignored
1861             cnt = strlen(stabstr);
1862             return(&(stabstr[cnt]));
1863             break;
1864
1865         default:
1866             //bperr( "ERROR: Unrecognized C++ str = %s\n", stabstr);
1867             cnt = strlen(stabstr);
1868             return(&(stabstr[cnt]));
1869             break;
1870     }
1871
1872     cnt++;              // skip to size
1873     if (isdigit(stabstr[cnt])) {
1874         structsize = parseSymDesc(stabstr, cnt);
1875     }
1876     
1877     if (stabstr[cnt] == 'V') cnt++;
1878     if (stabstr[cnt] == '(') cnt++;
1879
1880     if (sunStyle && (stabstr[cnt] != ';')) {
1881         int len;
1882         char *n;
1883
1884         // Class or Type Name
1885         n = &stabstr[cnt];
1886         while (stabstr[cnt] != ';') cnt++;
1887         len = &stabstr[cnt] - n;
1888         name = (char *) calloc(len + 1, sizeof(char));
1889         strncpy(name, n, len);
1890     } else {
1891         name = const_cast< char * >( mangledName );
1892     }
1893
1894     std::string tName = convertCharToString(name);
1895     //Create new type
1896     switch (typdescr) {
1897     case dataTypeClass:
1898     case dataStructure:
1899        newType = new typeStruct(ID, tName);
1900        newType2 = dynamic_cast<fieldListType *>(mod->getModuleTypes()->addOrUpdateType((typeStruct *) newType));
1901        break;
1902     case dataUnion:
1903        newType = new typeUnion(ID, tName);
1904        newType2 = dynamic_cast<fieldListType *>(mod->getModuleTypes()->addOrUpdateType((typeUnion *) newType));
1905        break;
1906     default:
1907        assert(0);
1908     }
1909     //add to type collection
1910
1911     if(newType2 != newType)
1912         newType->decrRefCount();
1913
1914     if (sunStyle) {
1915         cnt++;
1916         // base class(es) 
1917         while (stabstr[cnt] != ';') {
1918             // skip visibility flag
1919             cnt++;
1920
1921             int offset = parseSymDesc(stabstr, cnt);
1922
1923             // Find base class type identifier
1924             int baseID = parseSymDesc(stabstr, cnt);
1925             addBaseClassToClass(mod, baseID, newType2, offset);
1926         }
1927
1928         cnt++;  // skip ;
1929     }
1930
1931     // parse dataMembers
1932     stabstr = parseFieldList(mod, newType2, &stabstr[cnt], sunStyle);
1933     cnt = 0;
1934
1935     if (stabstr[0]) {
1936         // parse member functions
1937         cnt++;
1938         while (stabstr[cnt] && (stabstr[cnt] != ';')) {
1939             std::string pd_funcName = getIdentifier(stabstr, cnt, true);
1940             const char *funcName = pd_funcName.c_str();
1941
1942             funcName++; // skip ppp-code
1943
1944             if (*funcName == '-') funcName++; // it's a pure vitual
1945
1946             while (isdigit(*funcName)) funcName++; // skip virtual function index
1947             funcName++;
1948
1949             char *className = strdup(currentRawSymbolName.c_str());
1950             className[3] = 'c';
1951             className[strlen(className)-1] = '\0';      // remove tailing "_"
1952             std::string methodName = std::string(className) + std::string(funcName) + std::string("_");
1953                 char * name = P_cplus_demangle( methodName.c_str(), mod->exec()->isNativeCompiler() );
1954                 if( name != NULL ) {
1955                         funcName = strrchr( name, ':' );
1956                         if( funcName ) { funcName++; }
1957                         else { funcName = name; }
1958                         }
1959
1960             // should include position for virtual methods
1961             Type *fieldType = mod->getModuleTypes()->findType("void");
1962
1963             std::string fName = convertCharToString(funcName);
1964
1965             typeFunction *funcType = new typeFunction( ID, fieldType, fName);
1966             newType2->addField( fName, funcType);
1967                                             
1968             free(name);
1969             free(className);
1970             if (stabstr[cnt] == ' ') cnt++;
1971         }
1972     }
1973
1974     cnt = strlen(stabstr);
1975     return(&(stabstr[cnt]));
1976 }
1977
1978 //
1979 // This function takes a <typeDef> and parses it 
1980 //
1981 //      <typeDef> = <symDesc>   |
1982 //              <crossRef>      |       
1983 //              *<typeUse>      |       Pointer to a type
1984 //              <arrayDef>      |
1985 //              f<typeUse>      |       function type
1986 //              R<int>,<int>    |       Real type 
1987 //              b[u|s][c|]<int>;<int>;<int>     |       Builtin
1988 //              <rangeType>     |
1989 //              e<enumType>     |
1990 //              <attrType>      |
1991 //              <refType>       |
1992 //              k<typeDef>      |       SunPro constant
1993 //              B<typeDef>      |       SunPro volatile
1994 //              M<symDesc>;<int>|       Fortran CHARACTER array
1995 //              s<int><fields>  |       Structure <int> is size
1996 //              u<int><fields>  |       Union <int> is size
1997 //              V<typeUse>
1998 //
1999 //      <enumType> = <ident>:<int> | <ident>:<int>,<enumType>
2000 //
2001 // It adds the typeDef to the type definition with the name name, and id ID.
2002 //
2003 static char *parseTypeDef(Module *mod, char *stabstr, 
2004                           const char *name, int ID, unsigned int sizeHint)
2005 {
2006     Type * newType = NULL;
2007     fieldListType * newFieldType = NULL, *newFieldType2 = NULL;
2008     Type * ptrType = NULL;
2009   
2010     std::string compsymdesc;
2011   
2012     dataClass typdescr;
2013     int ptrID=0;
2014     
2015     int value;
2016     int cnt,i,j,k;
2017     int structsize;
2018     int type;
2019     cnt = i = j = k = 0;
2020 #ifdef IBM_BPATCH_COMPAT_STAB_DEBUG
2021     //bperr( "%s[%d]:  inside parseTypeDef, stabstr = %s\n", __FILE__, __LINE__, 
2022         //    (stabstr == NULL) ? "NULL" : stabstr);
2023 #endif
2024
2025     assert (stabstr[0] != '=');
2026
2027     // //bperr( "parsing %s\n", stabstr);
2028     if (isSymId(stabstr[0])) {
2029         typdescr = dataScalar;
2030         type = parseSymDesc(stabstr, cnt);
2031                     
2032     if (ID == type) {
2033         // Type:tFOO = FOO
2034         // as far as I can tell, this only happens when defining an empty
2035         // type (i.e. void)
2036
2037         std::string tName = convertCharToString(name);
2038         newType = new typeScalar(ID, 0, tName);
2039         newType = mod->getModuleTypes()->addOrUpdateType((typeScalar *) newType); 
2040     } else if (stabstr[cnt] == '=') {
2041         // XXX - in the new type t(0,1)=(0,2)=s... is possible
2042         //           skip the second id for now -- jkh 3/21/99
2043         stabstr = parseTypeDef(mod, &(stabstr[cnt+i+1]), name, type);
2044         cnt = 0;
2045         Type *oldType;
2046
2047         oldType = mod->getModuleTypes()->findOrCreateType(type);
2048         if(!oldType) oldType = mod->exec()->type_Untyped;
2049         std::string tName = convertCharToString(name);
2050         newType = new typeTypedef(ID, oldType, tName, sizeHint);
2051         mod->getModuleTypes()->addOrUpdateType((typeTypedef *) newType);
2052
2053     } else {
2054         Type *oldType;
2055         std::string tName = convertCharToString(name);
2056         oldType = mod->getModuleTypes()->findOrCreateType(type);
2057         newType = new typeTypedef(ID, oldType, tName, sizeHint);
2058         newType = mod->getModuleTypes()->addOrUpdateType((typeTypedef *) newType);
2059     }
2060     } else {
2061       switch (stabstr[0]) {
2062           case 'x':  //cross reference 
2063           {
2064             parseCrossRef(mod->getModuleTypes(), name, ID, stabstr, cnt);
2065             break;
2066           }   
2067           case '*':
2068           {
2069             /* pointer to another type */
2070             cnt++;
2071             ptrID = parseTypeUse(mod, stabstr, cnt, NULL);
2072
2073             // Create a new B_type that points to a structure
2074             ptrType = mod->getModuleTypes()->findOrCreateType(ptrID);
2075             if (!ptrType) ptrType = mod->exec()->type_Untyped;
2076
2077             newType = new typePointer(ID, ptrType);
2078             // Add to typeCollection
2079             newType = mod->getModuleTypes()->addOrUpdateType((typePointer *) newType);
2080             return(&(stabstr[cnt]));
2081             break;
2082           }
2083           case 'a':
2084       case 'A':
2085           {
2086               (void) parseArrayDef(mod, name, ID, stabstr, cnt, sizeHint);
2087               return (&stabstr[cnt]);
2088               break;
2089       }
2090       case 'g':  
2091           {
2092                 /* function with return type and prototype */
2093
2094                 // g<typeUse>[<typeUse>]*#
2095                 typdescr = dataFunction;
2096
2097                 cnt++; /* skip the g */
2098                 type = parseTypeUse(mod, stabstr, cnt, name);
2099                 ptrType = mod->getModuleTypes()->findOrCreateType(type);
2100
2101                 {
2102                    std::string tName = convertCharToString(name);
2103                    typeFunction *newFunction = 
2104                       new typeFunction(ID, ptrType, tName);
2105                    typeFunction *newFunction2 = NULL;
2106                    
2107                    if (newFunction) { 
2108                       newFunction2 = dynamic_cast<typeFunction*>(mod->getModuleTypes()->addOrUpdateType(newFunction)); 
2109                       if(newFunction2 != newFunction)
2110                               newFunction->decrRefCount();
2111                    }
2112                    if (!newFunction2) {
2113                       //bpfatal(" Can't Allocate new type ");
2114                             types_printf("%s[%d]: parseTypeDef: unable to allocate newType\n", FILE__, __LINE__);
2115                             //exit(-1);
2116                    }
2117                    
2118                    while ((stabstr[cnt] != '#') &&  (stabstr[cnt])) {
2119                       int paramType;
2120                       paramType = parseTypeUse(mod, stabstr, cnt, name);
2121                       newType = mod->getModuleTypes()->findOrCreateType(paramType);
2122                       newFunction2->addParam(newType);
2123                       //newFunction2->addField(buffer, newType->getDataClass(), newType, curOffset, newType->getSize());
2124                    }
2125                 }
2126
2127                 // skip #
2128                 if (stabstr[cnt] == '#') cnt++;
2129                 break;
2130           }
2131           case 'f':
2132           {
2133                 /* function type */
2134                 typdescr = dataFunction;
2135
2136                 cnt++; /* skip the f */
2137                 type = parseTypeUse(mod, stabstr, cnt, name);
2138                 ptrType = mod->getModuleTypes()->findOrCreateType(type);
2139
2140                 
2141                 std::string tName = convertCharToString(name);
2142                 newType = new typeFunction(ID, ptrType, tName);
2143                 newType = mod->getModuleTypes()->addOrUpdateType((typeFunction *) newType);
2144
2145                 // skip to end - SunPro Compilers output extra info here - jkh 6/9/3
2146                 // cnt = strlen(stabstr);
2147                 break;
2148          }
2149
2150          case 'M': 
2151          {
2152                 /* CHARACTER ??? */
2153                 cnt++; // skip  'M'
2154
2155                 int baseType = parseSymDesc(stabstr, cnt);
2156                 if (baseType != -2 || (stabstr[cnt] != ';')) {
2157                     //bperr("unexpected non character array %s\n", stabstr);
2158                 } else {
2159                     cnt++; // skip ';'
2160                     int size;
2161                     if (stabstr[cnt] == 'T') {
2162                       /* Fortran stack-based array bounds */
2163                       size = 0;
2164                       cnt++; // skip 'T'
2165                       (void) parseSymDesc(stabstr, cnt);
2166                     } else if (stabstr[cnt] == 'J') {
2167                       /* Unbounded range */
2168                       size = 0;
2169                       cnt++; // skip 'J';
2170                       (void) parseSymDesc(stabstr, cnt);
2171                     } else
2172                       size = parseSymDesc(stabstr, cnt);
2173
2174                     ptrType = mod->getModuleTypes()->findOrCreateType(baseType);
2175                     std::string tName = convertCharToString(name);
2176                     newType = new typeArray(ID, ptrType, 1, size, tName);
2177                     newType = mod->getModuleTypes()->addOrUpdateType((typeArray* ) newType);
2178                 }
2179                 break;
2180
2181          }
2182          case 'R': 
2183          {
2184                 // Define a floating point type - R fp-type; bytes;
2185                 cnt++;
2186                 (void) parseSymDesc(stabstr, cnt);
2187                 cnt ++;
2188
2189                 int bytes = parseSymDesc(stabstr, cnt);
2190
2191                 newType = new typeScalar(ID, bytes, name);
2192                 newType = mod->getModuleTypes()->addOrUpdateType((typeScalar *) newType);
2193
2194                 if (stabstr[cnt] == ';') cnt++; // skip the final ';'
2195
2196                 // gcc 3.0 adds an extra field that is always 0 (no indication in the code why)
2197                 if (stabstr[cnt] == '0') cnt += 2;      // skip the final '0;'
2198
2199                 break;
2200           }
2201
2202           case 'b': 
2203           {
2204                 // builtin type b  - signed char-flag width; offset; nbits
2205                 int limit = strlen(&stabstr[cnt]);
2206
2207                 // skip to width
2208                 while (!isdigit(stabstr[cnt+i]) && (i < limit)) i++;    
2209                 if (i >= limit) return(&(stabstr[cnt]));
2210
2211                 cnt += i;
2212                 int size = parseSymDesc(stabstr,cnt);
2213                 cnt -= i;
2214                 i++;    // skip the ';'
2215
2216                 // skip to bits
2217                 while (stabstr[cnt+i] != ';' && (i < limit)) i++;       
2218                 if (i >= limit) return(&(stabstr[cnt]));
2219                 i++;
2220
2221                 cnt += i;
2222                 parseSymDesc(stabstr, cnt);
2223                 
2224                 if (stabstr[cnt]) cnt++;        // skip the final ';'
2225
2226                 newType = new typeScalar(ID, size, name);
2227                 //Add to Collection
2228                 newType = mod->getModuleTypes()->addOrUpdateType((typeScalar *) newType);
2229
2230                 return &stabstr[cnt];
2231                 break;
2232         }
2233         case 'r':               // range type
2234         {    
2235             return parseRangeType(mod, name, ID, stabstr, sizeHint);
2236             break;
2237         }
2238         case 'e':               // Enumerated type
2239         {
2240             cnt++;      /* skip the 'e' */
2241
2242             // Create new Enum type
2243             std::string tName = convertCharToString(name);
2244             typeEnum *newEnumType = new typeEnum(ID, tName);
2245             // Add type to collection
2246             newEnumType = dynamic_cast<typeEnum *>(mod->getModuleTypes()->addOrUpdateType(newEnumType));
2247                 
2248             while (stabstr[cnt]) {
2249                 /* Get enum component value */
2250                 compsymdesc = getIdentifier(stabstr, cnt);
2251                 cnt++; /* skip colon */
2252
2253 #ifdef IBM_BPATCH_COMPAT_STAB_DEBUG
2254                 //bperr( "%s[%d]:  before parseSymDesc -- enumerated type \n", 
2255             //          __FILE__, __LINE__);
2256 #endif            
2257                 value = parseSymDesc(stabstr, cnt);
2258
2259                 // add enum field to type
2260                 newEnumType->addConstant(compsymdesc, value);
2261                   
2262                 cnt++; /* skip trailing comma */
2263                 if ((stabstr[cnt]) == ';') cnt++; /* End of enum stab record */
2264             }
2265             break;
2266         }    
2267         case '@':  // type attribute, defines size and type (negative num)
2268         {
2269             return parseAttrType(mod, name, ID, stabstr, cnt);
2270             break;
2271         }
2272         case '&': //XXX- Need to complete, may be more to parse jdd 4/22/99
2273         {    
2274             return parseRefType(mod, name, ID, stabstr, cnt);
2275             break;
2276         }
2277         case 'k':       // Sun constant type s<typeDef> - parse as <typeDef>
2278         {
2279             return parseTypeDef(mod, &stabstr[cnt+1], name, ID);
2280             break;
2281         }
2282         case 'V':       // AIX colatile ? type V<typeDef> - parse as <typeDef>
2283         case 'B':       // Sun volatile type B<typeDef> - parse as <typeDef>
2284             return parseTypeDef(mod, &stabstr[cnt+1], name, ID);
2285             break;
2286
2287         case 's':       // struct
2288         case 'u':       // union
2289     case 'T':   // Fortran TYPE
2290         {    
2291             /* Type descriptor */
2292             if (stabstr[cnt] == 's' || stabstr[cnt] == 'T') {
2293                 typdescr = dataStructure;
2294             } else {
2295                 typdescr = dataUnion;
2296             }
2297
2298             cnt++;              // skip to size
2299             structsize = parseSymDesc(stabstr, cnt);
2300            
2301             std::string tName = convertCharToString(name);
2302             //Create new type
2303             if (typdescr == dataStructure) {
2304                newFieldType = new typeStruct(ID, tName);
2305                newFieldType2 = dynamic_cast<fieldListType *>(mod->getModuleTypes()->addOrUpdateType((typeStruct *) newFieldType));
2306             }
2307             else {
2308                newFieldType = new typeUnion(ID, tName);
2309                newFieldType2 = dynamic_cast<fieldListType *>(mod->getModuleTypes()->addOrUpdateType((typeUnion *) newFieldType));
2310             }
2311             //add to type collection
2312
2313         //TODO What if two different files have the same structure?? // on AIX
2314         if(!newFieldType2)
2315                 newFieldType2 = dynamic_cast<fieldListType *>(newFieldType);
2316         if(newFieldType2 != newFieldType)
2317             newFieldType->decrRefCount();
2318             char *ret = parseFieldList(mod, newFieldType2, &stabstr[cnt], false);
2319         return ret;
2320
2321             break;
2322         }
2323         case 'Y':
2324         {
2325             // C++ specific stabs (Sun compiler)
2326             return parseCPlusPlusInfo(mod, stabstr, name, ID);
2327             break;
2328         }
2329         case 'Z':  // What is this ??? - jkh 10/14/99 (xlc compiler uses it)
2330         {    
2331             return (&stabstr[1]);
2332             break;
2333         }
2334         case '#':
2335         {
2336             //Class method definition
2337             cnt++; //Skip '#'
2338             if (stabstr[cnt] == '#') {
2339                 //Get return type
2340                 cnt++; //Skip '#'
2341                 parseTypeUse(mod, stabstr, cnt, name);
2342             }
2343             else {
2344                 while(1) {
2345                         //Skip class type, return typ and arg types
2346                         parseTypeUse(mod, stabstr, cnt, name);
2347                         if (stabstr[cnt] == ',')
2348                                 cnt++;
2349                         else if (stabstr[cnt] == ';')
2350                                 break;
2351                 }
2352             }
2353
2354             cnt++; //Skip ';'
2355             return(&(stabstr[cnt]));
2356             break;
2357         }
2358         default:
2359             //bperr( "ERROR: Unrecognized str = %s\n", &stabstr[cnt]);
2360             //      return NULL;
2361             // Null probably isn't the right choice here.
2362             cnt = strlen(stabstr);
2363             break;
2364       }
2365     }
2366
2367     return(&(stabstr[cnt]));
2368 } /* end of parseTypeDef*/
2369
2370 //
2371 // parseConstantUse - parse a constant (used by Fortran PARAMETERS)
2372 //
2373 // <constantUse> = =i<int> |
2374 //                 =r <float>
2375 //
2376 //
2377 static Type *parseConstantUse(Module *mod, char *stabstr, int &cnt)
2378 {
2379     // skip =
2380     cnt++;
2381
2382     Type *ret;
2383
2384     if (stabstr[cnt] == 'i') {
2385         ret = mod->getModuleTypes()->findType("integer*4");
2386     } else if (stabstr[cnt] == 'r') {
2387         ret = mod->getModuleTypes()->findType("double");
2388     } else if (stabstr[cnt] == 's') {
2389         ret = mod->getModuleTypes()->findType("char *");
2390     } else {
2391         //bperr("unknown constant type %s\n", &stabstr[cnt]);
2392         ret = NULL;
2393     }
2394
2395     cnt = strlen(stabstr);
2396
2397     return ret;
2398 }
2399