text: /* /% C %/ */
  /***********************************************************************
   * cint (C/C++ interpreter)
   ************************************************************************
   * Source file typedef.c
   ************************************************************************
   * Description:
   *  typedef handling
   ************************************************************************
   * Copyright(c) 1995~2003  Masaharu Goto
   *
   * For the licensing terms see the file COPYING
   *
   ************************************************************************/
  
  #include "common.h"
  #include "DataMemberHandle.h"
  
  extern "C" {
  
  static int G__static_parent_tagnum = -1;
  static int G__static_isconst = 0;
  
  // Static functions.
  static void G__shiftstring(char* s, int n);
  static int G__defined_typename_exact(char* type_name);
  static int G__make_uniqueP2Ftypedef(char* type_name);
  
  // Internal functions.
  void G__define_type();
  int G__defined_typename_noerror(const char* type_name, int noerror);
  
  // Functions in the C interface.
  int G__defined_typename(const char* type_name);
  int G__search_typename(const char* typenamein, int typein, int tagnum, int reftype);
  int G__search_typename2(const char* type_name, int typein, int tagnum, int reftype, int parent_tagnum);
  
  //______________________________________________________________________________
  //
  //  Static functions.
  //
  
  //______________________________________________________________________________
  static void G__shiftstring(char* s, int n)
  {
     int i = 0, j = n;
     while (s[j]) s[i++] = s[j++];
     s[i] = 0;
  }
  
  //______________________________________________________________________________
  static int G__defined_typename_exact(char* type_name)
  {
     // Search already defined typedef names, -1 is returned if not found
     int i, flag = 0;
     char ispointer = 0;
     int len = strlen(type_name) + 1;
     G__FastAllocString temp(len);
     char *p;
     G__FastAllocString temp2(type_name);
     int env_tagnum;
     char *par;
  
     /* find 'xxx::yyy' */
     p = (char*)G__find_last_scope_operator(temp2);
  
     /* abandon scope operator if 'zzz (xxx::yyy)www' */
     par = strchr(temp2, '(');
     if (par && p && par < p) p = (char*)NULL;
  
     if (p) {
        temp = p + 2;
        *p = '\0';
        if (temp2 == p) env_tagnum = -1; /* global scope */
  #ifndef G__STD_NAMESPACE
        else if (strcmp(temp2, "std") == 0
                 && G__ignore_stdnamespace
                ) env_tagnum = -1;
  #endif
        else {
           // first try a typedef, so we don't trigger autoloading here:
           long env_typenum = G__defined_typename_noerror(temp2, 1);
           if (env_typenum != -1 && G__newtype.type[env_typenum] == 'u')
              env_tagnum = G__newtype.tagnum[env_typenum];
           else
              env_tagnum = G__defined_tagname(temp2, 0);
        }
     }
     else {
        temp = temp2;
        env_tagnum = G__get_envtagnum();
     }
  
     len = strlen(temp);
  
     if (temp[len-1] == '*') {
        temp[--len] = '\0';
        ispointer = 'A' - 'a';
     }
  
     NameMap::Range nameRange = G__newtype.namerange->Find(temp);
     if (nameRange) {
        for (i = nameRange.First();i <= nameRange.Last(); i++) {
           if (len == G__newtype.hash[i] && strcmp(G__newtype.name[i], temp) == 0 && (
                    env_tagnum == G__newtype.parent_tagnum[i]
                 )) {
              flag = 1;
              /* This must be a bad manner. Somebody needs to reset G__var_type
               * especially when typein is 0. */
              G__var_type = G__newtype.type[i] + ispointer ;
              break;
           }
        }
     } else {
        i = G__newtype.alltype;
     }
  
     if (flag == 0) return(-1);
     return(i);
  }
  
  //______________________________________________________________________________
  static int G__make_uniqueP2Ftypedef(char* type_name)
  {
     //  input: 'void* (*)(int , void * , short )'
     // output: 'void* (*)(int,void*,short)'
     char *from;
     char *to;
     int spacecnt = 0;
     int isstart = 1;
  
     /*  input  'void* (*)(int , void * , short )'
      *         ^ start                         */
     from = strchr(type_name, '(');
     if (!from) return(1);
     from = strchr(from + 1, '(');
     if (!from) return(1);
     ++from;
     to = from;
     /*  input  'void* (*)(int , void * , short )'
      *                    ^ got this position  */
  
     while (*from) {
        if (isspace(*from)) {
           if (0 == spacecnt && 0 == isstart) {
              /*  input  'void* (*)(int   * , void  * , short )'
               *                       ^ here  */
              *(to++) = ' ';
           }
           else {
              /*  input  'void* (*)(int   * , void  * , short )'
               *                        ^^ here  */
              /* Ignore consequitive space */
           }
           if (0 == isstart) ++spacecnt;
           else           spacecnt = 0;
           isstart = 0;
        }
        else {
           isstart = 0;
           if (spacecnt) {
              switch (*from) {
                 case ',':
                    isstart = 1;
                    *(to - 1) = *from;
                    break;
                 case ')':
                 case '*':
                 case '&':
                    /*  input  'void* (*)(int   * , void  * , short )'
                     *                          ^ here
                     *  output 'void* (*)(int*
                     *                       ^ put here */
                    *(to - 1) = *from;
                    break;
                 default:
                    /*  input  'void* (*)(unsigned  int   * , void  * , short )'
                     *                              ^ here
                     *  output 'void* (*)(unsigned i
                     *                             ^ put here */
                    *(to++) = *from;
                    break;
              }
           }
           else {
              /*  input  'void* (*)(unsigned  int   * , void  * , short )'
               *                      ^ here   */
              *(to++) = *from;
           }
           spacecnt = 0;
        }
        ++from;
     }
  
     *to = 0;
  
     /* int (*)(void) to int (*)() */
     from = strchr(type_name, '(');
     if (!from) return(1);
     from = strchr(from + 1, '(');
     if (!from) return(1);
     if (strcmp(from, "(void)") == 0) {
        *(++from) = ')';
        *(++from) = 0;
     }
  
     return(0);
  }
  
  //______________________________________________________________________________
  //
  //  Internal Functions.
  //
  
  //______________________________________________________________________________
  void G__define_type()
  {
     // typedef [struct|union|enum] tagname { member } newtype;
     //        ^
     // typedef fundamentaltype   newtype;
     //        ^
     fpos_t rewind_fpos;
     int c;
     G__FastAllocString type1(G__LONGLINE);
     G__FastAllocString tagname(G__LONGLINE);
     G__FastAllocString type_name(G__LONGLINE);
     G__FastAllocString temp(G__LONGLINE);
     int isnext;
     fpos_t next_fpos;
     int store_tagnum;
     int store_def_struct_member = 0;
     struct G__var_array* store_local;
     G__FastAllocString memname(G__MAXNAME);
     G__FastAllocString val(G__ONELINE);
     char type;
     char tagtype = 0;
     int unsigned_flag = 0;
     int mem_def = 0;
     int temp_line;
     int len;
     int taglen;
     G__value enumval;
     int store_tagdefining;
     int itemp;
     int nindex = 0;
     int index[G__MAXVARDIM];
     G__FastAllocString aryindex(G__MAXNAME);
     char* p;
     int store_var_type;
     int typenum;
     int isorgtypepointer = 0;
     int store_def_tagnum;
     int reftype = G__PARANORMAL;
     int rawunsigned = 0;
     int env_tagnum;
     int isconst = 0;
     fpos_t pos_p2fcomment;
     int flag_p2f = 0;
     tagname[0] = '\0';
     fgetpos(G__ifile.fp, &pos_p2fcomment);
  #ifdef G__ASM
  #ifdef G__ASM_DBG
     if (G__asm_dbg && G__asm_noverflow) {
        G__genericerror(G__LOOPCOMPILEABORT);
     }
  #endif // G__ASM_DBG
     G__abortbytecode();
  #endif // G__ASM
     store_tagnum = G__tagnum;
     store_tagdefining = G__tagdefining;
     store_def_tagnum = G__def_tagnum;
  
     /*
      *  typedef  [struct|union|enum] tagname { member } newtype;
      *  typedef  fundamentaltype   newtype;
      *          ^
      * read type
      */
  
     c = G__fgetname_template(type1, 0, "*{");
     if (c == '*') {
        type1 += "*";
        c = ' ';
     }
     // Consume any const, volatile, mutable, or typename qualifier. // FIXME: mutable is illegal in a typedef.
     while (
        isspace(c) &&
        (
           !strcmp(type1, "const") ||
           !strcmp(type1, "volatile") ||
           !strcmp(type1, "mutable") ||
           !strcmp(type1, "typename")
        )
     ) {
        if (!strcmp(type1, "const")) {
           isconst |= G__CONSTVAR;
        }
        c = G__fgetname_template(type1, 0, "{");
     }
     if (!strcmp(type1, "::")) {
        // skip a :: without a namespace in front of it (i.e. global namespace!)
        c = G__fgetspace(); // skip the next ':'
        c = G__fgetname_template(type1, 0, "{");
     }
     if (!strncmp(type1, "::", 2)) {
        // Strip a leading :: (global namespace operator).
        // A leading '::' causes other typename matching
        // functions to fail so we remove it. This is not
        // the ideal solution (neither is the one above)
        // since it does not allow for decriminating between
        // global namespace and local namespace, but at
        // least it is an improvement over the current
        // behavior.
        //
        // Note: We must use memmove because the source
        //       and destination strings overlap!
        //
        int t1len = strlen(type1);
        memmove(type1, type1 + 2, t1len - 2);
        type1.Set(t1len - 2, '\0');
     }
     while (isspace(c)) {
        len = strlen(type1);
        c = G__fgetspace();
        if (c == ':') {
           c = G__fgetspace(); // skip the next ':'
           type1 += "::";
           c = G__fgetname_template(temp, 0, "{");
           type1 += temp;
        }
        else if ((c == '<') || (c == ',') || (type1[len-1] == '<') || (type1[len-1] == ',')) {
           type1[len++] = c;
           do { // ignore white space inside template
              // humm .. thoes this translate correctly nested templates?
              c = G__fgetstream_template(type1, len, ">");
              len = strlen(type1);
           }
           while (isspace(c));
           type1[len++] = c;
           type1[len] = '\0';
        }
        else if (c == '>') {
           type1[len++] = c;
           type1[len] = '\0';
        }
        else {
           c = ' ';
           fseek(G__ifile.fp, -1, SEEK_CUR);
           if (G__dispsource) {
              G__disp_mask = 1;
           }
           break;
        }
     }
  
     /*
      *  typedef unsigned  int  newtype ;
      *                   ^
      * read type
      */
  
     if (!strcmp(type1, "unsigned")) {
        unsigned_flag = 1;
        c = G__fgetname(type1, 0, "");
     }
     else if (!strcmp(type1, "signed")) {
        unsigned_flag = 0;
        c = G__fgetname(type1, 0, "");
     }
     else if (!strcmp(type1, "unsigned*")) {
        unsigned_flag = 1;
        type1 = "int*";
     }
     else if (!strcmp(type1, "signed*")) {
        unsigned_flag = 0;
        type1 = "int*";
     }
     else if (!strcmp(type1, "unsigned&")) {
        unsigned_flag = 1;
        type1 = "int&";
     }
     else if (!strcmp(type1, "signed&")) {
        unsigned_flag = 0;
        type1 = "int&";
     }
     else if (!strcmp(type1, "unsigned*&")) {
        unsigned_flag = 1;
        type1 = "int*&";
     }
     else if (!strcmp(type1, "signed*&")) {
        unsigned_flag = 0;
        type1 = "int*&";
     }
  
     /*
      *  typedef  [struct|union|enum]  tagname { member } newtype;
      *                               ^
      *  typedef  fundamentaltype   newtype;
      *                           ^
      *  typedef unsigned  int  newtype ;
      *                        ^
      */
  
     if (type1[0] && (type1[strlen(type1)-1] == '&')) {
        reftype = G__PARAREFERENCE;
        type1[strlen(type1)-1] = '\0';
     }
     if (type1[0] && (type1[strlen(type1)-1] == '*')) {
        isorgtypepointer = 'A' -'a';
        type1[strlen(type1)-1] = '\0';
        while (type1[0] && (type1[strlen(type1)-1] == '*')) {
           if (G__PARANORMAL == reftype) {
              reftype = G__PARAP2P;
           }
           else if (reftype >= G__PARAP2P) {
              ++reftype;
           }
           type1[strlen(type1)-1] = '\0';
        }
     }
  
     if (strcmp(type1, "char") == 0) {
        if (unsigned_flag == 0) type = 'c';
        else                 type = 'b';
     }
     else if (strcmp(type1, "short") == 0) {
        if (unsigned_flag == 0) type = 's';
        else                 type = 'r';
     }
     else if (strcmp(type1, "int") == 0) {
        if (unsigned_flag == 0) type = 'i';
        else                 type = 'h';
     }
     else if (strcmp(type1, "long") == 0) {
        if (unsigned_flag == 0) type = 'l';
        else                 type = 'k';
     }
     else if (strcmp(type1, "bool") == 0) {
        type = 'g';
     }
     else if (strcmp(type1, "void") == 0) {
        type = 'y';
     }
     else if (strcmp(type1, "float") == 0) {
        type = 'f';
     }
     else if (strcmp(type1, "double") == 0) {
        type = 'd';
     }
     else if (strcmp(type1, "FILE") == 0) {
        type = 'e';
     }
     else if ((strcmp(type1, "struct") == 0) || (strcmp(type1, "union") == 0) ||
              (strcmp(type1, "enum") == 0) || (strcmp(type1, "class") == 0)) {
        type = 'u';
        if (strcmp(type1, "struct") == 0) tagtype = 's';
        if (strcmp(type1, "class") == 0) tagtype = 'c';
        if (strcmp(type1, "union") == 0) tagtype = 'u';
        if (strcmp(type1, "enum") == 0) tagtype = 'e';
        tagname[0] = 0;
  
        /*  typedef [struct|union|enum]{ member } newtype;
         *                              ^ */
  
        /*  typedef [struct|union|enum]  tagname { member } newtype;
         *  typedef [struct|union|enum]  tagname  newtype;
         *  typedef [struct|union|enum]  { member } newtype;
         *                              ^
         *  read tagname
         */
        if (c != '{') {
           c = G__fgetname(tagname, 0, "{");
        }
  
  
        /*
         *  typedef [struct|union|enum]{ member } newtype;
         *                              ^
         *  typedef [struct|union|enum] tagname  { member } newtype;
         *                                      ^
         *  typedef [struct|union|enum] tagname{ member } newtype;
         *                                      ^
         *  typedef [struct|union|enum]              { member } newtype;
         *                                     ^
         *  typedef [struct|union|enum] tagname  newtype;
         *                                      ^            */
        if (c != '{') {
           c = G__fgetspace();
           /* typedef [struct] tag   { member } newtype;
            *                         ^
            * typedef [struct|union|enum] tagname  newtype;
            *                                       ^     */
           if (c != '{') {
              fseek(G__ifile.fp, -1, SEEK_CUR);
              if (G__dispsource) G__disp_mask = 1;
           }
        }
  
        /*  typedef [struct|union|enum]{ member } newtype;
         *                              ^
         *  typedef [struct|union|enum] tagname  { member } newtype;
         *                                        ^
         *  typedef [struct|union|enum] tagname{ member } newtype;
         *                                      ^
         *  typedef [struct|union|enum]              { member } newtype;
         *                                     ^
         *  typedef [struct|union|enum] tagname  newtype;
         *                                       ^
         *  skip member declaration if exists */
        if (c == '{') {
           mem_def = 1;
           fseek(G__ifile.fp, -1, SEEK_CUR);
           fgetpos(G__ifile.fp, &rewind_fpos);
           if (G__dispsource) G__disp_mask = 1;
           G__fgetc();
           G__fignorestream("}");
        }
     }
     else if (unsigned_flag) {
        len = strlen(type1);
        if (';' == type1[len-1]) {
           c = ';';
           type1[len-1] = '\0';
        }
        type = 'h';
        rawunsigned = 1;
     }
     else {
        itemp = G__defined_typename(type1);
        if (itemp != -1) {
           type = G__newtype.type[itemp];
           switch (reftype) {
              case G__PARANORMAL:
                 reftype = G__newtype.reftype[itemp];
                 break;
              case G__PARAREFERENCE:
                 switch (G__newtype.reftype[itemp]) {
                    case G__PARANORMAL:
                    case G__PARAREFERENCE:
                       break;
                    default:
                       if (G__newtype.reftype[itemp] < G__PARAREF) {
                          reftype = G__newtype.reftype[itemp] + G__PARAREF;
                       }
                       else {
                          reftype = G__newtype.reftype[itemp];
                       }
                       break;
                 }
                 break;
              default:
                 switch (G__newtype.reftype[itemp]) {
                    case G__PARANORMAL:
                       break;
                    case G__PARAREFERENCE:
                       G__fprinterr(G__serr, "Limitation: reference or pointer type not handled properly (2)");
                       G__printlinenum();
                       break;
                    default:
                       break;
                 }
                 break;
           }
           itemp = G__newtype.tagnum[itemp];
        }
        else {
           type = 'u';
           itemp = G__defined_tagname(type1, 0);
        }
        if (itemp != -1) {
           tagtype = G__struct.type[itemp];
  #ifndef G__OLDIMPLEMENTATION1503
           if (G__struct.parent_tagnum[itemp] != -1) {
              tagname = G__fulltagname(G__struct.parent_tagnum[itemp], 0);
              tagname += "::";
              tagname += G__struct.name[itemp];
           }
           else {
              tagname = G__struct.name[itemp];
           }
  #else // G__OLDIMPLEMENTATION1503
           tagname = G__fulltagname(itemp, 0);
  #endif // G__OLDIMPLEMENTATION1503
           ++G__struct.istypedefed[itemp];
        }
        else {
           tagtype = 0;
           tagname[0] = 0;
        }
     }
  
     if (isorgtypepointer) {
        type = toupper(type);
     }
  
     /*
      *  typedef [struct|union|enum] tagname { member } newtype ;
      *                                                ^^
      * skip member declaration if exists
      */
  
     if (rawunsigned) {
        type_name = type1;
     }
     else {
        c = G__fgetname_template(type_name, 0, ";,[");
     }
  
     if (
        !strncmp(type_name, "long", 4) &&
        (
           (strlen(type_name) == 4) ||
           (
              (strlen(type_name) >= 5) &&
              (
                 (type_name[4] == '&') ||
                 (type_name[4] == '*')
              )
           )
        )
     ) {
        // int tmptypenum;
        if (strlen(type_name) >= 5) {
           // Rewind.
           size_t copylen = strlen(type_name) - strlen("long") + 1;
           strncpy(type_name,type_name + strlen("long"),copylen);
        } else {
           c = G__fgetname(type_name, 0, ";,[");
        }
        tagname = "";
        if (type == 'l') {
           type = 'n';
        }
        else if (type == 'k') {
           type = 'm';
        }
     }
     if (
        !strncmp(type_name, "double", strlen("double")) &&
        (
           (strlen(type_name) == strlen("double")) ||
           (
              (strlen(type_name) > strlen("double")) &&
              (
                 (type_name[strlen("double")] == '&') ||
                 (type_name[strlen("double")] == '*')
              )
           )
        )
     ) {
        static const size_t lendouble = strlen("double");
        if (strlen(type_name) > lendouble) {
           // Rewind.
           size_t copylen = strlen(type_name) - lendouble + 1;
           strncpy(type_name,type_name + lendouble,copylen);
        } else {
           c = G__fgetname(type_name, 0, ";,[");
        }
        if (type == 'l') {
           // int tmptypenum;
           type = 'q';
           tagname = "";
        }
     }
  
     /* in case of
      *  typedef unsigned long int  int32;
      *                           ^
      *  read type_name
      */
     if (
        !strncmp(type_name, "int", 3) && // we have at least int, and
        (
           (strlen(type_name) == 3) || // we have exactly int, or
           (
              (strlen(type_name) >= 4) && // we have more than int, and
              (
                 (type_name[3] == '&') || // we have at least int&, or
                 (type_name[3] == '*') // we have at least int*
              )
           )
        )
     ) {
        static const size_t lenint = strlen("int");
        if (strlen(type_name) > lenint) { // we have at least int& or int*
           // Rewind.
           size_t copylen = strlen(type_name) - lenint + 1;
           strncpy(type_name,type_name + lenint,copylen);
        } else {
           c = G__fgetstream(type_name, 0, ";,[");
        }
     }
     if (!strcmp(type_name, "*")) {
        fpos_t tmppos;
        fgetpos(G__ifile.fp, &tmppos);
        int tmpline = G__ifile.line_number;
        c = G__fgetname(type_name, 1, ";,[");
        if (isspace(c) && !strcmp(type_name, "*const")) {
           isconst |= G__PCONSTVAR;
           c = G__fgetstream(type_name, 1, ";,[");
        }
        else {
           G__disp_mask = strlen(type_name) - 1;
           G__ifile.line_number = tmpline;
           fsetpos(G__ifile.fp, &tmppos);
           c = G__fgetstream(type_name, 1, ";,[");
        }
     }
     else if (!strcmp(type_name, "**")) {
        fpos_t tmppos;
        fgetpos(G__ifile.fp, &tmppos);
        int tmpline = G__ifile.line_number;
        c = G__fgetname(type_name, 1, ";,[");
        if (isspace(c) && !strcmp(type_name, "*const")) {
           isconst |= G__PCONSTVAR;
           c = G__fgetstream(type_name, 1, ";,[");
        }
        else {
           G__disp_mask = strlen(type_name) - 1;
           G__ifile.line_number = tmpline;
           fsetpos(G__ifile.fp, &tmppos);
           c = G__fgetstream(type_name, 1, ";,[");
        }
        isorgtypepointer = 1;
        type = toupper(type);
     }
     else if (!strcmp(type_name, "&")) {
        reftype = G__PARAREFERENCE;
        c = G__fgetstream(type_name, 0, ";,[");
     }
     else if (!strcmp(type_name, "*&")) {
        reftype = G__PARAREFERENCE;
        type = toupper(type);
        c = G__fgetstream(type_name, 0, ";,[");
     }
     else if (!strcmp(type_name, "*const")) {
        isconst |= G__PCONSTVAR;
        c = G__fgetstream(type_name, 1, ";,[");
     }
  #ifndef G__OLDIMPLEMENTATION1856
     else if (!strcmp(type_name, "const*")) {
        isconst |= G__CONSTVAR;
        type = toupper(type);
        c = G__fgetstream(type_name, 0, "*&;,[");
        if ((c == '*') && (type_name[0] != '*')) {
           if (!strcmp(type_name, "const")) {
              isconst |= G__CONSTVAR;
           }
           type_name[0] = '*';
           c = G__fgetstream(type_name, 1, ";,[");
        }
        if ((c == '&') && (type_name[0] != '&')) {
           reftype = G__PARAREFERENCE;
           if (!strcmp(type_name, "const")) {
              isconst |= G__CONSTVAR;
           }
           c = G__fgetstream(type_name, 0, ";,[");
        }
     }
     else if (!strcmp(type_name, "const**")) {
        isconst |= G__CONSTVAR;
        isorgtypepointer = 1;
        type = toupper(type);
        type_name[0] = '*';
        c = G__fgetstream(type_name, 1, "*;,[");
     }
     else if (!strcmp(type_name, "const*&")) {
        isconst |= G__CONSTVAR;
        reftype = G__PARAREFERENCE;
        type = toupper(type);
        c = G__fgetstream(type_name, 0, ";,[");
     }
  #endif
     if (isspace(c)) {
        if ((type_name[0] == '(') && (c != ';') && (c != ',')) {
           do {
              c = G__fgetstream(type_name, strlen(type_name), ";,");
              size_t lentype_name = strlen(type_name);
              type_name.Set(lentype_name, c);
              type_name.Set(lentype_name + 1, 0);
           }
           while ((c != ';') && (c != ','));
           type_name[strlen(type_name)-1] = 0;
        }
        else if (!strcmp(type_name, "const")) {
           isconst |= G__PCONSTVAR;
           c = G__fgetstream(type_name, 0, ";,[");
           if (!strncmp(type_name, "*const*", 7)) {
              isconst |= G__CONSTVAR;
              isorgtypepointer = 1;
              type = toupper(type);
              G__shiftstring(type_name, 6);
           }
           else if (!strncmp(type_name, "*const&", 7)) {
              isconst |= G__CONSTVAR;
              reftype = G__PARAREFERENCE;
              type = toupper(type);
              G__shiftstring(type_name, 7);
           }
           else if (!strncmp(type_name, "const*", 6)) {
           }
           else if (!strncmp(type_name, "const&", 6)) {
           }
        }
        else if (!strcmp(type_name, "const*")) {
           isconst |= G__PCONSTVAR;
           type_name[0] = '*';
           c = G__fgetstream(type_name, 1, ";,[");
        }
        else {
           G__FastAllocString ltemp1(G__LONGLINE);
           c = G__fgetstream(ltemp1, 0, ";,[");
           if (ltemp1[0] == '(') {
              type = 'q';
           }
        }
     }
     //
     // in case of
     //   typedef <unsigned long int|struct A {}>  int32 , *pint32;
     //                                                   ^
     //
     nindex = 0;
     while (c == '[') {
        store_var_type = G__var_type;
        G__var_type = 'p';
        c = G__fgetstream(aryindex, 0, "]");
        index[nindex++] = G__int(G__getexpr(aryindex));
        c = G__fignorestream("[,;");
        G__var_type = store_var_type;
     }
     next_name:
     p = strchr(type_name, '(');
     if (p) {
        flag_p2f = 1;
        if (p == type_name) {
           // function to pointer 'typedef type (*newtype)();'
           // handle this as 'typedef void* newtype;'
           val = p + 1;
           p = strchr(val, ')');
           if (p) {
              *p = '\0';
              type_name = val;
              type = 'y';
              p = strstr(type_name, "::*");
           }
           if (p) {
              // pointer to member function 'typedef type (A::*p)();
              val = p + 3;
              type_name = val;
              type = 'a';
           }
        }
        else if ((p == (type_name + 1)) && (type_name[0] == '*')) {
           // function to pointer 'typedef type *(*newtype)();'
           // handle this as 'typedef void* newtype;'
           val = p + 1;
           p = strchr(val, ')');
           if (p) {
              *p = '\0';
              type_name = val;
              type = 'Q';
              p = strstr(type_name, "::*");
           }
           if (p) {
              // pointer to member function 'typedef type (A::*p)();
              val = p + 3;
              type_name = val;
              type = 'a';
           }
        }
        else {
           // function type 'typedef type newtype();'
           // handle this as 'typedef void newtype;'
           *p = '\0';
           type = 'y';
        }
     }
     isnext = 0;
     if (c == ',') {
        isnext = 1;
        fgetpos(G__ifile.fp, &next_fpos);
     }
     //
     //  typedef [struct|union|enum] tagname { member } newtype  ;
     //                                                           ^
     //  read over. Store line number. This will be restored after
     //  struct,union.enum member declaration
     //
     temp_line = G__ifile.line_number;
     // typedef oldtype* newtype
     // newtype is a pointer to oldtype
     if (type_name[0] == '*') {
        int ix = 1;
        if (
           isupper(type)
  #ifndef G__OLDIMPLEMENTATION2191
              && (type != '1')
  #else // G__OLDIMPLEMENTATION2191
              && (type != 'Q')
  #endif // G__OLDIMPLEMENTATION2191
           // --
        ) {
           reftype = G__PARAP2P;
           while (type_name[ix] == '*') {
              if (G__PARANORMAL == reftype) {
                 reftype = G__PARAP2P;
              }
              else if (reftype >= G__PARAP2P) {
                 ++reftype;
              }
              ++ix;
           }
        }
        else {
           type = toupper(type);
           while (type_name[ix] == '*') {
              if (G__PARANORMAL == reftype) reftype = G__PARAP2P;
              else if (reftype >= G__PARAP2P) ++ reftype;
              ++ix;
           }
        }
        val = type_name;
        type_name = val + ix;
     }
     // typedef oldtype &newtype
     if (type_name[0] == '&') {
        if (reftype >= G__PARAP2P) {
           reftype += G__PARAREF;
        }
        else {
           reftype = G__PARAREFERENCE;
        }
        if (strlen(type_name) > 1) {
           val = type_name;
           type_name = val + 1;
        }
     }
     //
     //  Check if typedef is already defined.
     //
     typenum = G__defined_typename_exact(type_name);
     //
     //  If new typedef, add it to newtype table.
     //
     if (typenum != -1) { // return if the type is already defined
        if (c != ';') {
           G__fignorestream(";");
        }
        return;
     }
     else {
        if (G__newtype.alltype == G__MAXTYPEDEF) {
           G__fprinterr(G__serr, "Limitation: Number of typedef exceed %d FILE:%s LINE:%d\nFatal error, exit program. Increase G__MAXTYPEDEF in G__ci.h and recompile %s\n", G__MAXTYPEDEF, G__ifile.name, G__ifile.line_number, G__nam);
           G__eof = 1;
           return;
        }
        typenum = G__newtype.alltype;
        len = strlen(type_name);
        G__newtype.name[typenum] = (char*) malloc(len + 2);
        strcpy(G__newtype.name[typenum], type_name); // Okay, we allocated the right size
        G__newtype.namerange->Insert(G__newtype.name[typenum], typenum);
        G__newtype.iscpplink[typenum] = G__NOLINK;
        G__newtype.comment[typenum].p.com = 0;
        G__newtype.comment[typenum].filenum = -1;
        G__newtype.nindex[typenum] = nindex;
  #ifdef G__TYPEDEFFPOS
        // 21/05/07
        // G__ifile.filenum at this moment might point to a temporary file
        // but later on a real file will be registered with this number
        // and will create confusion.  If this is a temporary file just
        // ignore its number.
        if ((strlen(G__ifile.name) > 3) && !strncmp("(tmp", G__ifile.name, 4)) {
           G__newtype.filenum[typenum] = -1;
           G__newtype.linenum[typenum] = -1;
        }
        else {
           G__newtype.filenum[typenum] = G__ifile.filenum;
           G__newtype.linenum[typenum] = G__ifile.line_number;
        }
  #endif // G__TYPEDEFFPOS
        if (nindex) {
           G__newtype.index[typenum] = (int*) malloc(nindex * G__INTALLOC);
           memcpy((void*) G__newtype.index[typenum], (void*) index, nindex * G__INTALLOC);
        }
        G__newtype.hash[typenum] = len;
        if (!tagname[0]) {
           if (G__globalcomp == G__CPPLINK) {
              tagname = type_name;
           }
           else {
              tagname = "$";
              tagname += type_name;
           }
           taglen = strlen(tagname);
        }
        else {
           taglen = strlen(tagname);
           if (tagname[taglen-1] == '*') {
              type = toupper(type);
              tagname[taglen-1] = '\0';
           }
        }
        G__newtype.tagnum[typenum] = -1;
        G__newtype.type[typenum] = type;
        G__newtype.globalcomp[typenum] = G__default_link ? G__globalcomp : G__NOLINK;
        G__newtype.reftype[typenum] = reftype;
        G__newtype.isconst[typenum] = isconst;
        if (G__def_struct_member) {
           env_tagnum = G__tagnum;
        }
        else if (G__func_now != -1) {
           env_tagnum = -2;
           G__fprinterr(G__serr, "Limitation: In function typedef not allowed in cint");
           G__printlinenum();
        }
        else {
           env_tagnum = -1;
        }
        G__newtype.parent_tagnum[typenum] = env_tagnum;
        ++G__newtype.alltype;
     }
     if (tolower(type) == 'u') {
        G__tagnum = G__search_tagname(tagname, tagtype);
        if (G__tagnum < 0) {
           G__fignorestream(";");
           return;
        }
        G__newtype.tagnum[typenum] = G__tagnum;
        if (mem_def == 1) {
           if (!G__struct.size[G__tagnum]) {
              fsetpos(G__ifile.fp, &rewind_fpos);
              G__struct.line_number[G__tagnum] = G__ifile.line_number;
              G__struct.filenum[G__tagnum] = G__ifile.filenum;
              G__struct.parent_tagnum[G__tagnum] = env_tagnum;
              //
              // in case of enum
              //
              if (tagtype == 'e') {
                 G__disp_mask = 10000;
                 while ((c = G__fgetc()) != '{') {}
                 enumval.obj.i = -1;
                 enumval.type = 'i' ;
                 enumval.tagnum = G__tagnum ;
                 enumval.typenum = typenum ;
                 G__constvar = G__CONSTVAR;
                 G__enumdef = 1;
                 do {
                    c = G__fgetstream(memname, 0, "=,}");
                    if (c == '=') {
                       int store_prerun = G__prerun;
                       char store_var_type = G__var_type;
                       G__var_type = 'p';
                       G__prerun = 0;
                       c = G__fgetstream(val, 0, ",}");
                       enumval = G__getexpr(val);
                       G__prerun = store_prerun;
                       G__var_type = store_var_type;
                    }
                    else {
                       ++enumval.obj.i;
                    }
                    G__var_type = 'i';
                    if (store_tagnum != -1) {
                       store_def_struct_member = G__def_struct_member;
                       G__def_struct_member = 0;
                       G__static_alloc = 1;
                    }
                    Cint::G__DataMemberHandle member;
                    G__letvariable(memname, enumval, &G__global , G__p_local, member);
                    if (store_tagnum != -1) {
                       G__def_struct_member = store_def_struct_member;
                       G__static_alloc = 0;
                    }
                 }
                 while (c != '}');
                 G__constvar = 0;
                 G__enumdef = 0;
                 G__fignorestream(";");
                 G__disp_mask = 0;
                 G__ifile.line_number = temp_line;
              }
              //
              // in case of struct,union
              //
              else {
                 if (tagtype != 's' && tagtype != 'c' && tagtype != 'u') {
                    /* enum already handled above */
                    G__fprinterr(G__serr, "Error: Illegal tagtype. struct,union,enum expected\n");
                 }
                 store_local = G__p_local;
                 G__p_local = G__struct.memvar[G__tagnum];
                 store_def_struct_member = G__def_struct_member;
                 G__def_struct_member = 1;
                 G__disp_mask = 10000;
                 G__tagdefining = G__tagnum;
                 G__def_tagnum = G__tagdefining;
                 // Tell the parser to process the entire struct block.
                 int brace_level = 0;
                 // And call the parser.
                 G__exec_statement(&brace_level);
                 G__tagnum = G__tagdefining;
                 G__def_tagnum = store_def_tagnum;
                 //
                 // Padding for PA-RISC, Spark, etc
                 // If struct size can not be divided by G__DOUBLEALLOC the size is aligned.
                 //
                 if (G__struct.memvar[G__tagnum]->allvar == 1) {
                    // this is still questionable, inherit0.c
                    struct G__var_array* v = G__struct.memvar[G__tagnum];
                    if (v->type[0] == 'c') {
                       if (isupper(v->type[0])) {
                          int num_of_elements = v->varlabel[0][1] /* number of elements */;
                          if (!num_of_elements) {
                             num_of_elements = 1;
                          }
                          G__struct.size[G__tagnum] = num_of_elements * G__LONGALLOC;
                       }
                       else {
                          G__value buf;
                          buf.type = v->type[0];
                          buf.tagnum = v->p_tagtable[0];
                          buf.typenum = v->p_typetable[0];
                          int num_of_elements = v->varlabel[0][1] /* number of elements */;
                          if (!num_of_elements) {
                             num_of_elements = 1;
                          }
                          G__struct.size[G__tagnum] = num_of_elements * G__sizeof(&buf);
                       }
                    }
                 }
                 else if (G__struct.size[G__tagnum] % G__DOUBLEALLOC) {
                    G__struct.size[G__tagnum] += G__DOUBLEALLOC - G__struct.size[G__tagnum] % G__DOUBLEALLOC;
                 }
                 else if (!G__struct.size[G__tagnum]) {
                    G__struct.size[G__tagnum] = G__CHARALLOC;
                 }
                 G__tagdefining = store_tagdefining;
                 G__def_struct_member = store_def_struct_member;
                 G__p_local = store_local;
                 G__fignorestream(";");
                 G__disp_mask = 0;
                 G__ifile.line_number = temp_line;
              }
           }
        }
        G__tagnum = store_tagnum;
     }
     if (isnext) {
        fsetpos(G__ifile.fp, &next_fpos);
        c = G__fgetstream(type_name, 0, ",;");
        goto next_name;
     }
     if (G__fons_comment) {
        G__fsetcomment(&G__newtype.comment[G__newtype.alltype-1]);
     }
     if (
        flag_p2f &&
        (G__newtype.comment[G__newtype.alltype-1].filenum < 0) &&
        !G__newtype.comment[G__newtype.alltype-1].p.com
     ) {
        fpos_t xpos;
        if (G__ifile.filenum > G__nfile) {
           G__fprinterr(G__serr, "Warning: pointer to function typedef incomplete in command line or G__exec_text(). Declare in source file or use G__load_text()\n");
           return;
        }
        ++G__macroORtemplateINfile;
        fgetpos(G__ifile.fp, &xpos);
        fsetpos(G__ifile.fp, &pos_p2fcomment);
        if (G__ifile.fp == G__mfp) {
           G__newtype.comment[G__newtype.alltype-1].filenum = G__MAXFILE;
        }
        else {
           G__newtype.comment[G__newtype.alltype-1].filenum = G__ifile.filenum;
        }
        fgetpos(G__ifile.fp, &G__newtype.comment[G__newtype.alltype-1].p.pos);
        fsetpos(G__ifile.fp, &xpos);
     }
  }
  
  //______________________________________________________________________________
  int G__defined_typename_noerror(const char* type_name, int noerror)
  {
     // Search already defined typedef names, -1 is returned if not found
     //
     // Note: This functions modifies G__var_type.
     //
     int i;
     int len;
     char ispointer = 0;
     char* p;
     int env_tagnum;
     int typenum = -1;
     unsigned long matchflag = 0;
     unsigned long thisflag = 0;
     char* par;
  
     G__FastAllocString temp2(type_name);
  
     // find 'xxx::yyy'
     // const ns::T - the const does not belong to the ns!
     char* skipconst = temp2;
     while (!strncmp(skipconst, "const ", 6)) {
        skipconst += 6;
     }
     p = (char*) G__find_last_scope_operator(skipconst);
  
     G__FastAllocString temp(strlen(skipconst));
  
     // abandon scope operator if 'zzz (xxx::yyy)www'
     par = strchr(skipconst, '(');
     if (par && p && par < p) {
        p = 0;
     }
  
     if (p) {
        temp = p + 2;
        *p = '\0';
        if (skipconst == p) {
           env_tagnum = -1; // global scope
        }
  #ifndef G__STD_NAMESPACE /* ON745 */
        else if (!strcmp(skipconst, "std") && G__ignore_stdnamespace) {
           env_tagnum = -1;
        }
  #endif
        else {
           // first try a typedef, so we don't trigger autoloading here:
           long env_typenum = G__defined_typename_noerror(skipconst, 1);
           if (env_typenum != -1 && G__newtype.type[env_typenum] == 'u')
              env_tagnum = G__newtype.tagnum[env_typenum];
           else
              env_tagnum = G__defined_tagname(skipconst, noerror);
        }
     }
     else {
        temp = skipconst;
        env_tagnum = G__get_envtagnum();
     }
  
     len = strlen(temp);
  
     if ((len > 0) && (temp[len-1] == '*')) {
        temp[--len] = '\0';
        ispointer = 'A' - 'a';
     }
  
     if (G__newtype.namerange) {
        NameMap::Range nameRange = G__newtype.namerange->Find(temp);
        if (nameRange) {
           if (nameRange.Last() > G__newtype.alltype) 
              fprintf(stderr,"G__defined_typename_noerror %s, max=%d still have a set range of %d to %d\n",temp.data(),G__newtype.alltype,nameRange.First(),nameRange.Last());
           for (i = nameRange.First(); i <= nameRange.Last(); ++i) {
              if ((len == G__newtype.hash[i]) && !strcmp(G__newtype.name[i], temp)) {
                 thisflag = 0;
                 // global scope
                 if (
                     (G__newtype.parent_tagnum[i] == -1)
  #if !defined(G__OLDIMPLEMTATION2100)
                     && (!p || ((skipconst == p) || !strcmp("std", skipconst)))
  #elif !defined(G__OLDIMPLEMTATION1890)
                     && (!p || (skipconst == p))
  #endif
                     ) {
                    thisflag = 0x1;
                 }
                 // enclosing tag scope
                 if (G__isenclosingclass(G__newtype.parent_tagnum[i], env_tagnum)) {
                    thisflag = 0x2;
                 }
                 // template definition enclosing class scope
                 if (G__isenclosingclass(G__newtype.parent_tagnum[i], G__tmplt_def_tagnum)) {
                    thisflag = 0x4;
                 }
                 // baseclass tag scope
                 if (-1 != G__isanybase(G__newtype.parent_tagnum[i], env_tagnum, G__STATICRESOLUTION)) {
                    thisflag = 0x8;
                 }
                 // template definition base class scope
                 if (-1 != G__isanybase(G__newtype.parent_tagnum[i], G__tmplt_def_tagnum, G__STATICRESOLUTION)) {
                    thisflag = 0x10;
                 }
                 if (!thisflag && G__isenclosingclassbase(G__newtype.parent_tagnum[i], env_tagnum)) {
                    thisflag = 0x02;
                 }
                 if (!thisflag && G__isenclosingclassbase(G__newtype.parent_tagnum[i], G__tmplt_def_tagnum)) {
                    thisflag = 0x04;
                 }
                 // exact template definition scope
                 if ((G__tmplt_def_tagnum > -1) && (G__tmplt_def_tagnum == G__newtype.parent_tagnum[i])) {
                    thisflag = 0x20;
                 }
                 // exact tag scope
                 if ((env_tagnum > -1) && (env_tagnum == G__newtype.parent_tagnum[i])) {
                    thisflag = 0x40;
                 }
                 
                 if (thisflag && (thisflag >= matchflag)) {
                    matchflag = thisflag;
                    typenum = i;
                    G__var_type = G__newtype.type[i] + ispointer;
                 }
              }
           }
        } else {
           i = G__newtype.alltype;
        }
     } else {
        i = G__newtype.alltype;
     }      
     return typenum;
  }
  
  //______________________________________________________________________________
  //
  //  Functions in the C interface.
  //
  
  //______________________________________________________________________________
  int G__defined_typename(const char* type_name)
  {
     // Search already defined typedef names, -1 is returned if not found
     //
     // Note: This functions modifies G__var_type.
     //
     return G__defined_typename_noerror(type_name, 0);
  }
  
  //______________________________________________________________________________
  int G__search_typename(const char* typenamein, int typein, int tagnum, int reftype)
  {
     // Search typedef name, and if not found, allocate new entry if typein is not zero.
     int i, flag = 0, len;
     char ispointer = 0;
  
     G__FastAllocString type_name(typenamein);
     /* keep uniqueness for pointer to function typedefs */
  #ifndef G__OLDIMPLEMENTATION2191
     if ('1' == typein) G__make_uniqueP2Ftypedef(type_name);
  #else
     if ('Q' == typein) G__make_uniqueP2Ftypedef(type_name);
  #endif
  
     /* G__OLDIMPLEMENTATIONON620 should affect, but not implemented here */
     /* Doing exactly the same thing as G__defined_typename() */
     len = strlen(type_name);
     if (
        len &&
        type_name[len-1] == '*') {
        type_name[--len] = '\0';
        ispointer = 'A' - 'a';
     }
     const char *atom_tagname = type_name;
     if ( strstr(type_name,"(*)") == 0 && strstr(type_name,"::*)") == 0 ) {
        // Deal with potential scope in the name but only when not a function type
        char *p = (char*) G__find_last_scope_operator(type_name);
        if (p) {
           if (G__static_parent_tagnum != -1) {
              // humm something is wrong, we specify the parent in 2 different
              // ways.
           }
           atom_tagname = p+2;
           *p = '\0';
           int scope_tagnum = -1;
           if (p == type_name) {
              scope_tagnum = -1;  // global scope
           }
  #ifndef G__STD_NAMESPACE
           else if (!strcmp(type_name, "std") && G__ignore_stdnamespace) {
              scope_tagnum = -1;
           }
  #endif // G__STD_NAMESPACE
           else {
              // first try a typedef, so we don't trigger autoloading here:
              int scope_typenum = G__defined_typename_noerror(type_name, 1);
              if (scope_typenum != -1 && G__newtype.type[scope_typenum] == 'u')
                 scope_tagnum = G__newtype.tagnum[scope_typenum];
              else
                 scope_tagnum = G__defined_tagname(type_name, 0);
           }
           G__static_parent_tagnum = scope_tagnum;
           len = strlen(atom_tagname);
        }
     }
     
     NameMap::Range nameRange = G__newtype.namerange->Find(atom_tagname);
     if (nameRange) {
        for (i = nameRange.First();i <= nameRange.Last();i++) {
           if (len == G__newtype.hash[i] && strcmp(G__newtype.name[i], atom_tagname) == 0 &&
               (G__static_parent_tagnum == -1 ||
                G__newtype.parent_tagnum[i] == G__static_parent_tagnum)) {
              flag = 1;
              G__var_type = G__newtype.type[i] + ispointer ;
              break;
           }
        }
     } else {
        i = G__newtype.alltype;
     }
     /* Above is same as G__defined_typename() */
  
     /* allocate new type table entry */
     if (flag == 0 && typein) {
        // If we already have a type/class of the same name that is registered in G__struct as forward declared and/or autoload,
        // let's invalidate this entry.
  
        int store_def_tagnum = G__def_tagnum;
        int store_tagdefining = G__tagdefining;
        int store_tmplt_def_tagnum = G__tmplt_def_tagnum;
        G__def_tagnum = G__static_parent_tagnum;
        G__tagdefining = G__static_parent_tagnum;
        G__tmplt_def_tagnum = G__static_parent_tagnum;
        int alias = G__defined_tagname(type_name,4 | 0x1000); // We are looking for an exact match
        G__def_tagnum = store_def_tagnum;
        G__tagdefining = store_tagdefining;
        G__tmplt_def_tagnum = store_tmplt_def_tagnum;
  
        if (alias != -1 && G__struct.type[alias] == 'a') {
           char *old = G__struct.name[alias];
           G__struct.namerange->Remove(old, alias,G__struct.name);
           
           G__struct.name[alias] = (char*)malloc(strlen(old)+60);
           strcpy(G__struct.name[alias],"@@ ex autload entry remove by typedef declaration @@"); // Okay, we allocated enough space
           strcat(G__struct.name[alias],old); // Okay, we allocated enough space
           G__struct.type[alias] = 0;
           free(old);
        }
  
        if (G__newtype.alltype == G__MAXTYPEDEF) {
           G__fprinterr(G__serr,
                        "Limitation: Number of typedef exceed %d FILE:%s LINE:%d\nFatal error, exit program. Increase G__MAXTYPEDEF in G__ci.h and recompile %s\n"
                        , G__MAXTYPEDEF , G__ifile.name , G__ifile.line_number , G__nam);
           G__eof = 1;
           G__var_type = 'p';
           return(-1);
        }
        G__newtype.hash[G__newtype.alltype] = len;
        G__newtype.name[G__newtype.alltype] = (char*)malloc((size_t)(len + 1));
        strcpy(G__newtype.name[G__newtype.alltype], atom_tagname); // Okay, we allocated the right size
        G__newtype.namerange->Insert(G__newtype.name[G__newtype.alltype], G__newtype.alltype);
        G__newtype.nindex[G__newtype.alltype] = 0;
        G__newtype.parent_tagnum[G__newtype.alltype] = G__static_parent_tagnum;
        G__newtype.isconst[G__newtype.alltype] = G__static_isconst;
        G__newtype.type[G__newtype.alltype] = typein + ispointer;
        G__newtype.tagnum[G__newtype.alltype] = tagnum;
        G__newtype.globalcomp[G__newtype.alltype]
        = G__default_link ? G__globalcomp : G__NOLINK;
        G__newtype.reftype[G__newtype.alltype] = reftype;
        G__newtype.iscpplink[G__newtype.alltype] = G__NOLINK;
        G__newtype.comment[G__newtype.alltype].p.com = (char*)NULL;
        G__newtype.comment[G__newtype.alltype].filenum = -1;
  #ifdef G__TYPEDEFFPOS
        G__newtype.filenum[G__newtype.alltype] = G__ifile.filenum;
        G__newtype.linenum[G__newtype.alltype] = G__ifile.line_number;
  #endif
        ++G__newtype.alltype;
     }
     return(i);
  }
  
  //______________________________________________________________________________
  int G__search_typename2(const char* type_name, int typein, int tagnum, int reftype, int parent_tagnum)
  {
     int ret;
     G__static_parent_tagnum = parent_tagnum;
     if (-1 == G__static_parent_tagnum && G__def_struct_member &&
           'n' == G__struct.type[G__tagdefining]) {
        G__static_parent_tagnum = G__tagdefining;
     }
     G__static_isconst = reftype / 0x100;
     reftype = reftype % 0x100;
     ret = G__search_typename(type_name, typein, tagnum, reftype);
     G__static_parent_tagnum = -1;
     G__static_isconst = 0;
     G__setnewtype_settypeum(ret);
     return(ret);
  }
  
  } // extern "C"
  
  