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