compiler/libec: Parser improvements
[sdk] / compiler / libec / src / ast.ec
index ed68ff4..a758930 100644 (file)
@@ -1,7 +1,7 @@
 import "ecdefs"
 
 #define YYLTYPE Location
-#include "grammar.eh"
+#include "grammar.h"
 extern char * yytext;
 
 char * defaultNameSpace;
@@ -139,8 +139,9 @@ public TemplateParameter MkTypeTemplateParameter(Identifier identifier, Template
    if(identifier.string)
    {
       TemplateParameter param { type = TemplateParameterType::type, identifier = identifier, dataType = baseTplDatatype, defaultArgument = defaultArgument };
-      TemplatedType type { key = (uint)identifier.string, param = param };
-      curContext.templateTypes.Add((BTNode)type);
+      TemplatedType type { key = (uintptr)identifier.string, param = param };
+      if(!curContext.templateTypes.Add((BTNode)type))
+         delete type;
       return param;
    }
    return null;
@@ -212,7 +213,8 @@ public Expression MkExpIdentifier(Identifier id)
 
 public Expression MkExpDummy()
 {
-   return { type = dummyExp };
+   Expression exp { type = dummyExp };
+   return exp;
 }
 
 public Expression MkExpConstant(char * string)
@@ -225,19 +227,94 @@ Expression MkExpString(char * string)
    return { type = stringExp, string = CopyString(string) };
 }
 
-Map<String, Location> intlStrings { };
+// TODO: String is case sensitive..
+//       What should we do about it?
+/*public class CaseSensitiveString : String
+{
+   int OnCompare(CaseSensitiveString string2)
+   {
+      int result = 0;
+      if(this && string2)
+         result = strcmpi(this, string2);
+      else if(!this && string2)
+         result = 1;
+      else if(this && !string2)
+         result = -1;
+      return result;
+   }
+}*/
+
+public struct ContextStringPair
+{
+   String string, context;
+
+   // TODO: Should this be automated somehow?
+   void OnFree()
+   {
+      delete string;
+      delete context;
+   }
+
+   int OnCompare(ContextStringPair b)
+   {
+      int result;
+      result = (string && b.string) ? strcmp(string, b.string) :
+         (!string && b.string) ? 1 : (string && !b.string) ? -1 : 0;
+      if(result) return result;
+
+      result = (context && b.context) ? strcmp(context, b.context) :
+         (!context && b.context) ? 1 : (context && !b.context) ? -1 : 0;
+      // TODO: Support these
+      // result = CaseSensitiveString::OnCompare(string, b.string);
+      // result = ((CaseSensitiveString)string).OnCompare(b.string);
+      return result;
+   }
+};
+
+Map<ContextStringPair, List<Location> > intlStrings { };
 
-Expression MkExpIntlString(char * string)
+Expression MkExpIntlString(char * string, char * context)
 {
+   OldList * list = MkList();
    if(inCompiler)
    {
-      MapIterator<String, Location> it { map = intlStrings };
-      if(!it.Index(string, false))
+      ContextStringPair pair { };
+      List<Location> list;
+      int len = strlen(string);
+
+      pair.string = new byte[len-2+1]; memcpy(pair.string, string+1, len-2); pair.string[len-2] = '\0';
+      if(context) { len = strlen(context); pair.context = new byte[len-2+1]; memcpy(pair.context, context+1, len-2); pair.context[len-2] = '\0'; }
+
+      list = intlStrings[pair];
+      if(!list)
       {
-         intlStrings[string] = yylloc;
+         list = { };
+         intlStrings[pair] = list;
       }
+      else
+      {
+         delete pair.string;
+         delete pair.context;
+      }
+      list.Add(yylloc);
+   }
+   ListAdd(list, QMkExpId("__thisModule"));
+   ListAdd(list, MkExpString(string));
+   if(context)
+   {
+      int lenString = strlen(string), lenContext = strlen(context);
+      char * msgid = new char[lenString-2 + lenContext-2 + 4];
+      msgid[0] = '\"';
+      memcpy(msgid+1, context+1, lenContext-2);
+      msgid[1+lenContext-2] = 4; // EOT
+      memcpy(msgid+1+lenContext-2+1, string+1, lenString-2);
+      memcpy(msgid+1+lenContext-2+1+lenString-2, "\"", 2);
+      ListAdd(list, MkExpString(msgid));
+      delete msgid;
    }
-   return MkExpCall(QMkExpId("gettext"), MkListOne(MkExpString(string)));
+   else
+      ListAdd(list, QMkExpId("null"));
+   return MkExpCall(QMkExpId("GetTranslatedString"), list);
 }
 
 Expression MkExpOp(Expression exp1, int op, Expression exp2)
@@ -297,6 +374,11 @@ Expression MkExpTypeSize(TypeName typeName)
    return { type = typeSizeExp, typeName = typeName };
 }
 
+Expression MkExpTypeAlign(TypeName typeName)
+{
+   return { type = typeAlignExp, typeName = typeName };
+}
+
 Expression MkExpClassSize(Specifier _class)
 {
    return { type = classSizeExp, _class = _class };
@@ -352,9 +434,9 @@ Specifier MkSpecifierSubClass(Specifier _class)
    return { type = subClassSpecifier, _class = _class };
 }
 
-Specifier MkSpecifierExtended(char * name)
+Specifier MkSpecifierExtended(ExtDecl extDecl)
 {
-   return { type = extendedSpecifier, name = CopyString(name) };
+   return { type = extendedSpecifier, extDecl = extDecl /*name = CopyString(name)*/ };
 }
 
 Specifier MkEnum(Identifier id, OldList list)
@@ -375,13 +457,21 @@ Specifier MkEnum(Identifier id, OldList list)
 
       if(id)
       {
-         curContext.structSymbols.Add((BTNode)Symbol { string = CopyString(id.string), isStruct = true, type = type });
+         Symbol symbol { string = CopyString(id.string), isStruct = true, type = type };
          type.refCount++;
+         if(strstr(symbol.string, "::"))
+            curContext.hasNameSpace = true;
+         if(!curContext.structSymbols.Add((BTNode)symbol))
+            FreeSymbol(symbol);
       }
       for(e = list.first; e; e = e.next)
       {
-         (curContext.templateTypesOnly ? curContext.parent : curContext).symbols.Add((BTNode)Symbol { string = CopyString(e.id.string), type = type });
+         Symbol symbol { string = CopyString(e.id.string), type = type };
          type.refCount++;
+         if(strstr(symbol.string, "::"))
+            curContext.hasNameSpace = true;
+         if(!(curContext.templateTypesOnly ? curContext.parent : curContext).symbols.Add((BTNode)symbol))
+            FreeSymbol(symbol);
       }
       FreeType(type);
    }
@@ -397,8 +487,11 @@ Specifier MkStructOrUnion(SpecifierType type, Identifier id, OldList definitions
    if(definitions && id && !declMode)
    {
       OldList specs { };
+      Symbol symbol;
       specs.Add(spec);
-      curContext.structSymbols.Add((BTNode)Symbol { string = CopyString(id.string), type = ProcessType(specs, null), isStruct = true });
+      symbol = Symbol { string = CopyString(id.string), type = ProcessType(specs, null), isStruct = true };
+      if(!curContext.structSymbols.Add((BTNode)symbol))
+         FreeSymbol(symbol);
    }
    return spec;
 }
@@ -408,12 +501,37 @@ void AddStructDefinitions(Specifier spec, OldList definitions)
    spec.definitions = definitions;
    if(definitions && spec.id && !declMode)
    {
+      Symbol symbol;
       OldList specs { };
       specs.Add(spec);
-      curContext.parent.structSymbols.Add((BTNode)Symbol { string = CopyString(spec.id.string), type = ProcessType(specs, null), isStruct = true });
+      symbol = Symbol { string = CopyString(spec.id.string), type = ProcessType(specs, null), isStruct = true };
+      if(!curContext.parent.structSymbols.Add((BTNode)symbol))
+         FreeSymbol(symbol);
    }
 }
 
+Attribute MkAttribute(String attr, Expression exp)
+{
+   return { attr = attr, exp = exp };
+}
+
+Attrib MkAttrib(int type, OldList * attribs)
+{
+   return { type = type, attribs = attribs };
+}
+
+ExtDecl MkExtDeclString(String s)
+{
+   return { type = extDeclString, s = s };
+
+}
+
+ExtDecl MkExtDeclAttrib(Attrib attr)
+{
+   return { type = extDeclAttrib, attr = attr };
+}
+
+
 public Declarator MkDeclaratorIdentifier(Identifier id)
 {
    return { type = identifierDeclarator, identifier = id };
@@ -424,12 +542,12 @@ Declarator MkDeclaratorFunction(Declarator declarator, OldList parameters)
    return { type = functionDeclarator, declarator = declarator, function.parameters = parameters };
 }
 
-Declarator MkDeclaratorExtended(char * extended, Declarator declarator)
+Declarator MkDeclaratorExtended(ExtDecl extended, Declarator declarator)
 {
    return { type = extendedDeclarator, declarator = declarator, extended.extended = extended };
 }
 
-Declarator MkDeclaratorExtendedEnd(char * extended, Declarator declarator)
+Declarator MkDeclaratorExtendedEnd(ExtDecl extended, Declarator declarator)
 {
    return { type = extendedDeclaratorEnd, declarator = declarator, extended.extended = extended };
 }
@@ -493,6 +611,46 @@ public TypeName MkTypeName(OldList qualifiers, Declarator declarator)
    return { qualifiers = qualifiers, declarator = declarator };
 }
 
+public TypeName MkTypeNameGuessDecl(OldList qualifiers, Declarator declarator)
+{
+   TypeName typeName { qualifiers = qualifiers, declarator = declarator };
+   if(qualifiers != null)
+   {
+      bool gotType = false;
+      bool gotFullType = false;
+      Specifier spec;
+      for(spec = qualifiers.first; spec; spec = spec.next)
+      {
+         if(gotType && !declarator && ((spec.type == nameSpecifier && spec.name) || (spec.type == baseSpecifier && gotFullType)))
+         {
+            String s = null;
+            if(spec.type == nameSpecifier)
+            {
+               char * colon = RSearchString(spec.name, "::", strlen(spec.name), true, false);
+               s = colon ? colon + 2 : spec.name;
+            }
+            else if(spec.type == baseSpecifier)
+            {
+               if(spec.specifier == INT64) s = "int64";
+            }
+            if(s)
+            {
+               typeName.declarator = declarator = MkDeclaratorIdentifier(MkIdentifier(CopyString(s)));
+               qualifiers.Remove(spec);
+               FreeSpecifier(spec);
+            }
+         }
+         if(spec.type != extendedSpecifier)
+         {
+            if(spec.type != baseSpecifier || (spec.specifier != UNSIGNED && spec.specifier != SIGNED && spec.specifier != LONG))
+               gotFullType = true;
+            gotType = true;
+         }
+      }
+   }
+   return typeName;
+}
+
 public Identifier GetDeclId(Declarator decl)
 {
    while(decl && decl.type != identifierDeclarator)
@@ -542,7 +700,10 @@ Declaration MkDeclarationInst(Instantiation inst)
       type = MkClassTypeSymbol(inst._class.symbol);
    };
    symbol.idCode = symbol.id = curContext.nextID++;
-   (curContext.templateTypesOnly ? curContext.parent : curContext).symbols.Add((BTNode)symbol);
+   if(strstr(symbol.string, "::"))
+      curContext.hasNameSpace = true;
+   if(!(curContext.templateTypesOnly ? curContext.parent : curContext).symbols.Add((BTNode)symbol))
+      excludedSymbols->Add(symbol);
    decl.symbol = inst.symbol = symbol;
    return decl;
 }
@@ -584,7 +745,7 @@ Declaration MkDeclarationDefine(Identifier id, Expression exp)
    if(!eSystem_FindDefine(privateModule, id.string))
       eSystem_RegisterDefine(id.string, expString, privateModule, buildingECERECOMModule ? baseSystemAccess : publicAccess);
    else
-      Compiler_Warning("Redefinition of %s ignored\n", id.string);
+      Compiler_Warning($"Redefinition of %s ignored\n", id.string);
    return decl;
 }
 
@@ -595,6 +756,7 @@ Declaration MkDeclaration(OldList specifiers, OldList initDeclarators)
    
    if(specifiers != null)
    {
+      bool gotType = false;
       Specifier spec;
       for(spec = specifiers.first; spec; spec = spec.next)
       {
@@ -615,25 +777,40 @@ Declaration MkDeclaration(OldList specifiers, OldList initDeclarators)
                      };
                      type.id = type.idCode = curContext.nextID++;
 
-                     (curContext.templateTypesOnly ? curContext.parent : curContext).types.Add((BTNode)type);
+                     if(!(curContext.templateTypesOnly ? curContext.parent : curContext).types.Add((BTNode)type))
+                        excludedSymbols->Add(type);
                      decl.symbol = d.declarator.symbol = type;
                   }
                }
             }
             else if(spec.next)
             {
-               for(; spec; spec = spec.next)
+               //for(spec = spec.next; spec; spec = spec.next)
+               spec = specifiers.last;
                {
-                  if(spec.type == nameSpecifier && spec.name)
+                  if((spec.type == nameSpecifier && spec.name) || spec.type == baseSpecifier)
                   {
-                     Symbol type
+                     String s = null;
+                     if(spec.type == nameSpecifier)
                      {
-                        string = CopyString(spec.name);
-                        type = ProcessType(specifiers, null);
-                     };
-                     type.id = type.idCode = curContext.nextID++;
-                     (curContext.templateTypesOnly ? curContext.parent : curContext).types.Add((BTNode)type);
-                     decl.symbol = type;
+                        char * colon = RSearchString(spec.name, "::", strlen(spec.name), true, false);
+                        s = colon ? colon + 2 : spec.name;
+                     }
+                     else if(spec.type == baseSpecifier)
+                     {
+                        if(spec.specifier == INT64) s = "int64";
+                     }
+                     if(s)
+                     {
+                        Symbol type { string = CopyString(s), type = ProcessType(specifiers, null) };
+                        type.id = type.idCode = curContext.nextID++;
+                        decl.symbol = type;
+                        decl.declarators = initDeclarators = MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier(CopyString(s))), null));
+                        specifiers.Remove(spec);
+                        FreeSpecifier(spec);
+                        if(!(curContext.templateTypesOnly ? curContext.parent : curContext).types.Add((BTNode)type))
+                           excludedSymbols->Add(type);
+                     }
                   }
                }
             }
@@ -643,6 +820,30 @@ Declaration MkDeclaration(OldList specifiers, OldList initDeclarators)
          else if(spec.type == baseSpecifier && 
             (spec.specifier == STRUCT || spec.specifier == UNION))
             variable = false;
+         else
+         {
+            if(gotType && initDeclarators == null && !spec.next && ((spec.type == nameSpecifier && spec.name) || spec.type == baseSpecifier))
+            {
+               String s = null;
+               if(spec.type == nameSpecifier)
+               {
+                  char * colon = RSearchString(spec.name, "::", strlen(spec.name), true, false);
+                  s = colon ? colon + 2 : spec.name;
+               }
+               else if(spec.type == baseSpecifier)
+               {
+                  if(spec.specifier == INT64) s = "int64";
+               }
+               if(s)
+               {
+                  decl.declarators = initDeclarators = MkListOne(MkInitDeclarator(MkDeclaratorIdentifier(MkIdentifier(CopyString(s))), null));
+                  specifiers.Remove(spec);
+                  FreeSpecifier(spec);
+               }
+            }
+         }
+         if(spec.type != extendedSpecifier)
+            gotType = true;
       }
    }
    if(variable && initDeclarators)
@@ -683,44 +884,52 @@ Declaration MkDeclaration(OldList specifiers, OldList initDeclarators)
                   id.string = CopyString(name);
                }
                
-               symbol = Symbol { string = CopyString(id.string), type = ProcessType(specifiers, d.declarator) };
-               (curContext.templateTypesOnly ? curContext.parent : curContext).symbols.Add((BTNode)symbol);
-               // TODO: Add better support to count declarators
-               if(symbol.type && symbol.type.kind == arrayType && !symbol.type.arraySizeExp && d.initializer)
+               // Avoid memory leaks on duplicated symbols (BinaryTree::Add Would Fail)
+               symbol = (Symbol)(curContext.templateTypesOnly ? curContext.parent : curContext).symbols.FindString(id.string);
+               if(!symbol)
                {
-                  if(d.initializer.type == listInitializer)
-                  {
-                     char string[256];
-                     sprintf(string, "%d",d.initializer.list->count);
-                     symbol.type.arraySizeExp = MkExpConstant(string);
-                     symbol.type.freeExp = true;
-                  }
-                  else if(d.initializer.type == expInitializer && d.initializer.exp.type == stringExp && d.initializer.exp.string)
+                  symbol = Symbol { string = CopyString(id.string), type = ProcessType(specifiers, d.declarator) };
+                  if(strstr(symbol.string, "::"))
+                     curContext.hasNameSpace = true;
+                  if(!(curContext.templateTypesOnly ? curContext.parent : curContext).symbols.Add((BTNode)symbol))
+                     excludedSymbols->Add(symbol);
+                  // TODO: Add better support to count declarators
+                  if(symbol.type && symbol.type.kind == arrayType && !symbol.type.arraySizeExp && d.initializer)
                   {
-                     char string[256];
-                     int c, count = 0;
-                     char ch;
-                     bool escaped = false;
-                     char * s = d.initializer.exp.string;
-
-                     // MAKE MORE ACCURATE
-                     for(c = 1; (ch = s[c]); c++)
+                     if(d.initializer.type == listInitializer)
                      {
-                        if(ch == '\\' && !escaped)
-                           escaped = true;
-                        else
+                        char string[256];
+                        sprintf(string, "%d",d.initializer.list->count);
+                        symbol.type.arraySizeExp = MkExpConstant(string);
+                        symbol.type.freeExp = true;
+                     }
+                     else if(d.initializer.type == expInitializer && d.initializer.exp.type == stringExp && d.initializer.exp.string)
+                     {
+                        char string[256];
+                        int c, count = 0;
+                        char ch;
+                        bool escaped = false;
+                        char * s = d.initializer.exp.string;
+
+                        // MAKE MORE ACCURATE
+                        for(c = 1; (ch = s[c]); c++)
                         {
-                           count++;
-                           escaped = false;
+                           if(ch == '\\' && !escaped)
+                              escaped = true;
+                           else
+                           {
+                              count++;
+                              escaped = false;
+                           }
                         }
-                     }
 
-                     sprintf(string, "%d", count);
-                     symbol.type.arraySizeExp = MkExpConstant(string);
-                     symbol.type.freeExp = true;
+                        sprintf(string, "%d", count);
+                        symbol.type.arraySizeExp = MkExpConstant(string);
+                        symbol.type.freeExp = true;
+                     }
                   }
+                  symbol.id = symbol.idCode = curContext.nextID++;
                }
-               symbol.id = symbol.idCode = curContext.nextID++;
                decl.symbol = d.declarator.symbol = symbol;
             }
          }
@@ -737,7 +946,37 @@ Declaration MkDeclaration(OldList specifiers, OldList initDeclarators)
 
 Declaration MkStructDeclaration(OldList specifiers, OldList declarators, Specifier extStorage)
 {
-   return { type = structDeclaration, declarators = declarators, specifiers = specifiers, extStorage = extStorage, loc = yylloc };
+   Declaration decl { type = structDeclaration, declarators = declarators, specifiers = specifiers, extStorage = extStorage, loc = yylloc };
+   if(specifiers != null)
+   {
+      bool gotType = false;
+      Specifier spec;
+      for(spec = specifiers.first; spec; spec = spec.next)
+      {
+         if(gotType && declarators == null && ((spec.type == nameSpecifier && spec.name) || spec.type == baseSpecifier))
+         {
+            String s = null;
+            if(spec.type == nameSpecifier)
+            {
+               char * colon = RSearchString(spec.name, "::", strlen(spec.name), true, false);
+               s = colon ? colon + 2 : spec.name;
+            }
+            else if(spec.type == baseSpecifier)
+            {
+               if(spec.specifier == INT64) s = "int64";
+            }
+            if(s)
+            {
+               decl.declarators = declarators = MkListOne(MkDeclaratorIdentifier(MkIdentifier(CopyString(s))));
+               specifiers.Remove(spec);
+               FreeSpecifier(spec);
+            }
+         }
+         if(spec.type != extendedSpecifier)
+            gotType = true;
+      }
+   }
+   return decl;
 }
 
 Statement MkLabeledStmt(Identifier id, Statement statement)
@@ -851,7 +1090,8 @@ void ProcessFunctionBody(FunctionDefinition func, Statement body)
                if(!symbol && id)
                {
                   symbol = Symbol { string = CopyString(id.string), type = ProcessType(param.qualifiers, param.declarator), isParam = true };
-                  context.symbols.Add((BTNode)symbol);
+                  if(!context.symbols.Add((BTNode)symbol))
+                     excludedSymbols->Add(symbol);
 
                   // TODO: Fix this, the parameters' IDs should really be smaller...
                   symbol.id = context.nextID++;
@@ -893,7 +1133,10 @@ void ProcessFunctionBody(FunctionDefinition func, Statement body)
       }
       symbol = Symbol { string = CopyString(id.string), type = ProcessType(func.specifiers, declarator) };
       symbol.idCode = symbol.id = globalContext.nextID++;
-      globalContext.symbols.Add((BTNode)symbol);
+      if(strstr(symbol.string, "::"))
+         globalContext.hasNameSpace = true;
+      if(!globalContext.symbols.Add((BTNode)symbol))
+         excludedSymbols->Add(symbol);
       declarator.symbol = symbol;
    }
    else
@@ -902,7 +1145,10 @@ void ProcessFunctionBody(FunctionDefinition func, Statement body)
       excludedSymbols->Remove(declarator.symbol);
       delete symbol.string;
       symbol.string = CopyString(GetDeclId(declarator).string);
-      globalContext.symbols.Add((BTNode)symbol);
+      if(strstr(symbol.string, "::"))
+         globalContext.hasNameSpace = true;
+      if(!globalContext.symbols.Add((BTNode)symbol))
+         excludedSymbols->Add(symbol);
 
       if(!symbol.type)
          symbol.type = ProcessType(func.specifiers, declarator);
@@ -1204,7 +1450,8 @@ void ProcessClassFunctionBody(ClassFunction func, Statement body)
 
                   // TODO: Fix this, the parameters' IDs should really be smaller...
                   symbol.idCode = symbol.id = context.nextID++;
-                  context.symbols.Add((BTNode)symbol);
+                  if(!context.symbols.Add((BTNode)symbol))
+                     excludedSymbols->Add(symbol);
 
                   param.declarator.symbol = symbol;
                }
@@ -1320,7 +1567,7 @@ Instantiation MkInstantiationNamed(OldList specs, Expression exp, OldList member
          
       if(!spec)
       {
-         Compiler_Error("Expecting class specifier\n");
+         Compiler_Error($"Expecting class specifier\n");
          inst._class = MkSpecifierName /*MkClassName*/("");
          //exit(1);
          //return null;
@@ -1452,7 +1699,8 @@ Symbol _DeclClass(int symbolID, char * name)
          string = CopyString(name);
          idCode = symbolID, id = symbolID;
       };
-      globalContext.classes.Add((BTNode)symbol);
+      if(!globalContext.classes.Add((BTNode)symbol))
+         excludedSymbols->Add(symbol);
 
       {
          int start = 0, c;
@@ -1492,7 +1740,8 @@ void SetupBaseSpecs(Symbol symbol, OldList baseSpecs)
          for(copy = (TemplatedType)baseClass.ctx.templateTypes.first; copy; copy = (TemplatedType)copy.next)
          {
             TemplatedType type { key = copy.key, param = copy.param };
-            curContext.templateTypes.Add((BTNode)type);
+            if(!curContext.templateTypes.Add((BTNode)type))
+               delete type;
          }
       }
       else if(baseClass.registered)
@@ -1518,8 +1767,9 @@ void SetupBaseSpecs(Symbol symbol, OldList baseSpecs)
                         dataTypeString = p.dataTypeString /*, dataType = { specs, decl }*/
                      };
                   }
-                  type = TemplatedType { key = (uint)p.name, param = param };
-                  curContext.templateTypes.Add((BTNode)type);
+                  type = TemplatedType { key = (uintptr)p.name, param = param };
+                  if(!curContext.templateTypes.Add((BTNode)type))
+                     delete type;
                }
             }
          }
@@ -1531,6 +1781,27 @@ ClassDefinition MkClass(Symbol symbol, OldList baseSpecs, OldList definitions)
 {
    ClassDefinition classDef;
    SetupBaseSpecs(symbol, baseSpecs);
+   if(symbol.ctx)
+   {
+      ClassDefinition classDef = symbol.ctx.classDef;
+      if(classDef)
+      {
+         // This can occur if two instances of a class are defined...
+         // To avoid dangling 'parent' Contexts, we free the previous class definition
+         External external;
+         for(external = ast->first; external; external = external.next)
+         {
+            if(external.type == classExternal && external._class == classDef)
+            {
+               ast->Remove(external);
+               FreeExternal(external);
+               break;
+            }
+         }
+      }
+      FreeContext(symbol.ctx);
+      delete symbol.ctx;
+   }
    symbol.ctx = curContext;
    classDef = { symbol = symbol, _class = MkSpecifierName /*MkClassName*/(symbol.string), baseSpecs = baseSpecs, definitions = definitions, nameLoc = symbol.nameLoc };
    curContext.classDef = classDef;
@@ -1650,7 +1921,13 @@ Symbol FindType(Context ctx, char * name)
    Symbol type = null;
    if(curContext)
    {
+      //char output[8192];
       type = (Symbol)ctx.types.FindString(name);
+      /*if(!strcmp(name, "intptr_t") && !type)
+      {
+         ctx.types.Print(output, depthOrder);
+         puts(output);
+      }*/
       if(!type && ctx.parent)
          type = FindType(ctx.parent, name);
    }
@@ -1833,7 +2110,8 @@ public Symbol FindClass(char * name)
                cl.module = FindModule(_class.module);
             else
                cl.module = mainModule;
-            globalContext.classes.Add((BTNode)cl);
+            if(!globalContext.classes.Add((BTNode)cl))
+               excludedSymbols->Add(cl);
             if(strcmp(name, _class.name))
                cl.shortName = CopyString(_class.name);
          }
@@ -1857,7 +2135,8 @@ void CopyTypeInto(Type type, Type src)
       NamedLink member;
 
       type.members.Clear();
-      for(member = type.members.first; member; member = member.next)
+      // This must have been a mistake: member = **type**.members.first
+      for(member = src.members.first; member; member = member.next)
       {
          type.members.Add(NamedLink { name = CopyString(member.name), data = member.data });
       }
@@ -1913,13 +2192,12 @@ public Type ProcessType(OldList specs, Declarator decl)
             if(decl.structDecl.exp.type == constantExp)
                specType.bitFieldCount = strtoul(decl.structDecl.exp.constant, null, 0);
          }
-         if((decl.type == extendedDeclarator || decl.type == extendedDeclaratorEnd) && decl.extended.extended && 
-            (!strcmp(decl.extended.extended, "__declspec(dllexport)") || !strcmp(decl.extended.extended, "dllexport")))
+         if((decl.type == extendedDeclarator || decl.type == extendedDeclaratorEnd) && decl.extended.extended && decl.extended.extended.type == extDeclString &&
+            decl.extended.extended.s && (!strcmp(decl.extended.extended.s, "__declspec(dllexport)") || !strcmp(decl.extended.extended.s, "dllexport")))
          {
             dllExport = true;
          }
-         if((decl.type == extendedDeclarator || decl.type == extendedDeclaratorEnd) && decl.extended.extended && 
-            (strstr(decl.extended.extended, "__attribute__")))
+         if((decl.type == extendedDeclarator || decl.type == extendedDeclaratorEnd) && decl.extended.extended && decl.extended.extended.type == extDeclAttrib)
          {
             specType.keepCast = true;
          }
@@ -1935,16 +2213,16 @@ public Type ProcessType(OldList specs, Declarator decl)
             bool isLong = false;
             for(spec = specs.first; spec; spec = spec.next)
             {
-               if(spec.type == extendedSpecifier && (!strcmp(spec.name, "__declspec(dllexport)") || !strcmp(spec.name, "dllexport")))
+               if(spec.type == extendedSpecifier && spec.extDecl && spec.extDecl.type == extDeclString && spec.extDecl.s && (!strcmp(spec.extDecl.s, "__declspec(dllexport)") || !strcmp(spec.extDecl.s, "dllexport")))
                {
                   dllExport = true;
                }
-               if(spec.type == extendedSpecifier && strstr(spec.name, "__attribute__"))
+               if(spec.type == extendedSpecifier && spec.extDecl.type == extDeclAttrib)
                {
                   specType.keepCast = true;
                }
 
-               if(specType.kind == structType || specType.kind == unionType)
+               if(spec.specifier != CONST && (specType.kind == structType || specType.kind == unionType))
                {
                   FreeType(specType);
                   specType = { kind = intType, isSigned = true, refCount = 1 };
@@ -1992,20 +2270,40 @@ public Type ProcessType(OldList specs, Declarator decl)
                }
                else if(spec.type == nameSpecifier)
                {
-                  Symbol symbol = spec.name ? FindType(curContext, spec.name) : null;
-                  if(symbol && symbol.type)
+                  if(spec.name && (!strcmp(spec.name, "intptr") || !strcmp(spec.name, "uintptr")))
                   {
-                     CopyTypeInto(specType, symbol.type);
-                     specType.typeName = CopyString(symbol.type.name);
+                     specType.kind = intPtrType;
+                     if(!strcmp(spec.name, "uintptr"))
+                        specType.isSigned = false;
                   }
-                  else if(!isTypedef) // !specType.kind)    // TESTING THIS FOR enum / typedef problem
+                  else if(spec.name && (!strcmp(spec.name, "uintsize") || !strcmp(spec.name, "intsize")))
                   {
-                     // key.sym enum values need FindClass:
-                     specType._class = spec.name ? FindClass(spec.name) : null;
-                     // specType._class = spec.symbol; 
-                     specType.kind = classType;
-                     if(!specType._class)
-                        specType.kind = intType;
+                     specType.kind = intSizeType;
+                     if(!strcmp(spec.name, "uintsize"))
+                        specType.isSigned = false;
+                  }
+                  else
+                  {
+                     Symbol symbol = spec.name ? FindType(curContext, spec.name) : null;
+                     if(symbol && symbol.type)
+                     {
+                        // Free Type Contents:
+                        Type dummy { };
+                        *dummy = *specType;
+                        FreeType(dummy);
+
+                        CopyTypeInto(specType, symbol.type);
+                        specType.typeName = CopyString(symbol.type.name);
+                     }
+                     else if(!isTypedef) // !specType.kind)    // TESTING THIS FOR enum / typedef problem
+                     {
+                        // key.sym enum values need FindClass:
+                        specType._class = spec.name ? FindClass(spec.name) : null;
+                        // specType._class = spec.symbol; 
+                        specType.kind = classType;
+                        if(!specType._class)
+                           specType.kind = intType;
+                     }
                   }
                }
                else if(spec.type == enumSpecifier)
@@ -2020,7 +2318,9 @@ public Type ProcessType(OldList specs, Declarator decl)
                      int nextValue = 0;
                      for(e = spec.list->first; e; e = e.next)
                      {
-                        specType.members.Add(NamedItem { name = CopyString(e.id.string) });
+                        // TOFIX: NamedItem i { } causes cryptic error, bad .c!
+                        NamedLink i { name = CopyString(e.id.string) };
+                        specType.members.Add(i);
                         /*
                         if(e.exp && ComputeExpression(e.exp), e.exp.isConstant && e.exp.expType.kind == intType)
                            value.data = (void *) nextValue = strtol(e.exp.string, null, 0);
@@ -2096,9 +2396,10 @@ public Type ProcessType(OldList specs, Declarator decl)
                               NamedLink member;
 
                               specType.members.Clear();
-                              for(member = specType.members.first; member; member = member.next)
+                              for(member = symbol.type.members.first; member; member = member.next)
                               {
-                                 specType.members.Add(NamedLink { name = CopyString(member.name), data = member.data });
+                                 NamedLink item { name = CopyString(member.name), data = member.data };
+                                 specType.members.Add(item);
                               }
                            }
                            else if(symbol.type.kind == structType || symbol.type.kind == unionType)
@@ -2235,8 +2536,8 @@ public Type ProcessType(OldList specs, Declarator decl)
          // TESTING: Added extendedDeclarator here
          while(d && (d.type == bracketsDeclarator || d.type == extendedDeclarator || d.type == extendedDeclaratorEnd))
          {
-            if((d.type == extendedDeclarator || d.type == extendedDeclaratorEnd) && d.extended.extended && 
-               (!strcmp(d.extended.extended, "__declspec(dllexport)") || !strcmp(d.extended.extended, "dllexport")))
+            if((d.type == extendedDeclarator || d.type == extendedDeclaratorEnd) && d.extended.extended && d.extended.extended.type == extDeclString &&
+               d.extended.extended.s && (!strcmp(d.extended.extended.s, "__declspec(dllexport)") || !strcmp(d.extended.extended.s, "dllexport")))
             {
                dllExport = true;            
             }
@@ -2513,6 +2814,7 @@ public Type ProcessType(OldList specs, Declarator decl)
             *type = specType;
             delete type.name;
             type.name = decl ? CopyString(decl.identifier.string) : null;
+
          }   
       }
       delete specType;
@@ -2719,23 +3021,46 @@ Expression GetTemplateArgExp(TemplateParameter param, Class curClass, bool point
    return param.identifier ? GetTemplateArgExpByName(param.identifier.string, curClass, type) : null;
 }
 
+/*char * CreateMsgID(char * string, char * context)
+{
+   int lenString = strlen(string), lenContext = strlen(context);
+   char * msgid = new char[lenString + lenContext + 20];
+   memcpy(msgid, string, lenString);
+   memcpy(msgid+lenString, " [msgctxt: ", 11);
+   memcpy(msgid+lenString+11, context, lenContext);
+   memcpy(msgid+lenString+11+lenContext, "]", 2);
+   return msgid;
+}*/
+
 public void OutputIntlStrings()
 {
    if(intlStrings.count)
    {
       char * srcFile = GetSourceFile();
       char * objFile = GetOutputFile();
+      char srcFileFixed[MAX_LOCATION];
       char potFile[MAX_LOCATION];
       File f;
       ChangeExtension(objFile, "bowl", potFile);
       f = FileOpen(potFile, write);
       if(f)
       {
+         char * filePrefix = "";
+         if(!(srcFile[0] && (srcFile[1] == ':' || srcFile[0] == '/')))
+            filePrefix = "./"; //(GetRuntimePlatform() == win32) ? ".\\" : "./";
+         // GetSystemPathBuffer(srcFileFixed, srcFile);
+         GetSlashPathBuffer(srcFileFixed, srcFile);
          for(s : intlStrings)
          {
-            f.Printf("# %s %d\n", srcFile, s.start.line);
-            f.Printf("msgid %s\n", &s);
-            f.Printf("msgstr %s\n\n", &s);
+            // TOFIX: (#654) ContextStringPair * pair = &s;
+            ContextStringPair pair = &s;
+            for(l : s)
+               f.Printf("#: %s%s:%d\n", filePrefix, srcFileFixed, l.start.line);
+             // PoEdit now preserves and distinguish msgctxt
+            if(pair.context)
+               f.Printf("msgctxt \"%s\"\n", pair.context);
+            f.Printf("msgid \"%s\"\n", pair.string);
+            f.Printf("msgstr \"%s\"\n\n", pair.string);
          }
          delete f;
       }