瀏覽代碼

+ implemented support for codepage aware compiler messages. It can be enabled
per platform (currently only enabled for win32 and win64). Enabling it forces
code page conversion from the codepage of the .msg file to CP_ACP, before
writing the message to the console. Not enabling it keeps the previous
behaviour of not doing any kind of code page conversion for messages. This
feature should be tested and enabled per platform, because it requires code
page conversion support in the rtl (so it may require adding the appropriate
extra units, such as fpwidestring). When this feature is enabled for all
platforms, we can start keeping only one .msg file per language, because
having extra .msg files for different encodings for the same language becomes
redundant, since the compiler can do code page conversion to whatever code
page the console uses.

git-svn-id: trunk@36450 -

nickysn 8 年之前
父節點
當前提交
a34f531661
共有 5 個文件被更改,包括 46 次插入26 次删除
  1. 22 16
      compiler/cmsgs.pas
  2. 1 1
      compiler/compiler.pas
  3. 8 0
      compiler/fpcdefs.inc
  4. 9 3
      compiler/options.pas
  5. 6 6
      compiler/verbose.pas

+ 22 - 16
compiler/cmsgs.pas

@@ -53,19 +53,19 @@ type
     msgidx      : array[1..maxmsgidxparts] of PArrayOfPChar;
     msgidxmax   : array[1..maxmsgidxparts] of longint;
     msgstates   : array[1..maxmsgidxparts] of PArrayOfState;
+    msgcodepage : TSystemCodePage;
     { set if changes with $WARN need to be cleared at next module change }
     has_local_changes : boolean;
     constructor Init(n:longint;const idxmax:array of longint);
     destructor  Done;
-    function  LoadIntern(p:pointer;n:longint):boolean;
+    function  LoadIntern(p:pointer;n:longint;cp:TSystemCodePage):boolean;
     function  LoadExtern(const fn:string):boolean;
     procedure ClearIdx;
     procedure ResetStates;
     procedure CreateIdx;
-    function  GetPChar(nr:longint):pchar;
     { function  ClearVerbosity(nr:longint):boolean; not used anymore }
     function  SetVerbosity(nr:longint;newstate:tmsgstate):boolean;
-    function  Get(nr:longint;const args:array of TMsgStr):ansistring;
+    function  Get(nr:longint;const args:array of TMsgStr):TMsgStr;
   end;
 
 { this will read a line until #10 or #0 and also increase p }
@@ -79,7 +79,7 @@ uses
   cutils;
 
 
-function MsgReplace(const s:TMsgStr;const args:array of TMsgStr):ansistring;
+function MsgReplace(const s:TMsgStr;const args:array of TMsgStr):TMsgStr;
 var
   last,
   i  : longint;
@@ -117,6 +117,7 @@ begin
   has_local_changes:=false;
   msgsize:=0;
   msgparts:=n;
+  msgcodepage:=CP_ACP;
   if n<>high(idxmax)+1 then
    fail;
   for i:=1 to n do
@@ -154,8 +155,9 @@ begin
 end;
 
 
-function TMessage.LoadIntern(p:pointer;n:longint):boolean;
+function TMessage.LoadIntern(p:pointer;n:longint;cp:TSystemCodePage):boolean;
 begin
+  msgcodepage:=cp;
   msgtxt:=pchar(p);
   msgsize:=n;
   msgallocsize:=0;
@@ -185,6 +187,7 @@ var
 
 begin
   LoadExtern:=false;
+  msgcodepage:=CP_ACP;
   getmem(buf,bufsize);
   { Read the message file }
   assign(f,fn);
@@ -240,6 +243,10 @@ begin
             end
            else
             err('no = found');
+         end
+        else if (Length(s)>11) and (Copy(s,1,11)='# CodePage ') then
+         begin
+           msgcodepage:=StrToInt(Copy(s,12,Length(s)-11));
          end;
       end;
    end;
@@ -398,15 +405,6 @@ begin
 end;
 
 
-function TMessage.GetPChar(nr:longint):pchar;
-begin
-  if (nr div 1000 < msgparts) and
-     (nr mod 1000 <  msgidxmax[nr div 1000]) then
-    GetPChar:=msgidx[nr div 1000]^[nr mod 1000]
-  else
-    GetPChar:='';
-end;
-
 function TMessage.SetVerbosity(nr:longint;newstate:tmsgstate):boolean;
 var
   i: longint;
@@ -438,9 +436,10 @@ begin
 end;
 }
 
-function TMessage.Get(nr:longint;const args:array of TMsgStr):ansistring;
+function TMessage.Get(nr:longint;const args:array of TMsgStr):TMsgStr;
 var
   hp : pchar;
+  s: TMsgStr;
 begin
   if (nr div 1000 < msgparts) and
      (nr mod 1000 <  msgidxmax[nr div 1000]) then
@@ -450,7 +449,14 @@ begin
   if hp=nil then
     Get:='msg nr '+tostr(nr)
   else
-    Get:=MsgReplace(system.strpas(hp),args);
+    begin
+      s:=sysutils.StrPas(hp);
+{$ifdef cpawaremessages}
+      SetCodePage(RawByteString(s),msgcodepage,False);
+      SetCodePage(RawByteString(s),CP_ACP,True);
+{$endif cpawaremessages}
+      Get:=MsgReplace(s,args);
+    end;
 end;
 
 procedure TMessage.ResetStates;

+ 1 - 1
compiler/compiler.pas

@@ -284,7 +284,7 @@ begin
             totaltime:=trunc(totaltime) + 1;
           timestr:=tostr(trunc(totaltime))+'.'+tostr(round(frac(totaltime)*10));
           if status.codesize<>aword(-1) then
-            linkstr:=', '+tostr(status.codesize)+' ' +strpas(MessagePChar(general_text_bytes_code))+', '+tostr(status.datasize)+' '+strpas(MessagePChar(general_text_bytes_data))
+            linkstr:=', '+tostr(status.codesize)+' ' +MessageStr(general_text_bytes_code)+', '+tostr(status.datasize)+' '+MessageStr(general_text_bytes_data)
           else
             linkstr:='';
           Message3(general_i_abslines_compiled,tostr(status.compiledlines),timestr,linkstr);

+ 8 - 0
compiler/fpcdefs.inc

@@ -19,6 +19,14 @@
   exceptions in the constructors }
 {$IMPLICITEXCEPTIONS OFF}
 
+{ This define enables codepage-aware compiler messages handling. Turning it on
+  forces code page conversion from the codepage, specified in the .msg file to
+  CP_ACP, before printing the message to the console. Enable this for host
+  platforms, that have code page conversion support in their RTL. }
+{$if defined(win32) or defined(win64)}
+  {$define cpawaremessages}
+{$endif}
+
 { Inline small functions, but not when EXTDEBUG is used }
 {$ifndef EXTDEBUG}
   {$define USEINLINE}

+ 9 - 3
compiler/options.pas

@@ -188,11 +188,13 @@ end;
 
 procedure Toption.WriteLogo;
 var
+  msg : TMsgStr;
   p : pchar;
 begin
   if not LogoWritten then
     begin
-      p:=MessagePchar(option_logo);
+      msg:=MessageStr(option_logo);
+      p:=pchar(msg);
       while assigned(p) do
         Comment(V_Normal,GetMsgLine(p));
       LogoWritten:= true;
@@ -202,6 +204,7 @@ end;
 
 procedure Toption.WriteInfo (More: string);
 var
+  msg_str: TMsgStr;
   p : pchar;
   hs,hs1,hs3,s : TCmdStr;
   J: longint;
@@ -548,7 +551,8 @@ const
 begin
   if More = '' then
    begin
-    p:=MessagePchar(option_info);
+    msg_str:=MessageStr(option_info);
+    p:=pchar(msg_str);
     while assigned(p) do
      begin
       s:=GetMsgLine(p);
@@ -626,6 +630,7 @@ var
   HelpLine,
   s     : string;
   p     : pchar;
+  msg_str: TMsgStr;
 begin
   WriteLogo;
   Lines:=4;
@@ -634,7 +639,8 @@ begin
   else
    Message1(option_usage,FixFileName(system.paramstr(0)));
   lastident:=0;
-  p:=MessagePChar(option_help_pages);
+  msg_str:=MessageStr(option_help_pages);
+  p:=pchar(msg_str);
   while assigned(p) do
    begin
    { get a line and reset }

+ 6 - 6
compiler/verbose.pas

@@ -91,7 +91,7 @@ interface
     procedure GenerateError;
     procedure Internalerror(i:longint);{$ifndef VER2_6}noreturn;{$endif VER2_6}
     procedure Comment(l:longint;s:ansistring);
-    function  MessagePchar(w:longint):pchar;
+    function  MessageStr(w:longint):TMsgStr;
     procedure Message(w:longint;onqueue:tmsgqueueevent=nil);
     procedure Message1(w:longint;const s1:TMsgStr;onqueue:tmsgqueueevent=nil);
     procedure Message2(w:longint;const s1,s2:TMsgStr;onqueue:tmsgqueueevent=nil);
@@ -404,7 +404,7 @@ implementation
         { reload the internal messages if not already loaded }
 {$ifndef EXTERN_MSG}
         if not msg^.msgintern then
-         msg^.LoadIntern(@msgtxt,msgtxtsize);
+         msg^.LoadIntern(@msgtxt,msgtxtsize,msgtxt_codepage);
 {$endif}
         if not msg^.LoadExtern(fn) then
          begin
@@ -412,7 +412,7 @@ implementation
            writeln('Fatal: Cannot find error message file.');
            halt(3);
 {$else}
-           msg^.LoadIntern(@msgtxt,msgtxtsize);
+           msg^.LoadIntern(@msgtxt,msgtxtsize,msgtxt_codepage);
 {$endif}
          end;
         { reload the prefixes using the new messages }
@@ -756,10 +756,10 @@ implementation
       end;
 
 
-    function  MessagePchar(w:longint):pchar;
+    function  MessageStr(w:longint):TMsgStr;
       begin
         MaybeLoadMessageFile;
-        MessagePchar:=msg^.GetPchar(w)
+        MessageStr:=msg^.Get(w,[]);
       end;
 
 
@@ -987,7 +987,7 @@ implementation
            halt(3);
          end;
 {$ifndef EXTERN_MSG}
-        msg^.LoadIntern(@msgtxt,msgtxtsize);
+        msg^.LoadIntern(@msgtxt,msgtxtsize,msgtxt_codepage);
 {$else EXTERN_MSG}
         LoadMsgFile(exepath+'errore.msg');
 {$endif EXTERN_MSG}