Browse Source

* fixed unwanted disabling of a codepage set via -FcXXX/{$codepage XXX}
when {$modeswitch systemcodepage} gets disabled without having been
enabled first (such as when initially setting the syntax mode)
(mantis #28718)

git-svn-id: trunk@31831 -

Jonas Maebe 9 years ago
parent
commit
2cf8e50771

+ 4 - 0
.gitattributes

@@ -14740,6 +14740,10 @@ tests/webtbs/tw28593.pp svneol=native#text/plain
 tests/webtbs/tw28632.pp -text svneol=native#text/plain
 tests/webtbs/tw2865.pp svneol=native#text/plain
 tests/webtbs/tw28650.pp svneol=native#text/pascal
+tests/webtbs/tw28718a.pp svneol=native#text/plain
+tests/webtbs/tw28718b.pp svneol=native#text/plain
+tests/webtbs/tw28718c.pp svneol=native#text/plain
+tests/webtbs/tw28718d.pp svneol=native#text/plain
 tests/webtbs/tw2876.pp svneol=native#text/plain
 tests/webtbs/tw2883.pp svneol=native#text/plain
 tests/webtbs/tw2885.pp svneol=native#text/plain

+ 2 - 1
compiler/globtype.pas

@@ -160,7 +160,8 @@ interface
          cs_support_c_operators,
          { generation }
          cs_profile,cs_debuginfo,cs_compilesystem,
-         cs_lineinfo,cs_implicit_exceptions,cs_explicit_codepage,
+         cs_lineinfo,cs_implicit_exceptions,
+         cs_explicit_codepage,cs_system_codepage,
          { linking }
          cs_create_smart,cs_create_dynamic,cs_create_pic,
          { browser switches are back }

+ 4 - 0
compiler/options.pas

@@ -1456,6 +1456,10 @@ begin
                    autoloadunits:=more;
                  'c' :
                    begin
+                     { if we first specify that the system code page should be
+                       used and then explicitly specify a code page, unset the
+                       flag that we're using the system code page again }
+                     SetCompileModeSwitch('SYSTEMCODEPAGE-',true);
                      if (upper(more)='UTF8') or (upper(more)='UTF-8') then
                        init_settings.sourcecodepage:=CP_UTF8
                      else if not(cpavailable(more)) then

+ 3 - 0
compiler/scandir.pas

@@ -1654,6 +1654,9 @@ unit scandir;
               Message1(option_code_page_not_available,s)
             else
               current_settings.sourcecodepage:=codepagebyname(s);
+            { we're not using the system code page now }
+            exclude(current_settings.modeswitches,m_systemcodepage);
+            exclude(current_settings.moduleswitches,cs_system_codepage);
             include(current_settings.moduleswitches,cs_explicit_codepage);
           end;
       end;

+ 48 - 7
compiler/scanner.pas

@@ -392,26 +392,67 @@ implementation
         { turn on system codepage by default }
         if switch in [m_none,m_systemcodepage] then
           begin
+            { both m_systemcodepage and specifying a code page via -FcXXX or
+              "$codepage XXX" change current_settings.sourcecodepage. If
+              we used -FcXXX and then have a sourcefile with "$mode objfpc",
+              this routine will be called to disable m_systemcodepage (to ensure
+              it's off in case it would have been set on the command line, or
+              by a previous mode(switch).
+
+              In that case, we have to ensure that we don't overwrite
+              current_settings.sourcecodepage, as that would cancel out the
+              -FcXXX. This is why we use two separate module switches
+              (cs_explicit_codepage and cs_system_codepage) for the same setting
+              (current_settings.sourcecodepage)
+            }
             if m_systemcodepage in current_settings.modeswitches then
               begin
+                { m_systemcodepage gets enabled -> disable any -FcXXX and
+                  "codepage XXX" settings (exclude cs_explicit_codepage), and
+                  overwrite the sourcecode page }
                 current_settings.sourcecodepage:=DefaultSystemCodePage;
                 if (current_settings.sourcecodepage<>CP_UTF8) and not cpavailable(current_settings.sourcecodepage) then
                   begin
                     Message2(scan_w_unavailable_system_codepage,IntToStr(current_settings.sourcecodepage),IntToStr(default_settings.sourcecodepage));
                     current_settings.sourcecodepage:=default_settings.sourcecodepage;
                   end;
-                include(current_settings.moduleswitches,cs_explicit_codepage);
+                exclude(current_settings.moduleswitches,cs_explicit_codepage);
+                include(current_settings.moduleswitches,cs_system_codepage);
                 if changeinit then
-                begin
-                  init_settings.sourcecodepage:=current_settings.sourcecodepage;
-                  include(init_settings.moduleswitches,cs_explicit_codepage);
-                end;
+                  begin
+                    init_settings.sourcecodepage:=current_settings.sourcecodepage;
+                    exclude(init_settings.moduleswitches,cs_explicit_codepage);
+                    include(init_settings.moduleswitches,cs_system_codepage);
+                  end;
               end
             else
               begin
-                exclude(current_settings.moduleswitches,cs_explicit_codepage);
+                { m_systemcodepage gets disabled -> reset sourcecodepage only if
+                  cs_explicit_codepage is not set (it may be set in the scenario
+                  where -FcXXX was passed on the command line and then "$mode
+                  fpc" is used, because then the caller of this routine will
+                  set the "$mode fpc" modeswitches (which don't include
+                  m_systemcodepage) and call this routine with m_none).
+
+                  Or it can happen if -FcXXX was passed, and the sourcefile
+                  contains "$modeswitch systemcodepage-" statement.
+
+                  Since we unset cs_system_codepage if m_systemcodepage gets
+                  activated, we will revert to the default code page if you
+                  set a source file code page, then enable the systemcode page
+                  and finally disable it again. We don't keep a stack of
+                  settings, by design. The only thing we have to ensure is that
+                  disabling m_systemcodepage if it wasn't on in the first place
+                  doesn't overwrite the sourcecodepage }
+                exclude(current_settings.moduleswitches,cs_system_codepage);
+                if not(cs_explicit_codepage in current_settings.moduleswitches) then
+                  current_settings.sourcecodepage:=default_settings.sourcecodepage;
                 if changeinit then
-                  exclude(init_settings.moduleswitches,cs_explicit_codepage);
+                  begin
+                    exclude(init_settings.moduleswitches,cs_system_codepage);
+                    if not(cs_explicit_codepage in init_settings.moduleswitches) then
+                      init_settings.sourcecodepage:=default_settings.sourcecodepage;
+                  end;
               end;
           end;
       end;

+ 3 - 3
compiler/symdef.pas

@@ -1168,7 +1168,7 @@ implementation
 
     function getansistringcodepage:tstringencoding; inline;
       begin
-        if cs_explicit_codepage in current_settings.moduleswitches then
+        if ([cs_explicit_codepage,cs_system_codepage]*current_settings.moduleswitches)<>[] then
           result:=current_settings.sourcecodepage
         else
           result:=0;
@@ -1178,9 +1178,9 @@ implementation
       var
         symtable:tsymtable;
       begin
-        { if codepage is explicitly defined in this mudule we need to return
+        { if a codepage is explicitly defined in this mudule we need to return
           a replacement for ansistring def }
-        if cs_explicit_codepage in current_settings.moduleswitches then
+        if ([cs_explicit_codepage,cs_system_codepage]*current_settings.moduleswitches)<>[] then
           begin
             if not assigned(current_module) then
               internalerror(2011101301);

+ 17 - 0
tests/webtbs/tw28718a.pp

@@ -0,0 +1,17 @@
+{$codepage cp1258}
+
+{ should cancel/override the codepage setting above }
+{$modeswitch systemcodepage}
+
+program tw28718a;
+
+{ should restore the compiler's default code page (-> CP_ACP) }
+{$modeswitch systemcodepage-}
+
+var
+  a: ansistring;
+begin
+  a:='abc';
+  if stringcodepage(a)<>CP_ACP then
+    halt(1);
+end.

+ 15 - 0
tests/webtbs/tw28718b.pp

@@ -0,0 +1,15 @@
+{$codepage cp1258}
+
+{ should not have any effect, since the setting was not enabled }
+
+{$modeswitch systemcodepage-}
+
+program tw28718b;
+
+var
+  a: ansistring;
+begin
+  a:='abc';
+  if stringcodepage(a)<>1258 then
+    halt(1);
+end.

+ 15 - 0
tests/webtbs/tw28718c.pp

@@ -0,0 +1,15 @@
+{ %opt=-Fccp1258 }
+
+{ should not have any effect, since the setting was not enabled }
+
+{$modeswitch systemcodepage-}
+
+program tw28718c;
+
+var
+  a: ansistring;
+begin
+  a:='abc';
+  if stringcodepage(a)<>1258 then
+    halt(1);
+end.

+ 16 - 0
tests/webtbs/tw28718d.pp

@@ -0,0 +1,16 @@
+{ %opt=-Fccp1258 -Msystemcodepage }
+
+{ disabling the systemcodepage after enabling it goes back to the default
+  setting, there is no stack of previously set code pages }
+
+{$modeswitch systemcodepage-}
+
+program tw28718c;
+
+var
+  a: ansistring;
+begin
+  a:='abc';
+  if stringcodepage(a)<>CP_ACP then
+    halt(1);
+end.