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