compiler/i18n: Modified .bowl/.pot generation to always use '/' for paths, so as...
[sdk] / compiler / ecs / ecs.ec
index 41491af..1e5c755 100644 (file)
@@ -6,6 +6,9 @@ import "ecere"
 import "ec"
 #endif
 
+static define localeDir = "locale";
+static bool i18n;
+
 static Platform targetPlatform;
 
 static bool isConsole;
@@ -631,6 +634,14 @@ static void WriteMain(char * fileName)
          }
       }
 
+      for(defModule = ::modules.first; defModule; defModule = defModule.next)
+         if(defModule.globalInstance)
+         {
+            if(!strcmp(defModule.name, "i18n"))
+               f.Printf("   __ecereCreateModuleInstances_i18n();\n");
+         }
+      if(i18n)
+         f.Printf("      LoadTranslatedStrings(module, \"%s\");\n", projectName);
       if(isDynamicLibrary)
       {
          //f.Printf("   module._vTbl[10](module);\n");
@@ -657,6 +668,7 @@ static void WriteMain(char * fileName)
             if(defModule.globalInstance)
             {
                char moduleName[1024];
+               if(!strcmp(defModule.name, "i18n")) continue;
                strcpy(moduleName, defModule.name);
                ChangeCh(moduleName, ' ', '_');
                ChangeCh(moduleName, '-', '_');
@@ -703,20 +715,28 @@ static void WriteMain(char * fileName)
          f.Puts("   {\n");
       }
       // Then check if there's any global instances to destroy
-      if(::modules.count)
       {
-         for(defModule = ::modules.first; defModule; defModule = defModule.next)
-            if(defModule.globalInstance)
-            {
-               char moduleName[1024];
-               strcpy(moduleName, defModule.name);
-               ChangeCh(moduleName, ' ', '_');
-               ChangeCh(moduleName, '-', '_');
-               ChangeCh(moduleName, '.', '_');
-               f.Printf("   __ecereDestroyModuleInstances_%s();\n", moduleName);
-            }
+         bool destroyI18n = false;
+         if(::modules.count)
+         {
+            for(defModule = ::modules.first; defModule; defModule = defModule.next)
+               if(defModule.globalInstance)
+               {
+                  char moduleName[1024];
+                  if(!strcmp(defModule.name, "i18n")) { destroyI18n = true; continue; }
+                  strcpy(moduleName, defModule.name);
+                  ChangeCh(moduleName, ' ', '_');
+                  ChangeCh(moduleName, '-', '_');
+                  ChangeCh(moduleName, '.', '_');
+                  f.Printf("   __ecereDestroyModuleInstances_%s();\n", moduleName);
+               }
 
-         f.Printf("\n");
+            f.Printf("\n");
+         }
+         if(i18n)
+            f.Printf("   UnloadTranslatedStrings(__currentModule);\n");
+         if(destroyI18n)
+            f.Printf("   __ecereDestroyModuleInstances_i18n();\n");
       }
       if(isDynamicLibrary)
       {
@@ -1094,7 +1114,7 @@ static void BindDCOMClient()
                         f.Printf(" = 0");
                      f.Printf(";\n\n");
                   }
-                  //f.Printf("      incref this;\n");
+                  f.Printf("      incref this;\n");
                   for(param = method.dataType.params.first; param; param = param.next)
                   {
                      char type[1024] = "";
@@ -1155,7 +1175,7 @@ static void BindDCOMClient()
                   }
                   f.Printf("      }\n");
                   f.Printf("      __ecereBuffer.Free();\n");
-                  //f.Printf("      delete this;\n");
+                  f.Printf("      delete this;\n");
                   if(method.dataType.returnType.kind != voidType)
                   {
                      f.Printf("      return __ecereResult;\n");
@@ -1193,6 +1213,7 @@ static void BindDCOMClient()
 
 static void BindDCOMServer()
 {
+   bool mutexDeclared = false;
    Class _class;
    for(_class = privateModule.classes.first; _class; _class = _class.next)
    {
@@ -1235,6 +1256,8 @@ static void BindDCOMServer()
             // f.Printf("\n");
             f.Printf("   virtual void CallMethod(uint __ecereMethodID, SerialBuffer __ecereBuffer)\n");
             f.Printf("   {\n");
+            f.Printf("      %s inst = (%s)instance;\n", _class.fullName, _class.fullName);
+            f.Printf("      incref inst;\n");
             f.Printf("      switch(__ecereMethodID)\n");
             f.Printf("      {\n");
 
@@ -1391,6 +1414,7 @@ static void BindDCOMServer()
                }
             }
             f.Printf("      }\n");
+            f.Printf("      delete inst;\n");
             f.Printf("   }\n");
 
             // *** VIRTUAL FUNCTIONS BINDINGS ***
@@ -1404,6 +1428,20 @@ static void BindDCOMServer()
                      break;
                if(method)
                {
+                  if(!mutexDeclared)
+                  {
+                     DeclareClass(FindClass("ecere::sys::Mutex"), "__ecereClass___ecereNameSpace__ecere__sys__Mutex");
+                     DeclareMethod(
+                        eClass_FindMethod(
+                           eSystem_FindClass(privateModule, "ecere::sys::Mutex"), "Wait", privateModule), 
+                              "__ecereMethod___ecereNameSpace__ecere__sys__Mutex_Wait");
+                     DeclareMethod(
+                        eClass_FindMethod(
+                           eSystem_FindClass(privateModule, "ecere::sys::Mutex"), "Release", privateModule), 
+                              "__ecereMethod___ecereNameSpace__ecere__sys__Mutex_Release");
+                     mutexDeclared = true;
+                  }
+
                   f.Printf("\n");
                   if(!method.dataType)
                      method.dataType = ProcessTypeString(method.dataTypeString, false);
@@ -1454,6 +1492,10 @@ static void BindDCOMServer()
                               f.Printf(" = 0");
                            f.Printf(";\n\n");
                         }
+                        
+                        f.Printf("      incref __ecereObject;\n");
+                        f.Printf("      __ecereMethod___ecereNameSpace__ecere__sys__Mutex_Wait(__ecereObject.mutex);\n");
+
                         //f.Printf("      incref this;\n");
                         for(param = method.dataType.params.first; param; param = param.next)
                         {
@@ -1477,18 +1519,34 @@ static void BindDCOMServer()
                            if(param.kind == classType && !strcmp(param._class.string, "String"))
                            {
                               DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
-                              f.Printf("      __ecereObject.virtualsBuffer.Serialize((StaticString)%s);\n", param.name);
+                              f.Printf("      __ecereObject.argsBuffer.Serialize((StaticString)%s);\n", param.name);
                            }
                            else
-                              f.Printf("      __ecereObject.virtualsBuffer.Serialize(%s);\n", param.name);
+                              f.Printf("      __ecereObject.argsBuffer.Serialize(%s);\n", param.name);
                         }
 
                         DeclareMethod(
                            eClass_FindMethod(
                               eSystem_FindClass(privateModule, "ecere::net::DCOMServerObject"), "CallVirtualMethod", privateModule), 
-                           "__ecereMethod___ecereNameSpace__ecere__net__DCOMServerObject_CallVirutalMethod");
+                           "__ecereMethod___ecereNameSpace__ecere__net__DCOMServerObject_CallVirtualMethod");
 
-                        f.Printf("      if(__ecereObject.CallVirtualMethod(%d))\n", vid - _class.base.vTblSize);
+                        // Check if this method needs to return anything (hasReturnValue)
+                        {
+                           bool hasReturnValue = method.dataType.returnType.kind != voidType;
+                           if(!hasReturnValue)
+                           {
+                              for(param = method.dataType.params.first; param; param = param.next)
+                              {
+                                 if(param.kind == classType && ((param._class && param._class.registered && param._class.registered.type == structClass) || !strcmp(param._class.string, "String")) && !param.constant)
+                                 {
+                                    hasReturnValue = true;
+                                    break;
+                                 }
+                              }
+                           }
+                           f.Printf("      if(__ecereObject.CallVirtualMethod(%d, %s))\n", vid - _class.base.vTblSize,
+                              hasReturnValue ? "true" : "false");
+                        }
                         f.Printf("      {\n");
                         for(param = method.dataType.params.first; param; param = param.next)
                         {
@@ -1497,10 +1555,10 @@ static void BindDCOMServer()
                               if(!strcmp(param._class.string, "String"))
                               {
                                  DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
-                                 f.Printf("         __ecereObject.virtualsBuffer.Unserialize((StaticString)%s);\n", param.name);
+                                 f.Printf("         __ecereObject.returnBuffer.Unserialize((StaticString)%s);\n", param.name);
                               }
                               else
-                                 f.Printf("         __ecereObject.virtualsBuffer.Unserialize(%s);\n", param.name);
+                                 f.Printf("         __ecereObject.returnBuffer.Unserialize(%s);\n", param.name);
                            }
                         }
                         if(method.dataType.returnType.kind != voidType)
@@ -1508,10 +1566,10 @@ static void BindDCOMServer()
                            if(method.dataType.returnType.kind == classType && !strcmp(method.dataType.returnType._class.string, "String"))
                            {
                               DeclareClass(FindClass("StaticString"), "__ecereClass_StaticString");
-                              f.Printf("         __ecereObject.virtualsBuffer.Unserialize((StaticString)__ecereResult);\n");
+                              f.Printf("         __ecereObject.returnBuffer.Unserialize((StaticString)__ecereResult);\n");
                            }
                            else
-                              f.Printf("         __ecereObject.virtualsBuffer.Unserialize(__ecereResult);\n");
+                              f.Printf("         __ecereObject.returnBuffer.Unserialize(__ecereResult);\n");
                         }
                         f.Printf("      }\n");
                         f.Printf("      else\n");
@@ -1523,8 +1581,10 @@ static void BindDCOMServer()
                         }
                         f.Printf(");\n");
 
-                        f.Printf("      __ecereObject.virtualsBuffer.Free();\n");
+                        f.Printf("      __ecereObject.returnBuffer.Free();\n");
+                        f.Printf("      __ecereMethod___ecereNameSpace__ecere__sys__Mutex_Release(__ecereObject.mutex);\n");
                         //f.Printf("      delete this;\n");
+                        f.Printf("      delete __ecereObject;\n");
                         if(method.dataType.returnType.kind != voidType)
                         {
                            f.Printf("      return __ecereResult;\n");
@@ -1641,7 +1701,7 @@ class SymbolgenApp : Application
          valid = false;
      
       if(!valid)
-         printf("Syntax:\n   ecs [-t <target platform>] <input>[, <input>]* -o <output>\n");
+         printf($"Syntax:\n   ecs [-t <target platform>] <input>[, <input>]* -o <output>\n");
       else
       {
          int c;
@@ -1667,6 +1727,12 @@ class SymbolgenApp : Application
 
          //if(!strcmp(ext, "c"))
          {
+            String symbolsDir = GetSymbolsDir();
+            // Only generating .pot files when building from release.* directory for now
+            bool outputPot = symbolsDir && SearchString(symbolsDir, 0, "release.", false, false);
+            Map<ContextStringPair, List<String> > intlStrings { };
+            MapIterator<ContextStringPair, List<String>> it { map = intlStrings };
+
             for(c = 1; c<argc; c++)
             {
                char * file = argv[c];
@@ -1684,6 +1750,7 @@ class SymbolgenApp : Application
                }
             }
 
+            // What is this supposed to do?
             for(c = 1; c<argc; c++)
             {
                char * file = argv[c];
@@ -1699,6 +1766,7 @@ class SymbolgenApp : Application
                char * file = argv[c];
                if(file[0] == '-')
                {
+                  // Don't even know what it does here?
                   if(!strcmp(file, "-c"))
                      c++;
                }
@@ -1747,6 +1815,77 @@ class SymbolgenApp : Application
                         module.globalInstance = LoadSymbols(file, normalImport, false);
                         CheckDataRedefinitions();
                      }
+
+                     // I18n code
+                     {
+                        File f;
+                        ChangeExtension(file, "bowl", fileName);
+                        f = FileOpen(fileName, read);
+                        if(f)
+                        {
+                           static char line[65536];
+                           List<String> comments { };
+                           String msgid = null, msgstr = null, msgctxt = null;
+                           while(!f.Eof())
+                           {
+                              if(f.GetLine(line, sizeof(line)))
+                              {
+                                 int len;
+                                 TrimLSpaces(line, line);
+                                 if(line[0] == '#')
+                                 {
+                                    comments.Add(CopyString(line));
+                                 }
+                                 else if(strstr(line, "msgid \"") == line)
+                                 {
+                                    delete msgid;
+                                    msgid = CopyString(line + 7);
+                                    len = strlen(msgid);
+                                    if(len) msgid[len-1] = 0;
+                                 }
+                                 else if(strstr(line, "msgctxt \"") == line)
+                                 {
+                                    delete msgctxt;
+                                    msgctxt = CopyString(line + 9);
+                                    len = strlen(msgctxt);
+                                    if(len) msgctxt[len-1] = 0;
+                                 }
+                                 else if(strstr(line, "msgstr \"") == line)
+                                 {
+                                    delete msgstr;
+                                    msgstr = CopyString(line + 8);
+                                    len = strlen(msgstr);
+                                    if(len) msgstr[len-1] = 0;
+                                 }
+
+                                 if(msgid && msgstr)
+                                 {
+                                    ContextStringPair pair { msgid, msgctxt };
+                                    i18n = true;
+                                    if(!it.Index(pair, false))
+                                    {
+                                       msgid = null; msgctxt = null;
+                                       intlStrings[pair] = comments;
+                                       comments = { };
+                                    }
+                                    else
+                                    {
+                                       for(s : comments)
+                                          it.data.Add(s);
+                                       comments.RemoveAll();
+                                    }
+
+                                    delete msgid;
+                                    delete msgctxt;
+                                    delete msgstr;
+                                 }
+                              }
+                           }
+                           comments.Free();
+                           delete comments;
+                           delete f;
+                        }
+                     }
                   }
                }
             }
@@ -1768,6 +1907,57 @@ class SymbolgenApp : Application
                thisAppClass = SearchAppClass_Module(privateModule);
             }
             WriteMain(output);
+
+            if(outputPot && intlStrings.count)
+            {
+               File potFile;
+               char potFileName[MAX_LOCATION];
+               //strcpy(potFileName, output);
+               //StripExtension(potFileName);
+               strcpy(potFileName, "locale");
+               MakeDir(potFileName);
+               PathCat(potFileName, projectName);
+               ChangeExtension(potFileName, "pot", potFileName);
+               potFile = FileOpen(potFileName, write);
+               if(potFile)
+               {
+                  // Write header:
+                  potFile.Puts("msgid \"\"\n");
+                  potFile.Puts("msgstr \"\"\n");
+                  potFile.Puts("\"Project-Id-Version: \\n\"\n");
+                  potFile.Puts("\"POT-Creation-Date: \\n\"\n");
+                  potFile.Puts("\"PO-Revision-Date: \\n\"\n");
+                  potFile.Puts("\"Last-Translator: \\n\"\n");
+                  potFile.Puts("\"Language-Team: \\n\"\n");
+                  potFile.Puts("\"MIME-Version: 1.0\\n\"\n");
+                  potFile.Puts("\"Content-Type: text/plain; charset=iso-8859-1\\n\"\n");
+                  potFile.Puts("\"Content-Transfer-Encoding: 8bit\\n\"\n");
+                  potFile.Puts("\"X-Poedit-Basepath: ../\\n\"\n");
+                  potFile.Puts("\n");
+
+                  for(i : intlStrings)
+                  {
+                     ContextStringPair pair = &i;
+                     List<String> comments = i;
+                     for(s : comments)
+                     {
+                        potFile.Printf(s);
+                        potFile.Puts("\n");
+                     }
+
+                     if(pair.context)
+                     {
+                        potFile.Puts("msgctxt \""); potFile.Puts(pair.context); potFile.Puts("\"\n");
+                     }
+                     potFile.Puts("msgid \""); potFile.Puts(pair.string); potFile.Puts("\"\n");
+                     potFile.Puts("msgstr \""); potFile.Puts(pair.string); potFile.Puts("\"\n");
+                     potFile.Puts("\n");
+                  }
+                  intlStrings.Free();
+                  delete intlStrings;
+                  delete potFile;
+               }
+            }
          }
 
          FreeContext(theGlobalContext);