Browse Source

o merged cpstrrtl branch (includes unicode branch). In general, this adds
support for arbitrarily encoded ansistrings to many routines related to
file system access (and some others).

WARNING: while the parameters of many routines have been changed from
"ansistring" to "rawbytestring" to avoid data loss due to conversions,
this is not a panacea. If you pass a string concatenation to such a
parameter and not all strings in this concatenation have the same
code page, all strings and the result will be converted to
DefaultSystemCodePage (= ansi code page by default). In particular,
concatenating e.g. an Utf8String with a constant string and passing
the result to a RawByteString parameter will convert the result into
the DefaultSystemCodePage (unless the source code is compiler with
{$modeswitch systemcodepage} or {$mode delphiunicode} *and* the ansi
code page on the system you are compiling *on* happens to be UTF-8)

You can define and use alternative routines that explicitly accept
Utf8String parameters to avoid this pitfall. Internally, all of these
routines ensure that they never trigger this condition and ensure that
not unnecessary/unwanted code page conversions occur.

+ DefaultFileSystemCodePage variable that holds the code page used for
communicating with the OS single byte file system APIs, and for the
strings returned by those same APIs. Initialized with
o the result of GetACP in the system unit of Windows platforms, except for
WinCE which uses UTF-8 since its file system OS API calls already use
the UTF-16 versions
o CP_UTF8 on Unix platforms with FPCRTL_FILESYSTEM_UTF8 defined, and with
DefaultSystemCodePage on other Unix platforms
o DefaultSystemCodePage on Java/Android JVM targets
+ DefaultRTLFileSystemCodePage variable that holds the code page used to
encode strings returned by RTL routines that return filenames obtained
from OS API calls. By default the same as DefaultFileSystemCodePage on
all platforms. Separate from DefaultFileSystemCodePage for clarity on
platforms that may use either utf-16 or single byte OS API calls to
send/receive file names (such as most Windows platforms)
+ new scpFileSystemSingleByte enum that can be passed to
GetStandardCodePage() to get the default code page for OS single byte file
system APIs, with implementations for Unix and Windows
+ SetMultiByteFileSystemCodePage() procedure to override the value of
DefaultFileSystemCodePage
+ ToSingleByteFileSystemEncodedFileName() function to convert a string to to
DefaultFileSystemCodePage (does *not* take care of OS-specific quirks like
Darwin always returning file names in decomposed UTF-8)
+ support for CP_OEMCP
* textrec/filerec now store the filename by default using widechar. It is
possible to switch back to ansichars using the FPC_ANSI_TEXTFILEREC define.
In that case, from now on the filename will always be stored in
DefaultFileSystemEncoding
* fixed potential buffer overflows and non-null-terminated file names in
textrec/filerec

* when concatenating ansistrings, do not map CP_NONE (rawbytestring) to
CP_ACP (defaultsystemcodepage), because if all input strings have the
same code page then the result should also have that code page if it's
assigned to a rawbytestring rather than getting defaultsystemcodepage
* do not consider empty strings to determine the code page of the result
in fpc_AnsiStr_Concat_multi(), because that will cause a different
result than when using a sequence of fpc_AnsiStr_Concat() calls (it
ignores empty strings to determine the result code page) and it's also
slower

* do not consider the run time code page of the destination string in
fpc_AnsiStr_Concat(_multi)() because Delphi does not do so either. This
was introduced in r19118, probably to hide another bug + test
* never change the code page of a non-empty string when calling setlength on
it

* handle the fact that GetEnvironmentStringsA returns the environment in the
OEM instead of in the Ansi code page (mantis #22524, #15233)
* don't truncate environment variable strings in GetEnvironmentString(),
its result is now ansistring/unicodestring depending on whether the
RTL was compiled with FPC_RTL_UNICODE

* unix:
o made the ansistring parameters of the fp*() file system routine overloads
constant, changed them to rawbytestring and added
DefaultFileSystemCodePage conversions
o unicodestring support for POpen(), and DefaultFileSystemCodePage support
for POpen(RawByteString)

+ DefaultFileSystemCodePage support for dynlibs unit

+ rawbytestring/unicodestring overloads for:
o system: fexpand, lowercase, uppercase, getdir, mkdir, chdir, rmdir,
assign, erase, rename
o objpas: AssignFile,
o sysutils: FileCreate, FileOpen, FileExists, DirectoryExists, FileSetDate,
FileGetAttr, FileSetAttr, DeleteFile, RenameFile, FileSearch, ExeSearch,
FindFirst, FindNext, FindClose, FileIsReadOnly, GetCurrentDir,
SetCurrentDir, ChangeFileExt, ExtractFilePath, ExtractFileDrive,
ExtractFileName, ExtractFileExt, ExtractFileDir, ExtractShortPathName,
ExpandFileName, ExpandFileNameCase, ExpandUNCFileName,
ExtractRelativepath, IncludeTrailingPathDelimiter,
IncludeTrailingBackslash, ExcludeTrailingBackslash,
ExcludeTrailingPathDelimiter, IncludeLeadingPathDelimiter,
ExcludeLeadingPathDelimiter, IsPathDelimiter, DoDirSeparators,
SetDirSeparators, GetDirs, ConcatPaths, GetEnvironmentVariable

-- the default string type used by FindFirst/Next depends on whether the
RTL was compiled with FPC_RTL_UNICODE. To force the RawByteString
version pass a TRawByteSearchRec, for the UnicodeString version pass
a TUnicodeSearchRec.

+ paramstr(longint):unicodestring available for {$modeswitch unicodestrings}

+ pwidechar versions in sysutils of strecopy, strend, strcat, strcomp,
strlcomp, stricomp, strlcat, strrscan,strlower, strupper, strlicomp,
strpos, WideStrAlloc, StrBufSize, StrDispose + tests


git-svn-id: trunk@25432 -

Jonas Maebe 12 years ago
parent
commit
cde2d1b8ee
100 changed files with 3366 additions and 1724 deletions
  1. 52 0
      .gitattributes
  2. 1 1
      compiler/assemble.pas
  3. 1 1
      compiler/cfileutl.pas
  4. 8 2
      compiler/defcmp.pas
  5. 1 1
      compiler/globals.pas
  6. 6 2
      compiler/nadd.pas
  7. 32 52
      compiler/ncnv.pas
  8. 6 2
      compiler/nopt.pas
  9. 1 1
      compiler/options.pas
  10. 21 55
      compiler/symdef.pas
  11. 24 0
      rtl/aix/rtldefs.inc
  12. 28 6
      rtl/amiga/dos.pp
  13. 24 0
      rtl/amiga/rtldefs.inc
  14. 23 26
      rtl/amiga/sysdir.inc
  15. 3 3
      rtl/amiga/sysfile.inc
  16. 35 0
      rtl/amiga/sysos.inc
  17. 51 68
      rtl/amiga/sysutils.pp
  18. 24 0
      rtl/atari/rtldefs.inc
  19. 24 0
      rtl/beos/rtldefs.inc
  20. 24 0
      rtl/darwin/rtldefs.inc
  21. 29 0
      rtl/embedded/rtldefs.inc
  22. 27 3
      rtl/embedded/sysdir.inc
  23. 3 3
      rtl/embedded/sysfile.inc
  24. 20 39
      rtl/embedded/sysutils.pp
  25. 10 4
      rtl/emx/dos.pas
  26. 24 0
      rtl/emx/rtldefs.inc
  27. 35 40
      rtl/emx/sysdir.inc
  28. 26 11
      rtl/emx/sysfile.inc
  29. 99 107
      rtl/emx/sysutils.pp
  30. 24 0
      rtl/freebsd/rtldefs.inc
  31. 24 0
      rtl/gba/rtldefs.inc
  32. 4 4
      rtl/gba/sysdir.inc
  33. 3 3
      rtl/gba/sysfile.inc
  34. 20 39
      rtl/gba/sysutils.pp
  35. 18 0
      rtl/go32v2/dos.pp
  36. 24 0
      rtl/go32v2/rtldefs.inc
  37. 28 24
      rtl/go32v2/sysdir.inc
  38. 24 7
      rtl/go32v2/sysfile.inc
  39. 59 65
      rtl/go32v2/sysutils.pp
  40. 24 0
      rtl/haiku/rtldefs.inc
  41. 117 84
      rtl/inc/astrings.inc
  42. 5 1
      rtl/inc/compproc.inc
  43. 75 20
      rtl/inc/dynlibs.pas
  44. 6 6
      rtl/inc/exeinfo.pp
  45. 126 23
      rtl/inc/fexpand.inc
  46. 175 35
      rtl/inc/file.inc
  47. 1 1
      rtl/inc/filerec.inc
  48. 1 1
      rtl/inc/objects.pp
  49. 312 43
      rtl/inc/system.inc
  50. 99 37
      rtl/inc/systemh.inc
  51. 173 33
      rtl/inc/text.inc
  52. 4 2
      rtl/inc/textrec.inc
  53. 24 16
      rtl/inc/typefile.inc
  54. 8 3
      rtl/inc/ustringh.inc
  55. 50 15
      rtl/inc/ustrings.inc
  56. 24 0
      rtl/inc/uuchar.pp
  57. 2 5
      rtl/inc/wstrings.inc
  58. 73 55
      rtl/java/jastrings.inc
  59. 2 2
      rtl/java/jcompproc.inc
  60. 3 3
      rtl/java/jsstrings.inc
  61. 8 0
      rtl/java/jsystemh_types.inc
  62. 20 10
      rtl/java/justrings.inc
  63. 24 0
      rtl/java/rtldefs.inc
  64. 24 0
      rtl/linux/rtldefs.inc
  65. 10 2
      rtl/macos/dos.pp
  66. 24 0
      rtl/macos/rtldefs.inc
  67. 7 21
      rtl/macos/sysdir.inc
  68. 3 3
      rtl/macos/sysfile.inc
  69. 33 58
      rtl/macos/sysutils.pp
  70. 28 6
      rtl/morphos/dos.pp
  71. 24 0
      rtl/morphos/rtldefs.inc
  72. 22 19
      rtl/morphos/sysdir.inc
  73. 3 3
      rtl/morphos/sysfile.inc
  74. 35 0
      rtl/morphos/sysos.inc
  75. 56 76
      rtl/morphos/sysutils.pp
  76. 26 4
      rtl/msdos/dos.pp
  77. 24 0
      rtl/msdos/rtldefs.inc
  78. 28 24
      rtl/msdos/sysdir.inc
  79. 24 7
      rtl/msdos/sysfile.inc
  80. 27 54
      rtl/msdos/sysutils.pp
  81. 148 146
      rtl/nativent/Makefile
  82. 5 2
      rtl/nativent/Makefile.fpc
  83. 2 2
      rtl/nativent/ndkutils.pas
  84. 24 0
      rtl/nativent/rtldefs.inc
  85. 16 15
      rtl/nativent/sysdir.inc
  86. 26 11
      rtl/nativent/sysfile.inc
  87. 25 1
      rtl/nativent/sysos.inc
  88. 239 157
      rtl/nativent/sysutils.pp
  89. 24 0
      rtl/nds/rtldefs.inc
  90. 4 7
      rtl/nds/sysdir.inc
  91. 3 3
      rtl/nds/sysfile.inc
  92. 52 48
      rtl/nds/sysutils.pp
  93. 24 0
      rtl/netbsd/rtldefs.inc
  94. 3 3
      rtl/netware/dynlibs.inc
  95. 24 0
      rtl/netware/rtldefs.inc
  96. 13 13
      rtl/netware/sysdir.inc
  97. 3 3
      rtl/netware/sysfile.inc
  98. 61 67
      rtl/netware/sysutils.pp
  99. 24 3
      rtl/netwlibc/dos.pp
  100. 2 2
      rtl/netwlibc/dynlibs.inc

+ 52 - 0
.gitattributes

@@ -7432,6 +7432,7 @@ rtl/aix/osmacro.inc svneol=native#text/plain
 rtl/aix/ostypes.inc svneol=native#text/plain
 rtl/aix/pthread.inc svneol=native#text/plain
 rtl/aix/ptypes.inc svneol=native#text/plain
+rtl/aix/rtldefs.inc svneol=native#text/plain
 rtl/aix/sighnd.inc svneol=native#text/plain
 rtl/aix/sighndh.inc svneol=native#text/plain
 rtl/aix/signal.inc svneol=native#text/plain
@@ -7466,6 +7467,7 @@ rtl/amiga/powerpc/utild1.inc svneol=native#text/plain
 rtl/amiga/powerpc/utild2.inc svneol=native#text/plain
 rtl/amiga/powerpc/utilf.inc svneol=native#text/plain
 rtl/amiga/printer.pp svneol=native#text/plain
+rtl/amiga/rtldefs.inc svneol=native#text/plain
 rtl/amiga/sysdir.inc svneol=native#text/plain
 rtl/amiga/sysfile.inc svneol=native#text/plain
 rtl/amiga/sysheap.inc svneol=native#text/plain
@@ -7508,6 +7510,7 @@ rtl/arm/thumb2.inc svneol=native#text/plain
 rtl/atari/os.inc svneol=native#text/plain
 rtl/atari/prt0.as svneol=native#text/plain
 rtl/atari/readme -text
+rtl/atari/rtldefs.inc svneol=native#text/plain
 rtl/atari/sysatari.pas svneol=native#text/plain
 rtl/atari/system.pas svneol=native#text/plain
 rtl/avr/avr.inc svneol=native#text/plain
@@ -7535,6 +7538,7 @@ rtl/beos/osmacro.inc svneol=native#text/plain
 rtl/beos/ossysc.inc svneol=native#text/plain
 rtl/beos/ostypes.inc svneol=native#text/plain
 rtl/beos/ptypes.inc svneol=native#text/plain
+rtl/beos/rtldefs.inc svneol=native#text/plain
 rtl/beos/settimeo.inc svneol=native#text/plain
 rtl/beos/signal.inc svneol=native#text/plain
 rtl/beos/suuid.inc svneol=native#text/plain
@@ -7616,6 +7620,7 @@ rtl/darwin/ppcgen/ppchnd.inc svneol=native#text/plain
 rtl/darwin/ppcgen/sig_ppc.inc svneol=native#text/plain
 rtl/darwin/pthread.inc svneol=native#text/plain
 rtl/darwin/ptypes.inc svneol=native#text/plain
+rtl/darwin/rtldefs.inc svneol=native#text/plain
 rtl/darwin/signal.inc svneol=native#text/plain
 rtl/darwin/sysctlh.inc svneol=native#text/plain
 rtl/darwin/termio.pp svneol=native#text/plain
@@ -7662,6 +7667,7 @@ rtl/embedded/consoleio.pp svneol=native#text/pascal
 rtl/embedded/empty.cfg svneol=native#text/plain
 rtl/embedded/heapmgr.pp svneol=native#text/pascal
 rtl/embedded/rtl.cfg svneol=native#text/plain
+rtl/embedded/rtldefs.inc svneol=native#text/plain
 rtl/embedded/sysdir.inc svneol=native#text/plain
 rtl/embedded/sysfile.inc svneol=native#text/plain
 rtl/embedded/sysheap.inc svneol=native#text/plain
@@ -7679,6 +7685,7 @@ rtl/emx/emxwrap.imp -text
 rtl/emx/ports.pas svneol=native#text/plain
 rtl/emx/prt0.as svneol=native#text/plain
 rtl/emx/prt1.as svneol=native#text/plain
+rtl/emx/rtldefs.inc svneol=native#text/plain
 rtl/emx/sysdir.inc svneol=native#text/plain
 rtl/emx/sysemx.pas svneol=native#text/plain
 rtl/emx/sysfile.inc svneol=native#text/plain
@@ -7713,6 +7720,7 @@ rtl/freebsd/i386/x86h.inc svneol=native#text/plain
 rtl/freebsd/pmutext.inc svneol=native#text/plain
 rtl/freebsd/pthread.inc svneol=native#text/plain
 rtl/freebsd/ptypes.inc svneol=native#text/plain
+rtl/freebsd/rtldefs.inc svneol=native#text/plain
 rtl/freebsd/si_crt.pp svneol=native#text/plain
 rtl/freebsd/si_intf.inc svneol=native#text/plain
 rtl/freebsd/signal.inc svneol=native#text/plain
@@ -7744,6 +7752,7 @@ rtl/gba/gbabiosh.inc svneol=native#text/plain
 rtl/gba/libc.inc svneol=native#text/plain
 rtl/gba/libch.inc svneol=native#text/plain
 rtl/gba/prt0.as svneol=native#text/plain
+rtl/gba/rtldefs.inc svneol=native#text/plain
 rtl/gba/sysdir.inc svneol=native#text/plain
 rtl/gba/sysfile.inc svneol=native#text/plain
 rtl/gba/sysheap.inc svneol=native#text/plain
@@ -7776,6 +7785,7 @@ rtl/go32v2/msmouse.pp svneol=native#text/plain
 rtl/go32v2/ports.pp svneol=native#text/plain
 rtl/go32v2/printer.pp svneol=native#text/plain
 rtl/go32v2/profile.pp svneol=native#text/plain
+rtl/go32v2/rtldefs.inc svneol=native#text/plain
 rtl/go32v2/sbrk16.ah -text
 rtl/go32v2/sbrk16.asm -text
 rtl/go32v2/sysdir.inc svneol=native#text/plain
@@ -7809,6 +7819,7 @@ rtl/haiku/ossysc.inc svneol=native#text/plain
 rtl/haiku/ostypes.inc svneol=native#text/plain
 rtl/haiku/pthread.inc svneol=native#text/plain
 rtl/haiku/ptypes.inc svneol=native#text/plain
+rtl/haiku/rtldefs.inc svneol=native#text/plain
 rtl/haiku/settimeo.inc svneol=native#text/plain
 rtl/haiku/signal.inc svneol=native#text/plain
 rtl/haiku/suuid.inc svneol=native#text/plain
@@ -7989,6 +8000,7 @@ rtl/java/objpas.inc svneol=native#text/plain
 rtl/java/objpas.pp svneol=native#text/plain
 rtl/java/objpash.inc svneol=native#text/plain
 rtl/java/rtl.cfg svneol=native#text/plain
+rtl/java/rtldefs.inc svneol=native#text/plain
 rtl/java/rtti.inc svneol=native#text/plain
 rtl/java/sysos.inc svneol=native#text/plain
 rtl/java/sysosh.inc svneol=native#text/plain
@@ -8113,6 +8125,7 @@ rtl/linux/powerpc64/syscallh.inc svneol=native#text/plain
 rtl/linux/powerpc64/sysnr.inc svneol=native#text/plain
 rtl/linux/pthread.inc svneol=native#text/plain
 rtl/linux/ptypes.inc svneol=native#text/plain
+rtl/linux/rtldefs.inc svneol=native#text/plain
 rtl/linux/si_c.pp svneol=native#text/plain
 rtl/linux/si_c21.pp svneol=native#text/plain
 rtl/linux/si_c21g.pp svneol=native#text/plain
@@ -8184,6 +8197,7 @@ rtl/macos/macostp.inc svneol=native#text/plain
 rtl/macos/macostp.pp svneol=native#text/plain
 rtl/macos/macutils.inc svneol=native#text/plain
 rtl/macos/macutils.pp svneol=native#text/plain
+rtl/macos/rtldefs.inc svneol=native#text/plain
 rtl/macos/sysdir.inc svneol=native#text/plain
 rtl/macos/sysfile.inc svneol=native#text/plain
 rtl/macos/sysheap.inc svneol=native#text/plain
@@ -8242,6 +8256,7 @@ rtl/morphos/mouse.pp svneol=native#text/plain
 rtl/morphos/mui.pas -text svneol=unset#text/plain
 rtl/morphos/muihelper.pas -text svneol=unset#text/plain
 rtl/morphos/prt0.as svneol=native#text/plain
+rtl/morphos/rtldefs.inc svneol=native#text/plain
 rtl/morphos/sockets.pp svneol=native#text/plain
 rtl/morphos/sysdir.inc svneol=native#text/plain
 rtl/morphos/sysfile.inc svneol=native#text/plain
@@ -8274,6 +8289,7 @@ rtl/msdos/prt0s.asm svneol=native#text/plain
 rtl/msdos/prt0stm.asm svneol=native#text/plain
 rtl/msdos/prt0t.asm svneol=native#text/plain
 rtl/msdos/registers.inc svneol=native#text/plain
+rtl/msdos/rtldefs.inc svneol=native#text/plain
 rtl/msdos/sysdir.inc svneol=native#text/plain
 rtl/msdos/sysfile.inc svneol=native#text/plain
 rtl/msdos/sysheap.inc svneol=native#text/plain
@@ -8306,6 +8322,7 @@ rtl/nativent/ndk/rtltypes.inc svneol=native#text/plain
 rtl/nativent/ndk/umtypes.inc svneol=native#text/plain
 rtl/nativent/ndk/winnt.inc svneol=native#text/plain
 rtl/nativent/ndkutils.pas svneol=native#text/pascal
+rtl/nativent/rtldefs.inc svneol=native#text/plain
 rtl/nativent/sysdir.inc svneol=native#text/plain
 rtl/nativent/sysfile.inc svneol=native#text/plain
 rtl/nativent/sysheap.inc svneol=native#text/plain
@@ -8330,6 +8347,7 @@ rtl/nds/ndsbiosh.inc svneol=native#text/plain
 rtl/nds/ndsh.inc svneol=native#text/plain
 rtl/nds/prt07.as svneol=native#text/plain
 rtl/nds/prt09.as svneol=native#text/plain
+rtl/nds/rtldefs.inc svneol=native#text/plain
 rtl/nds/sysdir.inc svneol=native#text/plain
 rtl/nds/sysfile.inc svneol=native#text/plain
 rtl/nds/sysheap.inc svneol=native#text/plain
@@ -8357,6 +8375,7 @@ rtl/netbsd/powerpc/prt0.as svneol=native#text/plain
 rtl/netbsd/powerpc/sighnd.inc svneol=native#text/plain
 rtl/netbsd/pthread.inc svneol=native#text/plain
 rtl/netbsd/ptypes.inc svneol=native#text/plain
+rtl/netbsd/rtldefs.inc svneol=native#text/plain
 rtl/netbsd/signal.inc svneol=native#text/plain
 rtl/netbsd/syscalls.inc svneol=native#text/plain
 rtl/netbsd/sysconst.inc svneol=native#text/plain
@@ -8431,6 +8450,7 @@ rtl/netware/nwsys.inc svneol=native#text/plain
 rtl/netware/prelude.as svneol=native#text/plain
 rtl/netware/qos.inc svneol=native#text/plain
 rtl/netware/requestr.imp -text
+rtl/netware/rtldefs.inc svneol=native#text/plain
 rtl/netware/sockets.pp svneol=native#text/plain
 rtl/netware/socklib.imp -text
 rtl/netware/streams.imp -text
@@ -8475,6 +8495,7 @@ rtl/netwlibc/nwsnut.imp -text
 rtl/netwlibc/nwsnut.pp svneol=native#text/plain
 rtl/netwlibc/pre/libcpre.gcc.o -text
 rtl/netwlibc/qos.inc svneol=native#text/plain
+rtl/netwlibc/rtldefs.inc svneol=native#text/plain
 rtl/netwlibc/sockets.pp svneol=native#text/plain
 rtl/netwlibc/sysdir.inc svneol=native#text/plain
 rtl/netwlibc/sysfile.inc svneol=native#text/plain
@@ -8557,7 +8578,9 @@ rtl/objpas/strutils.pp svneol=native#text/plain
 rtl/objpas/sysconst.pp svneol=native#text/plain
 rtl/objpas/sysutils/dati.inc svneol=native#text/plain
 rtl/objpas/sysutils/datih.inc svneol=native#text/plain
+rtl/objpas/sysutils/disk.inc svneol=native#text/plain
 rtl/objpas/sysutils/diskh.inc svneol=native#text/plain
+rtl/objpas/sysutils/filutil.inc svneol=native#text/plain
 rtl/objpas/sysutils/filutilh.inc svneol=native#text/plain
 rtl/objpas/sysutils/fina.inc svneol=native#text/plain
 rtl/objpas/sysutils/finah.inc svneol=native#text/plain
@@ -8617,6 +8640,7 @@ rtl/openbsd/osdefs.inc svneol=native#text/plain
 rtl/openbsd/pmutext.inc svneol=native#text/plain
 rtl/openbsd/pthread.inc svneol=native#text/plain
 rtl/openbsd/ptypes.inc svneol=native#text/plain
+rtl/openbsd/rtldefs.inc svneol=native#text/plain
 rtl/openbsd/signal.inc svneol=native#text/plain
 rtl/openbsd/syscalls.inc svneol=native#text/plain
 rtl/openbsd/sysconst.inc svneol=native#text/plain
@@ -8669,6 +8693,7 @@ rtl/os2/pmwsock.pas svneol=native#text/plain
 rtl/os2/ports.pas svneol=native#text/plain
 rtl/os2/printer.pas svneol=native#text/plain
 rtl/os2/prt0.as svneol=native#text/plain
+rtl/os2/rtldefs.inc svneol=native#text/plain
 rtl/os2/so32dll.pas svneol=native#text/plain
 rtl/os2/sockets.pas svneol=native#text/plain
 rtl/os2/sysdir.inc svneol=native#text/plain
@@ -8724,6 +8749,7 @@ rtl/palmos/m68k/prt0.as svneol=native#text/plain
 rtl/palmos/os.inc svneol=native#text/plain
 rtl/palmos/pilot.pp svneol=native#text/plain
 rtl/palmos/readme -text
+rtl/palmos/rtldefs.inc svneol=native#text/plain
 rtl/palmos/syspalm.pp svneol=native#text/plain
 rtl/palmos/system.pp svneol=native#text/plain
 rtl/palmos/systraps.pp svneol=native#text/plain
@@ -8764,6 +8790,7 @@ rtl/qnx/osposix.inc svneol=native#text/plain
 rtl/qnx/osposixh.inc svneol=native#text/plain
 rtl/qnx/posix.pp svneol=native#text/plain
 rtl/qnx/qnx.inc svneol=native#text/plain
+rtl/qnx/rtldefs.inc svneol=native#text/plain
 rtl/qnx/signal.inc svneol=native#text/plain
 rtl/qnx/system.pp svneol=native#text/plain
 rtl/solaris/Makefile svneol=native#text/plain
@@ -8779,6 +8806,7 @@ rtl/solaris/osmacro.inc svneol=native#text/plain
 rtl/solaris/ostypes.inc svneol=native#text/plain
 rtl/solaris/pthread.inc svneol=native#text/plain
 rtl/solaris/ptypes.inc svneol=native#text/plain
+rtl/solaris/rtldefs.inc svneol=native#text/plain
 rtl/solaris/signal.inc svneol=native#text/plain
 rtl/solaris/sparc/sighnd.inc svneol=native#text/plain
 rtl/solaris/sparc/sighndh.inc svneol=native#text/plain
@@ -8811,6 +8839,7 @@ rtl/symbian/Makefile svneol=native#text/plain
 rtl/symbian/Makefile.fpc svneol=native#text/plain
 rtl/symbian/bindings/pbeexe.cpp -text
 rtl/symbian/buildrtl.pp svneol=native#text/plain
+rtl/symbian/rtldefs.inc svneol=native#text/plain
 rtl/symbian/symbian.pas svneol=native#text/plain
 rtl/symbian/symbianinc/e32def.inc svneol=native#text/plain
 rtl/symbian/symbianinc/e32err.inc svneol=native#text/plain
@@ -8909,6 +8938,7 @@ rtl/watcom/classes.pp svneol=native#text/plain
 rtl/watcom/crt.pp svneol=native#text/plain
 rtl/watcom/dos.pp svneol=native#text/plain
 rtl/watcom/prt0.as -text
+rtl/watcom/rtldefs.inc svneol=native#text/plain
 rtl/watcom/sysdir.inc svneol=native#text/plain
 rtl/watcom/sysfile.inc svneol=native#text/plain
 rtl/watcom/sysheap.inc svneol=native#text/plain
@@ -8924,6 +8954,7 @@ rtl/wii/classes.pp svneol=native#text/plain
 rtl/wii/dos.pp svneol=native#text/plain
 rtl/wii/libc.inc svneol=native#text/plain
 rtl/wii/libch.inc svneol=native#text/plain
+rtl/wii/rtldefs.inc svneol=native#text/plain
 rtl/wii/sysdir.inc svneol=native#text/plain
 rtl/wii/sysfile.inc svneol=native#text/plain
 rtl/wii/sysheap.inc svneol=native#text/plain
@@ -8987,6 +9018,7 @@ rtl/win32/classes.pp svneol=native#text/plain
 rtl/win32/gprt0.as svneol=native#text/plain
 rtl/win32/initc.pp svneol=native#text/plain
 rtl/win32/objinc.inc svneol=native#text/plain
+rtl/win32/rtldefs.inc svneol=native#text/plain
 rtl/win32/signals.pp svneol=native#text/plain
 rtl/win32/sysinit.inc svneol=native#text/plain
 rtl/win32/sysinitcyg.pp svneol=native#text/plain
@@ -9002,6 +9034,7 @@ rtl/win64/Makefile svneol=native#text/plain
 rtl/win64/Makefile.fpc svneol=native#text/plain
 rtl/win64/buildrtl.pp svneol=native#text/plain
 rtl/win64/classes.pp svneol=native#text/plain
+rtl/win64/rtldefs.inc svneol=native#text/plain
 rtl/win64/seh64.inc svneol=native#text/plain
 rtl/win64/signals.pp svneol=native#text/plain
 rtl/win64/system.pp svneol=native#text/plain
@@ -9013,6 +9046,7 @@ rtl/wince/dos.pp svneol=native#text/plain
 rtl/wince/dynlibs.inc svneol=native#text/plain
 rtl/wince/messages.pp svneol=native#text/plain
 rtl/wince/readme.txt svneol=native#text/plain
+rtl/wince/rtldefs.inc svneol=native#text/plain
 rtl/wince/system.pp svneol=native#text/plain
 rtl/wince/sysutils.pp svneol=native#text/plain
 rtl/wince/varutils.pp svneol=native#text/plain
@@ -9979,6 +10013,7 @@ tests/tbs/tb0596.pp svneol=native#text/pascal
 tests/tbs/tb0597.pp svneol=native#text/plain
 tests/tbs/tb0598.pp svneol=native#text/plain
 tests/tbs/tb0599.pp svneol=native#text/plain
+tests/tbs/tb0600.pp svneol=native#text/plain
 tests/tbs/tb205.pp svneol=native#text/plain
 tests/tbs/tbs0594.pp svneol=native#text/pascal
 tests/tbs/ub0060.pp svneol=native#text/plain
@@ -10979,6 +11014,12 @@ tests/test/tcpstr21a.pp svneol=native#text/pascal
 tests/test/tcpstr22.pp svneol=native#text/pascal
 tests/test/tcpstr23.pp svneol=native#text/pascal
 tests/test/tcpstr24.pp svneol=native#text/plain
+tests/test/tcpstr25.pp svneol=native#text/plain
+tests/test/tcpstr26.pp svneol=native#text/plain
+tests/test/tcpstr26a.pp svneol=native#text/plain
+tests/test/tcpstr26b.pp svneol=native#text/plain
+tests/test/tcpstr26c.pp svneol=native#text/plain
+tests/test/tcpstr26d.pp svneol=native#text/plain
 tests/test/tcpstr2a.pp svneol=native#text/plain
 tests/test/tcpstr3.pp svneol=native#text/plain
 tests/test/tcpstr4.pp svneol=native#text/plain
@@ -10997,6 +11038,7 @@ tests/test/tcpstrchar2ansistr.pp svneol=native#text/plain
 tests/test/tcpstrconcat.pp svneol=native#text/plain
 tests/test/tcpstrconcat2.pp svneol=native#text/plain
 tests/test/tcpstrconcat3.pp svneol=native#text/plain
+tests/test/tcpstrconcat4.pp svneol=native#text/plain
 tests/test/tcpstrconcatmulti.pp svneol=native#text/plain
 tests/test/tcpstrconcatmulti2.pp svneol=native#text/plain
 tests/test/tcpstrpchar2ansistr.pp svneol=native#text/plain
@@ -12044,10 +12086,12 @@ tests/test/units/system/tassert6.pp svneol=native#text/plain
 tests/test/units/system/tassert7.pp svneol=native#text/plain
 tests/test/units/system/tassignd.pp svneol=native#text/plain
 tests/test/units/system/tdir.pp svneol=native#text/plain
+tests/test/units/system/tdir2.pp svneol=native#text/plain
 tests/test/units/system/testmac.txt svneol=native#text/plain
 tests/test/units/system/testpc.txt svneol=native#text/plain
 tests/test/units/system/teststk.pp svneol=native#text/plain
 tests/test/units/system/testux.txt svneol=native#text/plain
+tests/test/units/system/tfiledir.pp svneol=native#text/plain
 tests/test/units/system/tgenstr.pp svneol=native#text/pascal
 tests/test/units/system/tincdec.pp svneol=native#text/plain
 tests/test/units/system/tint.pp svneol=native#text/plain
@@ -12108,6 +12152,8 @@ tests/test/units/sysutils/texec1.pp svneol=native#text/plain
 tests/test/units/sysutils/texec2.pp svneol=native#text/plain
 tests/test/units/sysutils/texpfncase.pp svneol=native#text/plain
 tests/test/units/sysutils/textractquote.pp svneol=native#text/plain
+tests/test/units/sysutils/tfexpand2.pp svneol=native#text/plain
+tests/test/units/sysutils/tffirst.pp svneol=native#text/plain
 tests/test/units/sysutils/tfile1.pp svneol=native#text/plain
 tests/test/units/sysutils/tfile2.pp svneol=native#text/plain
 tests/test/units/sysutils/tfilename.pp svneol=native#text/plain
@@ -12116,7 +12162,11 @@ tests/test/units/sysutils/tformat.pp svneol=native#text/plain
 tests/test/units/sysutils/tlocale.pp svneol=native#text/plain
 tests/test/units/sysutils/trwsync.pp svneol=native#text/plain
 tests/test/units/sysutils/tsscanf.pp svneol=native#text/plain
+tests/test/units/sysutils/tstrcmp.pp svneol=native#text/plain
 tests/test/units/sysutils/tstrtobool.pp svneol=native#text/plain
+tests/test/units/sysutils/tunifile.pp svneol=native#text/plain
+tests/test/units/sysutils/tuplow.pp svneol=native#text/plain
+tests/test/units/sysutils/twstrcmp.pp svneol=native#text/plain
 tests/test/units/ucomplex/tcsqr1.pp svneol=native#text/pascal
 tests/test/units/variants/tcustomvariant.pp svneol=native#text/plain
 tests/test/units/variants/tvararrayofintf.pp svneol=native#text/plain
@@ -13356,6 +13406,7 @@ tests/webtbs/tw21329.pp svneol=native#text/pascal
 tests/webtbs/tw21350a.pp svneol=native#text/pascal
 tests/webtbs/tw21350b.pp svneol=native#text/pascal
 tests/webtbs/tw21443.pp svneol=native#text/plain
+tests/webtbs/tw21443a.pp svneol=native#text/plain
 tests/webtbs/tw2145.pp svneol=native#text/plain
 tests/webtbs/tw21457.pp svneol=native#text/pascal
 tests/webtbs/tw21472.pp svneol=native#text/pascal
@@ -13695,6 +13746,7 @@ tests/webtbs/tw3226.pp svneol=native#text/plain
 tests/webtbs/tw3227.pp svneol=native#text/plain
 tests/webtbs/tw3227a.pp svneol=native#text/plain
 tests/webtbs/tw3235.pp svneol=native#text/plain
+tests/webtbs/tw3235a.pp svneol=native#text/plain
 tests/webtbs/tw3241a.pp svneol=native#text/plain
 tests/webtbs/tw3252.pp svneol=native#text/plain
 tests/webtbs/tw3255.pp svneol=native#text/plain

+ 1 - 1
compiler/assemble.pas

@@ -295,7 +295,7 @@ Implementation
 
         procedure DeleteFilesWithExt(const AExt:string);
         var
-          dir : TSearchRec;
+          dir : TRawByteSearchRec;
         begin
           if findfirst(s+source_info.dirsep+'*'+AExt,faAnyFile,dir) = 0 then
             begin

+ 1 - 1
compiler/cfileutl.pas

@@ -269,7 +269,7 @@ end;
 
     procedure TCachedDirectory.Reload;
       var
-        dir   : TSearchRec;
+        dir   : TRawByteSearchRec;
         entry : PCachedDirectoryEntry;
       begin
         FreeDirectoryEntries;

+ 8 - 2
compiler/defcmp.pas

@@ -1144,7 +1144,10 @@ implementation
                         (is_pchar(def_to) or is_pwidechar(def_to)) then
                       begin
                         doconv:=tc_cstring_2_pchar;
-                        eq:=te_convert_l2;
+                        if is_pwidechar(def_to)=(m_default_unicodestring in current_settings.modeswitches) then
+                          eq:=te_convert_l2
+                        else
+                          eq:=te_convert_l3
                       end
                      else
                       if (cdo_explicit in cdoptions) or (fromtreetype = arrayconstructorn) then
@@ -1175,7 +1178,10 @@ implementation
                            (is_pchar(def_to) or is_pwidechar(def_to)) then
                          begin
                            doconv:=tc_cchar_2_pchar;
-                           eq:=te_convert_l1;
+                           if is_pwidechar(def_to)=(m_default_unicodestring in current_settings.modeswitches) then
+                             eq:=te_convert_l1
+                           else
+                             eq:=te_convert_l2
                          end
                         else
                          if (m_delphi in current_settings.modeswitches) and is_integer(def_from) then

+ 1 - 1
compiler/globals.pas

@@ -889,7 +889,7 @@ implementation
       {$endif}
       {$ifdef mswindows}
         GetEnvPchar:=nil;
-        p:=GetEnvironmentStrings;
+        p:=GetEnvironmentStringsA;
         hp:=p;
         while hp^<>#0 do
          begin

+ 6 - 2
compiler/nadd.pas

@@ -2179,7 +2179,9 @@ implementation
                   if is_ansistring(resultdef) then
                     para:=ccallparanode.create(
                             cordconstnode.create(
-                              getparaencoding(resultdef),
+                              { don't use getparaencoding(), we have to know
+                                when the result is rawbytestring }
+                              tstringdef(resultdef).encoding,
                               u16inttype,
                               true
                             ),
@@ -2217,7 +2219,9 @@ implementation
                   if is_ansistring(resultdef) then
                     para:=ccallparanode.create(
                             cordconstnode.create(
-                              getparaencoding(resultdef),
+                              { don't use getparaencoding(), we have to know
+                                when the result is rawbytestring }
+                              tstringdef(resultdef).encoding,
                               u16inttype,
                               true
                             ),

+ 32 - 52
compiler/ncnv.pas

@@ -1125,9 +1125,11 @@ implementation
                               // Delphi converts UniocodeChar to ansistring at the compile time
                               // old behavior:
                               // hp:=cstringconstnode.createstr(unicode2asciichar(tcompilerwidechar(tordconstnode(left).value.uvalue)));
+                              para:=ccallparanode.create(left,nil);
+                              if tstringdef(resultdef).stringtype=st_ansistring then
+                                para:=ccallparanode.create(cordconstnode.create(getparaencoding(resultdef),u16inttype,true),para);
                               result:=ccallnode.createinternres('fpc_uchar_to_'+tstringdef(resultdef).stringtypname,
-                                   ccallparanode.create(cordconstnode.create(getparaencoding(resultdef),u16inttype,true),
-                                   ccallparanode.create(left,nil)),resultdef);
+                                para,resultdef);
                               left:=nil;
                               exit;
                             end
@@ -1159,57 +1161,35 @@ implementation
               (torddef(left.resultdef).ordtype=uwidechar) or
               (target_info.system in systems_managed_vm) then
              begin
-               if (tstringdef(resultdef).stringtype<>st_shortstring) then
+               { parameter }
+               para:=ccallparanode.create(left,nil);
+               { encoding required? }
+               if tstringdef(resultdef).stringtype=st_ansistring then
+                 para:=ccallparanode.create(cordconstnode.create(getparaencoding(resultdef),u16inttype,true),para);
+
+               { create the procname }
+               if torddef(left.resultdef).ordtype<>uwidechar then
                  begin
-                   { parameter }
-                   para:=ccallparanode.create(left,nil);
-                   { encoding required? }
-                   if tstringdef(resultdef).stringtype=st_ansistring then
-                     para:=ccallparanode.create(cordconstnode.create(getparaencoding(resultdef),u16inttype,true),para);
-
-                   { create the procname }
-                   if torddef(left.resultdef).ordtype<>uwidechar then
-                     begin
-                       procname:='fpc_char_to_';
-                       if tstringdef(resultdef).stringtype in [st_widestring,st_unicodestring] then
-                         if nf_explicit in flags then
-                           Message2(type_w_explicit_string_cast,left.resultdef.typename,resultdef.typename)
-                         else
-                           Message2(type_w_implicit_string_cast,left.resultdef.typename,resultdef.typename);
-                     end
-                   else
-                     begin
-                       procname:='fpc_uchar_to_';
-                       if not (tstringdef(resultdef).stringtype in [st_widestring,st_unicodestring]) then
-                         if nf_explicit in flags then
-                           Message2(type_w_explicit_string_cast_loss,left.resultdef.typename,resultdef.typename)
-                         else
-                           Message2(type_w_implicit_string_cast_loss,left.resultdef.typename,resultdef.typename);
-                     end;
-                   procname:=procname+tstringdef(resultdef).stringtypname;
-
-                   { and finally the call }
-                   result:=ccallnode.createinternres(procname,para,resultdef);
+                   procname:='fpc_char_to_';
+                   if tstringdef(resultdef).stringtype in [st_widestring,st_unicodestring] then
+                     if nf_explicit in flags then
+                       Message2(type_w_explicit_string_cast,left.resultdef.typename,resultdef.typename)
+                     else
+                       Message2(type_w_implicit_string_cast,left.resultdef.typename,resultdef.typename);
                  end
                else
                  begin
-                   if nf_explicit in flags then
-                     Message2(type_w_explicit_string_cast_loss,left.resultdef.typename,resultdef.typename)
-                   else
-                     Message2(type_w_implicit_string_cast_loss,left.resultdef.typename,resultdef.typename);
-                   newblock:=internalstatements(newstat);
-                   restemp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,false);
-                   addstatement(newstat,restemp);
-                   if torddef(left.resultdef).ordtype<>uwidechar then
-                     procname := 'fpc_char_to_shortstr'
-                   else
-                     procname := 'fpc_uchar_to_shortstr';
-                   addstatement(newstat,ccallnode.createintern(procname,ccallparanode.create(left,ccallparanode.create(
-                     ctemprefnode.create(restemp),nil))));
-                   addstatement(newstat,ctempdeletenode.create_normal_temp(restemp));
-                   addstatement(newstat,ctemprefnode.create(restemp));
-                   result:=newblock;
+                   procname:='fpc_uchar_to_';
+                   if not (tstringdef(resultdef).stringtype in [st_widestring,st_unicodestring]) then
+                     if nf_explicit in flags then
+                       Message2(type_w_explicit_string_cast_loss,left.resultdef.typename,resultdef.typename)
+                     else
+                       Message2(type_w_implicit_string_cast_loss,left.resultdef.typename,resultdef.typename);
                  end;
+               procname:=procname+tstringdef(resultdef).stringtypname;
+
+               { and finally the call }
+               result:=ccallnode.createinternres(procname,para,resultdef);
                left := nil;
              end
            else
@@ -1478,10 +1458,10 @@ implementation
 
       begin
          result:=nil;
-         if is_pwidechar(resultdef) then
-           inserttypeconv(left,cunicodestringtype)
-         else
-           inserttypeconv(left,cshortstringtype);
+         { handle any constants via cunicodestringtype because the compiler
+           cannot convert arbitrary unicodechar constants at compile time to
+           a shortstring (since it doesn't know the code page to use) }
+         inserttypeconv(left,cunicodestringtype);
          { evaluate again, reset resultdef so the convert_typ
            will be calculated again and cstring_to_pchar will
            be used for futher conversion }

+ 6 - 2
compiler/nopt.pas

@@ -349,7 +349,9 @@ begin
       if is_ansistring(p.resultdef) then
         para:=ccallparanode.create(
                 cordconstnode.create(
-                  getparaencoding(p.resultdef),
+                  { don't use getparaencoding(), we have to know
+                    when the result is rawbytestring }
+                  tstringdef(p.resultdef).encoding,
                   u16inttype,
                   true
                 ),
@@ -383,7 +385,9 @@ begin
       if is_ansistring(p.resultdef) then
         para:=ccallparanode.create(
                 cordconstnode.create(
-                  getparaencoding(p.resultdef),
+                  { don't use getparaencoding(), we have to know
+                    when the result is rawbytestring }
+                  tstringdef(p.resultdef).encoding,
                   u16inttype,
                   true
                 ),

+ 1 - 1
compiler/options.pas

@@ -3197,7 +3197,7 @@ begin
   { Add exepath if the exe is not in the current dir, because that is always searched already.
     Do not add it when linking on the target because then we can maybe already find
     .o files that are not for the target }
-  if (ExePath<>GetCurrentDir) and
+  if (ExePath<>cfileutl.GetCurrentDir) and
      not(cs_link_on_target in init_settings.globalswitches) then
    UnitSearchPath.AddPath(ExePath,false);
   { Add unit dir to the object and library path }

+ 21 - 55
compiler/symdef.pas

@@ -138,6 +138,7 @@ interface
           procedure deref;override;
           function  GetTypeName:string;override;
           function  getmangledparaname:TSymStr;override;
+          function  size:asizeint;override;
           procedure setsize;
        end;
 
@@ -1129,7 +1130,11 @@ implementation
     function getparaencoding(def:tdef):tstringencoding; inline;
       begin
         { don't pass CP_NONE encoding to internal functions
-          they expect 0 encoding instead }
+          they expect 0 encoding instead
+          exception: result of string concatenation, because if you pass the
+          result of a string concatenation to a rawbytestring, the result of
+          that concatenation shouldn't be converted to defaultsystemcodepage
+          if all strings have the same type }
         result:=tstringdef(def).encoding;
         if result=CP_NONE then
           result:=0
@@ -2614,7 +2619,6 @@ implementation
          inherited create(filedef);
          filetyp:=ft_text;
          typedfiledef:=nil;
-         setsize;
       end;
 
 
@@ -2623,7 +2627,6 @@ implementation
          inherited create(filedef);
          filetyp:=ft_untyped;
          typedfiledef:=nil;
-         setsize;
       end;
 
 
@@ -2632,7 +2635,6 @@ implementation
          inherited create(filedef);
          filetyp:=ft_typed;
          typedfiledef:=def;
-         setsize;
       end;
 
 
@@ -2644,7 +2646,6 @@ implementation
            ppufile.getderef(typedfiledefderef)
          else
            typedfiledef:=nil;
-         setsize;
       end;
 
 
@@ -2679,58 +2680,23 @@ implementation
       end;
 
 
+    function  tfiledef.size:asizeint;
+      begin
+        if savesize=0 then
+          setsize;
+        size:=savesize;
+      end;
+
+
     procedure tfiledef.setsize;
       begin
-{$ifdef cpu64bitaddr}
-        case filetyp of
-          ft_text :
-            if target_info.system in [system_x86_64_win64,system_ia64_win64] then
-              savesize:=640
-            else
-              savesize:=632;
-          ft_typed,
-          ft_untyped :
-            if target_info.system in [system_x86_64_win64,system_ia64_win64] then
-              savesize:=376
-            else
-              savesize:=368;
-        end;
-{$endif cpu64bitaddr}
-{$ifdef cpu32bitaddr}
-        case filetyp of
-          ft_text :
-            savesize:=596; { keep this dividable by 4 for proper alignment of arrays of text, see tw0754 e.g. on arm }
-          ft_typed,
-          ft_untyped :
-            savesize:=332;
-        end;
-{$endif cpu32bitaddr}
-{$ifdef cpu16bitaddr}
-        case filetyp of
-          ft_text :
-            {$if defined(avr)}
-              savesize:=96;
-            {$elseif defined(i8086)}
-              case current_settings.x86memorymodel of
-                mm_tiny,mm_small: savesize:=576;
-                mm_medium:        savesize:=584;
-                else
-                  internalerror(2013060901);
-              end;
-            {$else}
-              {$fatal TODO: define the textrec size for your cpu}
-            {$endif}
-          ft_typed,
-          ft_untyped :
-            {$if defined(avr)}
-              savesize:=76;
-            {$elseif defined(i8086)}
-              savesize:=316;
-            {$else}
-              {$fatal TODO: define the textrec size for your cpu}
-            {$endif}
-        end;
-{$endif cpu16bitaddr}
+       case filetyp of
+         ft_text    :
+           savesize:=search_system_type('TEXTREC').typedef.size;
+         ft_typed,
+         ft_untyped :
+           savesize:=search_system_type('FILEREC').typedef.size;
+         end;
       end;
 
 

+ 24 - 0
rtl/aix/rtldefs.inc

@@ -0,0 +1,24 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2012 by Free Pascal development team
+
+    This file contains platform-specific defines that are used in
+    multiple RTL units.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{ the single byte OS APIs always use UTF-8 }
+{ define FPCRTL_FILESYSTEM_UTF8}
+
+{ The OS supports a single byte file system operations API that we use }
+{$define FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+
+{ The OS supports a two byte file system operations API that we use }
+{ define FPCRTL_FILESYSTEM_TWO_BYTE_API}

+ 28 - 6
rtl/amiga/dos.pp

@@ -725,7 +725,11 @@ var
 begin
     DosError:=0;
     FTime := 0;
-    Str := StrPas(filerec(f).name);
+{$ifdef FPC_ANSI_TEXTFILEREC}
+    Str := strpas(filerec(f).Name);
+{$else}
+    Str := ToSingleByteFileSystemEncodedFileName(filerec(f).Name);
+{$endif}
     DoDirSeparators(Str);
     FLock := dosLock(Str, SHARED_LOCK);
     IF FLock <> 0 then begin
@@ -756,7 +760,11 @@ end;
     FLock: longint;
   Begin
     new(DateStamp);
-    Str := StrPas(filerec(f).name);
+{$ifdef FPC_ANSI_TEXTFILEREC}
+    Str := strpas(filerec(f).Name);
+{$else}
+    Str := ToSingleByteFileSystemEncodedFileName(filerec(f).Name);
+{$endif}
     DoDirSeparators(str);
     { Check first of all, if file exists }
     FLock := dosLock(Str, SHARED_LOCK);
@@ -788,7 +796,11 @@ begin
     DosError:=0;
     flags:=0;
     New(info);
-    Str := StrPas(filerec(f).name);
+{$ifdef FPC_ANSI_TEXTFILEREC}
+    Str := strpas(filerec(f).Name);
+{$else}
+    Str := ToSingleByteFileSystemEncodedFileName(filerec(f).Name);
+{$endif}
     DoDirSeparators(str);
     { open with shared lock to check if file exists }
     MyLock:=dosLock(Str,SHARED_LOCK);
@@ -825,7 +837,17 @@ procedure setfattr(var f; attr : word);
 var
   flags: longint;
   tmpLock : longint;
-begin
+{$ifndef FPC_ANSI_TEXTFILEREC}
+  r : rawbytestring;
+{$endif not FPC_ANSI_TEXTFILEREC}
+  p : pchar;
+begin
+{$ifdef FPC_ANSI_TEXTFILEREC}
+  p := @filerec(f).Name;
+{$else}
+  r := ToSingleByteFileSystemEncodedFileName(filerec(f).Name);
+  p := pchar(r);
+{$endif}
   DosError:=0;
   flags:=FIBF_WRITE;
 
@@ -836,10 +858,10 @@ begin
   { converts the path (KB) }
 
   { create a shared lock on the file }
-  tmpLock:=Lock(filerec(f).name,SHARED_LOCK);
+  tmpLock:=Lock(p,SHARED_LOCK);
   if tmpLock <> 0 then begin
     Unlock(tmpLock);
-    if not SetProtection(filerec(f).name,flags) then DosError:=5;
+    if not SetProtection(p,flags) then DosError:=5;
   end else
     DosError:=3;
 end;

+ 24 - 0
rtl/amiga/rtldefs.inc

@@ -0,0 +1,24 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2012 by Free Pascal development team
+
+    This file contains platform-specific defines that are used in
+    multiple RTL units.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{ the single byte OS APIs always use UTF-8 }
+{ define FPCRTL_FILESYSTEM_UTF8}
+
+{ The OS supports a single byte file system operations API that we use }
+{$define FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+
+{ The OS supports a two byte file system operations API that we use }
+{ define FPCRTL_FILESYSTEM_TWO_BYTE_API}

+ 23 - 26
rtl/amiga/sysdir.inc

@@ -3,7 +3,7 @@
     Copyright (c) 1999-2000 by Florian Klaempfl and Pavel Ozerski
     member of the Free Pascal development team.
 
-    FPC Pascal system unit for the Win32 API.
+    FPC Pascal system unit for Amiga.
 
     See the file COPYING.FPC, included in this distribution,
     for details about the copyright.
@@ -18,15 +18,14 @@
 {*****************************************************************************
                            Directory Handling
 *****************************************************************************}
-procedure mkdir(s : pchar; len : sizeuint); [IOCheck, public, alias : 'FPC_SYS_MKDIR'];
+procedure do_mkdir(const s : rawbytestring);
 var
-  tmpStr : array[0..255] of char;
+  tmpStr : rawbytestring;
   tmpLock: LongInt;
 begin
   checkCTRLC;
-  if (s='') or (InOutRes<>0) then exit;
-  tmpStr:=PathConv(s)+#0;
-  tmpLock:=dosCreateDir(@tmpStr);
+  tmpStr:=PathConv(s);
+  tmpLock:=dosCreateDir(pchar(tmpStr));
   if tmpLock=0 then begin
     dosError2InOut(IoErr);
     exit;
@@ -34,33 +33,35 @@ begin
   UnLock(tmpLock);
 end;
 
-procedure rmdir(s : pchar; len : sizeuint); [IOCheck, public, alias : 'FPC_SYS_RMDIR'];
+procedure do_rmdir(const s : rawbytestring);
 var
-  tmpStr : array[0..255] of Char;
+  tmpStr : rawbytestring;
 begin
   checkCTRLC;
-  if (s='.') then InOutRes:=16;
-  If (s='') or (InOutRes<>0) then exit;
-  tmpStr:=PathConv(s)+#0;
-  if not dosDeleteFile(@tmpStr) then
+  if (s='.') then
+    begin
+      InOutRes:=16;
+      exit;
+    end;
+  tmpStr:=PathConv(s);
+  if not dosDeleteFile(pchar(tmpStr)) then
     dosError2InOut(IoErr);
 end;
 
-procedure sys_chdir(s : pchar);
+procedure do_ChDir(const s: rawbytestring);
 var
-  tmpStr : array[0..255] of Char;
+  tmpStr : rawbytestring;
   tmpLock: LongInt;
   FIB    : PFileInfoBlock;
 begin
   checkCTRLC;
-  If (s='') or (InOutRes<>0) then exit;
-  tmpStr:=PathConv(s)+#0;
+  tmpStr:=PathConv(s);
   tmpLock:=0;
 
   { Changing the directory is a pretty complicated affair }
   {   1) Obtain a lock on the directory                   }
   {   2) CurrentDir the lock                              }
-  tmpLock:=Lock(@tmpStr,SHARED_LOCK);
+  tmpLock:=Lock(pchar(tmpStr),SHARED_LOCK);
   if tmpLock=0 then begin
     dosError2InOut(IoErr);
     exit;
@@ -81,14 +82,7 @@ begin
   if assigned(FIB) then dispose(FIB);
 end;
 
-Procedure ChDir(s: pchar;len:sizeuint);[IOCheck, public, alias : 'FPC_SYS_CHDIR'];
-begin
-  If not assigned(s) or (len=0) or (InOutRes <> 0) then
-    exit;
-  sys_chdir(s);
-end;
-
-procedure GetDir (DriveNr: byte; var Dir: ShortString);
+procedure do_GetDir (DriveNr: byte; var Dir: RawByteString);
 var tmpbuf: array[0..255] of char;
 begin
   checkCTRLC;
@@ -97,5 +91,8 @@ begin
   if not GetCurrentDirName(tmpbuf,256) then
     dosError2InOut(IoErr)
   else
-    Dir:=strpas(tmpbuf);
+    begin
+      Dir:=tmpbuf;
+      SetCodePage(Dir,DefaultFileSystemCodePage,false);
+    end;
 end;

+ 3 - 3
rtl/amiga/sysfile.inc

@@ -170,7 +170,7 @@ begin
   end;
 end;
 
-procedure do_erase(p : pchar);
+procedure do_erase(p : pchar; pchangeable: boolean);
 var
   tmpStr: array[0..255] of Char;
 begin
@@ -180,7 +180,7 @@ begin
     dosError2InOut(IoErr);
 end;
 
-procedure do_rename(p1,p2 : pchar);
+procedure do_rename(p1,p2 : pchar; p1changeable, p2changeable: boolean);
 { quite stack-effective code, huh? :) damn path conversions... (KB) }
 var
   tmpStr1: array[0..255] of Char;
@@ -306,7 +306,7 @@ begin
   end;
 end;
 
-procedure do_open(var f;p:pchar;flags:longint);
+procedure do_open(var f;p:pchar;flags:longint; pchangeable: boolean);
 {
   filerec and textrec have both handle and mode as the first items so
   they could use the same routine for opening/creating.

+ 35 - 0
rtl/amiga/sysos.inc

@@ -146,3 +146,38 @@ begin
   PathConv:=path;
 end;
 
+{ Converts an Unix-like path to Amiga-like path }
+function PathConv(const path: rawbytestring): rawbytestring; alias: 'PATHCONVRBS'; [public];
+var tmppos: longint;
+begin
+  { check for short paths }
+  if length(path)<=2 then begin
+    if (path='.') or (path='./') then PathConv:='' else
+    if path='..' then PathConv:='/' else
+    if path='*' then PathConv:='#?'
+    else PathConv:=path;
+  end else begin
+    { convert parent directories }
+    PathConv:=path;
+    tmppos:=pos('../',PathConv);
+    while tmppos<>0 do begin
+      { delete .. to have / as parent dir sign }
+      delete(PathConv,tmppos,2);
+      tmppos:=pos('../',PathConv);
+    end;
+    { convert current directories }
+    tmppos:=pos('./',PathConv);
+    while tmppos<>0 do begin
+      { delete ./ since we doesn't need to sign current directory }
+      delete(PathConv,tmppos,2);
+      tmppos:=pos('./',PathConv);
+    end;
+    { convert wildstart to #? }
+    tmppos:=pos('*',PathConv);
+    while tmppos<>0 do begin
+      delete(PathConv,tmppos,1);
+      insert('#?',PathConv,tmppos);
+      tmppos:=pos('*',PathConv);
+    end;
+  end;
+end;

+ 51 - 68
rtl/amiga/sysutils.pp

@@ -27,6 +27,12 @@ interface
 
 {$DEFINE HAS_SLEEP}
 {$DEFINE HAS_OSERROR}
+
+{ used OS file system APIs use ansistring }
+{$define SYSUTILS_HAS_ANSISTR_FILEUTIL_IMPL}
+{ OS has an ansistring/single byte environment variable API }
+{$define SYSUTILS_HAS_ANSISTR_ENVVAR_IMPL}
+
 { Include platform independent interface part }
 {$i sysutilh.inc}
 
@@ -57,6 +63,7 @@ uses dos,sysconst;
 
 { * Followings are implemented in the system unit! * }
 function PathConv(path: shortstring): shortstring; external name 'PATHCONV';
+function PathConv(path: RawByteString): shortstring; external name 'PATHCONVRBS';
 procedure AddToList(var l: Pointer; h: LongInt); external name 'ADDTOLIST';
 function RemoveFromList(var l: Pointer; h: LongInt): boolean; external name 'REMOVEFROMLIST';
 function CheckInList(var l: Pointer; h: LongInt): pointer; external name 'CHECKINLIST';
@@ -106,14 +113,14 @@ end;
 
 (****** non portable routines ******)
 
-function FileOpen(const FileName: string; Mode: Integer): LongInt;
+function FileOpen(const FileName: rawbytestring; Mode: Integer): LongInt;
 var
+  SystemFileName: RawByteString;
   dosResult: LongInt;
-  tmpStr   : array[0..255] of char;
 begin
+  SystemFileName:=PathConv(ToSingleByteFileSystemEncodedFileName(FileName));
   {$WARNING FIX ME! To do: FileOpen Access Modes}
-  tmpStr:=PathConv(FileName)+#0;
-  dosResult:=Open(@tmpStr,MODE_OLDFILE);
+  dosResult:=Open(PChar(SystemFileName),MODE_OLDFILE);
   if dosResult=0 then
     dosResult:=-1
   else
@@ -136,13 +143,13 @@ begin
 end;
 
 
-function FileCreate(const FileName: string) : LongInt;
+function FileCreate(const FileName: RawByteString) : LongInt;
 var
+  SystemFileName: RawByteString;
   dosResult: LongInt;
-  tmpStr   : array[0..255] of char;
 begin
- tmpStr:=PathConv(FileName)+#0;
- dosResult:=Open(@tmpStr,MODE_NEWFILE);
+ SystemFileName:=PathConv(ToSingleByteFileSystemEncodedFileName(FileName));
+ dosResult:=Open(PChar(FileName),MODE_NEWFILE);
  if dosResult=0 then
    dosResult:=-1
  else
@@ -152,13 +159,13 @@ begin
 end;
 
 
-function FileCreate(const FileName: string; Rights: integer): LongInt;
+function FileCreate(const FileName: RawByteString; Rights: integer): LongInt;
 begin
   {$WARNING FIX ME! To do: FileCreate Access Modes}
   FileCreate:=FileCreate(FileName);
 end;
 
-function FileCreate(const FileName: string; ShareMode: integer; Rights : Integer): LongInt;
+function FileCreate(const FileName: RawByteString; ShareMode: integer; Rights : Integer): LongInt;
 begin
   {$WARNING FIX ME! To do: FileCreate Access Modes}
   FileCreate:=FileCreate(FileName);
@@ -231,33 +238,33 @@ begin
 end;
 
 
-function DeleteFile(const FileName: string) : Boolean;
+function DeleteFile(const FileName: RawByteString) : Boolean;
 var
-  tmpStr: array[0..255] of char;
+  SystemFileName: RawByteString;
 begin
-  tmpStr:=PathConv(FileName)+#0;
+  SystemFileName:=PathConv(ToSingleByteFileSystemEncodedFileName(FileName));
 
-  DeleteFile:=dosDeleteFile(@tmpStr);
+  DeleteFile:=dosDeleteFile(PChar(SystemFileName));
 end;
 
 
 function RenameFile(const OldName, NewName: string): Boolean;
 var
-  tmpOldName, tmpNewName: array[0..255] of char;
+  OldSystemFileName, NewSystemFileName: RawByteString;
 begin
-  tmpOldName:=PathConv(OldName)+#0;
-  tmpNewName:=PathConv(NewName)+#0;
+  OldSystemFileName:=PathConv(ToSingleByteFileSystemEncodedFileName(OldName));
+  NewSystemFileName:=PathConv(ToSingleByteFileSystemEncodedFileName(NewName));
 
-  RenameFile:=dosRename(tmpOldName, tmpNewName);
+  RenameFile:=dosRename(PChar(OldSystemFileName), PChar(NewSystemFileName));
 end;
 
 
 (****** end of non portable routines ******)
 
 
-function FileAge (const FileName : String): Longint;
+function FileAge (const FileName : RawByteString): Longint;
 var
-  tmpName: String;
+  tmpName: RawByteString;
   tmpLock: Longint;
   tmpFIB : PFileInfoBlock;
   tmpDateTime: TDateTime;
@@ -265,7 +272,7 @@ var
 
 begin
   validFile:=false;
-  tmpName := PathConv(FileName);
+  tmpName := PathConv(ToSingleByteFileSystemEncodedFileName(FileName));
   tmpLock := dosLock(tmpName, SHARED_LOCK);
 
   if (tmpLock <> 0) then begin
@@ -284,16 +291,15 @@ begin
 end;
 
 
-function FileExists (const FileName : String) : Boolean;
+function FileExists (const FileName : RawByteString) : Boolean;
 var
-  tmpName: String;
   tmpLock: LongInt;
   tmpFIB : PFileInfoBlock;
-
+  SystemFileName: RawByteString;
 begin
   result:=false;
-  tmpName := PathConv(FileName);
-  tmpLock := dosLock(tmpName, SHARED_LOCK);
+  SystemFileName:=PathConv(ToSingleByteFileSystemEncodedFileName(FileName));
+  tmpLock := dosLock(PChar(SystemFileName), SHARED_LOCK);
 
   if (tmpLock <> 0) then begin
     new(tmpFIB);
@@ -305,15 +311,15 @@ begin
 end;
 
 
-function FindFirst(const Path: String; Attr : Longint; out Rslt: TSearchRec): Longint;
+Function InternalFindFirst (Const Path : RawByteString; Attr : Longint; out Rslt : TAbstractSearchRec; var Name: RawByteString) : Longint;
 var
-  tmpStr: array[0..255] of Char;
+  tmpStr: RawByteString;
   Anchor: PAnchorPath;
   tmpDateTime: TDateTime;
   validDate: boolean;
 begin
   result:=-1; { We emulate Linux/Unix behaviour, and return -1 on errors. }
-  tmpStr:=PathConv(path)+#0;
+  tmpStr:=PathConv(ToSingleByteEncodedFileName(path));
 
   { $1e = faHidden or faSysFile or faVolumeID or faDirectory }
   Rslt.ExcludeAttr := (not Attr) and ($1e);
@@ -322,11 +328,12 @@ begin
   new(Anchor);
   FillChar(Anchor^,sizeof(TAnchorPath),#0);
 
-  if MatchFirst(@tmpStr,Anchor)<>0 then exit;
+  if MatchFirst(pchar(tmpStr),Anchor)<>0 then exit;
   Rslt.FindHandle := longint(Anchor);
 
   with Anchor^.ap_Info do begin
-    Rslt.Name := StrPas(fib_FileName);
+    Name := fib_FileName;
+    SetCodePage(Name,DefaultFileSystemCodePage,false);
 
     Rslt.Size := fib_Size;
     Rslt.Time := DateTimeToFileDate(AmigaFileDateToDateTime(fib_Date,validDate));
@@ -344,7 +351,7 @@ begin
 end;
 
 
-function FindNext (var Rslt : TSearchRec): Longint;
+Function InternalFindNext (var Rslt : TAbstractSearchRec; var Name : RawByteString) : Longint;
 var
   Anchor: PAnchorPath;
   validDate: boolean;
@@ -356,7 +363,8 @@ begin
   if MatchNext(Anchor) <> 0 then exit;
 
   with Anchor^.ap_Info do begin
-    Rslt.Name := StrPas(fib_FileName);
+    Name := fib_FileName;
+    SetCodePage(Name,DefaultFileSystemCodePage,false);
     Rslt.Size := fib_Size;
     Rslt.Time := DateTimeToFileDate(AmigaFileDateToDateTime(fib_Date,validDate));
     if not validDate then exit;
@@ -372,20 +380,21 @@ begin
 end;
 
 
-procedure FindClose(var f: TSearchRec);
+Procedure InternalFindClose(var Handle: THandle);
 var
   Anchor: PAnchorPath;
 begin
-  Anchor:=PAnchorPath(f.FindHandle);
+  Anchor:=PAnchorPath(Handle);
   if not assigned(Anchor) then exit;
   MatchEnd(Anchor);
   Dispose(Anchor);
+  Handle:=THandle(nil);
 end;
 
 
 (****** end of non portable routines ******)
 
-Function FileGetAttr (Const FileName : String) : Longint;
+Function FileGetAttr (Const FileName : RawByteString) : Longint;
 var
  F: file;
  attr: word;
@@ -399,7 +408,7 @@ begin
 end;
 
 
-Function FileSetAttr (Const Filename : String; Attr: longint) : Longint;
+Function FileSetAttr (Const Filename : RawByteString; Attr: longint) : Longint;
 var
  F: file;
 begin
@@ -461,44 +470,18 @@ Begin
   DiskSize := dos.DiskSize(Drive);
 End;
 
-function GetCurrentDir : String;
-begin
-  GetDir (0,Result);
-end;
-
-
-Function SetCurrentDir (Const NewDir : String) : Boolean;
-begin
-  ChDir(NewDir);
-  result := (IOResult = 0);
-end;
-
-
-Function CreateDir (Const NewDir : String) : Boolean;
-begin
-  MkDir(NewDir);
-  result := (IOResult = 0);
-end;
-
-
-Function RemoveDir (Const Dir : String) : Boolean;
-begin
-  RmDir(Dir);
-  result := (IOResult = 0);
-end;
-
-
-function DirectoryExists(const Directory: string): Boolean;
+function DirectoryExists(const Directory: RawBytetring): Boolean;
 var
   tmpStr : String;
   tmpLock: LongInt;
   FIB    : PFileInfoBlock;
+  SystemFileName: RawByteString;
 begin
   result:=false;
   if (Directory='') or (InOutRes<>0) then exit;
-  tmpStr:=PathConv(Directory);
+  SystemFileName:=PathConv(ToSingleByteFileSystemEncodedFileName(FileName));
 
-  tmpLock:=dosLock(tmpStr,SHARED_LOCK);
+  tmpLock:=dosLock(PChar(SystemFileName),SHARED_LOCK);
   if tmpLock=0 then exit;
 
   FIB:=nil; new(FIB);
@@ -591,7 +574,7 @@ begin
   Result:=Dos.envCount;
 end;
 
-Function GetEnvironmentString(Index : Integer) : String;
+Function GetEnvironmentString(Index : Integer) : {$ifdef FPC_RTL_UNICODE}UnicodeString{$else}AnsiString{$endif};
 
 begin
   // Result:=FPCGetEnvStrFromP(Envp,Index);

+ 24 - 0
rtl/atari/rtldefs.inc

@@ -0,0 +1,24 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2012 by Free Pascal development team
+
+    This file contains platform-specific defines that are used in
+    multiple RTL units.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{ the single byte OS APIs always use UTF-8 }
+{ define FPCRTL_FILESYSTEM_UTF8}
+
+{ The OS supports a single byte file system operations API that we use }
+{$define FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+
+{ The OS supports a two byte file system operations API that we use }
+{ define FPCRTL_FILESYSTEM_TWO_BYTE_API}

+ 24 - 0
rtl/beos/rtldefs.inc

@@ -0,0 +1,24 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2012 by Free Pascal development team
+
+    This file contains platform-specific defines that are used in
+    multiple RTL units.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{ the single byte OS APIs always use UTF-8 }
+{ define FPCRTL_FILESYSTEM_UTF8}
+
+{ The OS supports a single byte file system operations API that we use }
+{$define FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+
+{ The OS supports a two byte file system operations API that we use }
+{ define FPCRTL_FILESYSTEM_TWO_BYTE_API}

+ 24 - 0
rtl/darwin/rtldefs.inc

@@ -0,0 +1,24 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2012 by Free Pascal development team
+
+    This file contains platform-specific defines that are used in
+    multiple RTL units.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{ the single byte OS APIs always use UTF-8 }
+{$define FPCRTL_FILESYSTEM_UTF8}
+
+{ The OS supports a single byte file system operations API that we use }
+{$define FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+
+{ The OS supports a two byte file system operations API that we use }
+{ define FPCRTL_FILESYSTEM_TWO_BYTE_API}

+ 29 - 0
rtl/embedded/rtldefs.inc

@@ -0,0 +1,29 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2012 by Free Pascal development team
+
+    This file contains platform-specific defines that are used in
+    multiple RTL units.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{ the single byte OS APIs always use UTF-8 }
+{ define FPCRTL_FILESYSTEM_UTF8}
+
+{ The OS supports a single byte file system operations API that we use }
+{$define FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+
+{ The OS supports a two byte file system operations API that we use }
+{ define FPCRTL_FILESYSTEM_TWO_BYTE_API}
+
+{ Use the shortstring version of do_getdir (should be converted to rawbytestring or
+  unicodestring for all but the OSes that don't support code pages and/or are
+  resource limited) }
+{$define FPCRTL_DO_GETDIR_SHORTSTRING}

+ 27 - 3
rtl/embedded/sysdir.inc

@@ -19,17 +19,40 @@
 {*****************************************************************************
                            Directory Handling
 *****************************************************************************}
-procedure mkdir(s: pchar;len:sizeuint);[IOCheck];
+{$if defined(FPC_HAS_FEATURE_ANSISTRINGS)}
+procedure do_mkdir(const s: rawbytestring);
 begin
   InOutRes:=3;
 end;
 
-procedure rmdir(s: pchar;len:sizeuint);[IOCheck];
+procedure do_rmdir(const s: rawbytestring);
 begin
   InOutRes:=3;
 end;
 
-procedure chdir(s: pchar;len:sizeuint);[IOCheck];
+procedure do_chdir(const s: rawbytestring);
+begin
+  InOutRes:=3;
+end;
+
+procedure do_GetDir (DriveNr: byte; var Dir: RawByteString);
+begin
+  InOutRes:=3;
+end;
+
+{$else FPC_HAS_FEATURE_ANSISTRINGS}
+
+procedure mkdir(const s: shortstring);
+begin
+  InOutRes:=3;
+end;
+
+procedure rmdir(const s: shortstring);
+begin
+  InOutRes:=3;
+end;
+
+procedure chdir(const s: shortstring);
 begin
   InOutRes:=3;
 end;
@@ -38,6 +61,7 @@ procedure GetDir (DriveNr: byte; var Dir: ShortString);
 begin
   InOutRes:=3;
 end;
+{$endif FPC_HAS_FEATURE_ANSISTRINGS}
 
 
 

+ 3 - 3
rtl/embedded/sysfile.inc

@@ -27,11 +27,11 @@ begin
 
 end;
 
-procedure do_erase(p : pchar);
+procedure do_erase(p : pchar; pchangeable: boolean);
 begin
 end;
 
-procedure do_rename(p1,p2 : pchar);
+procedure do_rename(p1,p2 : pchar; p1changeable, p2changeable: boolean);
 begin
 end;
 
@@ -69,7 +69,7 @@ procedure do_truncate(handle, pos: longint);
 begin
 end;
 
-procedure do_open(var f;p:pchar;flags:longint);
+procedure do_open(var f;p:pchar;flags:longint; pchangeable: boolean);
 begin
 end;
 

+ 20 - 39
rtl/embedded/sysutils.pp

@@ -20,6 +20,11 @@ unit sysutils;
 
 interface
 
+{ used OS file system APIs use ansistring }
+{$define SYSUTILS_HAS_ANSISTR_FILEUTIL_IMPL}
+{ OS has an ansistring/single byte environment variable API }
+{$define SYSUTILS_HAS_ANSISTR_ENVVAR_IMPL}
+
   { Include platform independent interface part }
   {$i sysutilh.inc}
 
@@ -34,7 +39,7 @@ uses
 {****************************************************************************
                               File Functions
 ****************************************************************************}
-function FileOpen(const FileName: string; Mode: Integer): LongInt;
+function FileOpen(const FileName: RawByteString; Mode: Integer): LongInt;
 begin
   result := -1;
 end;
@@ -52,19 +57,19 @@ begin
 end;
 
 
-function FileCreate(const FileName: string) : LongInt;
+function FileCreate(const FileName: RawByteString) : LongInt;
 begin
   result := -1;
 end;
 
 
-function FileCreate(const FileName: string; Rights: integer): LongInt;
+function FileCreate(const FileName: RawByteString; Rights: integer): LongInt;
 begin
   result := -1;
 end;
 
 
-function FileCreate(const FileName: string; ShareMode: integer; rights : integer): LongInt;
+function FileCreate(const FileName: RawByteString; ShareMode: integer; rights : integer): LongInt;
 begin
   result := -1;
 end;
@@ -104,54 +109,54 @@ begin
 end;
 
 
-function DeleteFile(const FileName: string) : Boolean;
+function DeleteFile(const FileName: RawByteString) : Boolean;
 begin
   result := false;
 end;
 
 
-function RenameFile(const OldName, NewName: string): Boolean;
+function RenameFile(const OldName, NewName: RawByteString): Boolean;
 begin
   result := false;
 end;
 
 
-Function FileAge (Const FileName : String): Longint;
+Function FileAge (Const FileName : RawByteString): Longint;
 begin
   result := -1;
 end;
 
 
-Function FileExists (Const FileName : String) : Boolean;
+Function FileExists (Const FileName : RawByteString) : Boolean;
 Begin
   result := false;
 end;
 
 
-Function FindFirst (Const Path : String; Attr : Longint; Out Rslt : TSearchRec) : Longint;
+Function InternalFindFirst (Const Path : RawByteString; Attr : Longint; out Rslt : TAbstractSearchRec; var Name: RawByteString) : Longint;
 begin
   result := -1;
 end;
 
 
-Function FindNext (Var Rslt : TSearchRec) : Longint;
+Function InternalFindNext (var Rslt : TAbstractSearchRec; var Name : RawByteString) : Longint;
 begin
   result := -1;
 end;
 
 
-Procedure FindClose (Var F : TSearchrec);
+Procedure InternalFindClose(var Handle: THandle);
 begin
 end;
 
 
-Function FileGetAttr (Const FileName : String) : Longint;
+Function FileGetAttr (Const FileName : RawByteString) : Longint;
 begin
   result := -1;
 end;
 
 
-Function FileSetAttr (Const Filename : String; Attr: longint) : Longint;
+Function FileSetAttr (Const Filename : RawByteString; Attr: longint) : Longint;
 begin
   result := -1;
 end;
@@ -178,31 +183,7 @@ Begin
 End;
 
 
-Function GetCurrentDir : String;
-begin
-  result := '';
-end;
-
-
-Function SetCurrentDir (Const NewDir : String) : Boolean;
-begin
-  result := false;
-end;
-
-
-Function CreateDir (Const NewDir : String) : Boolean;
-begin
-  result := false;
-end;
-
-
-Function RemoveDir (Const Dir : String) : Boolean;
-begin
-  result := false;
-end;
-
-
-function DirectoryExists(const Directory: string): Boolean;
+function DirectoryExists(const Directory: RawByteString): Boolean;
 begin
   result := false;
 end;
@@ -249,7 +230,7 @@ begin
 end;
 
 
-Function GetEnvironmentString(Index : Integer) : String;
+Function GetEnvironmentString(Index : Integer) : {$ifdef FPC_RTL_UNICODE}UnicodeString{$else}AnsiString{$endif};
 begin
   result := '';
 end;

+ 10 - 4
rtl/emx/dos.pas

@@ -944,8 +944,11 @@ var
  buffer:array[0..255] of char;
 begin
   DosError := 0;
-  path:='';
-  path := StrPas(filerec(f).Name);
+{$ifdef FPC_ANSI_TEXTFILEREC}
+  path:=filerec(f).Name;
+{$else}
+  path:=ToSingleByteFileSystemEncodedFileName(filerec(f).Name);
+{$endif}
   { Takes care of slash and backslash support }
   path:=FExpand(path);
   move(path[1],buffer,length(path));
@@ -974,9 +977,12 @@ var
  path:  pathstr;
  buffer:array[0..255] of char;
 begin
-  path:='';
   DosError := 0;
-  path := StrPas(filerec(f).Name);
+{$ifdef FPC_ANSI_TEXTFILEREC}
+  path:=filerec(f).Name;
+{$else}
+  path:=ToSingleByteFileSystemEncodedFileName(filerec(f).Name);
+{$endif}
   { Takes care of slash and backslash support }
   path:=FExpand(path);
   move(path[1],buffer,length(path));

+ 24 - 0
rtl/emx/rtldefs.inc

@@ -0,0 +1,24 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2012 by Free Pascal development team
+
+    This file contains platform-specific defines that are used in
+    multiple RTL units.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{ the single byte OS APIs always use UTF-8 }
+{ define FPCRTL_FILESYSTEM_UTF8}
+
+{ The OS supports a single byte file system operations API that we use }
+{$define FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+
+{ The OS supports a two byte file system operations API that we use }
+{ define FPCRTL_FILESYSTEM_TWO_BYTE_API}

+ 35 - 40
rtl/emx/sysdir.inc

@@ -3,7 +3,7 @@
     Copyright (c) 1999-2000 by Florian Klaempfl and Pavel Ozerski
     member of the Free Pascal development team.
 
-    FPC Pascal system unit for the Win32 API.
+    FPC Pascal system unit for EMX.
 
     See the file COPYING.FPC, included in this distribution,
     for details about the copyright.
@@ -19,7 +19,7 @@
                            Directory Handling
 *****************************************************************************}
 
-procedure DosDir (Func: byte; S: PChar);
+procedure DosDir (Func: byte; S: rawbytestring);
 
 begin
   DoDirSeparators (S);
@@ -33,17 +33,14 @@ begin
   end ['eax', 'edx'];
 end;
 
-procedure MkDir (S: pchar; Len: SizeUInt); [IOCheck, public, alias: 'FPC_SYS_MKDIR'];
+procedure do_MkDir (S: rawbytestring);
 var 
   RC: cardinal;
 begin
-  if not Assigned (S) or (Len = 0) or (InOutRes <> 0) then
-   Exit;
-
   if os_mode = osOs2 then
    begin
     DoDirSeparators (S);
-    RC := DosCreateDir (S, nil);
+    RC := DosCreateDir (pchar(S), nil);
     if RC <> 0 then
      begin
       InOutRes := RC;
@@ -60,49 +57,46 @@ begin
 end;
 
 
-procedure RmDir (S: PChar; Len: SizeUInt); [IOCheck, public, alias: 'FPC_SYS_RMDIR'];
+procedure do_RmDir (S: rawbytestring);
 var
   RC: cardinal;
 begin
-  if Assigned (S) and (Len <> 0) and (InOutRes = 0) then
-   begin
-    if (Len = 1) and (S^ = '.') then
-     InOutRes := 16
-    else
-     if os_mode = osOs2 then
+  if S = '.' then
+   InOutRes := 16
+  else
+   if os_mode = osOs2 then
+    begin
+     DoDirSeparators (S);
+     RC := DosDeleteDir (pchar(S));
+     if RC <> 0 then
       begin
-       DoDirSeparators (S);
-       RC := DosDeleteDir (S);
-       if RC <> 0 then
-        begin
-         InOutRes := RC;
-         Errno2InOutRes;
-        end;
-      end
-     else
-     { Under EMX 0.9d DOS this routine call may sometimes fail   }
-     { The syscall documentation indicates clearly that this     }
-     { routine was NOT tested.                                   }
-      DosDir ($3A, S);
-   end
+       InOutRes := RC;
+       Errno2InOutRes;
+      end;
+    end
+   else
+   { Under EMX 0.9d DOS this routine call may sometimes fail   }
+   { The syscall documentation indicates clearly that this     }
+   { routine was NOT tested.                                   }
+    DosDir ($3A, S);
 end;
 
 
 {$ASMMODE INTEL}
 
-procedure ChDir (S: PChar; Len: SizeUInt); [IOCheck, public, alias: 'FPC_SYS_CHDIR'];
+procedure do_ChDir (S: rawbytestring);
 var
   RC: cardinal;
+  Len: longint;
 begin
-  if not Assigned (S) or (Len = 0) or (InOutRes <> 0) then
-    exit;
 (* According to EMX documentation, EMX has only one current directory
    for all processes, so we'll use native calls under OS/2. *)
+  Len := Length (S);
   if os_Mode = osOS2 then
    begin
-    if (Len >= 2) and (S [1] = ':') then
+    if (Len >= 2) and (S [2] = ':') then
      begin
-      RC := DosSetDefaultDisk ((Ord (S^) and not ($20)) - $40);
+      RC := DosSetDefaultDisk ((Ord (S[1]) and not ($20)) - $40);
       if RC <> 0 then
        begin
         InOutRes := RC;
@@ -112,7 +106,7 @@ begin
        if Len > 2 then
         begin
          DoDirSeparators (S);
-         RC := DosSetCurrentDir (S);
+         RC := DosSetCurrentDir (pchar(S));
          if RC <> 0 then
           begin
            InOutRes := RC;
@@ -123,7 +117,7 @@ begin
     else
      begin
       DoDirSeparators (S);
-      RC := DosSetCurrentDir (S);
+      RC := DosSetCurrentDir (pchar(S));
       if RC <> 0 then
        begin
         InOutRes:= RC;
@@ -132,7 +126,7 @@ begin
      end;
    end
   else
-   if (Len >= 2) and (S [1] = ':') then
+   if (Len >= 2) and (S [2] = ':') then
     begin
      asm
       mov esi, S
@@ -163,7 +157,7 @@ end;
 
 {$ASMMODE ATT}
 
-procedure GetDir (DriveNr: byte; var Dir: ShortString);
+procedure do_GetDir (DriveNr: byte; var Dir: RawByteString);
 
 {Written by Michael Van Canneyt.}
 
@@ -171,6 +165,7 @@ var sof:Pchar;
     i:byte;
 
 begin
+    SetLength(Dir,260);
     Dir [4] := #0;
     { Used in case the specified drive isn't available }
     sof:=pchar(@dir[4]);
@@ -189,7 +184,6 @@ begin
     end [ 'eax','edx','esi'];
     { Now Dir should be filled with directory in ASCIIZ, }
     { starting from dir[4]                               }
-    dir[0]:=#3;
     dir[2]:=':';
     dir[3]:='\';
     i:=4;
@@ -199,10 +193,9 @@ begin
             { convert path name to DOS }
 			     if dir[i] in AllowDirectorySeparators then
 			       dir[i]:=DirectorySeparator;
-            dir[0]:=char(i);
             inc(i);
         end;
-    { upcase the string (FPC function) }
+    SetLength(dir,i-1);
     if drivenr<>0 then   { Drive was supplied. We know it }
         dir[1]:=chr(64+drivenr)
     else
@@ -217,5 +210,7 @@ begin
             end ['eax'];
             dir[1]:=char(i);
         end;
+    SetCodePage(dir,DefaultFileSystemCodePage,false);
+    { upcase the string (FPC function) }
     if not (FileNameCasePreserving) then dir:=upcase(dir);
 end;

+ 26 - 11
rtl/emx/sysfile.inc

@@ -40,10 +40,12 @@ begin
    end;
 end;
 
-procedure do_erase(p:Pchar);
-
+procedure do_erase(p:Pchar; pchangeable: boolean);
+var
+  oldp: pchar;
 begin
-    DoDirSeparators(p);
+    oldp:=p;
+    DoDirSeparators(p,pchangeable);
     asm
         movl P,%edx
         movb $0x41,%ah
@@ -52,13 +54,18 @@ begin
         movw %ax,inoutres
     .LERASE1:
     end ['eax', 'edx'];
+    if p<>oldp then
+      freemem(p);
 end;
 
-procedure do_rename(p1,p2:Pchar);
-
+procedure do_rename(p1,p2:Pchar; p1changeable, p2changeable: boolean);
+var
+  oldp1, oldp2 : pchar;
 begin
-    DoDirSeparators(p1);
-    DoDirSeparators(p2);
+    oldp1:=p1;
+    oldp2:=p2;
+    DoDirSeparators(p1,p1changeable);
+    DoDirSeparators(p2,p2changeable);
     asm
         movl P1, %edx
         movl P2, %edi
@@ -68,6 +75,10 @@ begin
         movw %ax,inoutres
     .LRENAME1:
     end ['eax', 'edx', 'edi'];
+  if p1<>oldp1 then
+    freemem(p1);
+  if p2<>oldp2 then
+    freemem(p2);
 end;
 
 function do_read (H: THandle; Addr: pointer; Len: longint): longint; assembler;
@@ -254,7 +265,7 @@ begin
         end;
 end;
 
-procedure do_open(var f;p:pchar;flags:longint);
+procedure do_open(var f;p:pchar;flags:longint; pchangeable: boolean);
 
 {
   filerec and textrec have both handle and mode as the first items so
@@ -264,10 +275,10 @@ procedure do_open(var f;p:pchar;flags:longint);
   when (flags and $10000) there is no check for close (needed for textfiles)
 }
 
-var Action: cardinal;
-
+var
+  Action: cardinal;
+  oldp : pchar;
 begin
-    DoDirSeparators(p);
     { close first if opened }
     if ((flags and $10000)=0) then
         begin
@@ -309,6 +320,8 @@ begin
             end;
             exit;
         end;
+    oldp:=p;
+    DoDirSeparators(p,pchangeable);
     Action := Action or (Flags and $FF);
 (* DenyNone if sharing not specified. *)
     if Flags and 112 = 0 then
@@ -356,6 +369,8 @@ begin
                     FileRec (F).Mode := fmOutput; {fool fmappend}
                 end;
         end;
+    if oldp<>p then
+      freemem(p);
 end;
 
 {$ASMMODE INTEL}

+ 99 - 107
rtl/emx/sysutils.pp

@@ -26,6 +26,12 @@ uses
  Dos;
 
 {$DEFINE HAS_SLEEP}
+
+{ used OS file system APIs use ansistring }
+{$define SYSUTILS_HAS_ANSISTR_FILEUTIL_IMPL}
+{ OS has an ansistring/single byte environment variable API }
+{$define SYSUTILS_HAS_ANSISTR_ENVVAR_IMPL}
+
 { Include platform independent interface part }
 {$i sysutilh.inc}
 
@@ -452,7 +458,7 @@ const
                              specification for DosFindFirst call.}
 
 {$ASMMODE INTEL}
-function FileOpen (const FileName: string; Mode: integer): longint; assembler;
+function FileOpen (const FileName: pointer; Mode: integer): longint; assembler;
 asm
  push ebx
 {$IFDEF REGCALL}
@@ -477,21 +483,28 @@ asm
  pop ebx
 end {['eax', 'ebx', 'ecx', 'edx']};
 
+function FileOpen (const FileName: rawbytestring; Mode: integer): longint;
+var
+  SystemFileName: RawByteString;
+begin
+  SystemFileName := ToSingleByteFileSystemEncodedFileName(FileName);
+  FileOpen := FileOpen(pointer(SystemFileName),Mode);
+end;
 
-function FileCreate (const FileName: string): longint;
+function FileCreate (const FileName: RawByteString): longint;
 begin
   FileCreate := FileCreate (FileName, ofReadWrite or faCreate or doDenyRW, 777);
                                                        (* Sharing to DenyAll *)
 end;
 
 
-function FileCreate (const FileName: string; Rights: integer): longint;
+function FileCreate (const FileName: RawByteString; Rights: integer): longint;
 begin
   FileCreate := FileCreate (FileName, ofReadWrite or faCreate or doDenyRW,
                                               Rights); (* Sharing to DenyAll *)
 end;
 
-function FileCreate (const FileName: string; ShareMode: integer; Rights: integer): longint; assembler;
+function FileCreate (const FileName: Pointer; ShareMode: integer; Rights: integer): longint; assembler;
 asm
  push ebx
 {$IFDEF REGCALL}
@@ -515,6 +528,13 @@ asm
  pop ebx
 end {['eax', 'ebx', 'ecx', 'edx']};
 
+function FileCreate (const FileName: RawByteString; ShareMode: integer; Rights: integer): longint;
+var
+  SystemFileName: RawByteString;
+begin
+  SystemFileName := ToSingleByteFileSystemEncodedFileName(FileName);
+  FileOpen := FileCreate(pointer(SystemFileName),ShareMode,Rights);
+end;
 
 function FileRead (Handle: longint; Out Buffer; Count: longint): longint;
                                                                      assembler;
@@ -623,7 +643,7 @@ asm
 end {['eax', 'ebx', 'ecx', 'edx']};
 
 
-function FileAge (const FileName: string): longint;
+function FileAge (const FileName: RawByteString): longint;
 var Handle: longint;
 begin
     Handle := FileOpen (FileName, 0);
@@ -637,10 +657,11 @@ begin
 end;
 
 
-function FileExists (const FileName: string): boolean;
+function FileExists (const FileName: RawByteString): boolean;
 var
   L: longint;
 begin
+  { no need to convert to DefaultFileSystemEncoding, FileGetAttr will do that }
   if FileName = '' then
    Result := false
   else
@@ -658,9 +679,10 @@ type
   end;
   PSearchRec = ^SearchRec;
 
-function FindFirst (const Path: string; Attr: longint; out Rslt: TSearchRec): longint;
+Function InternalFindFirst (Const Path : RawByteString; Attr : Longint; out Rslt : TAbstractSearchRec; var Name: RawByteString) : Longint;
 
 var
+  SystemEncodedPath: RawByteString;
   SR: PSearchRec;
   FStat: PFileFindBuf3L;
   Count: cardinal;
@@ -669,14 +691,15 @@ var
 begin
   if os_mode = osOS2 then
    begin
+    SystemEncodedPath:=ToSingleByteEncodedFileName(Path);
     New (FStat);
     Rslt.FindHandle := THandle ($FFFFFFFF);
     Count := 1;
     if FSApi64 then
-     Err := DosFindFirst (PChar (Path), Rslt.FindHandle,
+     Err := DosFindFirst (PChar (SystemEncodedPath), Rslt.FindHandle,
             Attr and FindResvdMask, FStat, SizeOf (FStat^), Count, ilStandardL)
     else
-     Err := DosFindFirst (PChar (Path), Rslt.FindHandle,
+     Err := DosFindFirst (PChar (SystemEncodedPath), Rslt.FindHandle,
             Attr and FindResvdMask, FStat, SizeOf (FStat^), Count, ilStandard);
     if (Err = 0) and (Count = 0) then
      Err := 18;
@@ -689,15 +712,16 @@ begin
       if FSApi64 then
        begin
         Rslt.Size := FStat^.FileSize;
-        Rslt.Name := FStat^.Name;
+        Name := FStat^.Name;
         Rslt.Attr := FStat^.AttrFile;
        end
       else
        begin
         Rslt.Size := PFileFindBuf3 (FStat)^.FileSize;
-        Rslt.Name := PFileFindBuf3 (FStat)^.Name;
+        Name := PFileFindBuf3 (FStat)^.Name;
         Rslt.Attr := PFileFindBuf3 (FStat)^.AttrFile;
        end;
+      SetCodePage(Name, DefaultFileSystemCodePage, false);
      end
     else
      FindClose (Rslt);
@@ -717,14 +741,15 @@ begin
       Rslt.Size := cardinal (SR^.Size);
       Rslt.Attr := SR^.Attr;
       Rslt.ExcludeAttr := 0;
-      Rslt.Name := SR^.Name;
+      Name := SR^.Name;
+      SetCodePage(Name, DefaultFileSystemCodePage, false);
      end;
     DOS.DosError := Err;
    end;
 end;
 
 
-function FindNext (var Rslt: TSearchRec): longint;
+Function InternalFindNext (var Rslt : TAbstractSearchRec; var Name : RawByteString) : Longint;
 
 var
   SR: PSearchRec;
@@ -749,15 +774,16 @@ begin
       if FSApi64 then
        begin
         Rslt.Size := FStat^.FileSize;
-        Rslt.Name := FStat^.Name;
+        Name := FStat^.Name;
         Rslt.Attr := FStat^.AttrFile;
        end
       else
        begin
         Rslt.Size := PFileFindBuf3 (FStat)^.FileSize;
-        Rslt.Name := PFileFindBuf3 (FStat)^.Name;
+        Name := PFileFindBuf3 (FStat)^.Name;
         Rslt.Attr := PFileFindBuf3 (FStat)^.AttrFile;
        end;
+      SetCodePage(Name, DefaultFileSystemCodePage, false);
      end;
     Dispose (FStat);
    end
@@ -775,29 +801,30 @@ begin
         Rslt.Size := cardinal (SR^.Size);
         Rslt.Attr := SR^.Attr;
         Rslt.ExcludeAttr := 0;
-        Rslt.Name := SR^.Name;
+        Name := SR^.Name;
+        SetCodePage(Name, DefaultFileSystemCodePage, false);
        end;
      end;
    end;
 end;
 
 
-procedure FindClose (var F: TSearchrec);
+Procedure InternalFindClose(var Handle: THandle);
 
 var SR: PSearchRec;
 
 begin
     if os_mode = osOS2 then
         begin
-            DosFindClose (F.FindHandle);
+            DosFindClose (Handle);
         end
     else
         begin
-            SR := PSearchRec (F.FindHandle);
+            SR := PSearchRec (Handle);
             DOS.FindClose (SR^);
             FreeMem (SR, SizeOf (SearchRec));
         end;
-    F.FindHandle := 0;
+    Handle := 0;
 end;
 
 
@@ -878,59 +905,56 @@ asm
 end {['eax', 'edx']};
 
 
-function FileSetAttr (const Filename: string; Attr: longint): longint; assembler;
-asm
-{$IFDEF REGCALL}
- mov ecx, edx
- mov edx, eax
-{$ELSE REGCALL}
- mov ecx, Attr
- mov edx, FileName
-{$ENDIF REGCALL}
- mov ax, 4301h
- call syscall
- mov eax, 0
- jnc @FSetAttrEnd
- mov eax, -1
-@FSetAttrEnd:
-end {['eax', 'ecx', 'edx']};
-
-
-function DeleteFile (const FileName: string): boolean; assembler;
-asm
-{$IFDEF REGCALL}
- mov edx, eax
-{$ELSE REGCALL}
- mov edx, FileName
-{$ENDIF REGCALL}
- mov ax, 4100h
- call syscall
- mov eax, 0
- jc @FDeleteEnd
- inc eax
-@FDeleteEnd:
-end {['eax', 'edx']};
-
+function FileSetAttr (const Filename: RawByteString; Attr: longint): longint;
+var
+  SystemFileName: RawByteString;
+begin
+  SystemFileName:=ToSingleByteFileSystemEncodedFileName(Filename);
+  asm
+   mov ecx, Attr
+   mov edx, SystemFileName
+   mov ax, 4301h
+   call syscall
+   mov @result, 0
+   jnc @FSetAttrEnd
+   mov @result, -1
+  @FSetAttrEnd:
+  end ['eax', 'ecx', 'edx'];
+end;
 
-function RenameFile (const OldName, NewName: string): boolean; assembler;
-asm
- push edi
-{$IFDEF REGCALL}
- mov edx, eax
- mov edi, edx
-{$ELSE REGCALL}
- mov edx, OldName
- mov edi, NewName
-{$ENDIF REGCALL}
- mov ax, 5600h
- call syscall
- mov eax, 0
- jc @FRenameEnd
- inc eax
-@FRenameEnd:
- pop edi
-end {['eax', 'edx', 'edi']};
+function DeleteFile (const FileName: string): boolean;
+var
+  SystemFileName: RawByteString;
+begin
+  SystemFileName:=ToSingleByteFileSystemEncodedFileName(Filename);
+  asm
+   mov edx, SystemFileName
+   mov ax, 4100h
+   call syscall
+   mov @result, 0
+   jc @FDeleteEnd
+   moc @result, 1
+  @FDeleteEnd:
+  end ['eax', 'edx'];
+end;
 
+function RenameFile (const OldName, NewName: string): boolean;
+var
+  OldSystemFileName, NewSystemFileName: RawByteString;
+Begin
+  OldSystemFileName:=ToSingleByteFileSystemEncodedFileName(OldName);
+  NewSystemFileName:=ToSingleByteFileSystemEncodedFileName(NewName);
+  asm
+   mov edx, OldSystemFileName
+   mov edi, NewSystemFileName
+   mov ax, 5600h
+   call syscall
+   mov @result, 0
+   jc @FRenameEnd
+   mov @result, 1
+  @FRenameEnd:
+  end ['eax', 'edx', 'edi'];
+end;
 
 {****************************************************************************
                               Disk Functions
@@ -1022,43 +1046,11 @@ begin
 end;
 
 
-function GetCurrentDir: string;
-begin
- GetDir (0, Result);
-end;
-
-
-function SetCurrentDir (const NewDir: string): boolean;
-begin
-{$I-}
- ChDir (NewDir);
- Result := (IOResult = 0);
-{$I+}
-end;
-
-
-function CreateDir (const NewDir: string): boolean;
-begin
-{$I-}
- MkDir (NewDir);
- Result := (IOResult = 0);
-{$I+}
-end;
-
-
-function RemoveDir (const Dir: string): boolean;
-begin
-{$I-}
- RmDir (Dir);
- Result := (IOResult = 0);
- {$I+}
-end;
-
-
-function DirectoryExists (const Directory: string): boolean;
+function DirectoryExists (const Directory: RawByteString): boolean;
 var
   L: longint;
 begin
+  { no need to convert to DefaultFileSystemEncoding, FileGetAttr will do that }
   if Directory = '' then
    Result := false
   else
@@ -1213,7 +1205,7 @@ end;
 Function GetEnvironmentVariable(Const EnvVar : String) : String;
 
 begin
-    GetEnvironmentVariable := StrPas (GetEnvPChar (EnvVar));
+    GetEnvironmentVariable := GetEnvPChar (EnvVar);
 end;
 
 
@@ -1225,7 +1217,7 @@ begin
 end;
 
 
-Function GetEnvironmentString(Index : Integer) : String;
+Function GetEnvironmentString(Index : Integer) : {$ifdef FPC_RTL_UNICODE}UnicodeString{$else}AnsiString{$endif};
 
 begin
   Result:=FPCGetEnvStrFromP (EnvP, Index);

+ 24 - 0
rtl/freebsd/rtldefs.inc

@@ -0,0 +1,24 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2012 by Free Pascal development team
+
+    This file contains platform-specific defines that are used in
+    multiple RTL units.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{ the single byte OS APIs always use UTF-8 }
+{ define FPCRTL_FILESYSTEM_UTF8}
+
+{ The OS supports a single byte file system operations API that we use }
+{$define FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+
+{ The OS supports a two byte file system operations API that we use }
+{ define FPCRTL_FILESYSTEM_TWO_BYTE_API}

+ 24 - 0
rtl/gba/rtldefs.inc

@@ -0,0 +1,24 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2012 by Free Pascal development team
+
+    This file contains platform-specific defines that are used in
+    multiple RTL units.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{ the single byte OS APIs always use UTF-8 }
+{ define FPCRTL_FILESYSTEM_UTF8}
+
+{ The OS supports a single byte file system operations API that we use }
+{$define FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+
+{ The OS supports a two byte file system operations API that we use }
+{ define FPCRTL_FILESYSTEM_TWO_BYTE_API}

+ 4 - 4
rtl/gba/sysdir.inc

@@ -19,22 +19,22 @@
 {*****************************************************************************
                            Directory Handling
 *****************************************************************************}
-procedure mkdir(s: pchar; len: sizeuint);[IOCheck, public, alias : 'FPC_SYS_MKDIR'];
+procedure do_mkdir(const s: rawbytestring);
 begin
 
 end;
 
-procedure rmdir(s: pchar; len: sizeuint);[IOCheck, public, alias : 'FPC_SYS_RMDIR'];
+procedure do_rmdir(const s: rawbytestring);
 begin
 
 end;
 
-procedure chdir(s: pchar; len: sizeuint);[IOCheck, public, alias : 'FPC_SYS_CHDIR'];
+procedure do_chdir(const s: rawbytestring);
 begin
 
 end;
 
-procedure GetDir(DriveNr: byte; var Dir: ShortString);
+procedure do_GetDir(DriveNr: byte; var Dir: RawByteString);
 begin
 
 end;

+ 3 - 3
rtl/gba/sysfile.inc

@@ -27,11 +27,11 @@ begin
 
 end;
 
-procedure do_erase(p : pchar);
+procedure do_erase(p : pchar; pchangeable: boolean);
 begin
 end;
 
-procedure do_rename(p1,p2 : pchar);
+procedure do_rename(p1,p2 : pchar; p1changeable, p2changeable: boolean);
 begin
 end;
 
@@ -69,7 +69,7 @@ procedure do_truncate(handle, pos: longint);
 begin
 end;
 
-procedure do_open(var f;p:pchar;flags:longint);
+procedure do_open(var f;p:pchar;flags:longint; pchangeable: boolean);
 begin
 end;
 

+ 20 - 39
rtl/gba/sysutils.pp

@@ -32,6 +32,11 @@ interface
 {$DEFINE HAS_SLEEP}
 {$DEFINE HAS_OSERROR}
 
+{ used OS file system APIs use ansistring }
+{$define SYSUTILS_HAS_ANSISTR_FILEUTIL_IMPL}
+{ OS has an ansistring/single byte environment variable API }
+{$define SYSUTILS_HAS_ANSISTR_ENVVAR_IMPL}
+
 { Include platform independent interface part }
 {$i sysutilh.inc}
 
@@ -48,7 +53,7 @@ uses
 {****************************************************************************
                               File Functions
 ****************************************************************************}
-function FileOpen(const FileName: string; Mode: Integer): LongInt;
+function FileOpen(const FileName: rawbytestring; Mode: Integer): LongInt;
 begin
   result := -1;
 end;
@@ -66,19 +71,19 @@ begin
 end;
 
 
-function FileCreate(const FileName: string) : LongInt;
+function FileCreate(const FileName: RawByteString) : LongInt;
 begin
   result := -1;
 end;
 
 
-function FileCreate(const FileName: string; Rights: integer): LongInt;
+function FileCreate(const FileName: RawByteString; Rights: integer): LongInt;
 begin
   result := -1;
 end;
 
 
-function FileCreate(const FileName: string; ShareMode: integer; rights : integer): LongInt;
+function FileCreate(const FileName: RawByteString; ShareMode: integer; rights : integer): LongInt;
 begin
   result := -1;
 end;
@@ -118,13 +123,13 @@ begin
 end;
 
 
-function DeleteFile(const FileName: string) : Boolean;
+function DeleteFile(const FileName: RawByteString) : Boolean;
 begin
   result := false;
 end;
 
 
-function RenameFile(const OldName, NewName: string): Boolean;
+function RenameFile(const OldName, NewName: RawByteString): Boolean;
 begin
   result := false;
 end;
@@ -133,41 +138,41 @@ end;
 (****** end of non portable routines ******)
 
 
-Function FileAge (Const FileName : String): Longint;
+Function FileAge (Const FileName : RawByteString): Longint;
 begin
   result := -1;
 end;
 
 
-Function FileExists (Const FileName : String) : Boolean;
+Function FileExists (Const FileName : RawByteString) : Boolean;
 Begin
   result := false;
 end;
 
 
 
-Function FindFirst (Const Path : String; Attr : Longint; Out Rslt : TSearchRec) : Longint;
+Function InternalFindFirst (Const Path : RawByteString; Attr : Longint; out Rslt : TAbstractSearchRec; var Name: RawByteString) : Longint;
 begin
   result := -1;
 end;
 
 
-Function FindNext (Var Rslt : TSearchRec) : Longint;
+Function InternalFindNext (var Rslt : TAbstractSearchRec; var Name : RawByteString) : Longint;
 begin
   result := -1;
 end;
 
-Procedure FindClose (Var F : TSearchrec);
+Procedure InternalFindClose(var Handle: THandle);
 begin
 end;
 
-Function FileGetAttr (Const FileName : String) : Longint;
+Function FileGetAttr (Const FileName : RawByteString) : Longint;
 begin
   result := -1;
 end;
 
 
-Function FileSetAttr (Const Filename : String; Attr: longint) : Longint;
+Function FileSetAttr (Const Filename : RawByteString; Attr: longint) : Longint;
 begin
   result := -1;
 end;
@@ -197,31 +202,7 @@ Begin
 End;
 
 
-Function GetCurrentDir : String;
-begin
-  result := '';
-end;
-
-
-Function SetCurrentDir (Const NewDir : String) : Boolean;
-begin
-  result := false;
-end;
-
-
-Function CreateDir (Const NewDir : String) : Boolean;
-begin
-  result := false;
-end;
-
-
-Function RemoveDir (Const Dir : String) : Boolean;
-begin
-  result := false;
-end;
-
-
-function DirectoryExists(const Directory: string): Boolean;
+function DirectoryExists(const Directory: RawByteString): Boolean;
 begin
   result := false;
 end;
@@ -290,7 +271,7 @@ begin
   result := -1;
 end;
 
-Function GetEnvironmentString(Index : Integer) : String;
+Function GetEnvironmentString(Index : Integer) : {$ifdef FPC_RTL_UNICODE}UnicodeString{$else}AnsiString{$endif};
 begin
   result := '';
 end;

+ 18 - 0
rtl/go32v2/dos.pp

@@ -1083,8 +1083,17 @@ end;
 
 
 procedure getfattr(var f;var attr : word);
+{$ifndef FPC_ANSI_TEXTFILEREC}
+var
+  r: rawbytestring;
+{$endif not FPC_ANSI_TEXTFILEREC}
 begin
+{$ifdef FPC_ANSI_TEXTFILEREC}
   copytodos(filerec(f).name,strlen(filerec(f).name)+1);
+{$else}
+  r:=ToSingleByteFileSystemEncodedFileName(filerec(f).name);
+  copytodos(pchar(r)^,length(r)+1);
+{$endif}
   dosregs.edx:=tb_offset;
   dosregs.ds:=tb_segment;
   if LFNSupport then
@@ -1101,6 +1110,10 @@ end;
 
 
 procedure setfattr(var f;attr : word);
+{$ifndef FPC_ANSI_TEXTFILEREC}
+var
+  r: rawbytestring;
+{$endif not FPC_ANSI_TEXTFILEREC}
 begin
   { Fail for setting VolumeId. }
   if ((attr and VolumeID)<>0) then
@@ -1108,7 +1121,12 @@ begin
     doserror:=5;
     exit;
   end;
+{$ifdef FPC_ANSI_TEXTFILEREC}
   copytodos(filerec(f).name,strlen(filerec(f).name)+1);
+{$else}
+  r:=ToSingleByteFileSystemEncodedFileName(filerec(f).name);
+  copytodos(pchar(r)^,length(r)+1);
+{$endif}
   dosregs.edx:=tb_offset;
   dosregs.ds:=tb_segment;
   if LFNSupport then

+ 24 - 0
rtl/go32v2/rtldefs.inc

@@ -0,0 +1,24 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2012 by Free Pascal development team
+
+    This file contains platform-specific defines that are used in
+    multiple RTL units.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{ the single byte OS APIs always use UTF-8 }
+{ define FPCRTL_FILESYSTEM_UTF8}
+
+{ The OS supports a single byte file system operations API that we use }
+{$define FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+
+{ The OS supports a two byte file system operations API that we use }
+{ define FPCRTL_FILESYSTEM_TWO_BYTE_API}

+ 28 - 24
rtl/go32v2/sysdir.inc

@@ -3,7 +3,7 @@
     Copyright (c) 1999-2000 by Florian Klaempfl and Pavel Ozerski
     member of the Free Pascal development team.
 
-    FPC Pascal system unit for the Win32 API.
+    FPC Pascal system unit for go32v2.
 
     See the file COPYING.FPC, included in this distribution,
     for details about the copyright.
@@ -18,18 +18,20 @@
                            Directory Handling
 *****************************************************************************}
 
-procedure DosDir(func:byte;s:pchar;len:integer);
+procedure DosDir(func:byte;s:rawbytestring);
 var
   regs   : trealregs;
+  len    : longint;
 begin
   DoDirSeparators(s);
   { True DOS does not like backslashes at end
     Win95 DOS accepts this !!
     but "\" and "c:\" should still be kept and accepted hopefully PM }
-  if (len>0) and (s[len-1]='\') and
-     Not ((len=1) or ((len=3) and (s[1]=':'))) then
-    s[len-1]:=#0;
-  syscopytodos(longint(s),len+1);
+  len:=length(s);
+  if (len>0) and (s[len]='\') and
+     Not ((len=1) or ((len=3) and (s[2]=':'))) then
+    s[len]:=#0;
+  syscopytodos(longint(pointer(s)),len+1);
   regs.realedx:=tb_offset;
   regs.realds:=tb_segment;
   if LFNSupport then
@@ -41,32 +43,31 @@ begin
    GetInOutRes(lo(regs.realeax));
 end;
 
-Procedure MkDir(s: pchar;len:sizeuint);[IOCheck, public, alias : 'FPC_SYS_MKDIR'];
+Procedure do_MkDir(const s: rawbytestring);
 begin
- If not assigned(s) or (len=0) or (InOutRes <> 0) then
-   exit;
-  DosDir($39,s,len);
+  DosDir($39,s);
 end;
 
-Procedure RmDir(s: pchar;len:sizeuint);[IOCheck, public, alias : 'FPC_SYS_RMDIR'];
+Procedure do_RmDir(const s: rawbytestring);
 begin
-  if (len=1) and (s[0] = '.' ) then
-    InOutRes := 16;
-  If not assigned(s) or (len=0) or (InOutRes <> 0) then
-   exit;
-  DosDir($3a,s,len);
+  if s='.' then
+    begin
+      InOutRes := 16;
+      exit;
+    end;
+  DosDir($3a,s);
 end;
 
-Procedure ChDir(s: pchar;len:sizeuint);[IOCheck, public, alias : 'FPC_SYS_CHDIR'];
+Procedure do_ChDir(const s: rawbytestring);
 var
   regs : trealregs;
+  len  : longint;
 begin
-  If not assigned(s) or (len=0) or (InOutRes <> 0) then
-   exit;
+  len:=length(s);
 { First handle Drive changes }
-  if (len>=2) and (s[1]=':') then
+  if (len>=2) and (s[2]=':') then
    begin
-     regs.realedx:=(ord(s[0]) and (not 32))-ord('A');
+     regs.realedx:=(ord(s[1]) and (not 32))-ord('A');
      regs.realeax:=$0e00;
      sysrealintr($21,regs);
      regs.realeax:=$1900;
@@ -82,10 +83,10 @@ begin
        exit;
    end;
 { do the normal dos chdir }
-  DosDir($3b,s,len);
+  DosDir($3b,s);
 end;
 
-procedure GetDir (DriveNr: byte; var Dir: ShortString);
+procedure do_GetDir (DriveNr: byte; var Dir: RawByteString);
 var
   temp : array[0..255] of char;
   i    : longint;
@@ -103,12 +104,14 @@ begin
    Begin
      GetInOutRes (lo(regs.realeax));
      Dir := char (DriveNr + 64) + ':\';
+     SetCodePage (Dir,DefaultFileSystemCodePage,false);
      exit;
    end
   else
    syscopyfromdos(longint(@temp),251);
 { conversion to Pascal string including slash conversion }
   i:=0;
+  SetLength(dir,260);
   while (temp[i]<>#0) do
    begin
      if temp[i] in AllowDirectorySeparators then
@@ -118,7 +121,8 @@ begin
    end;
   dir[2]:=':';
   dir[3]:='\';
-  dir[0]:=char(i+3);
+  SetLength(dir,i+3);
+  SetCodePage(dir,DefaultFileSystemCodePage,false);
 { upcase the string }
   if not FileNameCasePreserving then
    dir:=upcase(dir);

+ 24 - 7
rtl/go32v2/sysfile.inc

@@ -54,11 +54,13 @@ begin
 end;
 
 
-procedure do_erase(p : pchar);
+procedure do_erase(p : pchar; pchangeable: boolean);
 var
   regs : trealregs;
+  oldp : pchar;
 begin
-  DoDirSeparators(p);
+  oldp:=p;
+  DoDirSeparators(p,pchangeable);
   syscopytodos(longint(p),strlen(p)+1);
   regs.realedx:=tb_offset;
   regs.realds:=tb_segment;
@@ -71,15 +73,20 @@ begin
   sysrealintr($21,regs);
   if (regs.realflags and carryflag) <> 0 then
    GetInOutRes(lo(regs.realeax));
+  if p<>oldp then
+    freemem(p);
 end;
 
 
-procedure do_rename(p1,p2 : pchar);
+procedure do_rename(p1,p2 : pchar; p1changeable, p2changeable: boolean);
 var
   regs : trealregs;
+  oldp1, oldp2 : pchar;
 begin
-  DoDirSeparators(p1);
-  DoDirSeparators(p2);
+  oldp1:=p1;
+  oldp2:=p2;
+  DoDirSeparators(p1,p1changeable);
+  DoDirSeparators(p2,p2changeable);
   if strlen(p1)+strlen(p2)+3>tb_size then
    HandleError(217);
   sysseg_move(get_ds,longint(p2),dos_selector,tb,strlen(p2)+1);
@@ -96,6 +103,10 @@ begin
   sysrealintr($21,regs);
   if (regs.realflags and carryflag) <> 0 then
    GetInOutRes(lo(regs.realeax));
+  if p1<>oldp1 then
+    freemem(p1);
+  if p2<>oldp2 then
+    freemem(p2);
 end;
 
 
@@ -280,7 +291,7 @@ begin
 end;
 
 
-procedure do_open(var f;p:pchar;flags:longint);
+procedure do_open(var f;p:pchar;flags:longint; pchangeable: boolean);
 {
   filerec and textrec have both handle and mode as the first items so
   they could use the same routine for opening/creating.
@@ -291,8 +302,8 @@ procedure do_open(var f;p:pchar;flags:longint);
 var
   regs   : trealregs;
   action : longint;
+  oldp : pchar;
 begin
-  DoDirSeparators(p);
 { close first if opened }
   if ((flags and $10000)=0) then
    begin
@@ -334,6 +345,8 @@ begin
      end;
      exit;
    end;
+  oldp:=p;
+  DoDirSeparators(p,pchangeable);
 { real dos call }
   syscopytodos(longint(p),strlen(p)+1);
 {$ifndef RTLLITE}
@@ -385,6 +398,8 @@ begin
   if (regs.realflags and carryflag) <> 0 then
     begin
       GetInOutRes(lo(regs.realeax));
+      if oldp<>p then
+        freemem(p);
       exit;
     end
   else
@@ -419,6 +434,8 @@ begin
      do_seekend(filerec(f).handle);
      filerec(f).mode:=fmoutput; {fool fmappend}
    end;
+  if oldp<>p then
+    freemem(p);
 end;
 
 

+ 59 - 65
rtl/go32v2/sysutils.pp

@@ -28,6 +28,12 @@ uses
   go32,dos;
 
 {$DEFINE HAS_SLEEP}
+
+{ used OS file system APIs use ansistring }
+{$define SYSUTILS_HAS_ANSISTR_FILEUTIL_IMPL}
+{ OS has an ansistring/single byte environment variable API }
+{$define SYSUTILS_HAS_ANSISTR_ENVVAR_IMPL}
+
 { Include platform independent interface part }
 {$i sysutilh.inc}
 
@@ -64,12 +70,14 @@ Type
 
 {  converts S to a pchar and copies it to the transfer-buffer.   }
 
-procedure StringToTB(const S: string);
+procedure StringToTB(const S: rawbytestring);
 var
   P: pchar;
-  Len: integer;
+  Len: longint;
 begin
   Len := Length(S) + 1;
+  if Len > tb_size then
+    Len := tb_size;
   P := StrPCopy(StrAlloc(Len), S);
   SysCopyToDos(longint(P), Len);
   StrDispose(P);
@@ -78,7 +86,7 @@ end ;
 
 {  Native OpenFile function.
    if return value <> 0 call failed.  }
-function OpenFile(const FileName: string; var Handle: longint; Mode, Action: word): longint;
+function OpenFile(const FileName: rawbytestring; var Handle: longint; Mode, Action: word): longint;
 var
    Regs: registers;
 begin
@@ -110,33 +118,37 @@ begin
 end;
 
 
-Function FileOpen (Const FileName : string; Mode : Integer) : Longint;
+Function FileOpen (Const FileName : rawbytestring; Mode : Integer) : Longint;
 var
+  SystemFileName: RawByteString;
   e: integer;
-Begin
-  e := OpenFile(FileName, result, Mode, faOpen);
+begin
+  SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
+  e := OpenFile(SystemFileName, result, Mode, faOpen);
   if e <> 0 then
     result := -1;
 end;
 
 
-Function FileCreate (Const FileName : String) : Longint;
+Function FileCreate (Const FileName : RawByteString) : Longint;
 var
+  SystemFileName: RawByteString;
   e: integer;
 begin
-  e := OpenFile(FileName, result, ofReadWrite, faCreate or faOpenReplace);
+  SystemFileName := ToSingleByteFileSystemEncodedFileName(FileName);
+  e := OpenFile(SystemFileName, result, ofReadWrite, faCreate or faOpenReplace);
   if e <> 0 then
     result := -1;
 end;
 
 
-Function FileCreate (Const FileName : String; ShareMode:longint; Rights : longint) : Longint;
+Function FileCreate (Const FileName : RawByteString; ShareMode:longint; Rights : longint) : Longint;
 begin
   FileCreate:=FileCreate(FileName);
 end;
 
 
-Function FileCreate (Const FileName : String; Rights:longint) : Longint;
+Function FileCreate (Const FileName : RawByteString; Rights:longint) : Longint;
 begin
   FileCreate:=FileCreate(FileName);
 end;
@@ -270,7 +282,7 @@ begin
 end;
 
 
-Function FileAge (Const FileName : String): Longint;
+Function FileAge (Const FileName : RawByteString): Longint;
 var Handle: longint;
 begin
   Handle := FileOpen(FileName, 0);
@@ -284,7 +296,7 @@ begin
 end;
 
 
-function FileExists (const FileName: string): boolean;
+function FileExists (const FileName: RawByteString): boolean;
 var
   L: longint;
 begin
@@ -292,6 +304,7 @@ begin
    Result := false
   else
    begin
+    { no need to convert to DefaultFileSystemEncoding, FileGetAttr will do that }
     L := FileGetAttr (FileName);
     Result := (L >= 0) and (L and (faDirectory or faVolumeID) = 0);
 (* Neither VolumeIDs nor directories are files. *)
@@ -299,12 +312,13 @@ begin
 end;
 
 
-Function DirectoryExists (Const Directory : String) : Boolean;
+Function DirectoryExists (Const Directory : RawByteString) : Boolean;
 Var
-  Dir : String;
+  Dir : RawByteString;
   drive : byte;
   FADir, StoredIORes : longint;
 begin
+  { no need to convert to DefaultFileSystemEncoding, FileGetAttr will do that }
   Dir:=Directory;
   if (length(dir)=2) and (dir[2]=':') and
      ((dir[1] in ['A'..'Z']) or (dir[1] in ['a'..'z'])) then
@@ -340,7 +354,7 @@ begin
 end;
 
 
-Function FindFirst (Const Path : String; Attr : Longint; out Rslt : TSearchRec) : Longint;
+Function InternalFindFirst (Const Path : RawByteString; Attr : Longint; out Rslt : TAbstractSearchRec; var Name: RawByteString) : Longint;
 
 Var Sr : PSearchrec;
 
@@ -348,6 +362,8 @@ begin
   //!! Sr := New(PSearchRec);
   getmem(sr,sizeof(searchrec));
   Rslt.FindHandle := longint(Sr);
+  { no use in converting to defaultfilesystemcodepage, since the Dos shortstring
+    interface is called here }
   DOS.FindFirst(Path, Attr, Sr^);
   result := -DosError;
   if result = 0 then
@@ -356,12 +372,13 @@ begin
      Rslt.Size := Sr^.Size;
      Rslt.Attr := Sr^.Attr;
      Rslt.ExcludeAttr := 0;
-     Rslt.Name := Sr^.Name;
+     Name := Sr^.Name;
+     SetCodePage(Name,DefaultFileSystemCodePage,False);
    end ;
 end;
 
 
-Function FindNext (Var Rslt : TSearchRec) : Longint;
+Function InternalFindNext (var Rslt : TAbstractSearchRec; var Name : RawByteString) : Longint;
 var
   Sr: PSearchRec;
 begin
@@ -376,17 +393,18 @@ begin
         Rslt.Size := Sr^.Size;
         Rslt.Attr := Sr^.Attr;
         Rslt.ExcludeAttr := 0;
-        Rslt.Name := Sr^.Name;
+        Name := Sr^.Name;
+        SetCodePage(Name,DefaultFileSystemCodePage,False);
       end;
    end;
 end;
 
 
-Procedure FindClose (Var F : TSearchrec);
+Procedure InternalFindClose(var Handle: THandle);
 var
   Sr: PSearchRec;
 begin
-  Sr := PSearchRec(F.FindHandle);
+  Sr := PSearchRec(Handle);
   if Sr <> nil then
     begin
       //!! Dispose(Sr);
@@ -394,7 +412,7 @@ begin
       DOS.FindClose(SR^);
       freemem(sr,sizeof(searchrec));
     end;
-  F.FindHandle := 0;
+  Handle := 0;
 end;
 
 
@@ -432,11 +450,13 @@ begin
 end;
 
 
-Function FileGetAttr (Const FileName : String) : Longint;
+Function FileGetAttr (Const FileName : RawByteString) : Longint;
 var
   Regs: registers;
+  SystemFileName: RawByteString;
 begin
-  StringToTB(FileName);
+  SystemFileName:=ToSingleByteFileSystemEncodedFileName(Filename);
+  StringToTB(SystemFileName);
   Regs.Edx := tb_offset;
   Regs.Ds := tb_segment;
   if LFNSupport then
@@ -454,11 +474,13 @@ begin
 end;
 
 
-Function FileSetAttr (Const Filename : String; Attr: longint) : Longint;
+Function FileSetAttr (Const Filename : RawByteString; Attr: longint) : Longint;
 var
   Regs: registers;
+  SystemFileName: RawByteString;
 begin
-  StringToTB(FileName);
+  SystemFileName:=ToSingleByteFileSystemEncodedFileName(Filename);
+  StringToTB(SystemFileName);
   Regs.Edx := tb_offset;
   Regs.Ds := tb_segment;
   if LFNSupport then
@@ -477,11 +499,13 @@ begin
 end;
 
 
-Function DeleteFile (Const FileName : String) : Boolean;
+Function DeleteFile (Const FileName : RawByteString) : Boolean;
 var
   Regs: registers;
+  SystemFileName: RawByteString;
 begin
-  StringToTB(FileName);
+  SystemFileName:=ToSingleByteFileSystemEncodedFileName(Filename);
+  StringToTB(SystemFileName);
   Regs.Edx := tb_offset;
   Regs.Ds := tb_segment;
   if LFNSupport then
@@ -495,14 +519,17 @@ begin
 end;
 
 
-Function RenameFile (Const OldName, NewName : String) : Boolean;
+Function RenameFile (Const OldName, NewName : RawByteString) : Boolean;
 var
   Regs: registers;
-begin
-  StringToTB(OldName + #0 + NewName);
+  OldSystemFileName, NewSystemFileName: RawByteString;
+Begin
+  OldSystemFileName:=ToSingleByteFileSystemEncodedFileName(OldName);
+  NewSystemFileName:=ToSingleByteFileSystemEncodedFileName(NewName);
+  StringToTB(OldSystemFileName + #0 + NewSystemFileName);
   Regs.Edx := tb_offset;
   Regs.Ds := tb_segment;
-  Regs.Edi := tb_offset + Length(OldName) + 1;
+  Regs.Edi := tb_offset + Length(OldSystemFileName) + 1;
   Regs.Es := tb_segment;
   if LFNSupport then
     Regs.Eax := $7156
@@ -608,39 +635,6 @@ begin
 end;
 
 
-Function GetCurrentDir : String;
-begin
-  GetDir(0, result);
-end;
-
-
-Function SetCurrentDir (Const NewDir : String) : Boolean;
-begin
-  {$I-}
-   ChDir(NewDir);
-  {$I+}
-  result := (IOResult = 0);
-end;
-
-
-Function CreateDir (Const NewDir : String) : Boolean;
-begin
-  {$I-}
-   MkDir(NewDir);
-  {$I+}
-  result := (IOResult = 0);
-end;
-
-
-Function RemoveDir (Const Dir : String) : Boolean;
-begin
-  {$I-}
-   RmDir(Dir);
-  {$I+}
-  result := (IOResult = 0);
-end;
-
-
 {****************************************************************************
                               Time Functions
 ****************************************************************************}
@@ -794,7 +788,7 @@ begin
   Result:=FPCCountEnvVar(EnvP);
 end;
 
-Function GetEnvironmentString(Index : Integer) : String;
+Function GetEnvironmentString(Index : Integer) : {$ifdef FPC_RTL_UNICODE}UnicodeString{$else}AnsiString{$endif};
 
 begin
   Result:=FPCGetEnvStrFromP(Envp,Index);

+ 24 - 0
rtl/haiku/rtldefs.inc

@@ -0,0 +1,24 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2012 by Free Pascal development team
+
+    This file contains platform-specific defines that are used in
+    multiple RTL units.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{ the single byte OS APIs always use UTF-8 }
+{ define FPCRTL_FILESYSTEM_UTF8}
+
+{ The OS supports a single byte file system operations API that we use }
+{$define FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+
+{ The OS supports a two byte file system operations API that we use }
+{ define FPCRTL_FILESYSTEM_TWO_BYTE_API}

+ 117 - 84
rtl/inc/astrings.inc

@@ -59,6 +59,20 @@ Const
                     Internal functions, not in interface.
 ****************************************************************************}
 
+{$ifndef FPC_HAS_TRANSLATEPLACEHOLDERCP}
+{$define FPC_HAS_TRANSLATEPLACEHOLDERCP}
+function TranslatePlaceholderCP(cp: TSystemCodePage): TSystemCodePage; {$ifdef SYSTEMINLINE}inline;{$endif}
+begin
+  TranslatePlaceholderCP:=cp;
+  case cp of
+    CP_OEMCP,
+    CP_ACP:
+      TranslatePlaceholderCP:=DefaultSystemCodePage;
+  end;
+end;
+{$endif FPC_HAS_TRANSLATEPLACEHOLDERCP}
+
+
 {$ifndef FPC_HAS_PCHAR_ANSISTR_INTERN_CHARMOVE}
 {$define FPC_HAS_PCHAR_ANSISTR_INTERN_CHARMOVE}
 procedure fpc_pchar_ansistr_intern_charmove(const src: pchar; const srcindex: sizeint; var dst: rawbytestring; const dstindex, len: sizeint); {$ifdef FPC_HAS_CPSTRING}rtlproc;{$endif} {$ifdef SYSTEMINLINE}inline;{$endif}
@@ -200,15 +214,13 @@ Var
   S1CP, S2CP, DestCP: TSystemCodePage;
 begin
 {$ifdef FPC_HAS_CPSTRING}
-  if (Pointer(DestS)=nil) then
-    DestCP:=cp
-  else
-    DestCP:=StringCodePage(DestS);
+  DestCP:=cp;
+  if DestCp=CP_NONE then
+    DestCP:=DefaultSystemCodePage;
 {$else FPC_HAS_CPSTRING}
   DestCP:=StringCodePage(DestS);
 {$endif FPC_HAS_CPSTRING}
-  if (DestCP=CP_ACP) then
-    DestCP:=DefaultSystemCodePage;
+  DestCP:=TranslatePlaceholderCP(DestCP);
   { if codepages are different then concat using unicodestring,
     but avoid conversions if either addend is empty (StringCodePage will return
     DefaultSystemCodePage in that case, which may differ from other addend/dest) }
@@ -216,14 +228,19 @@ begin
     S1CP:=DestCP
   else
     S1CP:=StringCodePage(S1);
-  if (S1CP=CP_ACP) then
-    S1CP:=DefaultSystemCodePage;
+  S1CP:=TranslatePlaceholderCP(S1CP);
   if S2='' then
     S2CP:=DestCP
   else
     S2CP:=StringCodePage(S2);
-  if (S2CP=CP_ACP) then
-    S2CP:=DefaultSystemCodePage;
+  S2CP:=TranslatePlaceholderCP(S2CP);
+{$ifdef FPC_HAS_CPSTRING}
+  { if the result is rawbytestring and both strings have the same code page,
+    keep that code page }
+  if (cp=CP_NONE) and
+     (S1CP=S2CP) then
+    DestCP:=S1CP;
+{$endif FPC_HAS_CPSTRING}
   if (S1CP<>DestCP) or (S2CP<>DestCP) then
     begin
       ansistr_concat_complex(DestS,S1,S2,DestCP);
@@ -273,15 +290,17 @@ end;
 {$define FPC_HAS_ANSISTR_CONCAT_MULTI}
 procedure fpc_AnsiStr_Concat_multi (var DestS:RawByteString;const sarr:array of RawByteString{$ifdef FPC_HAS_CPSTRING};cp : TSystemCodePage{$endif FPC_HAS_CPSTRING}); compilerproc;
 Var
-  lowstart,i  : Longint;
+  lowstart,
+  nonemptystart,
+  i           : Longint;
   p,pc        : pointer;
   Size,NewLen,
   OldDestLen  : SizeInt;
   destcopy    : pointer;
-  DestCP      : TSystemCodePage;
   U           : UnicodeString;
-  sameCP      : Boolean;
+  DestCP,
   tmpCP       : TSystemCodePage;
+  sameCP      : Boolean;
 begin
   if high(sarr)=0 then
     begin
@@ -289,23 +308,26 @@ begin
       exit;
     end;
 {$ifdef FPC_HAS_CPSTRING}
-  if (Pointer(DestS)=nil) then
-    DestCP:=cp
-  else
-    DestCP:=StringCodePage(DestS);
+  DestCP:=cp;
+  if DestCp=CP_NONE then
+    DestCP:=DefaultSystemCodePage;
 {$else FPC_HAS_CPSTRING}
   DestCP:=StringCodePage(DestS);
 {$endif FPC_HAS_CPSTRING}
-  if (DestCP=CP_ACP) then
-    DestCP:=DefaultSystemCodePage;
+  DestCP:=TranslatePlaceholderCP(DestCP);
   sameCP:=true;
   lowstart:=low(sarr);
-  for i:=lowstart to high(sarr) do
+  { skip empty strings }
+  while (lowstart<=high(sarr)) and
+        (sarr[lowstart]='') do
+    inc(lowstart);
+  tmpCP:=TranslatePlaceholderCP(StringCodePage(sarr[lowstart]));
+  for i:=lowstart+1 to high(sarr) do
     begin
-      tmpCP:=StringCodePage(sarr[i]);
-      if tmpCP=CP_ACP then
-        tmpCP:=DefaultSystemCodePage;
-      if (DestCP<>tmpCp) then
+      { ignore the code page of empty strings, it will always be
+        DefaultSystemCodePage but it doesn't matter for the outcome }
+      if (sarr[i]<>'') and
+         (tmpCP<>TranslatePlaceholderCP(StringCodePage(sarr[i]))) then
         begin
           sameCP:=false;
           break;
@@ -314,48 +336,53 @@ begin
   if not sameCP then
     begin
       U:='';
-      for i:=lowstart to high(sarr) do begin
-        tmpCP:=StringCodePage(sarr[i]);
-        U:=U+UnicodeString(sarr[i]);
-      end;
+      for i:=lowstart to high(sarr) do
+        if sarr[i]<>'' then
+          U:=U+UnicodeString(sarr[i]);
 
       DestS:='';
       widestringmanager.Unicode2AnsiMoveProc(PUnicodeChar(Pointer(U)),DestS,DestCP,Length(U));
       exit;
     end;
-
+{$ifdef FPC_HAS_CPSTRING}
+  { if the result is rawbytestring and all strings have the same code page,
+    keep that code page }
+  if cp=CP_NONE then
+    DestCP:=tmpCP;
+{$endif FPC_HAS_CPSTRING}
   destcopy:=nil;
-  lowstart:=low(sarr);
-  if Pointer(DestS)=Pointer(sarr[lowstart]) then
-    inc(lowstart);
+  nonemptystart:=lowstart;
   { Check for another reuse, then we can't use
     the append optimization }
-  for i:=lowstart to high(sarr) do
+  if DestS<>'' then
     begin
-      if Pointer(DestS)=Pointer(sarr[i]) then
+      if Pointer(DestS)=Pointer(sarr[lowstart]) then
+        inc(lowstart);
+      for i:=lowstart to high(sarr) do
         begin
-          { if DestS is used somewhere in the middle of the expression,
-            we need to make sure the original string still exists after
-            we empty/modify DestS                                       }
-          destcopy:=pointer(dests);
-          fpc_AnsiStr_Incr_Ref(destcopy);
-          lowstart:=low(sarr);
-          break;
+          if Pointer(DestS)=Pointer(sarr[i]) then
+            begin
+              { if DestS is used somewhere in the middle of the expression,
+                we need to make sure the original string still exists after
+                we empty/modify DestS                                       }
+              destcopy:=pointer(dests);
+              fpc_AnsiStr_Incr_Ref(destcopy);
+              lowstart:=nonemptystart;
+              break;
+            end;
         end;
     end;
   { Start with empty DestS if we start with concatting
-    the first array element }
-  if lowstart=low(sarr) then
+    the first (non-empty) array element }
+  if lowstart=nonemptystart then
     DestS:='';
   OldDestLen:=length(DestS);
   { Calculate size of the result so we can do
     a single call to SetLength() }
   NewLen:=0;
-  for i:=low(sarr) to high(sarr) do
+  for i:=nonemptystart to high(sarr) do
     inc(NewLen,length(sarr[i]));
   SetLength(DestS,NewLen);
-  if (StringCodePage(DestS) <> DestCP) then
-    SetCodePage(DestS,DestCP,False);
   { Concat all strings, except the string we already
     copied in DestS }
   pc:=Pointer(DestS)+OldDestLen;
@@ -369,6 +396,8 @@ begin
           inc(pc,size);
         end;
     end;
+  SetCodePage(DestS,tmpCP,False);
+  SetCodePage(DestS,DestCP,True);
   fpc_AnsiStr_Decr_Ref(destcopy);
 end;
 {$endif FPC_HAS_ANSISTR_CONCAT_MULTI}
@@ -410,11 +439,8 @@ begin
   Size:=Length(S);
   if Size>0 then
     begin
-      if (cp=CP_ACP) then
-        cp:=DefaultSystemCodePage;
-      orgcp:=StringCodePage(S);
-      if (orgcp=CP_ACP) then
-        orgcp:=DefaultSystemCodePage;
+      cp:=TranslatePlaceholderCP(cp);
+      orgcp:=TranslatePlaceholderCP(StringCodePage(S));
       if (orgcp=cp) or (orgcp=CP_NONE) then
         begin
           SetLength(result,Size);
@@ -471,8 +497,7 @@ Var
 {$endif FPC_HAS_CPSTRING}
 begin
 {$ifdef FPC_HAS_CPSTRING}
-  if (cp=CP_ACP) then
-    cp:=DefaultSystemCodePage;
+  cp:=TranslatePlaceholderCP(cp);
 {$else FPC_HAS_CPSTRING}
   cp:=DefaultSystemCodePage;
 {$endif FPC_HAS_CPSTRING}
@@ -499,8 +524,7 @@ var
 {$endif FPC_HAS_CPSTRING}
 begin
 {$ifdef FPC_HAS_CPSTRING}
-  if (cp=CP_ACP) then
-    cp:=DefaultSystemCodePage;
+  cp:=TranslatePlaceholderCP(cp);
 {$else FPC_HAS_CPSTRING}
   cp:=DefaultSystemCodePage;
 {$endif FPC_HAS_CPSTRING}
@@ -529,8 +553,7 @@ begin
   if L > 0 then
     begin
 {$ifdef FPC_HAS_CPSTRING}
-      if (cp=CP_ACP) then
-        cp:=DefaultSystemCodePage;
+      cp:=TranslatePlaceholderCP(cp);
 {$else FPC_HAS_CPSTRING}
       cp:=DefaultSystemCodePage;
 {$endif FPC_HAS_CPSTRING}
@@ -567,8 +590,7 @@ begin
   if i > 0 then
     begin
 {$ifdef FPC_HAS_CPSTRING}
-      if (cp=CP_ACP) then
-        cp:=DefaultSystemCodePage;
+      cp:=TranslatePlaceholderCP(cp);
 {$else FPC_HAS_CPSTRING}
       cp:=DefaultSystemCodePage;
 {$endif FPC_HAS_CPSTRING}
@@ -628,12 +650,8 @@ begin
       result:=Length(S1);
       exit;
     end;
-  cp1:=StringCodePage(S1);
-  if cp1=CP_ACP then
-    cp1:=DefaultSystemCodePage;
-  cp2:=StringCodePage(S2);
-  if cp2=CP_ACP then
-    cp2:=DefaultSystemCodePage;
+  cp1:=TranslatePlaceholderCP(StringCodePage(S1));
+  cp2:=TranslatePlaceholderCP(StringCodePage(S2));
   if cp1=cp2 then
     begin
       Maxi:=Length(S1);
@@ -692,12 +710,8 @@ begin
       result:=1;
       exit;
     end;
-  cp1:=StringCodePage(S1);
-  if cp1=CP_ACP then
-    cp1:=DefaultSystemCodePage;
-  cp2:=StringCodePage(S2);
-  if cp2=CP_ACP then
-    cp2:=DefaultSystemCodePage;
+  cp1:=TranslatePlaceholderCP(StringCodePage(S1));
+  cp2:=TranslatePlaceholderCP(StringCodePage(S2));
   if cp1=cp2 then
     begin
       Maxi:=Length(S1);
@@ -750,6 +764,12 @@ begin
       if Pointer(S)=nil then
         begin
           Pointer(S):=NewAnsiString(L);
+{$ifdef FPC_HAS_CPSTRING}
+          cp:=TranslatePlaceholderCP(cp);
+          PAnsiRec(Pointer(S)-AnsiFirstOff)^.CodePage:=cp;
+{$else}
+          PAnsiRec(Pointer(S)-AnsiFirstOff)^.CodePage:=DefaultSystemCodePage;
+{$endif FPC_HAS_CPSTRING}
         end
       else if PAnsiRec(Pointer(S)-AnsiFirstOff)^.Ref=1 then
         begin
@@ -767,6 +787,7 @@ begin
         begin
           { Reallocation is needed... }
           Temp:=NewAnsiString(L);
+          PAnsiRec(Pointer(Temp)-AnsiFirstOff)^.CodePage:=PAnsiRec(Pointer(S)-AnsiFirstOff)^.CodePage;
           { also move terminating null }
           lens:=succ(length(s));
           if l<lens then
@@ -777,13 +798,6 @@ begin
           fpc_ansistr_decr_ref(Pointer(s));
           Pointer(S):=Temp;
         end;
-{$ifdef FPC_HAS_CPSTRING}
-      if (cp=CP_ACP) then
-        cp:=DefaultSystemCodePage;
-      PAnsiRec(Pointer(S)-AnsiFirstOff)^.CodePage:=cp;
-{$else}
-      PAnsiRec(Pointer(S)-AnsiFirstOff)^.CodePage:=DefaultSystemCodePage;
-{$endif FPC_HAS_CPSTRING}
       { Force nil termination in case it gets shorter }
       PByte(Pointer(S)+l)^:=0;
       PAnsiRec(Pointer(S)-AnsiFirstOff)^.Len:=l;
@@ -1280,9 +1294,7 @@ begin
    index := LS+1;
   Dec(Index);
   SetLength(Temp,Length(Source)+LS);
-  cp:=StringCodePage(S);
-  if (cp=CP_ACP) then
-    cp:=DefaultSystemCodePage;
+  cp:=TranslatePlaceholderCP(StringCodePage(S));
   SetCodePage(Temp,cp,false);
   If Index>0 then
     fpc_pchar_ansistr_intern_charmove(pchar(S),0,Temp,0,Index);
@@ -1408,10 +1420,19 @@ procedure InternalSetCodePage(var s : RawByteString; CodePage : TSystemCodePage;
 { use this wrapper for the simple case to avoid the generation of a temp. ansistring which causes
   extra exception frames }
 procedure SetCodePage(var s : RawByteString; CodePage : TSystemCodePage; Convert : Boolean = True);
+  var
+    TranslatedCodePage,
+    TranslatedCurrentCodePage: TSystemCodePage;
   begin
-    if (S='') or (PAnsiRec(pointer(S)-AnsiFirstOff)^.CodePage=CodePage) then
-      exit
-    else if not Convert and (PAnsiRec(pointer(S)-AnsiFirstOff)^.Ref=1) then
+    if (S='') then
+      exit;
+    { if we're just replacing a placeholder code page with its actual value or
+      vice versa, we don't have to perform any conversion }
+    TranslatedCurrentCodePage:=TranslatePlaceholderCP(PAnsiRec(pointer(S)-AnsiFirstOff)^.CodePage);
+    TranslatedCodePage:=TranslatePlaceholderCP(CodePage);
+    Convert:=Convert and
+      (TranslatedCurrentCodePage<>TranslatedCodePage);
+    if not Convert and (PAnsiRec(pointer(S)-AnsiFirstOff)^.Ref=1) then
       PAnsiRec(pointer(S)-AnsiFirstOff)^.CodePage:=CodePage
     else
       InternalSetCodePage(S,CodePage,Convert);
@@ -1424,3 +1445,15 @@ procedure SetMultiByteConversionCodePage(CodePage: TSystemCodePage);
     DefaultSystemCodePage:=CodePage;
   end;
 
+
+procedure SetMultiByteFileSystemCodePage(CodePage: TSystemCodePage);
+  begin
+    DefaultFileSystemCodePage:=CodePage;
+  end;
+
+
+procedure SetMultiByteRTLFileSystemCodePage(CodePage: TSystemCodePage);
+  begin
+    DefaultRTLFileSystemCodePage:=CodePage;
+  end;
+

+ 5 - 1
rtl/inc/compproc.inc

@@ -357,7 +357,11 @@ Function fpc_Char_To_UChar(const c : Char): UnicodeChar; compilerproc;
 Function fpc_UChar_To_Char(const c : UnicodeChar): Char; compilerproc;
 Function fpc_UChar_To_UnicodeStr(const c : UnicodeChar): UnicodeString; compilerproc;
 Function fpc_UChar_To_AnsiStr(const c : UnicodeChar{$ifdef FPC_HAS_CPSTRING};cp : TSystemCodePage{$endif FPC_HAS_CPSTRING}): AnsiString; compilerproc;
-procedure fpc_UChar_To_ShortStr(out res : shortstring;const c : WideChar) compilerproc;
+{$ifdef VER2_6}
+procedure fpc_UChar_To_ShortStr(out result : shortstring;const c : WideChar) compilerproc;
+{$else}
+function fpc_UChar_To_ShortStr(const c : WideChar): shortstring; compilerproc;
+{$endif}
 
 Function fpc_PWideChar_To_UnicodeStr(const p : pwidechar): unicodestring; compilerproc;
 {$ifdef FPC_HAS_FEATURE_ANSISTRINGS}

+ 75 - 20
rtl/inc/dynlibs.pas

@@ -20,6 +20,8 @@ unit dynlibs;
 
 interface
 
+{$i rtldefs.inc}
+
 { ---------------------------------------------------------------------
   Read OS-dependent interface declarations.
   ---------------------------------------------------------------------}
@@ -33,8 +35,11 @@ interface
   ---------------------------------------------------------------------}
 
 
-Function SafeLoadLibrary(const Name : AnsiString) : TLibHandle;
-Function LoadLibrary(const Name : AnsiString) : TLibHandle;
+Function SafeLoadLibrary(const Name : RawByteString) : TLibHandle;
+Function LoadLibrary(const Name : RawByteString) : TLibHandle;
+Function SafeLoadLibrary(const Name : UnicodeString) : TLibHandle;
+Function LoadLibrary(const Name : UnicodeString) : TLibHandle;
+
 Function GetProcedureAddress(Lib : TlibHandle; const ProcName : AnsiString) : Pointer;
 Function UnloadLibrary(Lib : TLibHandle) : Boolean;
 Function GetLoadErrorStr: string;
@@ -55,19 +60,11 @@ Implementation
 
 {$i dynlibs.inc}
 
-Function FreeLibrary(Lib : TLibHandle) : Boolean;
-
-begin
-  Result:=UnloadLibrary(lib);
-end;
-
-Function GetProcAddress(Lib : TlibHandle; const ProcName : AnsiString) : Pointer;
-
-begin
-  Result:=GetProcedureAddress(Lib,Procname);
-end;
-
-Function SafeLoadLibrary(const Name : AnsiString) : TLibHandle;
+{$ifndef FPCRTL_FILESYSTEM_TWO_BYTE_API}
+Function DoSafeLoadLibrary(const Name : RawByteString) : TLibHandle;
+{$else not FPCRTL_FILESYSTEM_TWO_BYTE_API}
+Function DoSafeLoadLibrary(const Name : UnicodeString) : TLibHandle;
+{$endif not FPCRTL_FILESYSTEM_TWO_BYTE_API}
 {$if defined(cpui386) or defined(cpux86_64)}
   var
     fpucw : Word;
@@ -82,11 +79,7 @@ Function SafeLoadLibrary(const Name : AnsiString) : TLibHandle;
 {$endif cpui386}
         ssecw:=GetSSECSR;
 {$endif}
-{$if defined(windows) or defined(win32)}
-      Result:=LoadLibraryA(PChar(Name));
-{$else}
-      Result:=loadlibrary(Name);
-{$endif}
+      Result:=doloadlibrary(Name);
       finally
 {$if defined(cpui386) or defined(cpux86_64)}
       Set8087CW(fpucw);
@@ -98,5 +91,67 @@ Function SafeLoadLibrary(const Name : AnsiString) : TLibHandle;
     end;
   end;
 
+{$ifndef FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+Function SafeLoadLibrary(const Name : RawByteString) : TLibHandle;
+begin
+  Result:=DoSafeLoadLibrary(UnicodeString(Name));
+end;
+
+Function LoadLibrary(const Name : RawByteString) : TLibHandle;
+begin
+  Result:=DoLoadLibrary(UnicodeString(Name));
+end;
+
+{$else not FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+
+Function SafeLoadLibrary(const Name : RawByteString) : TLibHandle;
+begin
+  Result:=DoSafeLoadLibrary(ToSingleByteFileSystemEncodedFileName(Name));
+end;
+
+Function LoadLibrary(const Name : RawByteString) : TLibHandle;
+begin
+  Result:=DoLoadLibrary(ToSingleByteFileSystemEncodedFileName(Name));
+end;
+{$endif not FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+
+
+{$ifndef FPCRTL_FILESYSTEM_TWO_BYTE_API}
+Function SafeLoadLibrary(const Name : UnicodeString) : TLibHandle;
+begin
+  Result:=DoSafeLoadLibrary(ToSingleByteFileSystemEncodedFileName(Name));
+end;
+
+Function LoadLibrary(const Name : UnicodeString) : TLibHandle;
+begin
+  Result:=DoLoadLibrary(ToSingleByteFileSystemEncodedFileName(Name));
+end;
+
+{$else not FPCRTL_FILESYSTEM_TWO_BYTE_API}
+
+Function SafeLoadLibrary(const Name : UnicodeString) : TLibHandle;
+begin
+  Result:=DoSafeLoadLibrary(Name);
+end;
+
+Function LoadLibrary(const Name : UnicodeString) : TLibHandle;
+begin
+  Result:=DoLoadLibrary(Name);
+end;
+{$endif not FPCRTL_FILESYSTEM_TWO_BYTE_API}
+
+
+Function FreeLibrary(Lib : TLibHandle) : Boolean;
+
+begin
+  Result:=UnloadLibrary(lib);
+end;
+
+Function GetProcAddress(Lib : TlibHandle; const ProcName : AnsiString) : Pointer;
+
+begin
+  Result:=GetProcedureAddress(Lib,Procname);
+end;
+
 
 end.

+ 6 - 6
rtl/inc/exeinfo.pp

@@ -71,11 +71,11 @@ uses
 
   var
     Tmm: TMemoryBasicInformation;
-{$ifdef wince}
+{$ifdef FPC_OS_UNICODE}
     TST: array[0..Max_Path] of WideChar;
-{$else wince}
+{$else}
     TST: array[0..Max_Path] of Char;
-{$endif wince}
+{$endif FPC_OS_UNICODE}
   procedure GetModuleByAddr(addr: pointer; var baseaddr: pointer; var filename: string);
     begin
       baseaddr:=nil;
@@ -86,11 +86,11 @@ uses
           baseaddr:=Tmm.AllocationBase;
           TST[0]:= #0;
           GetModuleFileName(THandle(Tmm.AllocationBase), TST, Length(TST));
-{$ifdef wince}
+{$ifdef FPC_OS_UNICODE}
           filename:= String(PWideChar(@TST));
-{$else wince}
+{$else}
           filename:= String(PChar(@TST));
-{$endif wince}
+{$endif FPC_OS_UNICODE}
         end;
     end;
 

+ 126 - 23
rtl/inc/fexpand.inc

@@ -50,7 +50,25 @@
  {$DEFINE FPC_FEXPAND_UPDIR_HELPER}
 {$ENDIF FPC_FEXPAND_DIRSEP_IS_UPDIR}
 
-procedure GetDirIO (DriveNr: byte; var Dir: String);
+{ this code is used both in sysutils and in the dos unit, and the dos
+  unit does not have a charinset routine }
+{$if not defined(FPC_FEXPAND_SYSUTILS) and not defined(FPC_FEXPAND_HAS_CHARINSET)}
+{$define FPC_FEXPAND_HAS_CHARINSET}
+type
+  TFExpandSysCharSet = set of ansichar;
+
+Function CharInSet(Ch:AnsiChar;Const CSet : TFExpandSysCharSet) : Boolean; inline;
+begin
+  CharInSet:=ch in CSet;
+end;
+
+Function CharInSet(Ch:WideChar;Const CSet : TFExpandSysCharSet) : Boolean;
+begin
+  CharInSet:=(Ch<=#$FF) and (ansichar(byte(ch)) in CSet);
+end;
+{$endif}
+
+procedure GetDirIO (DriveNr: byte; var Dir: {$IF defined(FPC_FEXPAND_SYSUTILS) and not defined(SYSUTILSUNICODE)}RawByteString{$else}PathStr{$endif});
 
 (* GetDirIO is supposed to return the root of the given drive   *)
 (* in case of an error for compatibility of FExpand with TP/BP. *)
@@ -67,7 +85,7 @@ end;
 
 {$IFDEF FPC_FEXPAND_VOLUMES}
  {$IFNDEF FPC_FEXPAND_NO_DEFAULT_PATHS}
-procedure GetDirIO (const VolumeName: OpenString; var Dir: string);
+procedure GetDirIO (const VolumeName: OpenString; var Dir: {$IF defined(FPC_FEXPAND_SYSUTILS) and not defined(SYSUTILSUNICODE)}RawByteString{$else}PathStr{$endif});
 
 var
   OldInOutRes: word;
@@ -110,7 +128,7 @@ const
     RootNotNeeded = false;
 {$ENDIF FPC_FEXPAND_UNC}
 
-var S, Pa, Dirs: PathStr;
+var S, Pa, Dirs, TmpS: {$IF defined(FPC_FEXPAND_SYSUTILS) and not defined(SYSUTILSUNICODE)}RawByteString{$else}PathStr{$endif};
     I, J: longint;
 
 begin
@@ -119,18 +137,31 @@ begin
 {$ENDIF FPC_FEXPAND_UNC}
 
 (* First convert the path to uppercase if appropriate for current platform. *)
+{$IF defined(FPC_FEXPAND_SYSUTILS) and not defined(SYSUTILSUNICODE)}
+    { for sysutils/rawbytestring, process everything in
+      DefaultFileSystemCodePage to prevent risking data loss that may be
+      relevant when the file name is used }
+    if FileNameCasePreserving then
+        Pa := ToSingleByteFileSystemEncodedFileName (Path)
+    else
+        Pa := UpCase (ToSingleByteFileSystemEncodedFileName (Path));
+{$ELSE FPC_FEXPAND_SYSUTILS and not SYSUTILSUNICODE}
     if FileNameCasePreserving then
         Pa := Path
     else
         Pa := UpCase (Path);
+{$ENDIF FPC_FEXPAND_SYSUTILS and not SYSUTILSUNICODE}
 
+{ already done before this routine is called from sysutils }
+{$IFNDEF FPC_FEXPAND_SYSUTILS}
 (* Allow both '/' and '\' as directory separators *)
 (* by converting all to the native one.           *)
 {$warnings off}
 	  for I := 1 to Length (Pa) do
-	    if Pa [I] in AllowDirectorySeparators  then
+	    if CharInSet(Pa [I], AllowDirectorySeparators)  then
 	      Pa [I] := DirectorySeparator;
 {$warnings on}
+{$ENDIF not FPC_FEXPAND_SYSUTILS}
 
 (* PathStart is amount of characters to strip to get beginning *)
 (* of path without volume/drive specification.                 *)
@@ -153,7 +184,11 @@ begin
                       ((Pa [2] = DirectorySeparator) or (Length (Pa) = 1)) then
         begin
  {$IFDEF FPC_FEXPAND_SYSUTILS}
-            S := GetEnvironmentVariable ('HOME');
+   {$IFDEF SYSUTILSUNICODE}
+            S := PathStr(GetEnvironmentVariable ('HOME'));
+   {$ELSE SYSUTILSUNICODE}
+            S := ToSingleByteFileSystemEncodedFileName(GetEnvironmentVariable ('HOME'));
+   {$ENDIF SYSUTILSUNICODE}
  {$ELSE FPC_FEXPAND_SYSUTILS}
   {$IFDEF FPC_FEXPAND_GETENV_PCHAR}
             S := StrPas (GetEnv ('HOME'));
@@ -176,7 +211,7 @@ begin
 {$IFDEF FPC_FEXPAND_VOLUMES}
     if PathStart > 1 then
 {$ELSE FPC_FEXPAND_VOLUMES}
-    if (Length (Pa) > 1) and (Pa [1] in ['A'..'Z', 'a'..'z']) and
+    if (Length (Pa) > 1) and CharInSet(Pa [1], ['A'..'Z', 'a'..'z']) and
       (Pa [2] = DriveSeparator) and (DriveSeparator <> DirectorySeparator) then
 {$ENDIF FPC_FEXPAND_VOLUMES}
         begin
@@ -189,7 +224,7 @@ begin
             GetDirIO (Copy (Pa, 1, PathStart - 2), S);
   {$ELSE FPC_FEXPAND_VOLUMES}
             { Always uppercase driveletter }
-            if (Pa [1] in ['a'..'z']) then
+            if CharInSet(Pa [1], ['a'..'z']) then
                 Pa [1] := Chr (Ord (Pa [1]) and not ($20));
             GetDirIO (Ord (Pa [1]) - Ord ('A') + 1, S);
   {$ENDIF FPC_FEXPAND_VOLUMES}
@@ -212,19 +247,38 @@ begin
                         begin
                             { remove ending slash if it already exists }
                             if S [Length (S)] = DirectorySeparator then
-                               SetLength(S,Length(s)-1);
+                               SetLength(S,Length(S)-1);
+{$IFDEF FPC_FEXPAND_SYSUTILS}
+                            { not "Pa := S + DirectorySeparator + ..." because
+                              that will convert the result to
+                              DefaultSystemCodePage in case of RawByteString due
+                              to DirectorySeparator being an ansichar }
+                            TmpS := S;
+                            SetLength(TmpS, Length(TmpS) + 1);
+                            TmpS[Length(TmpS)] := DirectorySeparator;
+                            Pa := TmpS +
+                              Copy (Pa, PathStart, Length (Pa) - PathStart + 1)
+{$ELSE FPC_FEXPAND_SYSUTILS}
                             Pa := S + DirectorySeparator +
                               Copy (Pa, PathStart, Length (Pa) - PathStart + 1)
+{$ENDIF FPC_FEXPAND_SYSUTILS}
                         end
                     else
+                      begin
+                        TmpS := DriveSeparator + DirectorySeparator;
+  {$IF defined(FPC_FEXPAND_SYSUTILS) and not defined(SYSUTILSUNICODE)}
+                        SetCodePage(TmpS, DefaultFileSystemCodePage, false);
+  {$ENDIF FPC_FEXPAND_SYSUTILS and not SYSUTILSUNICODE}
+
   {$IFDEF FPC_FEXPAND_VOLUMES}
-                        Pa := Copy (Pa, 1, PathStart - 2) + DriveSeparator
-                           + DirectorySeparator +
+                        Pa := Copy (Pa, 1, PathStart - 2) + TmpS +
                               Copy (Pa, PathStart, Length (Pa) - PathStart + 1)
   {$ELSE FPC_FEXPAND_VOLUMES}
-                        Pa := Pa [1] + DriveSeparator + DirectorySeparator +
+                        { copy() instead of Pa[1] to preserve string code page }
+                        Pa := Copy (Pa, 1, 1) + TmpS +
                               Copy (Pa, PathStart, Length (Pa) - PathStart + 1)
   {$ENDIF FPC_FEXPAND_VOLUMES}
+                      end
  {$ENDIF FPC_FEXPAND_NO_DEFAULT_PATHS}
         end
     else
@@ -277,8 +331,17 @@ begin
                                 {...or not even that one}
                                     PathStart := 2
                                 else
-                                    Pa := Pa + DirectorySeparator                            else
-                                if PathStart < Length (Pa) then
+                                  begin
+    {$IFDEF FPC_FEXPAND_SYSUTILS}
+                                    { no string concatenation to prevent code page
+                                      conversion for RawByteString }
+                                    SetLength(Pa, Length(Pa) + 1);
+                                    Pa[Length(Pa)] := DirectorySeparator
+    {$ELSE FPC_FEXPAND_SYSUTILS}
+                                    Pa := Pa + DirectorySeparator;
+    {$ENDIF FPC_FEXPAND_SYSUTILS}
+                                  end
+                                else if PathStart < Length (Pa) then
                                 {We have a resource name as well}
                                     begin
                                         RootNotNeeded := true;
@@ -291,8 +354,8 @@ begin
                         end
                     else
   {$ENDIF FPC_FEXPAND_UNC}
-  {$IFDEF FPC_FEXPAND_VOLUMES}
                         begin
+  {$IFDEF FPC_FEXPAND_VOLUMES}
                             I := Pos (DriveSeparator, S);
    {$IFDEF FPC_FEXPAND_DIRSEP_IS_UPDIR}
     {$IFDEF FPC_FEXPAND_DRIVESEP_IS_ROOT}
@@ -302,13 +365,20 @@ begin
                             Pa := Copy (S, 1, I) + Pa;
                             PathStart := I;
    {$ELSE FPC_FEXPAND_DIRSEP_IS_UPDIR}
-                            Pa := Copy (S, 1, Pred (I)) + DriveSeparator + Pa;
+                            TmpS := Copy (S, 1, Pred (I));
+                            SetLength(TmpS, Length(TmpS) + 1);
+                            TmpS[Length(TmpS)] := DriveSeparator;
+                            Pa := TmpS + Pa;
                             PathStart := Succ (I);
    {$ENDIF FPC_FEXPAND_DIRSEP_IS_UPDIR}
-                        end;
   {$ELSE FPC_FEXPAND_VOLUMES}
-                        Pa := S [1] + DriveSeparator + Pa;
+                            TmpS := S[1] + DriveSeparator;
+  {$IF defined(FPC_FEXPAND_SYSUTILS) and not defined(SYSUTILSUNICODE)}
+                            SetCodePage(TmpS, DefaultFileSystemCodePage, false);
+  {$ENDIF FPC_FEXPAND_SYSUTILS and not SYSUTILSUNICODE}
+                            Pa := TmpS + Pa;
   {$ENDIF FPC_FEXPAND_VOLUMES}
+                        end;
                 end
             else
  {$ENDIF FPC_FEXPAND_DRIVES}
@@ -328,18 +398,42 @@ begin
                     (* with an empty string for compatibility, except *)
                     (* for platforms where this is invalid.           *)
                     if Length (Pa) = 0 then
-{$IFDEF FPC_FEXPAND_DIRSEP_IS_UPDIR}
-                        Pa := S
-{$ELSE FPC_FEXPAND_DIRSEP_IS_UPDIR}
-                        Pa := S + DirectorySeparator
-{$ENDIF FPC_FEXPAND_DIRSEP_IS_UPDIR}
+                      begin
+                        Pa := S;
+{$IFNDEF FPC_FEXPAND_DIRSEP_IS_UPDIR}
+  {$IFDEF FPC_FEXPAND_SYSUTILS}
+                        { no string concatenation to prevent code page
+                          conversion for RawByteString }
+                        SetLength(Pa, Length(Pa) + 1);
+                        Pa[Length(Pa)] := DirectorySeparator
+  {$ELSE FPC_FEXPAND_SYSUTILS}
+                        Pa := Pa + DirectorySeparator;
+  {$ENDIF FPC_FEXPAND_SYSUTILS}
+{$ENDIF not FPC_FEXPAND_DIRSEP_IS_UPDIR}
+                      end
                     else
 {$IFDEF FPC_FEXPAND_UPDIR_HELPER}
                         if Pa [1] = DirectorySeparator then
                             Pa := S + Pa
                         else
 {$ENDIF FPC_FEXPAND_UPDIR_HELPER}
-                        Pa := S + DirectorySeparator + Pa;
+                          begin
+{$IFDEF FPC_FEXPAND_SYSUTILS}
+                            { not "Pa := S + DirectorySeparator + Pa" because
+                              that will convert the result to
+                              DefaultSystemCodePage in case of RawByteString due
+                              to DirectorySeparator being an ansichar. Don't
+                              always use this code because in case of
+                              truncation with shortstrings the result will be
+                              different }
+                            TmpS := S;
+                            SetLength(TmpS, Length(TmpS) + 1);
+                            TmpS[Length(TmpS)] := DirectorySeparator;
+                            Pa := TmpS + Pa;
+{$ELSE FPC_FEXPAND_SYSUTILS}
+                            Pa := S + DirectorySeparator + Pa
+{$ENDIF FPC_FEXPAND_SYSUTILS}
+                          end;
         end;
 
     {Get string of directories to only process relative references on this one}
@@ -477,7 +571,16 @@ begin
             Pa := Copy (Pa, 1, PathStart);
 {$IFNDEF FPC_FEXPAND_DRIVESEP_IS_ROOT}
             if Pa [PathStart] <> DirectorySeparator then
+              begin
+  {$IFDEF FPC_FEXPAND_SYSUTILS}
+                { no string concatenation to prevent code page
+                  conversion for RawByteString }
+                SetLength(Pa, Length(Pa) + 1);
+                Pa[Length(Pa)] := DirectorySeparator
+  {$ELSE FPC_FEXPAND_SYSUTILS}
                 Pa := Pa + DirectorySeparator;
+  {$ENDIF FPC_FEXPAND_SYSUTILS}
+              end
 {$ENDIF FPC_FEXPAND_DRIVESEP_IS_ROOT}
         end
     else

+ 175 - 35
rtl/inc/file.inc

@@ -18,35 +18,85 @@
 type
   UnTypedFile=File;
 
-Procedure Assign(out f:File;const Name:string);
+procedure InitFile(var f : file);
+begin
+  FillChar(f,SizeOf(FileRec),0);
+  FileRec(f).Handle:=UnusedHandle;
+  FileRec(f).mode:=fmClosed;
+end;
+
+
+{$ifdef FPC_HAS_FEATURE_WIDESTRINGS}
+Procedure Assign(out f:File;const Name: UnicodeString);
 {
   Assign Name to file f so it can be used with the file routines
 }
 Begin
-  FillChar(f,SizeOf(FileRec),0);
-  FileRec(f).Handle:=UnusedHandle;
-  FileRec(f).mode:=fmClosed;
-  Move(Name[1],FileRec(f).Name,Length(Name));
+  InitFile(F);
+{$ifdef FPC_ANSI_TEXTFILEREC}
+  FileRec(f).Name:=ToSingleByteFileSystemEncodedFileName(Name);
+{$else FPC_ANSI_TEXTFILEREC}
+  FileRec(f).Name:=Name;
+{$endif FPC_ANSI_TEXTFILEREC}
+  { null terminate, since the name array is regularly used as p(wide)char }
+  FileRec(f).Name[high(FileRec(f).Name)]:=#0;
 End;
+{$endif FPC_HAS_FEATURE_WIDESTRINGS}
 
 
-Procedure Assign(out f:File;p:pchar);
+{$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
+Procedure Assign(out f:File;const Name: RawByteString);
 {
   Assign Name to file f so it can be used with the file routines
 }
-begin
-  Assign(f,StrPas(p));
-end;
-
+Begin
+  InitFile(F);
+{$ifdef FPC_ANSI_TEXTFILEREC}
+  { ensure the characters in the record's filename are encoded correctly }
+  FileRec(f).Name:=ToSingleByteFileSystemEncodedFileName(Name);
+{$else FPC_ANSI_TEXTFILEREC}
+  FileRec(f).Name:=Name;
+{$endif FPC_ANSI_TEXTFILEREC}
+  { null terminate, since the name array is regularly used as p(wide)char }
+  FileRec(f).Name[high(FileRec(f).Name)]:=#0;
+End;
+{$endif FPC_HAS_FEATURE_ANSISTRINGS}
 
-Procedure Assign(out f:File;c:char);
+Procedure Assign(out f:File;const Name: ShortString);
 {
   Assign Name to file f so it can be used with the file routines
 }
-begin
-  Assign(f,string(c));
-end;
+Begin
+{$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
+  Assign(f,AnsiString(Name));
+{$else FPC_HAS_FEATURE_ANSISTRINGS}
+  InitFile(f);
+  { warning: no encoding support }
+  FileRec(f).Name:=Name;
+  { null terminate, since the name array is regularly used as p(wide)char }
+  FileRec(f).Name[high(FileRec(f).Name)]:=#0;
+{$endif FPC_HAS_FEATURE_ANSISTRINGS}
+End;
 
+Procedure Assign(out f:File;const p: PAnsiChar);
+Begin
+{$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
+  Assign(f,AnsiString(p));
+{$else FPC_HAS_FEATURE_ANSISTRINGS}
+  { no use in making this the one that does the work, since the name field is
+    limited to 255 characters anyway }
+  Assign(f,strpas(p));
+{$endif FPC_HAS_FEATURE_ANSISTRINGS}
+End;
+
+Procedure Assign(out f:File;const c: AnsiChar);
+Begin
+{$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
+  Assign(f,AnsiString(c));
+{$else FPC_HAS_FEATURE_ANSISTRINGS}
+  Assign(f,ShortString(c));
+{$endif FPC_HAS_FEATURE_ANSISTRINGS}
+End;
 
 Procedure Rewrite(var f:File;l:Longint);[IOCheck];
 {
@@ -69,7 +119,7 @@ Begin
   else
    Begin
      { Reopen with filemode 2, to be Tp compatible (PFV) }
-     Do_Open(f,PChar(@FileRec(f).Name),$1002);
+     Do_Open(f,PFileTextRecChar(@FileRec(f).Name),$1002,false);
      FileRec(f).RecSize:=l;
    End;
 End;
@@ -95,7 +145,7 @@ Begin
    InOutRes:=2
   else
    Begin
-     Do_Open(f,PChar(@FileRec(f).Name),Filemode);
+     Do_Open(f,PFileTextRecChar(@FileRec(f).Name),Filemode,false);
      FileRec(f).RecSize:=l;
    End;
 End;
@@ -383,44 +433,134 @@ Begin
   If InOutRes <> 0 then
    exit;
   If FileRec(f).mode=fmClosed Then
-   Do_Erase(PChar(@FileRec(f).Name));
+   Do_Erase(PFileTextRecChar(@FileRec(f).Name),false);
 End;
 
 
-Procedure Rename(var f : File;p:pchar);[IOCheck];
+Procedure Rename(var f : File; const S : UnicodeString);[IOCheck];
+{$ifdef FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+var
+  fs: RawByteString;
+{$endif FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
 Begin
-  If InOutRes <> 0 then
-   exit;
-  If FileRec(f).mode=fmClosed Then
-   Begin
-     Do_Rename(PChar(@FileRec(f).Name),p);
-     { check error code of do_rename }
-     If InOutRes = 0 then
-        Move(p^,FileRec(f).Name,StrLen(p)+1);
-   End;
+  If (InOutRes<>0) or
+     (FileRec(f).mode<>fmClosed) then
+    exit;
+{$ifdef FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+  { it's slightly faster to convert the unicodestring here to rawbytestring
+    than doing it in do_rename(), because here we still know the length }
+  fs:=ToSingleByteFileSystemEncodedFileName(s);
+  Do_Rename(PFileTextRecChar(@FileRec(f).Name),PAnsiChar(fs),false,true);
+  If InOutRes=0 then
+     FileRec(f).Name:=fs
+{$else FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+  Do_Rename(PFileTextRecChar(@FileRec(f).Name),PUnicodeChar(S),false,false);
+  If InOutRes=0 then
+{$ifdef FPC_ANSI_TEXTFILEREC}
+    FileRec(f).Name:=ToSingleByteFileSystemEncodedFileName(s);
+{$else FPC_ANSI_TEXTFILEREC}
+    FileRec(f).Name:=s
+{$endif FPC_ANSI_TEXTFILEREC}
+{$endif FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
 End;
 
 
-Procedure Rename(var f : File;const s : string);[IOCheck];
+Procedure Rename(var f : File;const s : RawByteString);[IOCheck];
+var
+{$ifdef FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+  fs: RawByteString;
+  pdst: PAnsiChar;
+{$else FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+  fs: UnicodeString;
+  pdst: PUnicodeChar;
+{$endif FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+  dstchangeable: boolean;
+Begin
+  If (InOutRes<>0) or
+     (FileRec(f).mode<>fmClosed) then
+    exit;
+{$ifdef FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+  dstchangeable:=false;
+  pdst:=PAnsiChar(s);
+  if StringCodePage(s)<>DefaultFileSystemCodePage then
+    begin
+      fs:=ToSingleByteFileSystemEncodedFileName(s);
+      pdst:=PAnsiChar(fs);
+      dstchangeable:=true;
+    end
+  else
+    fs:=s;
+{$else FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+   { it's slightly faster to convert the rawbytestring here to unicodestring
+     than doing it in do_rename, because here we still know the length }
+   fs:=unicodestring(s);
+   pdst:=PUnicodeChar(fs);
+   dstchangeable:=true;
+{$endif FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+  Do_Rename(PFileTextRecChar(@FileRec(f).Name),pdst,false,dstchangeable);
+  If InOutRes=0 then
+{$if defined(FPC_ANSI_TEXTFILEREC) and not defined(FPCRTL_FILESYSTEM_SINGLE_BYTE_API)}
+    FileRec(f).Name:=ToSingleByteFileSystemEncodedFileName(fs)
+{$else FPC_ANSI_TEXTFILEREC and not FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+    FileRec(f).Name:=fs
+{$endif FPC_ANSI_TEXTFILEREC and not FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+End;
+
+
+Procedure Rename(var f : File;const s : ShortString);[IOCheck];
+{$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
+Begin
+  Rename(f,AnsiString(s));
+End;
+{$else FPC_HAS_FEATURE_ANSISTRINGS}
 var
   p : array[0..255] Of Char;
 Begin
-  If InOutRes <> 0 then
-   exit;
   Move(s[1],p,Length(s));
   p[Length(s)]:=#0;
   Rename(f,Pchar(@p));
 End;
+{$endif FPC_HAS_FEATURE_ANSISTRINGS}
 
 
-Procedure Rename(var f : File;c : char);[IOCheck];
+Procedure Rename(var f:File;const p : PAnsiChar);[IOCheck];
+{$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
+Begin
+  Rename(f,AnsiString(p));
+End;
+{$else FPC_HAS_FEATURE_ANSISTRINGS}
 var
-  p : array[0..1] Of Char;
+  len: SizeInt
+Begin
+  If InOutRes<>0 then
+    exit;
+  If FileRec(f).mode=fmClosed Then
+    Begin
+      Do_Rename(PFileTextRecChar(@FileRec(f).Name),p,false);
+      { check error code of do_rename }
+      If InOutRes=0 then
+        begin
+          len:=min(StrLen(p),high(FileRec(f).Name));
+          Move(p^,FileRec(f).Name,len);
+          FileRec(f).Name[len]:=#0;
+        end;
+    End;
+End;
+{$endif FPC_HAS_FEATURE_ANSISTRINGS}
+
+
+Procedure Rename(var f:File;const c : AnsiChar);[IOCheck];
+{$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
+Begin
+  Rename(f,AnsiString(c));
+End;
+{$else FPC_HAS_FEATURE_ANSISTRINGS}
+var
+  p : array[0..1] Of AnsiChar;
 Begin
-  If InOutRes <> 0 then
-   exit;
   p[0]:=c;
   p[1]:=#0;
-  Rename(f,Pchar(@p));
+  Rename(f,PAnsiChar(@p));
 End;
+{$endif FPC_HAS_FEATURE_ANSISTRINGS}
 

+ 1 - 1
rtl/inc/filerec.inc

@@ -35,6 +35,6 @@ type
     RecSize   : SizeInt;
     _private  : array[1..3 * SizeOf(SizeInt) + 5 * SizeOf (pointer)] of byte;
     UserData  : array[1..32] of byte;
-    name      : array[0..filerecnamelength] of char;
+    name      : array[0..filerecnamelength] of TFileTextRecChar;
   End;
 

+ 1 - 1
rtl/inc/objects.pp

@@ -1389,7 +1389,7 @@ BEGIN
      Begin                        { Check status okay }
      If (Handle = InvalidHandle) Then
         Begin                      { File not open }
-          Assign(FileInfo,FName);
+          Assign(FileInfo,@FName);
           { Handle the mode }
           if OpenMode =stCreate then
             Begin

+ 312 - 43
rtl/inc/system.inc

@@ -57,18 +57,6 @@ Const
                                 Local types
 ****************************************************************************}
 
-{
-  TextRec and FileRec are put in a separate file to make it available to other
-  units without putting it explicitly in systemh.
-  This way we keep TP compatibility, and the TextRec definition is available
-  for everyone who needs it.
-}
-{$ifdef FPC_HAS_FEATURE_FILEIO}
-{$i filerec.inc}
-{$endif FPC_HAS_FEATURE_FILEIO}
-
-{$i textrec.inc}
-
 {$ifdef FPC_HAS_FEATURE_EXITCODE}
   {$ifdef FPC_OBJFPC_EXTENDED_IF}
     {$if High(errorcode)<>maxExitCode}
@@ -1430,13 +1418,49 @@ end;
 
 {$ifdef FPC_HAS_FEATURE_FILEIO}
 { Allow slash and backslash as separators }
-procedure DoDirSeparators(p:Pchar);
+procedure DoDirSeparators(var p: pchar; inplace: boolean = true);
 var
   i : longint;
+  len : sizeint;
+  newp : pchar;
 begin
-  for i:=0 to strlen(p) do
+  len:=length(p);
+  newp:=nil;
+  for i:=0 to len do
     if p[i] in AllowDirectorySeparators then
-      p[i]:=DirectorySeparator;
+      begin
+        if not inplace and
+           not assigned(newp) then
+          begin
+            getmem(newp,len+1);
+            move(p^,newp^,len+1);
+            p:=newp;
+          end;
+        p[i]:=DirectorySeparator;
+      end;
+end;
+
+procedure DoDirSeparators(var p: pwidechar; inplace: boolean = true);
+var
+  i : longint;
+  len : sizeint;
+  newp : pwidechar;
+begin
+  len:=length(p);
+  newp:=nil;
+  for i:=0 to len do
+    if (ord(p[i])<255) and
+       (ansichar(ord(p[i])) in AllowDirectorySeparators) then
+      begin
+        if not inplace and
+           not assigned(newp) then
+          begin
+            getmem(newp,(len+1)*2);
+            move(p^,newp^,(len+1)*2);
+            p:=newp;
+          end;
+        p[i]:=DirectorySeparator;
+      end;
 end;
 
 procedure DoDirSeparators(var p:shortstring);
@@ -1447,11 +1471,129 @@ begin
     if p[i] in AllowDirectorySeparators then
       p[i]:=DirectorySeparator;
 end;
+
+
+procedure DoDirSeparators(var ps:RawByteString);
+var
+  i : longint;
+  p : pchar;
+  unique : boolean;
+begin
+  unique:=false;
+  for i:=1 to length(ps) do
+    if ps[i] in AllowDirectorySeparators then
+      begin
+        if not unique then
+          begin
+            uniquestring(ps);
+            p:=pchar(ps);
+            unique:=true;
+          end;
+        p[i-1]:=DirectorySeparator;
+      end;
+end;
+
+procedure DoDirSeparators(var ps:UnicodeString);
+var
+  i : longint;
+  p : pwidechar;
+  unique : boolean;
+begin
+  unique:=false;
+  for i:=1 to length(ps) do
+    if ps[i] in AllowDirectorySeparators then
+      begin
+        if not unique then
+          begin
+            uniquestring(ps);
+            p:=pwidechar(ps);
+            unique:=true;
+          end;
+        p[i-1]:=DirectorySeparator;
+      end;
+end;
+
 {$endif FPC_HAS_FEATURE_FILEIO}
 
 { OS dependent low level file functions }
 {$ifdef FPC_HAS_FEATURE_FILEIO}
 {$i sysfile.inc}
+
+{$ifndef FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+{$ifdef FPC_ANSI_TEXTFILEREC}
+procedure do_open(var f; p: pansichar; flags: longint; pchangeable: boolean);
+var
+  u: UnicodeString;
+begin
+  widestringmanager.Ansi2UnicodeMoveProc(p,DefaultFileSystemCodePage,u,length(p));
+  do_open(f,pwidechar(u),flags,true);
+end;
+
+procedure do_erase(p: pansichar; pchangeable: boolean);
+var
+  u: UnicodeString;
+begin
+  widestringmanager.Ansi2UnicodeMoveProc(p,DefaultFileSystemCodePage,u,length(p));
+  do_erase(pwidechar(u),true);
+end;
+
+procedure do_rename(src, dst: pansichar; srcchangeable, dstchangeable: boolean);
+var
+  usrc, udst: UnicodeString;
+begin
+  widestringmanager.Ansi2UnicodeMoveProc(src,DefaultFileSystemCodePage,usrc,length(src));
+  widestringmanager.Ansi2UnicodeMoveProc(dst,DefaultFileSystemCodePage,udst,length(dst));
+  do_rename(pwidechar(usrc),pwidechar(udst),true,true);
+end;
+
+procedure do_rename(src: pansichar; dst: pwidechar; srcchangeable, dstchangeable: boolean);
+var
+  usrc: UnicodeString;
+begin
+  widestringmanager.Ansi2UnicodeMoveProc(src,DefaultFileSystemCodePage,usrc,length(src));
+  do_rename(pwidechar(usrc),dst,true,dstchangeable);
+end;
+{$endif FPC_ANSI_TEXTFILEREC}
+{$endif not FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+
+
+{$ifndef FPCRTL_FILESYSTEM_TWO_BYTE_API}
+{$ifndef FPC_ANSI_TEXTFILEREC}
+procedure do_open(var f; p: pwidechar; flags: longint; pchangeable: boolean);
+var
+  s: RawByteString;
+begin
+  widestringmanager.Unicode2AnsiMoveProc(p,s,DefaultFileSystemCodePage,length(p));
+  do_open(f,pansichar(s),flags,true);
+end;
+
+procedure do_erase(p: pwidechar; pchangeable: boolean);
+var
+  s: RawByteString;
+begin
+  widestringmanager.Unicode2AnsiMoveProc(p,s,DefaultFileSystemCodePage,length(p));
+  do_erase(pansichar(s),true);
+end;
+
+procedure do_rename(src, dst: pwidechar; srcchangeable, dstchangeable: boolean);
+var
+  rsrc, rdst: RawByteString;
+begin
+  widestringmanager.Unicode2AnsiMoveProc(src,rsrc,DefaultFileSystemCodePage,length(src));
+  widestringmanager.Unicode2AnsiMoveProc(dst,rdst,DefaultFileSystemCodePage,length(dst));
+  do_rename(pansichar(rsrc),pansichar(rdst),true,true);
+end;
+
+procedure do_rename(src: pwidechar; dst: pansichar; srcchangeable, dstchangeable: boolean);
+var
+  rsrc: RawByteString;
+begin
+  widestringmanager.Unicode2AnsiMoveProc(src,rsrc,DefaultFileSystemCodePage,length(src));
+  do_rename(pansichar(rsrc),dst,true,dstchangeable);
+end;
+{$endif not FPC_ANSI_TEXTFILEREC}
+{$endif not FPCRTL_FILESYSTEM_TWO_BYTE_API}
+
 {$endif FPC_HAS_FEATURE_FILEIO}
 
 { Text file }
@@ -1473,55 +1615,182 @@ end;
 {$ifdef FPC_HAS_FEATURE_FILEIO}
 { OS dependent dir functions }
 {$i sysdir.inc}
-{$endif FPC_HAS_FEATURE_FILEIO}
 
-{$if defined(FPC_HAS_FEATURE_FILEIO) and defined(FPC_HAS_FEATURE_ANSISTRINGS)}
-Procedure getdir(drivenr:byte;Var dir:ansistring);
-{ this is needed to also allow ansistrings, the shortstring version is
-  OS dependent }
+
+{$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
+
+{$ifndef FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+procedure do_getdir(drivenr : byte;var dir : rawbytestring);
 var
-  s : shortstring;
+  u: unicodestring;
 begin
-  getdir(drivenr,s);
-  dir:=s;
+  Do_getdir(drivenr,u);
+  widestringmanager.Unicode2AnsiMoveProc(pwidechar(u),dir,DefaultRTLFileSystemCodePage,length(u));
 end;
+{$endif FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+
+Procedure MkDir(Const s: RawByteString);[IOCheck];
+Begin
+  If (s='') or (InOutRes <> 0) then
+   exit;
+{$ifdef FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+  Do_mkdir(ToSingleByteFileSystemEncodedFileName(S));
+{$else FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+  Do_mkdir(S);
 {$endif}
+end;
 
-{$if defined(FPC_HAS_FEATURE_FILEIO)}
 
-Procedure MkDir(Const s: String);
-Var
-  Buffer: Array[0..255] of Char;
+Procedure RmDir(Const s: RawByteString);[IOCheck];
 Begin
   If (s='') or (InOutRes <> 0) then
    exit;
-  Move(s[1], Buffer, Length(s));
-  Buffer[Length(s)] := #0;
-  MkDir(@buffer[0],length(s));
+{$ifdef FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+  Do_rmdir(ToSingleByteFileSystemEncodedFileName(S));
+{$else FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+  Do_rmdir(S);
+{$endif}
 End;
 
-Procedure RmDir(Const s: String);
-Var
-  Buffer: Array[0..255] of Char;
+
+Procedure ChDir(Const s: RawByteString);[IOCheck];
 Begin
   If (s='') or (InOutRes <> 0) then
    exit;
-  Move(s[1], Buffer, Length(s));
-  Buffer[Length(s)] := #0;
-  RmDir(@buffer[0],length(s));
+{$ifdef FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+  Do_chdir(ToSingleByteFileSystemEncodedFileName(S));
+{$else FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+  Do_chdir(S);
+{$endif}
 End;
 
-Procedure ChDir(Const s: String);
-Var
-  Buffer: Array[0..255] of Char;
+
+Procedure getdir(drivenr:byte;Var dir:rawbytestring);
+begin
+  Do_getdir(drivenr,dir);
+  { we should return results in the DefaultRTLFileSystemCodePage -> convert if
+    necessary }
+  setcodepage(dir,DefaultRTLFileSystemCodePage,true);
+end;
+
+{ the generic shortstring ones are only implemented elsewhere for systems *not*
+  supporting ansi/unicodestrings; for now assume there are no systems that
+  support unicodestrings but not ansistrings }
+
+{ avoid double string conversions }
+{$ifdef FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+function GetDirStrFromShortstring(const s: shortstring): RawByteString;
+begin
+  GetDirStrFromShortstring:=ToSingleByteFileSystemEncodedFileName(ansistring(s));
+end;
+{$else FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+function GetDirStrFromShortstring(const s: shortstring): UnicodeString;
+begin
+  GetDirStrFromShortstring:=s;
+end;
+{$endif FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+
+Procedure MkDir(Const s: shortstring);[IOCheck];
 Begin
   If (s='') or (InOutRes <> 0) then
    exit;
-  Move(s[1], Buffer, Length(s));
-  Buffer[Length(s)] := #0;
-  ChDir(@buffer[0],length(s));
+  Do_mkdir(GetDirStrFromShortstring(S));
 End;
-{$endif}
+
+
+Procedure RmDir(Const s: shortstring);[IOCheck];
+Begin
+  If (s='') or (InOutRes <> 0) then
+   exit;
+  Do_rmdir(GetDirStrFromShortstring(S));
+End;
+
+
+Procedure ChDir(Const s: shortstring);[IOCheck];
+Begin
+  If (s='') or (InOutRes <> 0) then
+   exit;
+  Do_chdir(GetDirStrFromShortstring(S));
+End;
+
+
+Procedure getdir(drivenr:byte;Var dir:shortstring);
+var
+  s: rawbytestring;
+begin
+  Do_getdir(drivenr,s);
+  if length(s)<=high(dir) then
+    dir:=s
+  else
+    inoutres:=3;
+end;
+{$endif FPC_HAS_FEATURE_ANSISTRINGS}
+
+
+{$if defined(FPC_HAS_FEATURE_WIDESTRINGS)}
+
+{$ifndef FPCRTL_FILESYSTEM_TWO_BYTE_API}
+{ overloads required for mkdir/rmdir/chdir to ensure that the string is
+  converted to the right code page }
+procedure do_mkdir(const s: unicodestring); {$ifdef SYSTEMINLINE}inline;{$endif}
+begin
+  do_mkdir(ToSingleByteFileSystemEncodedFileName(s));
+end;
+
+
+procedure do_rmdir(const s: unicodestring); {$ifdef SYSTEMINLINE}inline;{$endif}
+begin
+  do_rmdir(ToSingleByteFileSystemEncodedFileName(s));
+end;
+
+
+procedure do_chdir(const s: unicodestring); {$ifdef SYSTEMINLINE}inline;{$endif}
+begin
+  do_chdir(ToSingleByteFileSystemEncodedFileName(s));
+end;
+
+
+procedure do_getdir(drivenr : byte;var dir : unicodestring);
+var
+  s: rawbytestring;
+begin
+  Do_getdir(drivenr,s);
+  dir:=s;
+end;
+{$endif FPCRTL_FILESYSTEM_TWO_BYTE_API}
+
+Procedure MkDir(Const s: UnicodeString);[IOCheck];
+Begin
+  if (s='') or (InOutRes <> 0) then
+   exit;
+  Do_mkdir(S);
+End;
+
+
+Procedure RmDir(Const s: UnicodeString);[IOCheck];
+Begin
+  if (s='') or (InOutRes <> 0) then
+   exit;
+  Do_rmdir(S);
+End;
+
+
+Procedure ChDir(Const s: UnicodeString);[IOCheck];
+Begin
+  if (s='') or (InOutRes <> 0) then
+   exit;
+  Do_chdir(S);
+End;
+
+
+Procedure getdir(drivenr:byte;Var dir:unicodestring);
+begin
+  Do_getdir(drivenr,dir);
+end;
+{$endif FPC_HAS_FEATURE_WIDESTRINGS}
+
+{$endif FPC_HAS_FEATURE_FILEIO}
+
 
 {*****************************************************************************
                             Resources support

+ 99 - 37
rtl/inc/systemh.inc

@@ -84,6 +84,17 @@
                          Global Types and Constants
 ****************************************************************************}
 
+{ some values which are used in RTL for TSystemCodePage type }
+const
+  CP_ACP     = 0;     // default to ANSI code page
+  CP_OEMCP   = 1;     // default to OEM (console) code page
+  CP_UTF16   = 1200;  // utf-16
+  CP_UTF16BE = 1201;  // unicodeFFFE
+  CP_UTF7    = 65000; // utf-7
+  CP_UTF8    = 65001; // utf-8
+  CP_ASCII   = 20127; // us-ascii
+  CP_NONE    = $FFFF; // rawbytestring encoding
+
 Type
   { The compiler has all integer types defined internally. Here
     we define only aliases }
@@ -380,17 +391,6 @@ Type
   PPChar              = ^PChar;
   PPPChar             = ^PPChar;
 
-{ some values which are used in RTL for TSystemCodePage type }
-const
-  CP_ACP     = 0;     // default to ANSI code page
-  CP_UTF16   = 1200;  // utf-16
-  CP_UTF16BE = 1201;  // unicodeFFFE
-  CP_UTF7    = 65000; // utf-7
-  CP_UTF8    = 65001; // utf-8
-  CP_ASCII   = 20127; // us-ascii
-  CP_NONE    = $FFFF; // rawbytestring encoding
-
-type
   { AnsiChar is equivalent of Char, so we need
     to use type renamings }
   TAnsiChar           = Char;
@@ -505,18 +505,39 @@ type
 
   TSystemCodePage     = Word;
 
-  { Needed for fpc_get_output }
-  PText               = ^Text;
+{$ifdef VER2_6}
+  { the size of textrec/filerec is hardcoded in the 2.6 compiler binary }
+  {$define FPC_ANSI_TEXTFILEREC}
+{$endif}
+  TFileTextRecChar    = {$ifdef FPC_ANSI_TEXTFILEREC}AnsiChar{$else}UnicodeChar{$endif};
+  PFileTextRecChar    = ^TFileTextRecChar;
 
   TTextLineBreakStyle = (tlbsLF,tlbsCRLF,tlbsCR);
 
 { procedure type }
   TProcedure  = Procedure;
 
-{ platform dependent types }
+{ platform-dependent types }
 {$i sysosh.inc}
 
+{ platform-dependent defines }
+{$i rtldefs.inc}
+
+{*****************************************************************************
+                   TextRec/FileRec exported to allow compiler to take size
+*****************************************************************************}
+
+{$ifdef FPC_HAS_FEATURE_FILEIO}
+{$i filerec.inc}
+{$endif FPC_HAS_FEATURE_FILEIO}
+
+{$i textrec.inc}
+
+
 type
+  { Needed for fpc_get_output }
+  PText               = ^Text;
+
   TEntryInformation = record
     InitFinalTable : Pointer;
     ThreadvarTablesTable : Pointer;
@@ -639,6 +660,13 @@ var
 
   DefaultSystemCodePage,
   DefaultUnicodeCodePage,
+  { the code page to use when sending paths/file names to OS file system API
+    calls using single byte strings, and to interpret the results gotten back
+    from such API calls }
+  DefaultFileSystemCodePage,
+  { the code page to use to return file names from single byte file system calls
+    in the RTL that return ansistrings (by default, same as a above) }
+  DefaultRTLFileSystemCodePage,
   UTF8CompareLocale : TSystemCodePage;
 
 
@@ -1066,6 +1094,8 @@ function StringElementSize(const S : RawByteString): Word; overload;
 function StringRefCount(const S : RawByteString): SizeInt; overload;
 procedure SetCodePage(var s : RawByteString; CodePage : TSystemCodePage; Convert : Boolean = True);
 procedure SetMultiByteConversionCodePage(CodePage: TSystemCodePage);
+procedure SetMultiByteFileSystemCodePage(CodePage: TSystemCodePage);
+procedure SetMultiByteRTLFileSystemCodePage(CodePage: TSystemCodePage);
 {$endif FPC_HAS_FEATURE_ANSISTRINGS}
 
 
@@ -1086,9 +1116,20 @@ procedure SetMultiByteConversionCodePage(CodePage: TSystemCodePage);
 ****************************************************************************}
 
 {$ifdef FPC_HAS_FEATURE_FILEIO}
-Procedure Assign(out f:File;const Name:string);
-Procedure Assign(out f:File;p:pchar);
-Procedure Assign(out f:File;c:char);
+Procedure Assign(out f:File;const Name: ShortString);
+Procedure Assign(out f:File;const p: PAnsiChar);
+Procedure Assign(out f:File;const c: AnsiChar);
+Procedure Rename(var f:File;const s : ShortString);
+Procedure Rename(var f:File;const p : PAnsiChar);
+Procedure Rename(var f:File;const c : AnsiChar);
+{$ifdef FPC_HAS_FEATURE_WIDESTRINGS}
+Procedure Assign(out f:File;const Name: UnicodeString);
+Procedure Rename(var f:File;const s : UnicodeString);
+{$endif FPC_HAS_FEATURE_WIDESTRINGS}
+{$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
+Procedure Assign(out f:File;const Name: RawByteString);
+Procedure Rename(var f:File;const s : RawByteString);
+{$endif FPC_HAS_FEATURE_ANSISTRINGS}
 Procedure Rewrite(var f:File;l:Longint);
 Procedure Rewrite(var f:File);
 Procedure Reset(var f:File;l:Longint);
@@ -1111,9 +1152,6 @@ Function  FileSize(var f:File):Int64;
 Procedure Seek(var f:File;Pos:Int64);
 Function  EOF(var f:File):Boolean;
 Procedure Erase(var f:File);
-Procedure Rename(var f:File;const s:string);
-Procedure Rename(var f:File;p:pchar);
-Procedure Rename(var f:File;c:char);
 Procedure Truncate (var F:File);
 {$endif FPC_HAS_FEATURE_FILEIO}
 
@@ -1123,9 +1161,15 @@ Procedure Truncate (var F:File);
 ****************************************************************************}
 
 {$ifdef FPC_HAS_FEATURE_FILEIO}
-Procedure Assign(out f:TypedFile;const Name:string);
-Procedure Assign(out f:TypedFile;p:pchar);
-Procedure Assign(out f:TypedFile;c:char);
+Procedure Assign(out f:TypedFile;const Name:shortstring);
+Procedure Assign(out f:TypedFile;const p:PAnsiChar);
+Procedure Assign(out f:TypedFile;const c:AnsiChar);
+{$ifdef FPC_HAS_FEATURE_WIDESTRINGS}
+Procedure Assign(out f:TypedFile;const Name:unicodestring);
+{$endif FPC_HAS_FEATURE_WIDESTRINGS}
+{$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
+Procedure Assign(out f:TypedFile;const Name:rawbytestring);
+{$endif FPC_HAS_FEATURE_ANSISTRINGS}
 Procedure Reset(var f : TypedFile);   [INTERNPROC: fpc_in_Reset_TypedFile];
 Procedure Rewrite(var f : TypedFile); [INTERNPROC: fpc_in_Rewrite_TypedFile];
 {$endif FPC_HAS_FEATURE_FILEIO}
@@ -1135,18 +1179,26 @@ Procedure Rewrite(var f : TypedFile); [INTERNPROC: fpc_in_Rewrite_TypedFile];
 ****************************************************************************}
 
 {$ifdef FPC_HAS_FEATURE_TEXTIO}
-Procedure Assign(out t:Text;const s:string);
-Procedure Assign(out t:Text;p:pchar);
-Procedure Assign(out t:Text;c:char);
+Procedure Assign(out t:Text;const s:shortstring);
+Procedure Rename(var t:Text;const s:shortstring);
+Procedure Assign(out t:Text;const p:PAnsiChar);
+Procedure Rename(var t:Text;const p:PAnsiChar);
+Procedure Assign(out t:Text;const c:AnsiChar);
+Procedure Rename(var t:Text;const c:AnsiChar);
+{$ifdef FPC_HAS_FEATURE_WIDESTRINGS}
+Procedure Assign(out t:Text;const s:unicodestring);
+Procedure Rename(var t:Text;const s:unicodestring);
+{$endif FPC_HAS_FEATURE_WIDESTRINGS}
+{$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
+Procedure Rename(var t:Text;const s:rawbytestring);
+Procedure Assign(out t:Text;const s:rawbytestring);
+{$endif FPC_HAS_FEATURE_ANSISTRINGS}
 Procedure Close(var t:Text);
 Procedure Rewrite(var t:Text);
 Procedure Reset(var t:Text);
 Procedure Append(var t:Text);
 Procedure Flush(var t:Text);
 Procedure Erase(var t:Text);
-Procedure Rename(var t:Text;const s:string);
-Procedure Rename(var t:Text;p:pchar);
-Procedure Rename(var t:Text;c:char);
 Function  EOF(var t:Text):Boolean;
 Function  EOF:Boolean;
 Function  EOLn(var t:Text):Boolean;
@@ -1166,19 +1218,29 @@ procedure SetTextCodePage(var T: Text; CodePage: TSystemCodePage);
                             Directory Management
 ****************************************************************************}
 
-
 {$ifdef FPC_HAS_FEATURE_FILEIO}
-Procedure chdir(const s:string); overload;
-Procedure mkdir(const s:string); overload;
-Procedure rmdir(const s:string); overload;
-// the pchar versions are exported via alias for use in objpas
-
-Procedure getdir(drivenr:byte;var dir:shortstring);
+Procedure chdir(const s:shortstring); overload;
+Procedure mkdir(const s:shortstring); overload;
+Procedure rmdir(const s:shortstring); overload;
+Procedure getdir(drivenr:byte;var dir:shortstring);overload;
 {$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
-Procedure getdir(drivenr:byte;var dir:ansistring);
+Procedure chdir(const s:rawbytestring); overload;
+Procedure mkdir(const s:rawbytestring); overload;
+Procedure rmdir(const s:rawbytestring); overload;
+// defaultrtlfilesystemcodepage is returned here
+Procedure getdir(drivenr:byte;var dir: rawbytestring);overload;{$ifdef FPC_HAS_CPSTRING}rtlproc;{$endif FPC_HAS_CPSTRING}
 {$endif FPC_HAS_FEATURE_ANSISTRINGS}
+{$ifdef FPC_HAS_FEATURE_WIDESTRINGS}
+Procedure chdir(const s:unicodestring); overload;
+Procedure mkdir(const s:unicodestring); overload;
+Procedure rmdir(const s:unicodestring); overload;
+Procedure getdir(drivenr:byte;var dir: unicodestring);overload;
+{$endif FPC_HAS_FEATURE_WIDESTRINGS}
+
 {$endif FPC_HAS_FEATURE_FILEIO}
 
+
+
 {*****************************************************************************
                              Miscellaneous
 *****************************************************************************}

+ 173 - 33
rtl/inc/text.inc

@@ -57,7 +57,7 @@ Begin
      exit;
    end;
   End;
-  Do_Open(t,PChar(@t.Name),Flags);
+  Do_Open(t,PFileTextRecChar(@t.Name),Flags,False);
   t.CloseFunc:=@FileCloseFunc;
   t.FlushFunc:=nil;
   if t.Mode=fmInput then
@@ -74,9 +74,9 @@ Begin
    end;
 End;
 
+Procedure InitText(Var t : Text);
 
-Procedure Assign(out t:Text;const s:String);
-Begin
+begin
   FillChar(t,SizeOf(TextRec),0);
 { only set things that are not zero }
   TextRec(t).Handle:=UnusedHandle;
@@ -89,20 +89,74 @@ Begin
     tlbsCRLF: TextRec(t).LineEnd := #13#10;
     tlbsCR: TextRec(t).LineEnd := #13;
   End;
-  Move(s[1],TextRec(t).Name,Length(s));
-End;
+end;
 
 
-Procedure Assign(out t:Text;p:pchar);
+{$ifdef FPC_HAS_FEATURE_WIDESTRINGS}
+Procedure Assign(out t:Text;const s : UnicodeString);
 begin
-  Assign(t,StrPas(p));
+  InitText(t);
+{$ifdef FPC_ANSI_TEXTFILEREC}
+  TextRec(t).Name:=ToSingleByteFileSystemEncodedFileName(S);
+{$else FPC_ANSI_TEXTFILEREC}
+  TextRec(t).Name:=S;
+{$endif FPC_ANSI_TEXTFILEREC}
+  { null terminate, since the name array is regularly used as p(wide)char }
+  TextRec(t).Name[high(TextRec(t).Name)]:=#0;
 end;
+{$endif FPC_HAS_FEATURE_WIDESTRINGS}
 
 
-Procedure Assign(out t:Text;c:char);
-begin
-  Assign(t,string(c));
-end;
+{$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
+Procedure Assign(out t:Text;const s: RawByteString);
+Begin
+  InitText(t);
+{$ifdef FPC_ANSI_TEXTFILEREC}
+  { ensure the characters in the record's filename are encoded correctly }
+  TextRec(t).Name:=ToSingleByteFileSystemEncodedFileName(S);
+{$else FPC_ANSI_TEXTFILEREC}
+  TextRec(t).Name:=S;
+{$endif FPC_ANSI_TEXTFILEREC}
+  { null terminate, since the name array is regularly used as p(wide)char }
+  TextRec(t).Name[high(TextRec(t).Name)]:=#0;
+End;
+{$endif FPC_HAS_FEATURE_ANSISTRINGS}
+
+
+Procedure Assign(out t:Text;const s: ShortString);
+Begin
+{$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
+  Assign(t,AnsiString(s));
+{$else FPC_HAS_FEATURE_ANSISTRINGS}
+  InitText(t);
+  { warning: no encoding support }
+  TextRec(t).Name:=s;
+  { null terminate, since the name array is regularly used as p(wide)char }
+  TextRec(t).Name[high(TextRec(t).Name)]:=#0;
+{$endif FPC_HAS_FEATURE_ANSISTRINGS}
+End;
+
+
+Procedure Assign(out t:Text;const p: PAnsiChar);
+Begin
+{$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
+  Assign(t,AnsiString(p));
+{$else FPC_HAS_FEATURE_ANSISTRINGS}
+  { no use in making this the one that does the work, since the name field is
+    limited to 255 characters anyway }
+  Assign(t,strpas(p));
+{$endif FPC_HAS_FEATURE_ANSISTRINGS}
+End;
+
+
+Procedure Assign(out t:Text;const c: AnsiChar);
+Begin
+{$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
+  Assign(t,AnsiString(c));
+{$else FPC_HAS_FEATURE_ANSISTRINGS}
+  Assign(t,ShortString(c));
+{$endif FPC_HAS_FEATURE_ANSISTRINGS}
+End;
 
 
 Procedure Close(var t : Text);[IOCheck];
@@ -148,8 +202,7 @@ Begin
   TextRec(t).bufend:=0;
   {$ifdef FPC_HAS_CPSTRING}
   { if no codepage is yet assigned then assign default ansi codepage }
-  if TextRec(t).CodePage=CP_ACP then
-    TextRec(t).CodePage:=DefaultSystemCodePage;
+  TextRec(t).CodePage:=TranslatePlaceholderCP(TextRec(t).CodePage);
   {$endif}
   FileFunc(TextRec(t).OpenFunc)(TextRec(t));
   { reset the mode to closed when an error has occured }
@@ -205,47 +258,134 @@ Begin
   If InOutRes <> 0 then
    exit;
   If TextRec(t).mode=fmClosed Then
-   Do_Erase(PChar(@TextRec(t).Name));
+   Do_Erase(PFileTextRecChar(@TextRec(t).Name),false);
 End;
 
 
-Procedure Rename(var t : text;p:pchar);[IOCheck];
+Procedure Rename(var t : Text;const s : unicodestring);[IOCheck];
+{$ifdef FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+var
+  fs: RawByteString;
+{$endif FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
 Begin
-  If InOutRes <> 0 then
-   exit;
-  If TextRec(t).mode=fmClosed Then
-   Begin
-     Do_Rename(PChar(@TextRec(t).Name),p);
-     { check error code of do_rename }
-     If InOutRes = 0 then
-         Move(p^,TextRec(t).Name,StrLen(p)+1);
-   End;
+  If (InOutRes<>0) or
+     (TextRec(t).mode<>fmClosed) then
+    exit;
+{$ifdef FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+  { it's slightly faster to convert the unicodestring here to rawbytestring
+    than doing it in do_rename(), because here we still know the length }
+  fs:=ToSingleByteFileSystemEncodedFileName(s);
+  Do_Rename(PFileTextRecChar(@TextRec(t).Name),PAnsiChar(fs),false,true);
+  If InOutRes=0 then
+     TextRec(t).Name:=fs
+{$else FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+  Do_Rename(PFileTextRecChar(@TextRec(t).Name),PUnicodeChar(S),false,false);
+  If InOutRes=0 then
+{$ifdef FPC_ANSI_TEXTTextRec}
+    TextRec(t).Name:=ToSingleByteFileSystemEncodedFileName(s);
+{$else FPC_ANSI_TEXTFILEREC}
+    TextRec(t).Name:=s
+{$endif FPC_ANSI_TEXTFILEREC}
+{$endif FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
 End;
 
 
-Procedure Rename(var t : Text;const s : string);[IOCheck];
+Procedure Rename(var t : Text;const s : rawbytestring);[IOCheck];
+var
+{$ifdef FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+  fs: RawByteString;
+  pdst: PAnsiChar;
+{$else FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+  fs: UnicodeString;
+  pdst: PUnicodeChar;
+{$endif FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+  dstchangeable: boolean;
+Begin
+  If (InOutRes<>0) or
+     (TextRec(t).mode<>fmClosed) then
+    exit;
+{$ifdef FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+  dstchangeable:=false;
+  pdst:=PAnsiChar(s);
+  if StringCodePage(s)<>DefaultFileSystemCodePage then
+    begin
+      fs:=ToSingleByteFileSystemEncodedFileName(s);
+      pdst:=PAnsiChar(fs);
+      dstchangeable:=true;
+    end
+  else
+    fs:=s;
+{$else FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+   { it's slightly faster to convert the rawbytestring here to unicodestring
+     than doing it in do_rename, because here we still know the length }
+   fs:=unicodestring(s);
+   pdst:=PUnicodeChar(fs);
+   dstchangeable:=true;
+{$endif FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+  Do_Rename(PFileTextRecChar(@TextRec(t).Name),pdst,false,dstchangeable);
+  If InOutRes=0 then
+{$if defined(FPC_ANSI_TEXTTextRec) and not defined(FPCRTL_FILESYSTEM_SINGLE_BYTE_API)}
+    TextRec(t).Name:=ToSingleByteFileSystemEncodedFileName(fs)
+{$else FPC_ANSI_TEXTTextRec and not FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+    TextRec(t).Name:=fs
+{$endif FPC_ANSI_TEXTTextRec and not FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+End;
+
+
+Procedure Rename(var t : Text;const s : ShortString);[IOCheck];
+{$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
+Begin
+  Rename(t,AnsiString(s));
+End;
+{$else FPC_HAS_FEATURE_ANSISTRINGS}
 var
   p : array[0..255] Of Char;
 Begin
-  If InOutRes <> 0 then
-   exit;
   Move(s[1],p,Length(s));
   p[Length(s)]:=#0;
   Rename(t,Pchar(@p));
 End;
+{$endif FPC_HAS_FEATURE_ANSISTRINGS}
 
+Procedure Rename(var t:Text;const p:PAnsiChar);
+{$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
+Begin
+  Rename(t,AnsiString(p));
+End;
+{$else FPC_HAS_FEATURE_ANSISTRINGS}
+var
+  len: SizeInt
+Begin
+  If InOutRes<>0 then
+    exit;
+  If TextRec(t).mode=fmClosed Then
+    Begin
+      Do_Rename(PFileTextRecChar(@TextRec(t).Name),p,false);
+      { check error code of do_rename }
+      If InOutRes=0 then
+        begin
+          len:=min(StrLen(p),high(TextRec(t).Name));
+          Move(p^,TextRec(t).Name,len);
+          TextRec(t).Name[len]:=#0;
+        end;
+    End;
+End;
+{$endif FPC_HAS_FEATURE_ANSISTRINGS}
 
-Procedure Rename(var t : Text;c : char);[IOCheck];
+Procedure Rename(var t : Text;const c : AnsiChar);[IOCheck];
+{$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
+Begin
+  Rename(t,AnsiString(c));
+End;
+{$else FPC_HAS_FEATURE_ANSISTRINGS}
 var
-  p : array[0..1] Of Char;
+  p : array[0..1] Of AnsiChar;
 Begin
-  If InOutRes <> 0 then
-   exit;
   p[0]:=c;
   p[1]:=#0;
-  Rename(t,Pchar(@p));
+  Rename(t,PAnsiChar(@p));
 End;
-
+{$endif FPC_HAS_FEATURE_ANSISTRINGS}
 
 Function Eof(Var t: Text): Boolean;[IOCheck];
 Begin

+ 4 - 2
rtl/inc/textrec.inc

@@ -29,7 +29,9 @@ const
 {$endif CPUAVR}
 type
   TLineEndStr = string [3];
-  TextBuf = array[0..TextRecBufSize-1] of char;
+  TextBuf = array[0..TextRecBufSize-1] of ansichar;
+  TTextBuf = TextBuf;
+
   { using packed makes the compiler to generate ugly code on some CPUs, further
     using packed causes the compiler to handle arrays of text wrongly, see  see tw0754 e.g. on arm  }
   TextRec = {$ifdef VER2_6} packed {$endif} Record
@@ -45,7 +47,7 @@ type
     flushfunc,
     closefunc : codepointer;
     UserData  : array[1..32] of byte;
-    name      : array[0..textrecnamelength-1] of char;
+    name      : array[0..textrecnamelength-1] of TFileTextRecChar;
     LineEnd   : TLineEndStr;
     buffer    : textbuf;
 {$ifdef FPC_HAS_CPSTRING}

+ 24 - 16
rtl/inc/typefile.inc

@@ -15,48 +15,56 @@
                     subroutines for typed file handling
 ****************************************************************************}
 
-Procedure Assign(out f:TypedFile;const Name:string);
+{$ifdef FPC_HAS_FEATURE_WIDESTRINGS}
+Procedure Assign(out f:TypedFile;const Name: UnicodeString);
 {
   Assign Name to file f so it can be used with the file routines
 }
 Begin
-  FillChar(f,SizeOF(FileRec),0);
-  FileRec(f).Handle:=UnusedHandle;
-  FileRec(f).mode:=fmClosed;
-  Move(Name[1],FileRec(f).Name,Length(Name));
+  Assign(UnTypedFile(f),Name);
 End;
+{$endif FPC_HAS_FEATURE_WIDESTRINGS}
 
 
-Procedure Assign(out f:TypedFile;p:pchar);
+{$ifdef FPC_HAS_FEATURE_ANSISTRINGS}
+Procedure Assign(out f:TypedFile;const Name: RawByteString);
 {
   Assign Name to file f so it can be used with the file routines
 }
-begin
-  Assign(f,StrPas(p));
-end;
+Begin
+  Assign(UnTypedFile(f),Name);
+End;
+{$endif FPC_HAS_FEATURE_ANSISTRINGS}
 
 
-Procedure Assign(out f:TypedFile;c:char);
+Procedure Assign(out f:TypedFile;const Name: ShortString);
 {
   Assign Name to file f so it can be used with the file routines
 }
-begin
-  Assign(f,string(c));
+Begin
+  Assign(UnTypedFile(f),Name);
+End;
+
+
+Procedure Assign(out f:TypedFile;const p:PAnsiChar);
+Begin
+  Assign(UnTypedFile(f),p);
 end;
 
 
+Procedure Assign(out f:TypedFile;const c:AnsiChar);
+Begin
+  Assign(UnTypedFile(f),c);
+end;
+
 Procedure fpc_reset_typed(var f : TypedFile;Size : Longint);[Public,IOCheck, Alias:'FPC_RESET_TYPED']; compilerproc;
 Begin
-  If InOutRes <> 0 then
-   exit;
   Reset(UnTypedFile(f),Size);
 End;
 
 
 Procedure fpc_rewrite_typed(var f : TypedFile;Size : Longint);[Public,IOCheck, Alias:'FPC_REWRITE_TYPED']; compilerproc;
 Begin
-  If InOutRes <> 0 then
-   exit;
   Rewrite(UnTypedFile(f),Size);
 End;
 

+ 8 - 3
rtl/inc/ustringh.inc

@@ -53,9 +53,10 @@ procedure DefaultAnsi2UnicodeMove(source:pchar;cp : TSystemCodePage;var dest:uni
 
 Type
   TStandardCodePageEnum = (
-    scpAnsi,          // system Ansi code page (GetACP on windows)
-    scpConsoleInput,  // system console input code page (GetConsoleCP on windows)
-    scpConsoleOutput  // system console output code page (GetConsoleOutputCP on windows)
+    scpAnsi,                 // system Ansi code page (GetACP on windows)
+    scpConsoleInput,         // system console input code page (GetConsoleCP on windows)
+    scpConsoleOutput,        // system console output code page (GetConsoleOutputCP on windows)
+    scpFileSystemSingleByte  // file system code page used by single byte OS FileSystem APIs (GetACP on Windows),
   );
 
 {$ifndef FPC_HAS_BUILTIN_WIDESTR_MANAGER}
@@ -144,3 +145,7 @@ Procedure SetUnicodeStringManager (Const New : TUnicodeStringManager; Var Old: T
 function StringElementSize(const S : UnicodeString): Word; overload;
 function StringRefCount(const S : UnicodeString): SizeInt; overload;
 function StringCodePage(const S : UnicodeString): TSystemCodePage; overload;
+
+Function ToSingleByteFileSystemEncodedFileName(const Str: UnicodeString): RawByteString;
+Function ToSingleByteFileSystemEncodedFileName(const arr: array of widechar): RawByteString;
+Function ToSingleByteFileSystemEncodedFileName(const Str: RawByteString): RawByteString;

+ 50 - 15
rtl/inc/ustrings.inc

@@ -70,7 +70,7 @@ begin
   setlength(dest,len);
   if not assigned(pointer(dest)) then
     exit;
-  PAnsiRec(dest)^.CodePage:=cp;
+  SetCodePage(dest,cp,false);
   p:=pointer(dest);         {SetLength guarantees that dest is unique}
   for i:=1 to len do
     begin
@@ -124,7 +124,13 @@ function DefaultCodePointLength(const Str: PChar; MaxLookAead: PtrInt): Ptrint;
 function DefaultGetStandardCodePage(const stdcp: TStandardCodePageEnum): TSystemCodePage;
   begin
     { don't raise an exception here. We need this for text file handling }
-    Result:=DefaultSystemCodePage;
+    if stdcp<>scpFileSystemSingleByte then
+      Result:=DefaultSystemCodePage
+    else
+      { we could return UTF-8 here in case of FPCRTL_FILESYSTEM_UTF8, but
+        without a fully functional widestring manager that will probably cause
+        more problems that it solves }
+      Result:=DefaultFileSystemCodePage
   end;
 
 Procedure GetUnicodeStringManager (Var Manager : TUnicodeStringManager);
@@ -306,8 +312,7 @@ begin
   Size:=Length(S2);
   if Size>0 then
   begin
-    if (cp=CP_ACP) then
-      cp:=DefaultSystemCodePage;
+    cp:=TranslatePlaceholderCP(cp);
     widestringmanager.Unicode2AnsiMoveProc(PUnicodeChar(Pointer(S2)),result,cp,Size);
   end;
 end;
@@ -328,9 +333,7 @@ begin
   Size:=Length(S2);
   if Size>0 then
   begin
-    cp:=StringCodePage(S2);
-    if (cp=CP_ACP) then
-      cp:=DefaultSystemCodePage;
+    cp:=TranslatePlaceholderCP(StringCodePage(S2));
     widestringmanager.Ansi2UnicodeMoveProc(PChar(S2),cp,result,Size);
   end;
 end;
@@ -595,7 +598,11 @@ end;
 
 {$ifndef FPC_HAS_UCHAR_TO_SHORTSTR}
 {$define FPC_HAS_UCHAR_TO_SHORTSTR}
-procedure fpc_UChar_To_ShortStr(out res : shortstring;const c : WideChar) compilerproc;
+{$ifdef VER2_6}
+procedure fpc_UChar_To_ShortStr(out result : shortstring;const c : WideChar); compilerproc;
+{$else}
+function fpc_UChar_To_ShortStr(const c : WideChar): shortstring; compilerproc;
+{$endif}
 {
   Converts a WideChar to a ShortString;
 }
@@ -603,7 +610,7 @@ var
   s: ansistring;
 begin
   widestringmanager.Wide2AnsiMoveProc(@c,s,DefaultSystemCodePage,1);
-  res:=s;
+  result:=s;
 end;
 {$endif FPC_HAS_UCHAR_TO_SHORTSTR}
 
@@ -635,8 +642,7 @@ begin
 {$ifndef FPC_HAS_CPSTRING}
   cp:=DefaultSystemCodePage;
 {$endif FPC_HAS_CPSTRING}     
-  if (cp=CP_ACP) then
-    cp:=DefaultSystemCodePage;
+  cp:=TranslatePlaceholderCP(cp);
   widestringmanager.Unicode2AnsiMoveProc(@c, fpc_UChar_To_AnsiStr, cp, 1);
 end;
 {$endif FPC_HAS_UCHAR_TO_ANSISTR}
@@ -943,14 +949,18 @@ Procedure fpc_UnicodeStr_SetLength(Var S : UnicodeString; l : SizeInt);[Public,A
 Var
   Temp : Pointer;
   movelen: SizeInt;
-  lens, lena : SizeUInt;
+  nl,lens, lena : SizeUInt;
 begin
+  nl:=l;
+{$IFDEF VER2_6}
+  nl:=nl*2;
+{$ENDIF}
    if (l>0) then
     begin
       if Pointer(S)=nil then
         begin
           { Need a complete new string...}
-          Pointer(s):=NewUnicodeString(l);
+          Pointer(s):=NewUnicodeString(nl);
         end
       else
         if (PUnicodeRec(Pointer(S)-UnicodeFirstOff)^.Ref = 1) then
@@ -967,7 +977,7 @@ begin
       else
         begin
           { Reallocation is needed... }
-          Temp:=NewUnicodeString(L);
+          Temp:=NewUnicodeString(nL);
           if Length(S)>0 then
             begin
               if l < succ(length(s)) then
@@ -982,7 +992,7 @@ begin
         end;
       { Force nil termination in case it gets shorter }
       PWord(Pointer(S)+l*sizeof(UnicodeChar))^:=0;
-      PUnicodeRec(Pointer(S)-UnicodeFirstOff)^.Len:=l;
+      PUnicodeRec(Pointer(S)-UnicodeFirstOff)^.Len:=nl;
     end
   else  { length=0, deallocate the string }
     fpc_unicodestr_decr_ref (Pointer(S));
@@ -2275,3 +2285,28 @@ procedure initunicodestringmanager;
   end;
 {$endif FPC_HAS_BUILTIN_WIDESTR_MANAGER}
 
+
+{$ifndef FPC_HAS_TOSINGLEBYTEFILESYSTEMENCODEDFILENAME_UNICODESTRING}
+{$define FPC_HAS_TOSINGLEBYTEFILESYSTEMENCODEDFILENAME_UNICODESTRING}
+Function ToSingleByteFileSystemEncodedFileName(const Str: UnicodeString): RawByteString;
+Begin
+  widestringmanager.Unicode2AnsiMoveProc(punicodechar(Str),Result,
+    DefaultFileSystemCodePage,Length(Str));
+End;
+{$endif FPC_HAS_TOSINGLEBYTEFILESYSTEMENCODEDFILENAME_UNICODESTRING}
+
+
+{$ifndef FPC_HAS_TOSINGLEBYTEFILESYSTEMENCODEDFILENAME_UNICODECHARARRAY}
+{$define FPC_HAS_TOSINGLEBYTEFILESYSTEMENCODEDFILENAME_UNICODECHARARRAY}
+Function ToSingleByteFileSystemEncodedFileName(const arr: array of widechar): RawByteString;
+Begin
+  widestringmanager.Unicode2AnsiMoveProc(@arr[0],Result,
+    DefaultFileSystemCodePage,length(pwidechar(@arr[0])));
+End;
+{$endif FPC_HAS_TOSINGLEBYTEFILESYSTEMENCODEDFILENAME_UNICODECHARARRAY}
+
+Function ToSingleByteFileSystemEncodedFileName(const Str: RawByteString): RawByteString;
+Begin
+  Result:=Str;
+  SetCodePage(Result,DefaultFileSystemCodePage,True);
+End;

+ 24 - 0
rtl/inc/uuchar.pp

@@ -21,7 +21,31 @@ interface
     char = widechar;
     pchar = pwidechar;
 
+
+{$ifdef FPC_HAS_FEATURE_COMMANDARGS}
+Function ParamStr(Param: Longint): UnicodeString;
+{$endif FPC_HAS_FEATURE_COMMANDARGS}
+
 implementation
 
+{$ifdef FPC_HAS_FEATURE_COMMANDARGS}
+Function ParamStr(Param: Longint): UnicodeString;
+  begin
+  {
+    Paramstr(0) should return the name of the binary.
+    Since this functionality is included in the system unit,
+    we fetch it from there.
+    Normally, pathnames are less than 255 chars anyway,
+    so this will work correct in 99% of all cases.
+    In time, the system unit should get a GetExeName call.
+  }
+    if (Param=0) then
+      Paramstr:=System.Paramstr(0)
+    else if (Param>0) and (Param<argc) then
+      paramstr:=UnicodeString(Argv[Param])
+    else
+      paramstr:='';
+  end;
+{$endif FPC_HAS_FEATURE_COMMANDARGS}
 
 end.

+ 2 - 5
rtl/inc/wstrings.inc

@@ -194,8 +194,7 @@ begin
   Size:=Length(S2);
   if Size>0 then
   begin
-    if (cp=CP_ACP) then
-      cp:=DefaultSystemCodePage;
+    cp:=TranslatePlaceholderCP(cp);
     widestringmanager.Wide2AnsiMoveProc(PWideChar(Pointer(S2)),result,cp,Size);
   end;
 end;
@@ -213,9 +212,7 @@ begin
   Size:=Length(S2);
   if Size>0 then
   begin
-    cp:=StringCodePage(S2);
-    if (cp=CP_ACP) then
-      cp:=DefaultSystemCodePage;
+    cp:=TranslatePlaceholderCP(StringCodePage(S2));
     widestringmanager.Ansi2WideMoveProc(PChar(S2),cp,result,Size);
   end;
 end;

+ 73 - 55
rtl/java/jastrings.inc

@@ -17,6 +17,18 @@
 { This will release some functions for special shortstring support }
 { define EXTRAANSISHORT}
 
+{$define FPC_HAS_TRANSLATEPLACEHOLDERCP}
+function TranslatePlaceholderCP(cp: TSystemCodePage): TSystemCodePage; {$ifdef SYSTEMINLINE}inline;{$endif}
+begin
+  TranslatePlaceholderCP:=cp;
+  case cp of
+    CP_OEMCP,
+    CP_ACP:
+      TranslatePlaceholderCP:=DefaultSystemCodePage;
+  end;
+end;
+
+
 constructor AnsistringClass.Create(len: longint; cp: TSystemCodePage);
 begin
   fElementSize:=1;
@@ -146,7 +158,7 @@ end;
 
 function AnsistringClass.toUnicodeString: unicodestring;
 begin
-  widestringmanager.Ansi2UnicodeMoveProc(pchar(fdata),fCodePage,result,system.length(fdata)-1);
+  widestringmanager.Ansi2UnicodeMoveProc(pchar(fdata),TranslatePlaceholderCP(fCodePage),result,system.length(fdata)-1);
 end;
 
 
@@ -302,11 +314,8 @@ begin
   Size:=Length(S);
   if Size>0 then
     begin
-      if (cp=CP_ACP) then
-        cp:=DefaultSystemCodePage;
-      orgcp:=StringCodePage(S);
-      if (orgcp=CP_ACP) then
-        orgcp:=DefaultSystemCodePage;
+      cp:=TranslatePlaceholderCP(cp);
+      orgcp:=TranslatePlaceholderCP(StringCodePage(S));
       if (orgcp=cp) or (orgcp=CP_NONE) then
         begin
           result:=RawByteString(AnsistringClass.Create(S,cp));
@@ -325,16 +334,17 @@ Function fpc_AnsiStr_To_AnsiStr (const S : RawByteString;cp : TSystemCodePage):
 {$define FPC_HAS_ANSISTR_CONCAT_MULTI}
 procedure fpc_AnsiStr_Concat_multi (var DestS:RawByteString;const sarr:array of RawByteString{$ifdef FPC_HAS_CPSTRING};cp : TSystemCodePage{$endif FPC_HAS_CPSTRING}); compilerproc;
 Var
-  lowstart,i  : Longint;
+  lowstart,
+  nonemptystart,
+  i           : Longint;
   p           : pointer;
   Size,NewLen,
   OldDestLen  : SizeInt;
   destcopy    : RawByteString;
-  DestCP      : TSystemCodePage;
   U           : UnicodeString;
-  sameCP      : Boolean;
-  tmpStr      : RawByteString;
+  DestCP      : TSystemCodePage;
   tmpCP       : TSystemCodePage;
+  sameCP      : Boolean;
 begin
   if high(sarr)=0 then
     begin
@@ -342,23 +352,26 @@ begin
       exit;
     end;
 {$ifdef FPC_HAS_CPSTRING}
-  if (Pointer(DestS)=nil) then
-    DestCP:=cp
-  else
-    DestCP:=StringCodePage(DestS);
+  DestCP:=cp;
+  if DestCp=CP_NONE then
+    DestCP:=DefaultSystemCodePage;
 {$else FPC_HAS_CPSTRING}
   DestCP:=StringCodePage(DestS);
 {$endif FPC_HAS_CPSTRING}
-  if (DestCP=CP_ACP) then
-    DestCP:=DefaultSystemCodePage;
+  DestCP:=TranslatePlaceholderCP(DestCP);
   sameCP:=true;
   lowstart:=low(sarr);
-  for i:=lowstart to high(sarr) do
+  { skip empty strings }
+  while (lowstart<=high(sarr)) and
+        (sarr[lowstart]='') do
+    inc(lowstart);
+  tmpCP:=TranslatePlaceholderCP(StringCodePage(sarr[lowstart]));
+  for i:=lowstart+1 to high(sarr) do
     begin
-      tmpCP:=StringCodePage(sarr[i]);
-      if tmpCP=CP_ACP then
-        tmpCP:=DefaultSystemCodePage;
-      if (DestCP<>tmpCp) then
+      { ignore the code page of empty strings, it will always be
+        DefaultSystemCodePage but it doesn't matter for the outcome }
+      if (sarr[i]<>'') and
+         (tmpCP<>TranslatePlaceholderCP(StringCodePage(sarr[i]))) then
         begin
           sameCP:=false;
           break;
@@ -367,43 +380,44 @@ begin
   if not sameCP then
     begin
       U:='';
-      for i:=lowstart to high(sarr) do begin
-        tmpCP:=StringCodePage(sarr[i]);
-        if (tmpCP=CP_ACP) then
-          begin
-            tmpStr:=sarr[i];
-            SetCodePage(tmpStr,DefaultSystemCodePage,False);
-            U:=U+UnicodeString(tmpStr);
-          end
-        else
+      for i:=lowstart to high(sarr) do
+        if sarr[i]<>'' then
           U:=U+UnicodeString(sarr[i]);
-      end;
 
       DestS:='';
       widestringmanager.Unicode2AnsiMoveProc(PUnicodeChar(JLString(U).toCharArray),DestS,DestCP,Length(U));
       exit;
     end;
-
-  lowstart:=low(sarr);
-  if Pointer(DestS)=Pointer(sarr[lowstart]) then
-    inc(lowstart);
+  {$ifdef FPC_HAS_CPSTRING}
+    { if the result is rawbytestring and all strings have the same code page,
+      keep that code page }
+    if cp=CP_NONE then
+      DestCP:=tmpCP;
+  {$endif FPC_HAS_CPSTRING}
+
+  nonemptystart:=lowstart;
   { Check for another reuse, then we can't use
     the append optimization }
-  for i:=lowstart to high(sarr) do
+  if DestS<>'' then
     begin
-      if Pointer(DestS)=Pointer(sarr[i]) then
+      if Pointer(DestS)=Pointer(sarr[lowstart]) then
+        inc(lowstart);
+      for i:=lowstart to high(sarr) do
         begin
-          { if DestS is used somewhere in the middle of the expression,
-            we need to make sure the original string still exists after
-            we empty/modify DestS -- not necessary on JVM platform, ansistrings
-            are not explicitly refrence counted there }
-          lowstart:=low(sarr);
-          break;
+          if Pointer(DestS)=Pointer(sarr[i]) then
+            begin
+              { if DestS is used somewhere in the middle of the expression,
+                we need to make sure the original string still exists after
+                we empty/modify DestS -- not necessary on JVM platform, ansistrings
+                are not explicitly refrence counted there }
+              lowstart:=nonemptystart;
+              break;
+            end;
         end;
     end;
   { Start with empty DestS if we start with concatting
-    the first array element }
-  if lowstart=low(sarr) then
+    the first (non-empty) array element }
+  if lowstart=nonemptystart then
     DestS:='';
   OldDestLen:=length(DestS);
   { Calculate size of the result so we can do
@@ -412,8 +426,6 @@ begin
   for i:=low(sarr) to high(sarr) do
     inc(NewLen,length(sarr[i]));
   SetLength(DestS,NewLen);
-  if (StringCodePage(DestS) <> DestCP) then
-    SetCodePage(DestS,DestCP,False);
   { Concat all strings, except the string we already
     copied in DestS }
   NewLen:=OldDestLen;
@@ -427,6 +439,11 @@ begin
           inc(NewLen,size);
         end;
     end;
+  if NewLen<>0 then
+    begin
+      SetCodePage(DestS,tmpCP,False);
+      SetCodePage(DestS,DestCP,True);
+    end;
 end;
 
 
@@ -468,8 +485,7 @@ begin
   if L > 0 then
     begin
 {$ifdef FPC_HAS_CPSTRING}
-      if (cp=CP_ACP) then
-        cp:=DefaultSystemCodePage;
+      cp:=TranslatePlaceholderCP(cp);
 {$else FPC_HAS_CPSTRING}
       cp:=DefaultSystemCodePage;
 {$endif FPC_HAS_CPSTRING}
@@ -552,10 +568,11 @@ begin
   else
     begin
       r1:=S1;
-      if (cp1=CP_ACP) then
+      cp1:=TranslatePlaceholderCP(cp1);
+      if (cp1<>StringCodePage(r1)) then
         SetCodePage(r1,DefaultSystemCodePage,false);
       r2:=S2;
-      if (cp2=CP_ACP) then
+      if (cp2<>StringCodePage(r2)) then
         SetCodePage(r2,DefaultSystemCodePage,false);
       //convert them to utf8 then compare
       SetCodePage(r1,65001);
@@ -599,10 +616,12 @@ begin
   if cp1<>cp2 then
     begin
       r1:=S1;
-      if (cp1=CP_ACP) then
+      cp1:=TranslatePlaceholderCP(cp1);
+      if (cp1<>StringCodePage(r1)) then
         SetCodePage(r1,DefaultSystemCodePage,false);
       r2:=S2;
-      if (cp2=CP_ACP) then
+      cp2:=TranslatePlaceholderCP(cp2);
+      if (cp2<>StringCodePage(r2)) then
         SetCodePage(r2,DefaultSystemCodePage,false);
       //convert them to utf8 then compare
       SetCodePage(r1,65001);
@@ -631,8 +650,7 @@ var
   oldlen: longint;
   result: RawByteString;
 begin
-  if (cp=CP_ACP) then
-    cp:=DefaultSystemCodePage;
+  cp:=TranslatePlaceholderCP(cp);
   { no explicit reference counting possible -> can't reuse S because we don't
     know how many references exist to it }
   result:=RawByteString(AnsistringClass.Create(l,cp));

+ 2 - 2
rtl/java/jcompproc.inc

@@ -36,7 +36,7 @@ procedure fpc_Shortstr_SetLength(var s:shortstring;len:SizeInt); compilerproc;
 //procedure fpc_shortstr_assign(len:longint;sstr,dstr:pointer); compilerproc;
 procedure fpc_shortstr_to_shortstr(out res:shortstring; const sstr: shortstring); compilerproc;
 { JVM-specific }
-procedure fpc_Char_To_ShortStr(out res : shortstring;const c : AnsiChar) compilerproc;
+function fpc_Char_To_ShortStr(const c : AnsiChar): ShortString; compilerproc;
 
 
 procedure fpc_shortstr_concat(var dests:shortstring;const s1,s2:shortstring);compilerproc;
@@ -285,7 +285,7 @@ Function fpc_Char_To_UChar(const c : AnsiChar): UnicodeChar; compilerproc;
 Function fpc_UChar_To_Char(const c : UnicodeChar): AnsiChar; compilerproc;
 Function fpc_UChar_To_UnicodeStr(const c : UnicodeChar): UnicodeString; compilerproc;
 Function fpc_UChar_To_AnsiStr(const c : UnicodeChar{$ifdef FPC_HAS_CPSTRING};cp : TSystemCodePage{$endif FPC_HAS_CPSTRING}): AnsiString; compilerproc;
-procedure fpc_UChar_To_ShortStr(out res : shortstring;const c : UnicodeChar) compilerproc;
+function fpc_UChar_To_ShortStr(const c : UnicodeChar): shortstring; compilerproc;
 
 Function fpc_PWideChar_To_UnicodeStr(const p : pwidechar): unicodestring; compilerproc;
 {$ifdef FPC_HAS_FEATURE_ANSISTRINGS}

+ 3 - 3
rtl/java/jsstrings.inc

@@ -220,13 +220,13 @@ end;
 
 
 {$define FPC_HAS_CHAR_TO_SHORTSTR}
-procedure fpc_Char_To_ShortStr(out res : shortstring;const c : AnsiChar) compilerproc;
+function fpc_Char_To_ShortStr(const c : AnsiChar): shortstring; compilerproc;
 {
   Converts an AnsiChar to a ShortString;
 }
 begin
-  setlength(res,1);
-  ShortstringClass(@res).fdata[0]:=c;
+  setlength(result,1);
+  ShortstringClass(@result).fdata[0]:=c;
 end;
 
 

+ 8 - 0
rtl/java/jsystemh_types.inc

@@ -295,6 +295,7 @@ Type
 { some values which are used in RTL for TSystemCodePage type }
 const
   CP_ACP     = 0;     // default to ANSI code page
+  CP_OEMCP   = 1;     // default to OEM (console) code page
   CP_UTF16   = 1200;  // utf-16
   CP_UTF16BE = 1201;  // unicodeFFFE
   CP_UTF7    = 65000; // utf-7
@@ -533,6 +534,13 @@ var
 
   DefaultSystemCodePage,
   DefaultUnicodeCodePage,
+  { the code page to use when sending paths/file names to OS file system API
+    calls using single byte strings, and to interpret the results gotten back
+    from such API calls }
+  DefaultFileSystemCodePage,
+  { the code page to use to return file names from single byte file system calls
+    in the RTL that return ansistrings (by default, same as a above) }
+  DefaultRTLFileSystemCodePage,
   UTF8CompareLocale : TSystemCodePage;
 
 

+ 20 - 10
rtl/java/justrings.inc

@@ -122,8 +122,7 @@ Function fpc_UnicodeStr_To_AnsiStr (const S2 : UnicodeString{$ifdef FPC_HAS_CPST
 Var
   Size : SizeInt;
 begin
-  if (cp=CP_ACP) then
-    cp:=DefaultSystemCodePage;
+  cp:=TranslatePlaceholderCP(cp);
   { avoid codepage conversion -- why isn't the result rawbytestring? }
   pointer(result):=pointer(AnsistringClass.Create(s2,cp));
 end;
@@ -185,8 +184,7 @@ begin
   if (p=nil) or
      (p^=#0) then
     exit;
-  if (cp=CP_ACP) then
-    cp:=DefaultSystemCodePage;
+  cp:=TranslatePlaceholderCP(cp);
   pointer(result):=pointer(AnsistringClass.Create(unicodestring(p),cp));
 end;
 
@@ -317,14 +315,13 @@ var
   arr: array[0..0] of unicodechar;
 begin
   arr[0]:=c;
-  if (cp=CP_ACP) then
-    cp:=DefaultSystemCodePage;
+  cp:=TranslatePlaceholderCP(cp);
   widestringmanager.Unicode2AnsiMoveProc(punicodechar(@arr), RawByteString(fpc_UChar_To_AnsiStr), cp, 1);
 end;
 
 
 {$define FPC_HAS_UCHAR_TO_SHORTSTR}
-procedure fpc_UChar_To_ShortStr(out res : shortstring;const c : UnicodeChar) compilerproc;
+function fpc_UChar_To_ShortStr(const c : UnicodeChar): shortstring; compilerproc;
 {
   Converts a UnicodeChar to a AnsiString;
 }
@@ -332,7 +329,7 @@ var
   u: unicodestring;
 begin
   u:=c;
-  res:=u;
+  result:=u;
 end;
 
 
@@ -351,8 +348,7 @@ begin
 {$ifndef FPC_HAS_CPSTRING}
   cp:=DefaultSystemCodePage;
 {$endif FPC_HAS_CPSTRING}
-  if (cp=CP_ACP) then
-    cp:=DefaultSystemCodePage;
+  cp:=TranslatePlaceholderCP(cp);
   arr[0]:=c;
   widestringmanager.Unicode2AnsiMoveProc(punicodechar(@arr[0]), fpc_UChar_To_AnsiStr, cp, 1);
 end;
@@ -906,6 +902,18 @@ function StringCodePage(const S : UnicodeString): TSystemCodePage;
       result:=DefaultUnicodeCodePage;
   end;
 
+{$define FPC_HAS_TOSINGLEBYTEFILESYSTEMENCODEDFILENAME_UNICODESTRING}
+Function ToSingleByteFileSystemEncodedFileName(const Str: UnicodeString): RawByteString;
+Begin
+  result:=AnsiString(AnsistringClass.Create(Str,DefaultFileSystemCodePage));
+End;
+
+{$define FPC_HAS_TOSINGLEBYTEFILESYSTEMENCODEDFILENAME_UNICODECHARARRAY}
+Function ToSingleByteFileSystemEncodedFileName(const arr: array of widechar): RawByteString;
+Begin
+  result:=AnsiString(AnsistringClass.Create(arr,DefaultFileSystemCodePage));
+End;
+
 
 { helpers for converting between Windows and Java code page identifiers }
 
@@ -1009,6 +1017,8 @@ class constructor TUnicodeStringManager.ClassCreate;
       stdin etc, so setting this to utf-8 or so won't help) }
     if DefaultSystemCodePage=65535 then
       DefaultSystemCodePage:=20127;
+    DefaultFileSystemCodePage:=DefaultSystemCodePage;
+    DefaultRTLFileSystemCodePage:=DefaultFileSystemCodePage;
     DefaultUnicodeCodePage:=CP_UTF16BE;
   end;
 

+ 24 - 0
rtl/java/rtldefs.inc

@@ -0,0 +1,24 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2012 by Free Pascal development team
+
+    This file contains platform-specific defines that are used in
+    multiple RTL units.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{ the single byte OS APIs always use UTF-8 }
+{ define FPCRTL_FILESYSTEM_UTF8}
+
+{ The OS supports a single byte file system operations API that we use }
+{ define FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+
+{ The OS supports a two byte file system operations API that we use }
+{$define FPCRTL_FILESYSTEM_TWO_BYTE_API}

+ 24 - 0
rtl/linux/rtldefs.inc

@@ -0,0 +1,24 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2012 by Free Pascal development team
+
+    This file contains platform-specific defines that are used in
+    multiple RTL units.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{ the single byte OS APIs always use UTF-8 }
+{ define FPCRTL_FILESYSTEM_UTF8}
+
+{ The OS supports a single byte file system operations API that we use }
+{$define FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+
+{ The OS supports a two byte file system operations API that we use }
+{ define FPCRTL_FILESYSTEM_TWO_BYTE_API}

+ 10 - 2
rtl/macos/dos.pp

@@ -803,7 +803,11 @@ End;
       paramBlock: CInfoPBRec;
 
   begin
-    DosError := PathArgToFSSpec(StrPas(filerec(f).name), spec);
+{$ifdef FPC_ANSI_TEXTFILEREC}
+    DosError := PathArgToFSSpec(filerec(f).name, spec);
+{$else}
+    DosError := PathArgToFSSpec(ToSingleByteFileSystemEncodedFileName(filerec(f).name), spec);
+{$endif}
     if (DosError = 0) or (DosError = 2) then
       begin
         DosError := DoFindOne(spec, paramBlock);
@@ -822,7 +826,11 @@ End;
       macfiletime: UInt32;
 
   begin
-    DosError := PathArgToFSSpec(StrPas(filerec(f).name), spec);
+{$ifdef FPC_ANSI_TEXTFILEREC}
+    DosError := PathArgToFSSpec(filerec(f).name, spec);
+{$else}
+    DosError := PathArgToFSSpec(ToSingleByteFileSystemEncodedFileName(filerec(f).name), spec);
+{$endif}
     if (DosError = 0) or (DosError = 2) then
       begin
         DosError := DoFindOne(spec, paramBlock);

+ 24 - 0
rtl/macos/rtldefs.inc

@@ -0,0 +1,24 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2012 by Free Pascal development team
+
+    This file contains platform-specific defines that are used in
+    multiple RTL units.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{ the single byte OS APIs always use UTF-8 }
+{ define FPCRTL_FILESYSTEM_UTF8}
+
+{ The OS supports a single byte file system operations API that we use }
+{$define FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+
+{ The OS supports a two byte file system operations API that we use }
+{ define FPCRTL_FILESYSTEM_TWO_BYTE_API}

+ 7 - 21
rtl/macos/sysdir.inc

@@ -18,16 +18,14 @@
                            Directory Handling
 *****************************************************************************}
 
-procedure mkdir(const s:string);[IOCheck];
+procedure do_mkdir(const s: rawbytestring);
 var
   spec: FSSpec;
   createdDirID: Longint;
   err: OSErr;
   res: Integer;
 begin
-  If (s='') or (InOutRes <> 0) then
-    exit;
-
+  { TODO: convert PathArgToFSSpec (and the routines it calls) to rawbytestring }
   res:= PathArgToFSSpec(s, spec);
   if (res = 0) or (res = 2) then
     begin
@@ -38,7 +36,7 @@ begin
     InOutRes:=res;
 end;
 
-procedure rmdir(const s:string);[IOCheck];
+procedure do_rmdir(const s: rawbytestring);
 
 var
   spec: FSSpec;
@@ -46,9 +44,6 @@ var
   res: Integer;
 
 begin
-  If (s='') or (InOutRes <> 0) then
-    exit;
-
   res:= PathArgToFSSpec(s, spec);
 
   if (res = 0) then
@@ -65,15 +60,12 @@ begin
     InOutRes:=res;
 end;
 
-procedure chdir(const s:string);[IOCheck];
+procedure do_chdir(const s: rawbytestring);
 var
   spec, newDirSpec: FSSpec;
   err: OSErr;
   res: Integer;
 begin
-  if (s='') or (InOutRes <> 0) then
-    exit;
-
   res:= PathArgToFSSpec(s, spec);
   if (res = 0) or (res = 2) then
     begin
@@ -98,22 +90,16 @@ begin
     InOutRes:=res;
 end;
 
-procedure getDir (DriveNr: byte; var Dir: ShortString);
+procedure do_getDir (DriveNr: byte; var Dir: RawByteString);
 
 var
-  fullPath: AnsiString;
   pathHandleSize: Longint;
 
 begin
-  if FSpGetFullPath(workingDirectorySpec, fullPath, false) <> noErr then
+  if FSpGetFullPath(workingDirectorySpec, Dir, false) <> noErr then
     Halt(3);  {exit code 3 according to MPW}
 
-  if Length(fullPath) <= 255 then {because dir is ShortString}
-    InOutRes := 0
-  else
-    InOutRes := 1; //TODO Exchange to something better
-
-  dir:= fullPath;
+  SetCodePage(Dir,DefaultFileSystemCodePage,false);
 end;
 
 

+ 3 - 3
rtl/macos/sysfile.inc

@@ -40,7 +40,7 @@ begin
   {$endif}
 end;
 
-procedure do_erase(p : pchar);
+procedure do_erase(p : pchar; pchangeable: boolean);
 
 var
   spec: FSSpec;
@@ -63,7 +63,7 @@ begin
     InOutRes:=res;
 end;
 
-procedure do_rename(p1,p2 : pchar);
+procedure do_rename(p1,p2 : pchar; p1changeable, p2changeable: boolean);
 var
   s1,s2: AnsiString;
 begin
@@ -196,7 +196,7 @@ begin
   {$endif}
 end;
 
-procedure do_open(var f;p:pchar;flags:longint);
+procedure do_open(var f;p:pchar;flags:longint; pchangeable: boolean);
 {
   filerec and textrec have both handle and mode as the first items so
   they could use the same routine for opening/creating.

+ 33 - 58
rtl/macos/sysutils.pp

@@ -44,6 +44,11 @@ type
                 exactMatch: Boolean;
   end;
 
+{ used OS file system APIs use ansistring }
+{$define SYSUTILS_HAS_ANSISTR_FILEUTIL_IMPL}
+{ OS has an ansistring/single byte environment variable API }
+{$define SYSUTILS_HAS_ANSISTR_ENVVAR_IMPL}
+
 { Include platform independent interface part }
 {$i sysutilh.inc}
 
@@ -66,12 +71,13 @@ uses
                               File Functions
 ****************************************************************************}
 
-Function FileOpen (Const FileName : string; Mode : Integer) : Longint;
+Function FileOpen (Const FileName : rawbytestring; Mode : Integer) : Longint;
 
 Var LinuxFlags : longint;
-
-BEGIN
+    SystemFileName: RawByteString;
+begin
   (* TODO fix
+  SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
   LinuxFlags:=0;
   Case (Mode and 3) of
     0 : LinuxFlags:=LinuxFlags or Open_RdOnly;
@@ -84,7 +90,7 @@ BEGIN
 end;
 
 
-Function FileCreate (Const FileName : String) : Longint;
+Function FileCreate (Const FileName : RawByteString) : Longint;
 
 begin
   (* TODO fix
@@ -93,7 +99,7 @@ begin
 end;
 
 
-Function FileCreate (Const FileName : String;Rights : Longint) : Longint;
+Function FileCreate (Const FileName : RawByteString;Rights : Longint) : Longint;
 
 Var LinuxFlags : longint;
 
@@ -109,7 +115,7 @@ BEGIN
   *)
 end;
 
-Function FileCreate (Const FileName : String;ShareMode : Longint; Rights : Longint) : Longint;
+Function FileCreate (Const FileName : RawByteString;ShareMode : Longint; Rights : Longint) : Longint;
 
 Var LinuxFlags : longint;
 
@@ -179,7 +185,7 @@ begin
   *)
 end;
 
-Function FileAge (Const FileName : String): Longint;
+Function FileAge (Const FileName : RawByteString): Longint;
 
   (*
 Var Info : Stat;
@@ -199,7 +205,7 @@ begin
 end;
 
 
-Function FileExists (Const FileName : String) : Boolean;
+Function FileExists (Const FileName : RawByteString) : Boolean;
 
   (*
 Var Info : Stat;
@@ -212,7 +218,7 @@ begin
 end;
 
 
-Function DirectoryExists (Const Directory : String) : Boolean;
+Function DirectoryExists (Const Directory : RawByteString) : Boolean;
 
   (*
 Var Info : Stat;
@@ -289,7 +295,7 @@ end;
 *)
 
 
-procedure DoFind (var F: TSearchRec; firstTime: Boolean);
+procedure DoFind (var F: TSearchRec; var retname: RawByteString; firstTime: Boolean);
 
   var
     err: OSErr;
@@ -323,7 +329,8 @@ begin
           attr := GetFileAttrFromPB(Rslt.paramBlock);
           if ((Attr and not(searchAttr)) = 0) then
             begin
-              name := s;
+              retname := s;
+              SetCodePage(retname, DefaultFileSystemCodePage, false);
               UpperString(s, true);
 
               if FNMatch(Rslt.searchFSSpec.name, s) then
@@ -339,13 +346,11 @@ begin
 end;
 
 
-Function FindFirst (Const Path : String; Attr : Longint; out Rslt : TSearchRec) : Longint;
+Function InternalFindFirst (Const Path : RawByteString; Attr : Longint; out Rslt : TAbstractSearchRec; var Name: RawByteString) : Longint;
   var
     s: Str255;
 
 begin
-  fillchar(Rslt, sizeof(Rslt), 0);
-
   if path = '' then
     begin
       Result := 3;
@@ -355,10 +360,12 @@ begin
   {We always also search for readonly and archive, regardless of Attr.}
   Rslt.searchAttr := (Attr or (archive or readonly));
 
+  { TODO: convert PathArgToFSSpec (and the routines it calls) to rawbytestring }
   Result := PathArgToFSSpec(path, Rslt.searchFSSpec);
   with Rslt do
     if (Result = 0) or (Result = 2) then
       begin
+        { FIXME: SearchSpec is a shortstring -> ignores encoding }
         SearchSpec := path;
         NamePos := Length(path) - Length(searchFSSpec.name);
 
@@ -372,6 +379,7 @@ begin
                 if ((Attr and not(searchAttr)) = 0) then
                   begin
                     name := searchFSSpec.name;
+                    SetCodePage(name, DefaultFileSystemCodePage, false);
                     size := GetFileSizeFromPB(paramBlock);
                     time := MacTimeToDosPackedTime(paramBlock.ioFlMdDat);
                   end
@@ -389,23 +397,23 @@ begin
             UpperString(s, true);
             Rslt.searchFSSpec.name := s;
 
-            DoFind(Rslt, true);
+            DoFind(Rslt, name, true);
           end;
       end;
 end;
 
 
-Function FindNext (Var Rslt : TSearchRec) : Longint;
+Function InternalFindNext (var Rslt : TAbstractSearchRec; var Name : RawByteString) : Longint;
 
 begin
   if F.exactMatch then
     Result := 18
   else
-    Result:=DoFind (Rslt);
+    Result:=DoFind (Rslt, Name, false);
 end;
 
 
-Procedure FindClose (Var F : TSearchrec);
+Procedure InternalFindClose (var Handle: THandle; var FindData: TFindData);
 
   (*
 Var
@@ -414,7 +422,7 @@ Var
 
 begin
   (* TODO fix
-  GlobSearchRec:=PGlobSearchRec(F.FindHandle);
+  GlobSearchRec:=PGlobSearchRec(Handle);
   GlobFree (GlobSearchRec^.GlobHandle);
   Dispose(GlobSearchRec);
   *)
@@ -446,7 +454,7 @@ begin
 end;
 
 
-Function FileGetAttr (Const FileName : String) : Longint;
+Function FileGetAttr (Const FileName : RawByteString) : Longint;
 
   (*
 Var Info : Stat;
@@ -462,14 +470,14 @@ begin
 end;
 
 
-Function FileSetAttr (Const Filename : String; Attr: longint) : Longint;
+Function FileSetAttr (Const Filename : RawByteString; Attr: longint) : Longint;
 
 begin
   Result:=-1;
 end;
 
 
-Function DeleteFile (Const FileName : String) : Boolean;
+Function DeleteFile (Const FileName : RawByteString) : Boolean;
 
 begin
   (* TODO fix
@@ -478,7 +486,7 @@ begin
 end;
 
 
-Function RenameFile (Const OldName, NewName : String) : Boolean;
+Function RenameFile (Const OldName, NewName : RawByteString) : Boolean;
 
 begin
   (* TODO fix
@@ -558,39 +566,6 @@ Begin
   *)
 End;
 
-Function GetCurrentDir : String;
-begin
-  GetDir (0,Result);
-end;
-
-
-Function SetCurrentDir (Const NewDir : String) : Boolean;
-begin
-  {$I-}
-   ChDir(NewDir);
-  {$I+}
-  result := (IOResult = 0);
-end;
-
-
-Function CreateDir (Const NewDir : String) : Boolean;
-begin
-  {$I-}
-   MkDir(NewDir);
-  {$I+}
-  result := (IOResult = 0);
-end;
-
-
-Function RemoveDir (Const Dir : String) : Boolean;
-begin
-  {$I-}
-   RmDir(Dir);
-  {$I+}
-  result := (IOResult = 0);
-end;
-
-
 {****************************************************************************
                               Misc Functions
 ****************************************************************************}
@@ -660,7 +635,7 @@ Function GetEnvironmentVariable(Const EnvVar : String) : String;
 
 begin
   (* TODO fix
-  Result:=StrPas(Unix.Getenv(PChar(EnvVar)));
+  Result:=Unix.Getenv(PChar(EnvVar));
   *)
 end;
 
@@ -671,7 +646,7 @@ begin
   Result:=0;
 end;
 
-Function GetEnvironmentString(Index : Integer) : String;
+Function GetEnvironmentString(Index : Integer) : {$ifdef FPC_RTL_UNICODE}UnicodeString{$else}AnsiString{$endif};
 
 begin
   // Result:=FPCGetEnvStrFromP(Envp,Index);

+ 28 - 6
rtl/morphos/dos.pp

@@ -725,7 +725,11 @@ var
 begin
     DosError:=0;
     FTime := 0;
-    Str := StrPas(filerec(f).name);
+{$ifdef FPC_ANSI_TEXTFILEREC}
+    Str := strpas(filerec(f).Name);
+{$else}
+    Str := ToSingleByteFileSystemEncodedFileName(filerec(f).Name);
+{$endif}
     DoDirSeparators(Str);
     FLock := dosLock(Str, SHARED_LOCK);
     IF FLock <> 0 then begin
@@ -756,7 +760,11 @@ end;
     FLock: longint;
   Begin
     new(DateStamp);
-    Str := StrPas(filerec(f).name);
+{$ifdef FPC_ANSI_TEXTFILEREC}
+    Str := strpas(filerec(f).Name);
+{$else}
+    Str := ToSingleByteFileSystemEncodedFileName(filerec(f).Name);
+{$endif}
     DoDirSeparators(str);
     { Check first of all, if file exists }
     FLock := dosLock(Str, SHARED_LOCK);
@@ -788,7 +796,11 @@ begin
     DosError:=0;
     flags:=0;
     New(info);
-    Str := StrPas(filerec(f).name);
+{$ifdef FPC_ANSI_TEXTFILEREC}
+    Str := strpas(filerec(f).Name);
+{$else}
+    Str := ToSingleByteFileSystemEncodedFileName(filerec(f).Name);
+{$endif}
     DoDirSeparators(str);
     { open with shared lock to check if file exists }
     MyLock:=dosLock(Str,SHARED_LOCK);
@@ -825,7 +837,17 @@ procedure setfattr(var f; attr : word);
 var
   flags: longint;
   tmpLock : longint;
-begin
+{$ifndef FPC_ANSI_TEXTFILEREC}
+  r : rawbytestring;
+{$endif not FPC_ANSI_TEXTFILEREC}
+  p : pchar;
+begin
+{$ifdef FPC_ANSI_TEXTFILEREC}
+    p := @filerec(f).Name;
+{$else}
+    r := ToSingleByteFileSystemEncodedFileName(filerec(f).Name);
+    p := pchar(r);
+{$endif}
   DosError:=0;
   flags:=FIBF_WRITE;
 
@@ -836,10 +858,10 @@ begin
   { converts the path (KB) }
 
   { create a shared lock on the file }
-  tmpLock:=Lock(filerec(f).name,SHARED_LOCK);
+  tmpLock:=Lock(p,SHARED_LOCK);
   if tmpLock <> 0 then begin
     Unlock(tmpLock);
-    if not SetProtection(filerec(f).name,flags) then DosError:=5;
+    if not SetProtection(p,flags) then DosError:=5;
   end else
     DosError:=3;
 end;

+ 24 - 0
rtl/morphos/rtldefs.inc

@@ -0,0 +1,24 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2012 by Free Pascal development team
+
+    This file contains platform-specific defines that are used in
+    multiple RTL units.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{ the single byte OS APIs always use UTF-8 }
+{ define FPCRTL_FILESYSTEM_UTF8}
+
+{ The OS supports a single byte file system operations API that we use }
+{$define FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+
+{ The OS supports a two byte file system operations API that we use }
+{ define FPCRTL_FILESYSTEM_TWO_BYTE_API}

+ 22 - 19
rtl/morphos/sysdir.inc

@@ -17,15 +17,14 @@
 {*****************************************************************************
                            Directory Handling
 *****************************************************************************}
-Procedure MkDir(s: pchar;len:sizeuint);[IOCheck, public, alias : 'FPC_SYS_MKDIR'];
+Procedure do_MkDir(const s: rawbytestring);
 var
-  tmpStr : array[0..255] of char;
+  tmpStr : rawbytestring;
   tmpLock: LongInt;
 begin
   checkCTRLC;
-  if not assigned(s) or (len=0) or (InOutRes<>0) then exit;
-  tmpStr:=PathConv(strpas(s))+#0;
-  tmpLock:=dosCreateDir(@tmpStr);
+  tmpStr:=PathConv(s);
+  tmpLock:=dosCreateDir(pchar(tmpStr));
   if tmpLock=0 then begin
     dosError2InOut(IoErr);
     exit;
@@ -33,34 +32,35 @@ begin
   UnLock(tmpLock);
 end;
 
-Procedure RmDir(s: pchar;len:sizeuint);[IOCheck, public, alias : 'FPC_SYS_RMDIR'];
+Procedure do_RmDir(const s: rawbytestring);
 var
-  tmpStr : array[0..255] of Char;
+  tmpStr : rawbytestring;
 begin
   checkCTRLC;
-  if not assigned(s) or (len=0) then exit;
-  if (s='.') then InOutRes:=16;
-  If (s='') or (InOutRes<>0) then exit;
-  tmpStr:=PathConv(strpas(s))+#0;
-  if not dosDeleteFile(@tmpStr) then
+  if (s='.') then
+    begin
+      InOutRes:=16;
+      exit;
+    end;
+  tmpStr:=PathConv(s);
+  if not dosDeleteFile(pchar(tmpStr)) then
     dosError2InOut(IoErr);
 end;
 
-Procedure ChDir(s: pchar;len:sizeuint);[IOCheck, public, alias : 'FPC_SYS_CHDIR'];
+Procedure do_ChDir(const s: rawbytestring);
 var
-  tmpStr : array[0..255] of Char;
+  tmpStr : rawbytestring;
   tmpLock: LongInt;
   FIB    : PFileInfoBlock;
 begin
   checkCTRLC;
-  if not assigned(s) or (len=0) or (InOutRes<>0) then exit;
-  tmpStr:=PathConv(strpas(s))+#0;
+  tmpStr:=PathConv(s);
   tmpLock:=0;
 
   { Changing the directory is a pretty complicated affair }
   {   1) Obtain a lock on the directory                   }
   {   2) CurrentDir the lock                              }
-  tmpLock:=Lock(@tmpStr,SHARED_LOCK);
+  tmpLock:=Lock(pchar(tmpStr),SHARED_LOCK);
   if tmpLock=0 then begin
     dosError2InOut(IoErr);
     exit;
@@ -83,7 +83,7 @@ begin
   if assigned(FIB) then dispose(FIB);
 end;
 
-procedure GetDir (DriveNr: byte; var Dir: ShortString);
+procedure do_GetDir (DriveNr: byte; var Dir: RawByteString);
 var tmpbuf: array[0..255] of char;
 begin
   checkCTRLC;
@@ -91,5 +91,8 @@ begin
   if not GetCurrentDirName(tmpbuf,256) then
     dosError2InOut(IoErr)
   else
-    Dir:=strpas(tmpbuf);
+    begin
+      Dir:=tmpbuf;
+      SetCodePage(Dir,DefaultFileSystemCodePage,false);
+    end;
 end;

+ 3 - 3
rtl/morphos/sysfile.inc

@@ -171,7 +171,7 @@ begin
   end;
 end;
 
-procedure do_erase(p : pchar);
+procedure do_erase(p : pchar; pchangeable: boolean);
 var
   tmpStr: array[0..255] of Char;
 begin
@@ -181,7 +181,7 @@ begin
     dosError2InOut(IoErr);
 end;
 
-procedure do_rename(p1,p2 : pchar);
+procedure do_rename(p1,p2 : pchar; p1changeable, p2changeable: boolean);
 { quite stack-effective code, huh? :) damn path conversions... (KB) }
 var
   tmpStr1: array[0..255] of Char;
@@ -311,7 +311,7 @@ begin
   end;
 end;
 
-procedure do_open(var f;p:pchar;flags:longint);
+procedure do_open(var f;p:pchar;flags:longint; pchangeable: boolean);
 {
   filerec and textrec have both handle and mode as the first items so
   they could use the same routine for opening/creating.

+ 35 - 0
rtl/morphos/sysos.inc

@@ -137,5 +137,40 @@ begin
 end;
 
 
+{ Converts an Unix-like path to Amiga-like path }
+function PathConv(const path: rawbytestring): rawbytestring; alias: 'PATHCONVRBS'; [public];
+var tmppos: longint;
+begin
+  { check for short paths }
+  if length(path)<=2 then begin
+    if (path='.') or (path='./') then PathConv:='' else
+    if path='..' then PathConv:='/' else
+    if path='*' then PathConv:='#?'
+    else PathConv:=path;
+  end else begin
+    { convert parent directories }
+    PathConv:=path;
+    tmppos:=pos('../',PathConv);
+    while tmppos<>0 do begin
+      { delete .. to have / as parent dir sign }
+      delete(PathConv,tmppos,2);
+      tmppos:=pos('../',PathConv);
+    end;
+    { convert current directories }
+    tmppos:=pos('./',PathConv);
+    while tmppos<>0 do begin
+      { delete ./ since we doesn't need to sign current directory }
+      delete(PathConv,tmppos,2);
+      tmppos:=pos('./',PathConv);
+    end;
+    { convert wildstart to #? }
+    tmppos:=pos('*',PathConv);
+    while tmppos<>0 do begin
+      delete(PathConv,tmppos,1);
+      insert('#?',PathConv,tmppos);
+      tmppos:=pos('*',PathConv);
+    end;
+  end;
+end;
 
 

+ 56 - 76
rtl/morphos/sysutils.pp

@@ -28,6 +28,12 @@ interface
 {$DEFINE OS_FILESETDATEBYNAME}
 {$DEFINE HAS_SLEEP}
 {$DEFINE HAS_OSERROR}
+
+{ used OS file system APIs use ansistring }
+{$define SYSUTILS_HAS_ANSISTR_FILEUTIL_IMPL}
+{ OS has an ansistring/single byte environment variable API }
+{$define SYSUTILS_HAS_ANSISTR_ENVVAR_IMPL}
+
 { Include platform independent interface part }
 {$i sysutilh.inc}
 
@@ -58,6 +64,7 @@ uses dos,sysconst;
 
 { * Followings are implemented in the system unit! * }
 function PathConv(path: shortstring): shortstring; external name 'PATHCONV';
+function PathConv(path: RawByteString): shortstring; external name 'PATHCONVRBS';
 procedure AddToList(var l: Pointer; h: LongInt); external name 'ADDTOLIST';
 function RemoveFromList(var l: Pointer; h: LongInt): boolean; external name 'REMOVEFROMLIST';
 function CheckInList(var l: Pointer; h: LongInt): pointer; external name 'CHECKINLIST';
@@ -126,14 +133,14 @@ end;
 
 (****** non portable routines ******)
 
-function FileOpen(const FileName: string; Mode: Integer): LongInt;
+function FileOpen(const FileName: rawbytestring; Mode: Integer): LongInt;
 var
+  SystemFileName: RawByteString;
   dosResult: LongInt;
-  tmpStr   : array[0..255] of char;
 begin
+  SystemFileName:=PathConv(ToSingleByteFileSystemEncodedFileName(FileName));
   {$WARNING FIX ME! To do: FileOpen Access Modes}
-  tmpStr:=PathConv(FileName)+#0;
-  dosResult:=Open(@tmpStr,MODE_OLDFILE);
+  dosResult:=Open(PChar(SystemFileName),MODE_OLDFILE);
   if dosResult=0 then
     dosResult:=-1
   else
@@ -184,33 +191,33 @@ begin
 end;
 
 
-function FileSetDate(const FileName: string; Age: LongInt) : LongInt;
+function FileSetDate(const FileName: RawByteString; Age: LongInt) : LongInt;
 var
   tmpDateStamp: TDateStamp;
-  tmpName: array[0..255] of char;
+  SystemFileName: RawByteString;
 begin
   result:=0;
-  tmpName:=PathConv(FileName)+#0;
+  SystemFileName:=PathConv(ToSingleByteFileSystemEncodedFileName(FileName));
   tmpDateStamp:=DateTimeToAmigaDateStamp(FileDateToDateTime(Age));
-  if not SetFileDate(@tmpName,@tmpDateStamp) then begin
+  if not SetFileDate(PChar(SystemFileName),@tmpDateStamp) then begin
     IoErr(); // dump the error code for now (TODO)
     result:=-1;
   end;
 end;
 
 
-function FileCreate(const FileName: string) : LongInt;
+function FileCreate(const FileName: RawByteString) : LongInt;
 var
+  SystemFileName: RawByteString;
   dosResult: LongInt;
-  tmpStr   : array[0..255] of char;
 begin
   dosResult:=-1;
 
   { Open file in MODDE_READWRITE, then truncate it by hand rather than
     opening it in MODE_NEWFILE, because that returns an exclusive lock 
     so some operations might fail with it (KB) }
-  tmpStr:=PathConv(FileName)+#0;
-  dosResult:=Open(@tmpStr,MODE_READWRITE);
+  SystemFileName:=PathConv(ToSingleByteFileSystemEncodedFileName(FileName));
+  dosResult:=Open(PChar(SystemFileName),MODE_READWRITE);
   if dosResult = 0 then exit;
 
   if SetFileSize(dosResult, 0, OFFSET_BEGINNING) = 0 then 
@@ -223,13 +230,13 @@ begin
   FileCreate:=dosResult;
 end;
 
-function FileCreate(const FileName: string; Rights: integer): LongInt;
+function FileCreate(const FileName: RawByteString; Rights: integer): LongInt;
 begin
   {$WARNING FIX ME! To do: FileCreate Access Modes}
   FileCreate:=FileCreate(FileName);
 end;
 
-function FileCreate(const FileName: string; ShareMode: integer; Rights : integer): LongInt;
+function FileCreate(const FileName: RawByteString; ShareMode: integer; Rights : integer): LongInt;
 begin
   {$WARNING FIX ME! To do: FileCreate Access Modes}
   FileCreate:=FileCreate(FileName);
@@ -304,33 +311,31 @@ begin
 end;
 
 
-function DeleteFile(const FileName: string) : Boolean;
+function DeleteFile(const FileName: RawByteString) : Boolean;
 var
-  tmpStr: array[0..255] of char;
+  SystemFileName: RawByteString;
 begin
-  tmpStr:=PathConv(FileName)+#0;
-
-  DeleteFile:=dosDeleteFile(@tmpStr);
+  SystemFileName:=PathConv(ToSingleByteFileSystemEncodedFileName(FileName));
+  DeleteFile:=dosDeleteFile(PChar(SystemFileName));
 end;
 
 
-function RenameFile(const OldName, NewName: string): Boolean;
+function RenameFile(const OldName, NewName: RawByteString): Boolean;
 var
-  tmpOldName, tmpNewName: array[0..255] of char;
+  OldSystemFileName, NewSystemFileName: RawByteString;
 begin
-  tmpOldName:=PathConv(OldName)+#0;
-  tmpNewName:=PathConv(NewName)+#0;
-
-  RenameFile:=dosRename(tmpOldName, tmpNewName);
+  OldSystemFileName:=PathConv(ToSingleByteFileSystemEncodedFileName(OldName));
+  NewSystemFileName:=PathConv(ToSingleByteFileSystemEncodedFileName(NewName));
+  RenameFile:=dosRename(PChar(OldSystemFileName), PChar(NewSystemFileName));
 end;
 
 
 (****** end of non portable routines ******)
 
 
-function FileAge (const FileName : String): Longint;
+function FileAge (const FileName : RawByteString): Longint;
 var
-  tmpName: String;
+  tmpName: RawByteString;
   tmpLock: Longint;
   tmpFIB : PFileInfoBlock;
   tmpDateTime: TDateTime;
@@ -338,7 +343,7 @@ var
 
 begin
   validFile:=false;
-  tmpName := PathConv(FileName);
+  tmpName := PathConv(ToSingleByteFileSystemEncodedFileName(FileName));
   tmpLock := dosLock(tmpName, SHARED_LOCK);
 
   if (tmpLock <> 0) then begin
@@ -357,16 +362,15 @@ begin
 end;
 
 
-function FileExists (const FileName : String) : Boolean;
+function FileExists (const FileName : RawByteString) : Boolean;
 var
-  tmpName: String;
   tmpLock: LongInt;
   tmpFIB : PFileInfoBlock;
-
+  SystemFileName: RawByteString;
 begin
   result:=false;
-  tmpName := PathConv(FileName);
-  tmpLock := dosLock(tmpName, SHARED_LOCK);
+  SystemFileName:=PathConv(ToSingleByteFileSystemEncodedFileName(FileName));
+  tmpLock := dosLock(PChar(SystemFileName), SHARED_LOCK);
 
   if (tmpLock <> 0) then begin
     new(tmpFIB);
@@ -378,15 +382,15 @@ begin
 end;
 
 
-function FindFirst(const Path: String; Attr : Longint; out Rslt: TSearchRec): Longint;
+Function InternalFindFirst (Const Path : RawByteString; Attr : Longint; out Rslt : TAbstractSearchRec; var Name: RawByteString) : Longint;
 var
-  tmpStr: array[0..255] of Char;
+  tmpStr: RawByteString;
   Anchor: PAnchorPath;
   tmpDateTime: TDateTime;
   validDate: boolean;
 begin
   result:=-1; { We emulate Linux/Unix behaviour, and return -1 on errors. }
-  tmpStr:=PathConv(path)+#0;
+  tmpStr:=PathConv(ToSingleByteFileSystemEncodedFileName(Path));
 
   { $1e = faHidden or faSysFile or faVolumeID or faDirectory }
   Rslt.ExcludeAttr := (not Attr) and ($1e);
@@ -395,11 +399,12 @@ begin
   new(Anchor);
   FillChar(Anchor^,sizeof(TAnchorPath),#0);
 
-  if MatchFirst(@tmpStr,Anchor)<>0 then exit;
+  if MatchFirst(pchar(tmpStr),Anchor)<>0 then exit;
   Rslt.FindHandle := longint(Anchor);
 
   with Anchor^.ap_Info do begin
-    Rslt.Name := StrPas(fib_FileName);
+    Name := fib_FileName;
+    SetCodePage(Name,DefaultFileSystemCodePage,False);
 
     Rslt.Size := fib_Size;
     Rslt.Time := DateTimeToFileDate(AmigaFileDateToDateTime(fib_Date,validDate));
@@ -417,7 +422,7 @@ begin
 end;
 
 
-function FindNext (var Rslt : TSearchRec): Longint;
+Function InternalFindNext (var Rslt : TAbstractSearchRec; var Name : RawByteString) : Longint;
 var
   Anchor: PAnchorPath;
   validDate: boolean;
@@ -429,7 +434,8 @@ begin
   if MatchNext(Anchor) <> 0 then exit;
 
   with Anchor^.ap_Info do begin
-    Rslt.Name := StrPas(fib_FileName);
+    Name := fib_FileName;
+    SetCodePage(Name,DefaultFileSystemCodePage,False);
     Rslt.Size := fib_Size;
     Rslt.Time := DateTimeToFileDate(AmigaFileDateToDateTime(fib_Date,validDate));
     if not validDate then exit;
@@ -445,20 +451,21 @@ begin
 end;
 
 
-procedure FindClose(var f: TSearchRec);
+Procedure InternalFindClose(var Handle: THandle);
 var
   Anchor: PAnchorPath;
 begin
-  Anchor:=PAnchorPath(f.FindHandle);
+  Anchor:=PAnchorPath(Handle);
   if not assigned(Anchor) then exit;
   MatchEnd(Anchor);
   Dispose(Anchor);
+  Handle:=THandle(nil);
 end;
 
 
 (****** end of non portable routines ******)
 
-Function FileGetAttr (Const FileName : String) : Longint;
+Function FileGetAttr (Const FileName : RawByteString) : Longint;
 var
  F: file;
  attr: word;
@@ -472,7 +479,7 @@ begin
 end;
 
 
-Function FileSetAttr (Const Filename : String; Attr: longint) : Longint;
+Function FileSetAttr (Const Filename : RawByteString; Attr: longint) : Longint;
 var
  F: file;
 begin
@@ -534,44 +541,17 @@ Begin
   DiskSize := dos.DiskSize(Drive);
 End;
 
-function GetCurrentDir : String;
-begin
-  GetDir (0,Result);
-end;
-
-
-Function SetCurrentDir (Const NewDir : String) : Boolean;
-begin
-  ChDir(NewDir);
-  result := (IOResult = 0);
-end;
-
-
-Function CreateDir (Const NewDir : String) : Boolean;
-begin
-  MkDir(NewDir);
-  result := (IOResult = 0);
-end;
-
-
-Function RemoveDir (Const Dir : String) : Boolean;
-begin
-  RmDir(Dir);
-  result := (IOResult = 0);
-end;
-
-
-function DirectoryExists(const Directory: string): Boolean;
+function DirectoryExists(const Directory: RawByteString): Boolean;
 var
-  tmpStr : String;
   tmpLock: LongInt;
   FIB    : PFileInfoBlock;
+  SystemFileName: RawByteString;
 begin
   result:=false;
   if (Directory='') or (InOutRes<>0) then exit;
-  tmpStr:=PathConv(Directory);
+  SystemFileName:=PathConv(ToSingleByteFileSystemEncodedFileName(Directory));
 
-  tmpLock:=dosLock(tmpStr,SHARED_LOCK);
+  tmpLock:=dosLock(PChar(SystemFileName),SHARED_LOCK);
   if tmpLock=0 then exit;
 
   FIB:=nil; new(FIB);
@@ -654,7 +634,7 @@ begin
   Result:=Dos.envCount;
 end;
 
-Function GetEnvironmentString(Index : Integer) : String;
+Function GetEnvironmentString(Index : Integer) : {$ifdef FPC_RTL_UNICODE}UnicodeString{$else}AnsiString{$endif};
 
 begin
   // Result:=FPCGetEnvStrFromP(Envp,Index);

+ 26 - 4
rtl/msdos/dos.pp

@@ -902,9 +902,20 @@ end;
 
 
 procedure getfattr(var f;var attr : word);
+var
+  path: pchar;
+{$ifndef FPC_ANSI_TEXTFILEREC}
+  r: rawbytestring;
+{$endif not FPC_ANSI_TEXTFILEREC}
 begin
-  dosregs.dx:=Ofs(filerec(f).name);
-  dosregs.ds:=Seg(filerec(f).name);
+{$ifdef FPC_ANSI_TEXTFILEREC}
+  path:=@filerec(f).Name;
+{$else}
+  r:=ToSingleByteFileSystemEncodedFileName(filerec(f).Name);
+  path:=pchar(r);
+{$endif}
+  dosregs.dx:=Ofs(path^);
+  dosregs.ds:=Seg(path^);
   if LFNSupport then
    begin
      dosregs.ax:=$7143;
@@ -919,6 +930,11 @@ end;
 
 
 procedure setfattr(var f;attr : word);
+var
+  path: pchar;
+{$ifndef FPC_ANSI_TEXTFILEREC}
+  r: rawbytestring;
+{$endif not FPC_ANSI_TEXTFILEREC}
 begin
   { Fail for setting VolumeId. }
   if ((attr and VolumeID)<>0) then
@@ -926,8 +942,14 @@ begin
     doserror:=5;
     exit;
   end;
-  dosregs.dx:=Ofs(filerec(f).name);
-  dosregs.ds:=Seg(filerec(f).name);
+{$ifdef FPC_ANSI_TEXTFILEREC}
+  path:=@filerec(f).Name;
+{$else}
+  r:=ToSingleByteFileSystemEncodedFileName(filerec(f).Name);
+  path:=pchar(r);
+{$endif}
+  dosregs.dx:=Ofs(path);
+  dosregs.ds:=Seg(path);
   if LFNSupport then
    begin
      dosregs.ax:=$7143;

+ 24 - 0
rtl/msdos/rtldefs.inc

@@ -0,0 +1,24 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2012 by Free Pascal development team
+
+    This file contains platform-specific defines that are used in
+    multiple RTL units.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{ the single byte OS APIs always use UTF-8 }
+{ define FPCRTL_FILESYSTEM_UTF8}
+
+{ The OS supports a single byte file system operations API that we use }
+{$define FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+
+{ The OS supports a two byte file system operations API that we use }
+{ define FPCRTL_FILESYSTEM_TWO_BYTE_API}

+ 28 - 24
rtl/msdos/sysdir.inc

@@ -18,19 +18,21 @@
                            Directory Handling
 *****************************************************************************}
 
-procedure DosDir(func:byte;s:pchar;len:integer);
+procedure DosDir(func:byte;s: rawbytestring);
 var
   regs   : Registers;
+  len    : Longint;
 begin
   DoDirSeparators(s);
   { True DOS does not like backslashes at end
     Win95 DOS accepts this !!
     but "\" and "c:\" should still be kept and accepted hopefully PM }
-  if (len>0) and (s[len-1]='\') and
-     Not ((len=1) or ((len=3) and (s[1]=':'))) then
-    s[len-1]:=#0;
-  regs.DX:=Ofs(s^);
-  regs.DS:=Seg(s^);
+  len:=length(s);
+  if (len>0) and (s[len]='\') and
+     Not ((len=1) or ((len=3) and (s[2]=':'))) then
+    s[len]:=#0;
+  regs.DX:=Ofs(s[1]);
+  regs.DS:=Seg(s[1]);
   if LFNSupport then
    regs.AX:=$7100+func
   else
@@ -40,32 +42,31 @@ begin
    GetInOutRes(regs.AX);
 end;
 
-Procedure MkDir(s: pchar;len:sizeuint);[IOCheck, public, alias : 'FPC_SYS_MKDIR'];
+Procedure do_MkDir(const s: rawbytestring);
 begin
-  If not assigned(s) or (len=0) or (InOutRes <> 0) then
-    exit;
-   DosDir($39,s,len);
+   DosDir($39,s);
 end;
 
-Procedure RmDir(s: pchar;len:sizeuint);[IOCheck, public, alias : 'FPC_SYS_RMDIR'];
+Procedure do_RmDir(const s: rawbytestring);
 begin
-  if (len=1) and (s[0] = '.' ) then
-    InOutRes := 16;
-  If not assigned(s) or (len=0) or (InOutRes <> 0) then
-   exit;
-  DosDir($3a,s,len);
+  if s='.' then
+    begin
+      InOutRes:=16;
+      exit;
+    end;
+  DosDir($3a,s);
 end;
 
-Procedure ChDir(s: pchar;len:sizeuint);[IOCheck, public, alias : 'FPC_SYS_CHDIR'];
+Procedure do_ChDir(const s: rawbytestring);
 var
   regs : Registers;
+  len  : Longint;
 begin
-  If not assigned(s) or (len=0) or (InOutRes <> 0) then
-   exit;
+  len:=Length(s);
 { First handle Drive changes }
-  if (len>=2) and (s[1]=':') then
+  if (len>=2) and (s[2]=':') then
    begin
-     regs.DX:=(ord(s[0]) and (not 32))-ord('A');
+     regs.DX:=(ord(s[1]) and (not 32))-ord('A');
      regs.AX:=$0e00;
      MsDos(regs);
      regs.AX:=$1900;
@@ -81,10 +82,10 @@ begin
        exit;
    end;
 { do the normal dos chdir }
-  DosDir($3b,s,len);
+  DosDir($3b,s);
 end;
 
-procedure GetDir (DriveNr: byte; var Dir: ShortString);
+procedure do_GetDir (DriveNr: byte; var Dir: RawByteString);
 var
   temp : array[0..260] of char;
   i    : longint;
@@ -102,12 +103,14 @@ begin
    Begin
      GetInOutRes (regs.AX);
      Dir := char (DriveNr + 64) + ':\';
+     SetCodePage (Dir,DefaultFileSystemCodePage,false);
      exit;
    end
   else
     temp[252] := #0;  { to avoid shortstring buffer overflow }
 { conversion to Pascal string including slash conversion }
   i:=0;
+  SetLength(dir,260);
   while (temp[i]<>#0) do
    begin
      if temp[i] in AllowDirectorySeparators then
@@ -117,7 +120,8 @@ begin
    end;
   dir[2]:=':';
   dir[3]:='\';
-  dir[0]:=char(i+3);
+  SetLength(dir,i+3);
+  SetCodePage (dir,DefaultFileSystemCodePage,false);
 { upcase the string }
   if not FileNameCasePreserving then
    dir:=upcase(dir);

+ 24 - 7
rtl/msdos/sysfile.inc

@@ -54,11 +54,13 @@ begin
 end;
 
 
-procedure do_erase(p : pchar);
+procedure do_erase(p : pchar; pchangeable: boolean);
 var
   regs : Registers;
+  oldp : pchar;
 begin
-  DoDirSeparators(p);
+  oldp:=p;
+  DoDirSeparators(p,pchangeable);
   regs.DX:=Ofs(p^);
   regs.DS:=Seg(p^);
   if LFNSupport then
@@ -70,15 +72,20 @@ begin
   MsDos(regs);
   if (regs.Flags and fCarry) <> 0 then
    GetInOutRes(regs.AX);
+  if p<>oldp then
+    freemem(p);
 end;
 
 
-procedure do_rename(p1,p2 : pchar);
+procedure do_rename(p1,p2 : pchar; p1changeable, p2changeable: boolean);
 var
   regs : Registers;
+  oldp1, oldp2 : pchar;
 begin
-  DoDirSeparators(p1);
-  DoDirSeparators(p2);
+  oldp1:=p1;
+  oldp2:=p2;
+  DoDirSeparators(p1,p1changeable);
+  DoDirSeparators(p2,p2changeable);
   regs.DS:=Seg(p1^);
   regs.DX:=Ofs(p1^);
   regs.ES:=Seg(p2^);
@@ -91,6 +98,10 @@ begin
   MsDos(regs);
   if (regs.Flags and fCarry) <> 0 then
    GetInOutRes(regs.AX);
+  if p1<>oldp1 then
+    freemem(p1);
+  if p2<>oldp2 then
+    freemem(p2);
 end;
 
 
@@ -229,7 +240,7 @@ begin
     Increase_file_handle_count:=true;
 end;
 
-procedure do_open(var f;p:pchar;flags:longint);
+procedure do_open(var f;p:pchar;flags:longint; pchangeable: boolean);
 {
   filerec and textrec have both handle and mode as the first items so
   they could use the same routine for opening/creating.
@@ -240,8 +251,8 @@ procedure do_open(var f;p:pchar;flags:longint);
 var
   regs   : Registers;
   action : longint;
+  oldp : pchar;
 begin
-  DoDirSeparators(p);
 { close first if opened }
   if ((flags and $10000)=0) then
    begin
@@ -283,6 +294,8 @@ begin
      end;
      exit;
    end;
+  oldp:=p;
+  DoDirSeparators(p,pchangeable);
 {$ifndef RTLLITE}
   if LFNSupport then
    begin
@@ -332,6 +345,8 @@ begin
   if (regs.Flags and fCarry) <> 0 then
     begin
       GetInOutRes(regs.AX);
+      if oldp<>p then
+        freemem(p);
       exit;
     end
   else
@@ -366,6 +381,8 @@ begin
      do_seekend(filerec(f).handle);
      filerec(f).mode:=fmoutput; {fool fmappend}
    end;
+  if oldp<>p then
+    freemem(p);
 end;
 
 

+ 27 - 54
rtl/msdos/sysutils.pp

@@ -28,6 +28,12 @@ uses
   {go32,}dos;
 
 {$DEFINE HAS_SLEEP}
+
+{ used OS file system APIs use ansistring }
+{$define SYSUTILS_HAS_ANSISTR_FILEUTIL_IMPL}
+{ OS has an ansistring/single byte environment variable API }
+{$define SYSUTILS_HAS_ANSISTR_ENVVAR_IMPL}
+
 { Include platform independent interface part }
 {$i sysutilh.inc}
 
@@ -78,7 +84,7 @@ end ;}
 
 {  Native OpenFile function.
    if return value <> 0 call failed.  }
-function OpenFile(const FileName: string; var Handle: THandle; Mode, Action: word): longint;
+function OpenFile(const FileName: RawByteString; var Handle: THandle; Mode, Action: word): longint;
 var
    Regs: registers;
 begin
@@ -110,7 +116,7 @@ begin
 end;
 
 
-Function FileOpen (Const FileName : string; Mode : Integer) : THandle;
+Function FileOpen (Const FileName : RawByteString; Mode : Integer) : THandle;
 var
   e: integer;
 Begin
@@ -120,7 +126,7 @@ Begin
 end;
 
 
-Function FileCreate (Const FileName : String) : THandle;
+Function FileCreate (Const FileName : RawByteString) : THandle;
 var
   e: integer;
 begin
@@ -130,13 +136,13 @@ begin
 end;
 
 
-Function FileCreate (Const FileName : String; ShareMode:longint; Rights : longint) : THandle;
+Function FileCreate (Const FileName : RawByteString; ShareMode:longint; Rights : longint) : THandle;
 begin
   FileCreate:=FileCreate(FileName);
 end;
 
 
-Function FileCreate (Const FileName : String; Rights:longint) : THandle;
+Function FileCreate (Const FileName : RawByteString; Rights:longint) : THandle;
 begin
   FileCreate:=FileCreate(FileName);
 end;
@@ -270,7 +276,7 @@ begin
 end;
 
 
-Function FileAge (Const FileName : String): Longint;
+Function FileAge (Const FileName : RawByteString): Longint;
 var Handle: longint;
 begin
   Handle := FileOpen(FileName, 0);
@@ -284,7 +290,7 @@ begin
 end;
 
 
-function FileExists (const FileName: string): boolean;
+function FileExists (const FileName: RawByteString): boolean;
 var
   L: longint;
 begin
@@ -299,9 +305,9 @@ begin
 end;
 
 
-Function DirectoryExists (Const Directory : String) : Boolean;
+Function DirectoryExists (Const Directory : RawByteString) : Boolean;
 Var
-  Dir : String;
+  Dir : RawByteString;
   drive : byte;
   FADir, StoredIORes : longint;
 begin
@@ -340,7 +346,7 @@ begin
 end;
 
 
-Function FindFirst (Const Path : String; Attr : Longint; out Rslt : TSearchRec) : Longint;
+Function InternalFindFirst (Const Path : RawByteString; Attr : Longint; out Rslt : TAbstractSearchRec; var Name: RawByteString) : Longint;
 
 Var Sr : PSearchrec;
 
@@ -356,12 +362,12 @@ begin
      Rslt.Size := Sr^.Size;
      Rslt.Attr := Sr^.Attr;
      Rslt.ExcludeAttr := 0;
-     Rslt.Name := Sr^.Name;
+     Name := Sr^.Name;
    end ;
 end;
 
 
-Function FindNext (Var Rslt : TSearchRec) : Longint;
+Function InternalFindNext (var Rslt : TAbstractSearchRec; var Name : RawByteString) : Longint;
 var
   Sr: PSearchRec;
 begin
@@ -376,17 +382,17 @@ begin
         Rslt.Size := Sr^.Size;
         Rslt.Attr := Sr^.Attr;
         Rslt.ExcludeAttr := 0;
-        Rslt.Name := Sr^.Name;
+        Name := Sr^.Name;
       end;
    end;
 end;
 
 
-Procedure FindClose (Var F : TSearchrec);
+Procedure InternalFindClose(var Handle: THandle);
 var
   Sr: PSearchRec;
 begin
-  Sr := PSearchRec(F.FindHandle);
+  Sr := PSearchRec(Handle);
   if Sr <> nil then
     begin
       //!! Dispose(Sr);
@@ -394,7 +400,7 @@ begin
       DOS.FindClose(SR^);
       freemem(sr,sizeof(searchrec));
     end;
-  F.FindHandle := 0;
+  Handle := 0;
 end;
 
 
@@ -432,7 +438,7 @@ begin
 end;
 
 
-Function FileGetAttr (Const FileName : String) : Longint;
+Function FileGetAttr (Const FileName : RawByteString) : Longint;
 var
   Regs: registers;
 begin
@@ -453,7 +459,7 @@ begin
 end;
 
 
-Function FileSetAttr (Const Filename : String; Attr: longint) : Longint;
+Function FileSetAttr (Const Filename : RawByteString; Attr: longint) : Longint;
 var
   Regs: registers;
 begin
@@ -475,7 +481,7 @@ begin
 end;
 
 
-Function DeleteFile (Const FileName : String) : Boolean;
+Function DeleteFile (Const FileName : RawByteString) : Boolean;
 var
   Regs: registers;
 begin
@@ -492,7 +498,7 @@ begin
 end;
 
 
-Function RenameFile (Const OldName, NewName : String) : Boolean;
+Function RenameFile (Const OldName, NewName : RawByteString) : Boolean;
 var
   Regs: registers;
 begin
@@ -607,39 +613,6 @@ begin
 end;
 
 
-Function GetCurrentDir : String;
-begin
-  GetDir(0, result);
-end;
-
-
-Function SetCurrentDir (Const NewDir : String) : Boolean;
-begin
-  {$I-}
-   ChDir(NewDir);
-  {$I+}
-  result := (IOResult = 0);
-end;
-
-
-Function CreateDir (Const NewDir : String) : Boolean;
-begin
-  {$I-}
-   MkDir(NewDir);
-  {$I+}
-  result := (IOResult = 0);
-end;
-
-
-Function RemoveDir (Const Dir : String) : Boolean;
-begin
-  {$I-}
-   RmDir(Dir);
-  {$I+}
-  result := (IOResult = 0);
-end;
-
-
 {****************************************************************************
                               Time Functions
 ****************************************************************************}
@@ -794,7 +767,7 @@ begin
   Result:=FPCCountEnvVar(EnvP);
 end;
 
-Function GetEnvironmentString(Index : Integer) : String;
+Function GetEnvironmentString(Index : Integer) : {$ifdef FPC_RTL_UNICODE}UnicodeString{$else}AnsiString{$endif};
 
 begin
   Result:=FPCGetEnvStrFromP(Envp,Index);

+ 148 - 146
rtl/nativent/Makefile

@@ -345,442 +345,442 @@ endif
 OBJPASDIR=$(RTL)/objpas
 WINDOWS_SOURCE_FILES=$(addprefix $(WININC)/,$(addsuffix .inc,$(WINDOWS_FILES)))
 ifeq ($(FULL_TARGET),i386-linux)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),i386-go32v2)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),i386-win32)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),i386-os2)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),i386-freebsd)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),i386-beos)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),i386-haiku)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),i386-netbsd)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),i386-solaris)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),i386-qnx)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),i386-netware)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),i386-openbsd)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),i386-wdosx)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),i386-darwin)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),i386-emx)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),i386-watcom)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),i386-netwlibc)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),i386-wince)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),i386-embedded)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),i386-symbian)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),i386-nativent)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),i386-iphonesim)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),i386-android)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),m68k-linux)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),m68k-freebsd)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),m68k-netbsd)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),m68k-amiga)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),m68k-atari)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),m68k-openbsd)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),m68k-palmos)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),m68k-embedded)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),powerpc-linux)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),powerpc-netbsd)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),powerpc-amiga)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),powerpc-macos)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),powerpc-darwin)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),powerpc-morphos)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),powerpc-embedded)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),powerpc-wii)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),powerpc-aix)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),sparc-linux)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),sparc-netbsd)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),sparc-solaris)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),sparc-embedded)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),x86_64-linux)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),x86_64-netbsd)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),x86_64-solaris)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),x86_64-openbsd)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),x86_64-win64)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),x86_64-embedded)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),arm-linux)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),arm-palmos)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),arm-darwin)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),arm-wince)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),arm-gba)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),arm-nds)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),arm-embedded)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),arm-symbian)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),arm-android)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),powerpc64-linux)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),powerpc64-darwin)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),powerpc64-embedded)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),powerpc64-aix)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),avr-embedded)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),armeb-linux)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),armeb-embedded)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),mips-linux)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),mipsel-linux)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),jvm-java)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),jvm-android)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),i8086-msdos)
-override TARGET_UNITS+=system uuchar objpas iso7185 buildrtl
+override TARGET_UNITS+=system uuchar objpas iso7185 cpall buildrtl
 endif
 ifeq ($(FULL_TARGET),i386-linux)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),i386-go32v2)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),i386-win32)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),i386-os2)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),i386-freebsd)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),i386-beos)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),i386-haiku)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),i386-netbsd)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),i386-solaris)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),i386-qnx)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),i386-netware)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),i386-openbsd)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),i386-wdosx)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),i386-darwin)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),i386-emx)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),i386-watcom)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),i386-netwlibc)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),i386-wince)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),i386-embedded)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),i386-symbian)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),i386-nativent)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),i386-iphonesim)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),i386-android)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),m68k-linux)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),m68k-freebsd)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),m68k-netbsd)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),m68k-amiga)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),m68k-atari)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),m68k-openbsd)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),m68k-palmos)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),m68k-embedded)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),powerpc-linux)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),powerpc-netbsd)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),powerpc-amiga)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),powerpc-macos)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),powerpc-darwin)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),powerpc-morphos)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),powerpc-embedded)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),powerpc-wii)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),powerpc-aix)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),sparc-linux)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),sparc-netbsd)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),sparc-solaris)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),sparc-embedded)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),x86_64-linux)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),x86_64-netbsd)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),x86_64-solaris)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),x86_64-openbsd)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),x86_64-win64)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),x86_64-embedded)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),arm-linux)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),arm-palmos)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),arm-darwin)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),arm-wince)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),arm-gba)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),arm-nds)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),arm-embedded)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),arm-symbian)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),arm-android)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),powerpc64-linux)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),powerpc64-darwin)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),powerpc64-embedded)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),powerpc64-aix)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),avr-embedded)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),armeb-linux)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),armeb-embedded)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),mips-linux)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),mipsel-linux)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),jvm-java)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),jvm-android)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),i8086-msdos)
-override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
+override TARGET_IMPLICITUNITS+=ndk ndkutils ddk ctypes strings matrix rtlconsts sysconst sysutils math types strutils dateutils varutils variants typinfo fgl classes convutils stdconvs $(CPU_UNITS) charset ucomplex getopts fmtbcd cp1250 cp1251 cp1252 cp1253 cp1254 cp1255 cp1256 cp1257 cp1258 cp437 cp646 cp850 cp866 cp874 cp932 cp936 cp949 cp950 cp8859_1 cp8859_5
 endif
 ifeq ($(FULL_TARGET),i386-linux)
 override TARGET_RSTS+=math varutils typinfo variants classes dateutils sysconst
@@ -2601,3 +2601,5 @@ macpas$(PPUEXT) : $(INC)/macpas.pp objpas$(PPUEXT) buildrtl$(PPUEXT)
 	$(COMPILER) $(INC)/macpas.pp $(REDIR)
 buildrtl$(PPUEXT): buildrtl.pp system$(PPUEXT) objpas$(PPUEXT)
 	$(COMPILER) -Fi$(OBJPASDIR)/sysutils -Fi$(OBJPASDIR)/classes -Fu$(PROCINC) -I$(OBJPASDIR) -Fi$(DDKINC) -I$(INC) -Fu$(INC) -Fu$(OBJPASDIR) buildrtl
+cpall$(PPUEXT): $(RTL)/charmaps/cpall.pas system$(PPUEXT) objpas$(PPUEXT)
+	$(COMPILER) -Fu$(INC) -Fi$(RTL)/charmaps $(RTL)/charmaps/cpall.pas

+ 5 - 2
rtl/nativent/Makefile.fpc

@@ -8,7 +8,7 @@ main=rtl
 [target]
 loaders=
 #units=system objpas macpas iso7185 buildrtl lineinfo lnfodwrf
-units=system uuchar objpas iso7185 buildrtl
+units=system uuchar objpas iso7185 cpall buildrtl
 implicitunits=ndk ndkutils ddk \
       ctypes strings \
 #      heaptrc
@@ -17,7 +17,7 @@ implicitunits=ndk ndkutils ddk \
 #      dos crt objects \
       rtlconsts sysconst sysutils math types \
       strutils dateutils varutils variants typinfo fgl classes \
-      convutils stdconvs $(CPU_UNITS) charset cpall ucomplex getopts \
+      convutils stdconvs $(CPU_UNITS) charset ucomplex getopts \
 #      sockets printer \
 #      video mouse keyboard
        fmtbcd \
@@ -124,3 +124,6 @@ macpas$(PPUEXT) : $(INC)/macpas.pp objpas$(PPUEXT) buildrtl$(PPUEXT)
 
 buildrtl$(PPUEXT): buildrtl.pp system$(PPUEXT) objpas$(PPUEXT)
         $(COMPILER) -Fi$(OBJPASDIR)/sysutils -Fi$(OBJPASDIR)/classes -Fu$(PROCINC) -I$(OBJPASDIR) -Fi$(DDKINC) -I$(INC) -Fu$(INC) -Fu$(OBJPASDIR) buildrtl
+
+cpall$(PPUEXT): $(RTL)/charmaps/cpall.pas system$(PPUEXT) objpas$(PPUEXT)
+        $(COMPILER) -Fu$(INC) -Fi$(RTL)/charmaps $(RTL)/charmaps/cpall.pas

+ 2 - 2
rtl/nativent/ndkutils.pas

@@ -24,7 +24,7 @@ uses
 
 // Helpers for converting Pascal string types to NT's UNICODE_STRING
 procedure ShortStrToNTStr(aStr: ShortString; var aNTStr: UNICODE_STRING);
-procedure AnsiStrToNTStr(const aStr: String; var aNTStr: UNICODE_STRING);
+procedure AnsiStrToNTStr(const aStr: RawByteString; var aNTStr: UNICODE_STRING);
 procedure UnicodeStrToNtStr(const aStr: UnicodeString;
     var aNTStr: UNICODE_STRING);
 procedure PCharToNTStr(aStr: PChar; aLen: Cardinal; var aNTStr: UNICODE_STRING);
@@ -53,7 +53,7 @@ begin
   aNTStr.MaximumLength := aNTStr.Length;
 end;
 
-procedure AnsiStrToNTStr(const aStr: String; var aNTStr: UNICODE_STRING);
+procedure AnsiStrToNTStr(const aStr: RawByteString; var aNTStr: UNICODE_STRING);
 var
   buf: PWideChar;
   i: Integer;

+ 24 - 0
rtl/nativent/rtldefs.inc

@@ -0,0 +1,24 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2012 by Free Pascal development team
+
+    This file contains platform-specific defines that are used in
+    multiple RTL units.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{ the single byte OS APIs always use UTF-8 }
+{ define FPCRTL_FILESYSTEM_UTF8}
+
+{ The OS supports a single byte file system operations API that we use }
+{ define FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+
+{ The OS supports a two byte file system operations API that we use }
+{$define FPCRTL_FILESYSTEM_TWO_BYTE_API}

+ 16 - 15
rtl/nativent/sysdir.inc

@@ -17,7 +17,7 @@
                            Directory Handling
 *****************************************************************************}
 
-procedure MkDir(s: pchar; len: sizeuint); [IOCheck, public, alias : 'FPC_SYS_MKDIR'];
+procedure do_MkDir(const s: UnicodeString);
 var
   objattr: TObjectAttributes;
   name: TNtUnicodeString;
@@ -25,10 +25,7 @@ var
   iostatus: TIOStatusBlock;
   h: THandle;
 begin
-  if not Assigned(s) or (len <= 1) or (InOutRes <> 0) then
-    Exit;
-
-  SysPCharToNtStr(name, s, len);
+  SysUnicodeStringToNtStr(name, s);
 
   { first we try to create a directory object }
   SysInitializeObjectAttributes(objattr, @name, OBJ_PERMANENT, 0, Nil);
@@ -61,7 +58,7 @@ begin
   SysFreeNtStr(name);
 end;
 
-procedure RmDir(s: pchar;len:sizeuint);[IOCheck, public, alias : 'FPC_SYS_RMDIR'];
+procedure do_RmDir(const s: UnicodeString);
 var
   ntstr: TNtUnicodeString;
   objattr: TObjectAttributes;
@@ -70,14 +67,18 @@ var
   disp: TFileDispositionInformation;
   res: LongInt;
 begin
-  if (len = 1) and (s^ = '.') then
-    InOutRes := 16;
-  if not assigned(s) or (len = 0) or (InOutRes <> 0) then
-    Exit;
-  if (len = 2) and (s[0] = '.') and (s[1] = '.') then
-    InOutRes := 5;
+  if s = '.' then
+    begin
+      InOutRes := 16;
+      exit;
+    end;
+  if s = '..' then
+    begin
+      InOutRes := 5;
+      exit;
+    end;
 
-  SysPCharToNtStr(ntstr, s, len);
+  SysUnicodeStringToNtStr(ntstr, s);
   SysInitializeObjectAttributes(objattr, @ntstr, 0, 0, Nil);
 
   res := NtOpenDirectoryObject(@h, STANDARD_RIGHTS_REQUIRED, @objattr);
@@ -115,13 +116,13 @@ begin
   Errno2InoutRes;
 end;
 
-procedure ChDir(s: pchar; len: sizeuint);[IOCheck, public, alias : 'FPC_SYS_CHDIR'];
+procedure do_ChDir(const s: UnicodeString);
 begin
   { for now this is not supported }
   InOutRes := 3;
 end;
 
-procedure GetDir(DriveNr: byte; var Dir: ShortString);
+procedure do_GetDir(DriveNr: byte; var Dir: UnicodeString);
 begin
   { for now we return simply the root directory }
   Dir := DirectorySeparator;

+ 26 - 11
rtl/nativent/sysfile.inc

@@ -34,7 +34,7 @@ begin
 end;
 
 
-procedure do_erase(p : pchar);
+procedure do_erase(p : pwidechar; pchangeable: boolean);
 var
   ntstr: TNtUnicodeString;
   objattr: TObjectAttributes;
@@ -42,11 +42,13 @@ var
   h: THandle;
   disp: TFileDispositionInformation;
   res: LongInt;
+  oldp: pwidechar;
 begin
   InoutRes := 4;
-  DoDirSeparators(p);
+  oldp:=p;
+  DoDirSeparators(p,pchangeable);
 
-  SysPCharToNtStr(ntstr, p, 0);
+  SysPWideCharToNtStr(ntstr, p, 0);
   SysInitializeObjectAttributes(objattr, @ntstr, 0, 0, Nil);
 
   res := NtCreateFile(@h, NT_DELETE or NT_SYNCHRONIZE, @objattr, @iostatus, Nil,
@@ -71,10 +73,12 @@ begin
 
   SysFreeNtStr(ntstr);
   Errno2InoutRes;
+  if p<>oldp then
+    freemem(p);
 end;
 
 
-procedure do_rename(p1,p2 : pchar);
+procedure do_rename(p1,p2 : pwidechar; p1changeable, p2changeable: boolean);
 var
   h: THandle;
   objattr: TObjectAttributes;
@@ -82,12 +86,14 @@ var
   dest, src: TNtUnicodeString;
   renameinfo: PFileRenameInformation;
   res: LongInt;
+  oldp1, oldp2 : pwidechar;
 begin
-  DoDirSeparators(p1);
-  DoDirSeparators(p2);
+  oldp1:=p1;
+  oldp2:=p2;
 
   { check whether the destination exists first }
-  SysPCharToNtStr(dest, p2, 0);
+  DoDirSeparators(p2,p2changeable);
+  SysPWideCharToNtStr(dest, p2, 0);
   SysInitializeObjectAttributes(objattr, @dest, 0, 0, Nil);
 
   res := NtCreateFile(@h, 0, @objattr, @iostatus, Nil, 0,
@@ -99,7 +105,8 @@ begin
     errno := 5;
     Errno2InoutRes;
   end else begin
-    SysPCharToNtStr(src, p1, 0);
+    DoDirSeparators(p1,p1changeable);
+    SysPWideCharToNtStr(src, p1, 0);
     SysInitializeObjectAttributes(objattr, @src, 0, 0, Nil);
 
     res := NtCreateFile(@h, GENERIC_ALL or NT_SYNCHRONIZE or FILE_READ_ATTRIBUTES,
@@ -138,6 +145,10 @@ begin
   end;
 
   SysFreeNtStr(dest);
+  if p1<>oldp1 then
+    freemem(p1);
+  if p2<>oldp2 then
+    freemem(p2);
 end;
 
 
@@ -292,7 +303,7 @@ begin
 end;
 
 
-procedure do_open(var f;p:pchar;flags:longint);
+procedure do_open(var f;p:pwidechar;flags:longint; pchangeable: boolean);
 {
   filerec and textrec have both handle and mode as the first items so
   they could use the same routine for opening/creating.
@@ -306,8 +317,8 @@ var
   iostatus: TIoStatusBlock;
   ntstr: TNtUnicodeString;
   res: LongInt;
+  oldp : pwidechar;
 begin
-  DoDirSeparators(p);
   { close first if opened }
   if ((flags and $10000)=0) then
    begin
@@ -378,7 +389,9 @@ begin
      exit;
    end;
 
-  SysPCharToNtStr(ntstr, p, 0);
+  oldp:=p;
+  DoDirSeparators(p,pchangeable);
+  SysPWideCharToNtStr(ntstr, p, 0);
 
   SysInitializeObjectAttributes(objattr, @ntstr, OBJ_INHERIT, 0, Nil);
 
@@ -399,4 +412,6 @@ begin
     errno := res;
     Errno2InoutRes;
   end;
+  if oldp<>p then
+    freemem(p);
 end;

+ 25 - 1
rtl/nativent/sysos.inc

@@ -368,10 +368,34 @@ begin
   aNtStr.Length := aLen * SizeOf(WideChar);
   aNtStr.MaximumLength := aNtStr.Length;
   aNtStr.Buffer := GetMem(aNtStr.Length);
-  for i := 0 to aLen do
+  for i := 0 to aLen-1 do
     aNtStr.Buffer[i] := aText[i];
 end;
 
+procedure SysPWideCharToNtStr(var aNtStr: TNtUnicodeString; aText: PWideChar;
+  aLen: LongWord);
+var
+  i: Integer;
+begin
+  if (aLen = 0) and (aText <> Nil) and (aText^ <> #0) then
+    aLen := Length(aText);
+  aNtStr.Length := aLen * SizeOf(WideChar);
+  aNtStr.MaximumLength := aNtStr.Length;
+  aNtStr.Buffer := GetMem(aNtStr.Length);
+  Move(aText[0],aNtStr.Buffer[0],aLen);
+end;
+
+procedure SysUnicodeStringToNtStr(var aNtStr: TNtUnicodeString; const s: UnicodeString);
+var
+  i: Integer;
+begin
+  aNtStr.Length := Length(s) * SizeOf(WideChar);
+  aNtStr.MaximumLength := aNtStr.Length;
+  aNtStr.Buffer := GetMem(aNtStr.Length);
+  if aNtStr.Length<>0 then
+    Move(s[1],aNtStr.Buffer[0],aNtStr.Length);
+end;
+
 procedure SysFreeNtStr(var aNtStr: TNtUnicodeString);
 begin
   if aNtStr.Buffer <> Nil then begin

+ 239 - 157
rtl/nativent/sysutils.pp

@@ -30,7 +30,7 @@ uses
 
 type
   TNativeNTFindData = record
-    SearchSpec: String;
+    SearchSpec: UnicodeString;
     NamePos: LongInt;
     Handle: THandle;
     IsDirObj: Boolean;
@@ -39,6 +39,12 @@ type
     LastRes: NTSTATUS;
   end;
 
+{ used OS file system APIs use ansistring }
+{$define SYSUTILS_HAS_UNICODESTR_FILEUTIL_IMPL}
+{ OS has an ansistring/single byte environment variable API (actually it's
+  unicodestring, but that's not yet implemented) }
+{$define SYSUTILS_HAS_ANSISTR_ENVVAR_IMPL}
+
 { Include platform independent interface part }
 {$i sysutilh.inc}
 
@@ -56,7 +62,7 @@ implementation
                               File Functions
 ****************************************************************************}
 
-function FileOpen(const FileName : string; Mode : Integer) : THandle;
+function FileOpen(const FileName : UnicodeString; Mode : Integer) : THandle;
 const
   AccessMode: array[0..2] of ACCESS_MASK  = (
     GENERIC_READ,
@@ -73,7 +79,7 @@ var
   objattr: OBJECT_ATTRIBUTES;
   iostatus: IO_STATUS_BLOCK;
 begin
-  AnsiStrToNtStr(FileName, ntstr);
+  UnicodeStrToNtStr(FileName, ntstr);
   InitializeObjectAttributes(objattr, @ntstr, 0, 0, Nil);
   NtCreateFile(@Result, AccessMode[Mode and 3] or NT_SYNCHRONIZE, @objattr,
     @iostatus, Nil, FILE_ATTRIBUTE_NORMAL, ShareMode[(Mode and $F0) shr 4],
@@ -82,19 +88,19 @@ begin
 end;
 
 
-function FileCreate(const FileName : String) : THandle;
+function FileCreate(const FileName : UnicodeString) : THandle;
 begin
   FileCreate := FileCreate(FileName, fmShareDenyNone, 0);
 end;
 
 
-function FileCreate(const FileName : String; Rights: longint) : THandle;
+function FileCreate(const FileName : UnicodeString; Rights: longint) : THandle;
 begin
   FileCreate := FileCreate(FileName, fmShareDenyNone, Rights);
 end;
 
 
-function FileCreate(const FileName : String; ShareMode : longint; Rights: longint) : THandle;
+function FileCreate(const FileName : UnicodeString; ShareMode : longint; Rights: longint) : THandle;
 const
   ShareModeFlags: array[0..4] of ULONG = (
                0,
@@ -108,7 +114,7 @@ var
   iostatus: IO_STATUS_BLOCK;
   res: NTSTATUS;
 begin
-  AnsiStrToNTStr(FileName, ntstr);
+  UnicodeStrToNtStr(FileName, ntstr);
   InitializeObjectAttributes(objattr, @ntstr, 0, 0, Nil);
   NtCreateFile(@Result, GENERIC_READ or GENERIC_WRITE or NT_SYNCHRONIZE,
     @objattr, @iostatus, Nil, FILE_ATTRIBUTE_NORMAL,
@@ -305,14 +311,14 @@ begin
   aNtTime.QuadPart := local.QuadPart + bias.QuadPart;
 end;
 
-function FileAge(const FileName: String): Longint;
+function FileAge(const FileName: UnicodeString): Longint;
 begin
   { TODO }
   Result := -1;
 end;
 
 
-function FileExists(const FileName: String): Boolean;
+function FileExists(const FileName: UnicodeString): Boolean;
 var
   ntstr: UNICODE_STRING;
   objattr: OBJECT_ATTRIBUTES;
@@ -320,7 +326,7 @@ var
   iostatus: IO_STATUS_BLOCK;
   h: THandle;
 begin
-  AnsiStrToNtStr(FileName, ntstr);
+  UnicodeStrToNtStr(FileName, ntstr);
   InitializeObjectAttributes(objattr, @ntstr, 0, 0, Nil);
   res := NtOpenFile(@h, FILE_READ_ATTRIBUTES or NT_SYNCHRONIZE, @objattr,
            @iostatus, FILE_SHARE_READ or FILE_SHARE_WRITE,
@@ -333,7 +339,7 @@ begin
 end;
 
 
-function DirectoryExists(const Directory : String) : Boolean;
+function DirectoryExists(const Directory : UnicodeString) : Boolean;
 var
   ntstr: UNICODE_STRING;
   objattr: OBJECT_ATTRIBUTES;
@@ -341,7 +347,7 @@ var
   iostatus: IO_STATUS_BLOCK;
   h: THandle;
 begin
-  AnsiStrToNtStr(Directory, ntstr);
+  UnicodeStrToNtStr(Directory, ntstr);
   InitializeObjectAttributes(objattr, @ntstr, 0, 0, Nil);
 
   { first test wether this is a object directory }
@@ -364,80 +370,193 @@ begin
   FreeNtStr(ntstr);
 end;
 
-{ copied from rtl/unix/sysutils.pp }
-Function FNMatch(const Pattern,Name:string):Boolean;
+{ copied from rtl/unix/sysutils.pp and adapted to UTF-16 }
+Function FNMatch(const Pattern,Name:UnicodeString):Boolean;
 Var
   LenPat,LenName : longint;
 
+  function NameUtf16CodePointLen(index: longint): longint;
+    begin
+      { see https://en.wikipedia.org/wiki/UTF-16#Description for details }
+      Result:=1;
+      { valid surrogate pair? }
+      if (Name[index]>=#$D800) and
+         (Name[index]<=#$DBFF) then
+        begin
+          if (index+1<=LenName) and
+             (Name[index+1]>=#$DC00) and
+             (Name[index+1]<=#$DFFF) then
+            inc(Result)
+          else
+            exit;
+        end;
+      { combining diacritics?
+          1) U+0300 - U+036F
+          2) U+1DC0 - U+1DFF
+          3) U+20D0 - U+20FF
+          4) U+FE20 - U+FE2F
+      }
+      while (index+Result+1<=LenName) and
+            ((word(ord(Name[index+Result+1])-$0300) <= word($036F-$0300)) or
+             (word(ord(Name[index+Result+1])-$1DC0) <= word($1DFF-$1DC0)) or
+             (word(ord(Name[index+Result+1])-$20D0) <= word($20FF-$20D0)) or
+             (word(ord(Name[index+Result+1])-$FE20) <= word($FE2F-$FE20))) do
+        begin
+          inc(Result)
+        end;
+    end;
+
+    procedure GoToLastByteOfUtf16CodePoint(var j: longint);
+    begin
+      { Take one less, because we have to stop at the last word of the sequence.
+      }
+      inc(j,NameUtf16CodePointLen(j)-1);
+    end;
+
+  { input:
+      i: current position in pattern (start of utf-16 code point)
+      j: current position in name (start of utf-16 code point)
+      update_i_j: should i and j be changed by the routine or not
+
+    output:
+      i: if update_i_j, then position of last matching part of code point in
+         pattern, or first non-matching code point in pattern. Otherwise the
+         same value as on input.
+      j: if update_i_j, then position of last matching part of code point in
+         name, or first non-matching code point in name. Otherwise the
+         same value as on input.
+      result: true if match, false if no match
+  }
+  function CompareUtf16CodePoint(var i,j: longint; update_i_j: boolean): Boolean;
+    var
+      words,
+      new_i,
+      new_j: longint;
+    begin
+      words:=NameUtf16CodePointLen(j);
+      new_i:=i;
+      new_j:=j;
+      { ensure that a part of an UTF-8 codepoint isn't interpreted
+        as '*' or '?' }
+      repeat
+        dec(words);
+        Result:=
+          (new_j<=LenName) and
+          (new_i<=LenPat) and
+          (Pattern[new_i]=Name[new_j]);
+        inc(new_i);
+        inc(new_j);
+      until not(Result) or
+            (words=0);
+      if update_i_j then
+        begin
+          i:=new_i;
+          j:=new_j;
+        end;
+    end;
+
+
   Function DoFNMatch(i,j:longint):Boolean;
   Var
     Found : boolean;
   Begin
-  Found:=true;
-  While Found and (i<=LenPat) Do
-   Begin
-     Case Pattern[i] of
-      '?' : Found:=(j<=LenName);
-      '*' : Begin
-            {find the next character in pattern, different of ? and *}
-              while Found do
-                begin
-                inc(i);
-                if i>LenPat then Break;
-                case Pattern[i] of
-                  '*' : ;
-                  '?' : begin
-                          if j>LenName then begin DoFNMatch:=false; Exit; end;
+    Found:=true;
+    While Found and (i<=LenPat) Do
+     Begin
+       Case Pattern[i] of
+        '?' :
+          begin
+            Found:=(j<=LenName);
+            GoToLastByteOfUtf16CodePoint(j);
+          end;
+        '*' : Begin
+              {find the next character in pattern, different of ? and *}
+                while Found do
+                  begin
+                    inc(i);
+                    if i>LenPat then
+                      Break;
+                    case Pattern[i] of
+                      '*' : ;
+                      '?' : begin
+                              if j>LenName then
+                                begin
+                                  DoFNMatch:=false;
+                                  Exit;
+                                end;
+                              GoToLastByteOfUtf16CodePoint(j);
+                              inc(j);
+                            end;
+                      else
+                        Found:=false;
+                      end;
+                 end;
+                Assert((i>LenPat) or ( (Pattern[i]<>'*') and (Pattern[i]<>'?') ));
+                { Now, find in name the character which i points to, if the * or
+                  ? wasn't the last character in the pattern, else, use up all
+                  the chars in name }
+                Found:=false;
+                if (i<=LenPat) then
+                  begin
+                    repeat
+                      {find a letter (not only first !) which maches pattern[i]}
+                      while (j<=LenName) and
+                            ((name[j]<>pattern[i]) or
+                             not CompareUtf16CodePoint(i,j,false)) do
+                        begin
+                          GoToLastByteOfUtf16CodePoint(j);
                           inc(j);
                         end;
+                      if (j<LenName) then
+                        begin
+                          { while positions i/j have already been checked, we have to
+                            ensure that we don't split a code point }
+                          if DoFnMatch(i,j) then
+                            begin
+                              i:=LenPat;
+                              j:=LenName;{we can stop}
+                              Found:=true;
+                              Break;
+                            end
+                          { We didn't find one, need to look further }
+                          else
+                            begin
+                              GoToLastByteOfUtf16CodePoint(j);
+                              inc(j);
+                            end;
+                        end
+                      else if j=LenName then
+                        begin
+                          Found:=true;
+                          Break;
+                        end;
+                      { This 'until' condition must be j>LenName, not j>=LenName.
+                        That's because when we 'need to look further' and
+                        j = LenName then loop must not terminate. }
+                    until (j>LenName);
+                  end
                 else
-                  Found:=false;
-                end;
-               end;
-              Assert((i>LenPat) or ( (Pattern[i]<>'*') and (Pattern[i]<>'?') ));
-            {Now, find in name the character which i points to, if the * or ?
-             wasn't the last character in the pattern, else, use up all the
-             chars in name}
-              Found:=false;
-              if (i<=LenPat) then
-              begin
-                repeat
-                  {find a letter (not only first !) which maches pattern[i]}
-                  while (j<=LenName) and (name[j]<>pattern[i]) do
-                    inc (j);
-                  if (j<LenName) then
-                  begin
-                    if DoFnMatch(i+1,j+1) then
-                    begin
-                      i:=LenPat;
-                      j:=LenName;{we can stop}
-                      Found:=true;
-                      Break;
-                    end else
-                      inc(j);{We didn't find one, need to look further}
-                  end else
-                  if j=LenName then
                   begin
+                    j:=LenName;{we can stop}
                     Found:=true;
-                    Break;
                   end;
-                  { This 'until' condition must be j>LenName, not j>=LenName.
-                    That's because when we 'need to look further' and
-                    j = LenName then loop must not terminate. }
-                until (j>LenName);
-              end else
-              begin
-                j:=LenName;{we can stop}
-                Found:=true;
               end;
-            end;
-     else {not a wildcard character in pattern}
-       Found:=(j<=LenName) and (pattern[i]=name[j]);
+        #$D800..#$DBFF:
+          begin
+            { ensure that a part of an UTF-16 codepoint isn't matched with
+              '*' or '?' }
+            Found:=CompareUtf16CodePoint(i,j,true);
+            { at this point, either Found is false (and we'll stop), or
+              both pattern[i] and name[j] are the end of the current code
+              point and equal }
+          end
+       else {not a wildcard character in pattern}
+         Found:=(j<=LenName) and (pattern[i]=name[j]);
+       end;
+       inc(i);
+       inc(j);
      end;
-     inc(i);
-     inc(j);
-   end;
-  DoFnMatch:=Found and (j>LenName);
+    DoFnMatch:=Found and (j>LenName);
   end;
 
 Begin {start FNMatch}
@@ -447,7 +566,7 @@ Begin {start FNMatch}
 End;
 
 
-function FindGetFileInfo(const s: String; var f: TSearchRec): Boolean;
+function FindGetFileInfo(const s: UnicodeString; var f: TAbstractSearchRec; var Name: UnicodeString): Boolean;
 var
   ntstr: UNICODE_STRING;
   objattr: OBJECT_ATTRIBUTES;
@@ -455,14 +574,13 @@ var
   h: THandle;
   iostatus: IO_STATUS_BLOCK;
   attr: LongInt;
-  filename: String;
+  filename: UnicodeString;
   isfileobj: Boolean;
-  buf: array of Byte;
   objinfo: OBJECT_BASIC_INFORMATION;
   fileinfo: FILE_BASIC_INFORMATION;
   time: LongInt;
 begin
-  AnsiStrToNtStr(s, ntstr);
+  UnicodeStrToNtStr(s, ntstr);
   InitializeObjectAttributes(objattr, @ntstr, 0, 0, Nil);
 
   filename := ExtractFileName(s);
@@ -545,7 +663,7 @@ begin
   end;
 
   if (attr and not f.FindData.SearchAttr) = 0 then begin
-    f.Name := filename;
+    Name := filename;
     f.Attr := attr;
     f.Size := 0;
 {$ifndef FPUNONE}
@@ -564,21 +682,24 @@ begin
 end;
 
 
-procedure FindClose(var F: TSearchrec);
+Procedure InternalFindClose (var Handle: THandle; var FindData: TFindData);
 begin
-  if f.FindData.Handle <> 0 then
-    NtClose(f.FindData.Handle);
+  if FindData.Handle <> 0 then
+    begin
+      NtClose(FindData.Handle);
+      FindData.Handle:=0;
+    end;
 end;
 
 
-function FindNext(var Rslt: TSearchRec): LongInt;
+Function InternalFindNext (Var Rslt : TAbstractSearchRec; var Name: UnicodeString) : Longint;
 {
   re-opens dir if not already in array and calls FindGetFileInfo
 }
 Var
-  DirName  : String;
+  DirName  : UnicodeString;
   FName,
-  SName    : string;
+  SName    : UnicodeString;
   Found,
   Finished : boolean;
   ntstr: UNICODE_STRING;
@@ -590,7 +711,7 @@ Var
   dirinfo: POBJECT_DIRECTORY_INFORMATION;
   filedirinfo: PFILE_DIRECTORY_INFORMATION;
   pc: PChar;
-  name: AnsiString;
+  filename: UnicodeString;
   iostatus: IO_STATUS_BLOCK;
 begin
   { TODO : relative directories }
@@ -606,13 +727,13 @@ begin
 
   if Rslt.FindData.Handle = 0 then begin
     if Rslt.FindData.NamePos > 1 then
-      name := Copy(Rslt.FindData.SearchSpec, 1, Rslt.FindData.NamePos - 1)
+      filename := Copy(Rslt.FindData.SearchSpec, 1, Rslt.FindData.NamePos - 1)
     else
     if Rslt.FindData.NamePos = 1 then
-      name := Copy(Rslt.FindData.SearchSpec, 1, 1)
+      filename := Copy(Rslt.FindData.SearchSpec, 1, 1)
     else
-      name := Rslt.FindData.SearchSpec;
-    AnsiStrToNtStr(name, ntstr);
+      filename := Rslt.FindData.SearchSpec;
+    UnicodeStrToNtStr(filename, ntstr);
     InitializeObjectAttributes(objattr, @ntstr, 0, 0, Nil);
 
     res := NtOpenDirectoryObject(@Rslt.FindData.Handle,
@@ -664,14 +785,7 @@ begin
       Rslt.FindData.LastRes := res;
       if dirinfo^.Name.Length > 0 then begin
         SetLength(FName, dirinfo^.Name.Length div 2);
-        pc := PChar(FName);
-        for i := 0 to dirinfo^.Name.Length div 2 - 1 do begin
-          if dirinfo^.Name.Buffer[i] < #256 then
-            pc^ := AnsiChar(Byte(dirinfo^.Name.Buffer[i]))
-          else
-            pc^ := '?';
-          pc := pc + 1;
-        end;
+        move(dirinfo^.Name.Buffer[0],FName[1],dirinfo^.Name.Length);
 {$ifdef debug_findnext}
         Write(FName, ' (');
         for i := 0 to dirinfo^.TypeName.Length div 2 - 1 do
@@ -685,21 +799,14 @@ begin
         FName := '';
     end else begin
       SetLength(FName, filedirinfo^.FileNameLength div 2);
-      pc := PChar(FName);
-      for i := 0 to filedirinfo^.FileNameLength div 2 - 1 do begin
-        if filedirinfo^.FileName[i] < #256 then
-          pc^ := AnsiChar(Byte(filedirinfo^.FileName[i]))
-        else
-          pc^ := '?';
-        pc := pc + 1;
-      end;
+      move(filedirinfo^.FileName[0],FName[1],filedirinfo^.FileNameLength);
     end;
     if FName = '' then
       Finished := True
     else begin
       if FNMatch(SName, FName) then begin
         Found := FindGetFileInfo(Copy(Rslt.FindData.SearchSpec, 1,
-                   Rslt.FindData.NamePos) + FName, Rslt);
+                   Rslt.FindData.NamePos) + FName, Rslt, Name);
         if Found then begin
           Result := 0;
           Exit;
@@ -710,19 +817,18 @@ begin
 end;
 
 
-function FindFirst(const Path: String; Attr: Longint; out Rslt: TSearchRec): Longint;
+Function InternalFindFirst (Const Path : UnicodeString; Attr : Longint; out Rslt : TAbstractSearchRec; var Name : UnicodeString) : Longint;
 {
   opens dir and calls FindNext if needed.
 }
 Begin
   Result := -1;
-  FillChar(Rslt, SizeOf(Rslt), 0);
   if Path = '' then
     Exit;
   Rslt.FindData.SearchAttr := Attr;
   {Wildcards?}
   if (Pos('?', Path) = 0) and (Pos('*', Path) = 0) then begin
-    if FindGetFileInfo(Path, Rslt) then
+    if FindGetFileInfo(Path, Rslt, Name) then
       Result := 0;
   end else begin
     {Create Info}
@@ -732,10 +838,10 @@ Begin
         and (Rslt.FindData.SearchSpec[Rslt.FindData.NamePos] <> DirectorySeparator)
         do
       Dec(Rslt.FindData.NamePos);
-    Result := FindNext(Rslt);
+    Result := InternalFindNext(Rslt,Name);
   end;
   if Result <> 0 then
-    FindClose(Rslt);
+    InternalFindClose(Rslt.FindHandle,Rslt.FindData);
 end;
 
 
@@ -779,14 +885,14 @@ begin
 end;
 
 
-function FileGetAttr(const FileName: String): Longint;
+function FileGetAttr(const FileName: UnicodeString): Longint;
 var
   objattr: OBJECT_ATTRIBUTES;
   info: FILE_NETWORK_OPEN_INFORMATION;
   res: NTSTATUS;
   ntstr: UNICODE_STRING;
 begin
-  AnsiStrToNtStr(FileName, ntstr);
+  UnicodeStrToNtStr(FileName, ntstr);
   InitializeObjectAttributes(objattr, @ntstr, 0, 0, Nil);
 
   res := NtQueryFullAttributesFile(@objattr, @info);
@@ -799,7 +905,7 @@ begin
 end;
 
 
-function FileSetAttr(const Filename: String; Attr: LongInt): Longint;
+function FileSetAttr(const Filename: UnicodeString; Attr: LongInt): Longint;
 var
   h: THandle;
   objattr: OBJECT_ATTRIBUTES;
@@ -808,7 +914,7 @@ var
   res: NTSTATUS;
   iostatus: IO_STATUS_BLOCK;
 begin
-  AnsiStrToNtStr(Filename, ntstr);
+  UnicodeStrToNtStr(Filename, ntstr);
   InitializeObjectAttributes(objattr, @ntstr, 0, 0, Nil);
   res := NtOpenFile(@h,
            NT_SYNCHRONIZE or FILE_READ_ATTRIBUTES or FILE_WRITE_ATTRIBUTES,
@@ -834,7 +940,7 @@ begin
 end;
 
 
-function DeleteFile(const FileName: String): Boolean;
+function DeleteFile(const FileName: UnicodeString): Boolean;
 var
   h: THandle;
   objattr: OBJECT_ATTRIBUTES;
@@ -843,7 +949,7 @@ var
   res: NTSTATUS;
   iostatus: IO_STATUS_BLOCK;
 begin
-  AnsiStrToNtStr(Filename, ntstr);
+  UnicodeStrToNtStr(Filename, ntstr);
   InitializeObjectAttributes(objattr, @ntstr, 0, 0, Nil);
   res := NtOpenFile(@h, NT_DELETE, @objattr, @iostatus,
            FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
@@ -865,7 +971,7 @@ begin
 end;
 
 
-function RenameFile(const OldName, NewName: String): Boolean;
+function RenameFile(const OldName, NewName: UnicodeString): Boolean;
 var
   h: THandle;
   objattr: OBJECT_ATTRIBUTES;
@@ -875,7 +981,7 @@ var
   res: LongInt;
 begin
   { check whether the destination exists first }
-  AnsiStrToNtStr(NewName, dest);
+  UnicodeStrToNtStr(NewName, dest);
   InitializeObjectAttributes(objattr, @dest, 0, 0, Nil);
 
   res := NtCreateFile(@h, 0, @objattr, @iostatus, Nil, 0,
@@ -886,7 +992,7 @@ begin
     NtClose(h);
     Result := False;
   end else begin
-    AnsiStrToNtStr(OldName, src);
+    UnicodeStrToNtStr(OldName, src);
     InitializeObjectAttributes(objattr, @src, 0, 0, Nil);
 
     res := NtCreateFile(@h,
@@ -945,39 +1051,6 @@ begin
 end;
 
 
-function GetCurrentDir: String;
-begin
-  GetDir(0, result);
-end;
-
-
-function SetCurrentDir(const NewDir: String): Boolean;
-begin
-{$I-}
-  ChDir(NewDir);
-{$I+}
-  Result := IOResult = 0;
-end;
-
-
-function CreateDir(const NewDir: String): Boolean;
-begin
-{$I-}
-  MkDir(NewDir);
-{$I+}
-  Result := IOResult = 0;
-end;
-
-
-function RemoveDir(const Dir: String): Boolean;
-begin
-{$I-}
-  RmDir(Dir);
-{$I+}
-  Result := IOResult = 0;
-end;
-
-
 {****************************************************************************
                               Time Functions
 ****************************************************************************}
@@ -1047,7 +1120,7 @@ function wstrlen(p: PWideChar): SizeInt; external name 'FPC_PWIDECHAR_LENGTH';
 
 function GetEnvironmentVariable(const EnvVar: String): String;
 var
-   s : string;
+   s, upperenvvar : UTF8String;
    i : longint;
    hp: pwidechar;
    len: sizeint;
@@ -1055,15 +1128,19 @@ begin
    { TODO : test once I know how to execute processes }
    Result:='';
    hp:=PPEB(CurrentPEB)^.ProcessParameters^.Environment;
+   { first convert to UTF-8, then uppercase in order to avoid potential data
+     loss }
+   upperenvvar:=EnvVar;
+   upperenvvar:=UpperCase(upperenvvar);
    while hp^<>#0 do
      begin
         len:=UnicodeToUTF8(Nil, hp, 0);
         SetLength(s,len);
         UnicodeToUTF8(PChar(s), hp, len);
-        //s:=strpas(hp);
         i:=pos('=',s);
-        if uppercase(copy(s,1,i-1))=upcase(envvar) then
+        if uppercase(copy(s,1,i-1))=upperenvvar then
           begin
+             { copy() returns a rawbytestring -> will keep UTF-8 encoding }
              Result:=copy(s,i+1,length(s)-i);
              break;
           end;
@@ -1086,7 +1163,7 @@ begin
       end;
 end;
 
-function GetEnvironmentString(Index: Integer): String;
+function GetEnvironmentString(Index: Integer): {$ifdef FPC_RTL_UNICODE}UnicodeString{$else}AnsiString{$endif};
 var
   hp : pwidechar;
   len: sizeint;
@@ -1097,14 +1174,19 @@ begin
     begin
     while (hp^<>#0) and (Index>1) do
       begin
-      Dec(Index);
-      hp:=hp+wstrlen(hp)+1;
+        Dec(Index);
+        hp:=hp+wstrlen(hp)+1;
       end;
     If (hp^<>#0) then
       begin
+{$ifdef FPC_RTL_UNICODE}
+        Result:=hp;
+{$else}
         len:=UnicodeToUTF8(Nil, hp, 0);
         SetLength(Result, len);
         UnicodeToUTF8(PChar(Result), hp, len);
+        SetCodePage(RawByteString(Result),CP_UTF8,false);
+{$endif}
       end;
     end;
 end;

+ 24 - 0
rtl/nds/rtldefs.inc

@@ -0,0 +1,24 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2012 by Free Pascal development team
+
+    This file contains platform-specific defines that are used in
+    multiple RTL units.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{ the single byte OS APIs always use UTF-8 }
+{ define FPCRTL_FILESYSTEM_UTF8}
+
+{ The OS supports a single byte file system operations API that we use }
+{$define FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+
+{ The OS supports a two byte file system operations API that we use }
+{ define FPCRTL_FILESYSTEM_TWO_BYTE_API}

+ 4 - 7
rtl/nds/sysdir.inc

@@ -19,25 +19,22 @@
 {*****************************************************************************
                            Directory Handling
 *****************************************************************************}
-procedure mkdir(s: pchar; len: sizeuint);[IOCheck, public, alias : 'FPC_SYS_MKDIR'];
+procedure do_mkdir(const s: rawbytestring);
 begin
-  if not assigned(s) or (len=0) or (InOutRes<>0) then exit;
 
 end;
 
-procedure rmdir(s: pchar; len: sizeuint);[IOCheck, public, alias : 'FPC_SYS_RMDIR'];
+procedure do_rmdir(const s: rawbytestring);
 begin
-  if not assigned(s) or (len=0) then exit;
 
 end;
 
-procedure chdir(s: pchar; len: sizeuint);[IOCheck, public, alias : 'FPC_SYS_CHDIR'];
+procedure do_chdir(const s: rawbytestring);
 begin
-  if not assigned(s) or (len=0) then exit;
 
 end;
 
-procedure GetDir(DriveNr: byte; var Dir: ShortString);
+procedure do_GetDir(DriveNr: byte; var Dir: RawByteString);
 begin
 
 end;

+ 3 - 3
rtl/nds/sysfile.inc

@@ -88,7 +88,7 @@ begin
     InOutRes := 0;
 end;
 
-procedure do_erase(p: pchar);
+procedure do_erase(p: pchar; pchangeable: boolean);
 var
   res: longint;
 begin
@@ -100,7 +100,7 @@ begin
     InOutRes := 0;  
 end;
 
-procedure do_rename(p1, p2: pchar);
+procedure do_rename(p1, p2: pchar; p1changeable, p2changeable: boolean);
 var
   res: longint;
 begin
@@ -209,7 +209,7 @@ begin
     InOutRes := 0;  
 end;
 
-procedure do_open(var f;p:pchar;flags:longint);
+procedure do_open(var f;p:pchar;flags:longint; pchangeable: boolean);
 {
   filerec and textrec have both handle and mode as the first items so
   they could use the same routine for opening/creating.

+ 52 - 48
rtl/nds/sysutils.pp

@@ -29,6 +29,11 @@ interface
 { force ansistrings }
 {$H+}
 
+{ used OS file system APIs use ansistring }
+{$define SYSUTILS_HAS_ANSISTR_FILEUTIL_IMPL}
+{ OS has an ansistring/single byte environment variable API }
+{$define SYSUTILS_HAS_ANSISTR_ENVVAR_IMPL}
+
 { Include platform independent interface part }
 {$i sysutilh.inc}
 
@@ -44,10 +49,12 @@ uses
 {****************************************************************************
                               File Functions
 ****************************************************************************}
-function FileOpen(const FileName: string; Mode: Integer): LongInt;
+function FileOpen(const FileName: rawbytestring; Mode: Integer): LongInt;
 var
   NDSFlags: longint;
+  SystemFileName: RawByteString;
 begin
+  SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
   NDSFlags := 0;
 
   case (Mode and (fmOpenRead or fmOpenWrite or fmOpenReadWrite)) of
@@ -55,7 +62,7 @@ begin
     fmOpenWrite : NDSFlags := NDSFlags or O_WrOnly;
     fmOpenReadWrite : NDSFlags := NDSFlags or O_RdWr;
   end;
-  FileOpen := _open(pchar(FileName), NDSFlags);
+  FileOpen := _open(pchar(SystemFileName), NDSFlags);
 end;
 
 
@@ -71,19 +78,25 @@ begin
 end;
 
 
-function FileCreate(const FileName: string) : LongInt;
+function FileCreate(const FileName: RawByteString) : LongInt;
+var
+  SystemFileName: RawByteString;
 begin
-  FileCreate:=_open(pointer(FileName), O_RdWr or O_Creat or O_Trunc);
+  SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
+  FileCreate:=_open(pointer(SystemFileName), O_RdWr or O_Creat or O_Trunc);
 end;
 
 
-function FileCreate(const FileName: string; Rights: integer): LongInt;
+function FileCreate(const FileName: RawByteString; Rights: integer): LongInt;
+var
+  SystemFileName: RawByteString;
 begin
-  FileCreate:=_Open(pointer(FileName),O_RdWr or O_Creat or O_Trunc,Rights);
+  SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
+  FileCreate:=_Open(pointer(SystemFileName),O_RdWr or O_Creat or O_Trunc,Rights);
 end;
 
 
-function FileCreate(const FileName: string; ShareMode : Integer; Rights: integer): LongInt;
+function FileCreate(const FileName: RawByteString; ShareMode : Integer; Rights: integer): LongInt;
 begin
   result := FileCreate(FileName, Rights);
 end;
@@ -127,66 +140,81 @@ begin
 end;
 
 
-function DeleteFile(const FileName: string) : Boolean;
+function DeleteFile(const FileName: RawByteString) : Boolean;
+var
+  SystemFileName: RawByteString;
 begin
-  Result := _UnLink(pointer(FileName))>= 0;
+  SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
+  Result := _UnLink(pointer(SystemFileName))>= 0;
 end;
 
 
-function RenameFile(const OldName, NewName: string): Boolean;
+function RenameFile(const OldName, NewName: RawByteString): Boolean;
+var
+  OldSystemFileName, NewSystemFileName: RawByteString;
 begin
-  RenameFile := _Rename(pointer(OldNAme), pointer(NewName)) >= 0;
+  OldSystemFileName:=ToSingleByteFileSystemEncodedFileName(OldName);
+  NewSystemFileName:=ToSingleByteFileSystemEncodedFileName(NewName);
+  RenameFile := _Rename(pointer(OldSystemFileName), pointer(NewSystemFileName)) >= 0;
 end;
 
 
 (****** end of non portable routines ******)
 
 
-Function FileAge (Const FileName : String): Longint;
+Function FileAge (Const FileName : RawByteString): Longint;
 var 
   info: Stat;
+  SystemFileName: RawByteString;
 begin
-  if (_stat(pchar(FileName), Info) < 0) or S_ISDIR(info.st_mode) then
+  SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
+  if (_stat(pchar(SystemFileName), Info) < 0) or S_ISDIR(info.st_mode) then
     exit(-1)
   else 
     Result := (info.st_mtime);
 end;
 
 
-Function FileExists (Const FileName : String) : Boolean;
+Function FileExists (Const FileName : RawByteString) : Boolean;
+var
+  SystemFileName: RawByteString;
 begin
-  FileExists := _Access(pointer(filename), F_OK) = 0;
+  SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
+  FileExists := _Access(pointer(SystemFileName), F_OK) = 0;
 end;
 
 
 
-Function FindFirst (Const Path : String; Attr : Longint; Out Rslt : TSearchRec) : Longint;
+Function InternalFindFirst (Const Path : RawByteString; Attr : Longint; out Rslt : TAbstractSearchRec; var Name: RawByteString) : Longint;
 begin
   result := -1;
 end;
 
 
-Function FindNext (Var Rslt : TSearchRec) : Longint;
+Function InternalFindNext (var Rslt : TAbstractSearchRec; var Name : RawByteString) : Longint;
 begin
   result := -1;
 end;
 
-Procedure FindClose (Var F : TSearchrec);
+Procedure InternalFindClose(var Handle: Pointer);
 begin
 
 end;
 
-Function FileGetAttr (Const FileName : String) : Longint;
-Var Info : TStat;
+Function FileGetAttr (Const FileName : RawByteString) : Longint;
+var
+  Info : TStat;
+  SystemFileName: RawByteString;
 begin
-  If _stat(pchar(FileName), Info) <> 0 then
+  SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
+  If _stat(pchar(SystemFileName), Info) <> 0 then
     Result := -1
   Else
     Result := (Info.st_mode shr 16) and $ffff;
 end;
 
 
-Function FileSetAttr (Const Filename : String; Attr: longint) : Longint;
+Function FileSetAttr (Const Filename : RawByteString; Attr: longint) : Longint;
 begin
   result := -1;
 end;
@@ -216,31 +244,7 @@ Begin
 End;
 
 
-Function GetCurrentDir : String;
-begin
-  result := '';
-end;
-
-
-Function SetCurrentDir (Const NewDir : String) : Boolean;
-begin
-  result := false;
-end;
-
-
-Function CreateDir (Const NewDir : String) : Boolean;
-begin
-  result := false;
-end;
-
-
-Function RemoveDir (Const Dir : String) : Boolean;
-begin
-  result := false;
-end;
-
-
-function DirectoryExists(const Directory: string): Boolean;
+function DirectoryExists(const Directory: RawByteString): Boolean;
 begin
   result := false;
 end;
@@ -285,7 +289,7 @@ begin
   result := -1;
 end;
 
-Function GetEnvironmentString(Index : Integer) : String;
+Function GetEnvironmentString(Index : Integer) : {$ifdef FPC_RTL_UNICODE}UnicodeString{$else}AnsiString{$endif};
 begin
   result := '';
 end;

+ 24 - 0
rtl/netbsd/rtldefs.inc

@@ -0,0 +1,24 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2012 by Free Pascal development team
+
+    This file contains platform-specific defines that are used in
+    multiple RTL units.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{ the single byte OS APIs always use UTF-8 }
+{ define FPCRTL_FILESYSTEM_UTF8}
+
+{ The OS supports a single byte file system operations API that we use }
+{$define FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+
+{ The OS supports a two byte file system operations API that we use }
+{ define FPCRTL_FILESYSTEM_TWO_BYTE_API}

+ 3 - 3
rtl/netware/dynlibs.inc

@@ -36,10 +36,10 @@ Const
 
 Uses nwserv;
 
-Function LoadLibrary(const Name : AnsiString) : TlibHandle;
-var args : array[0..1] of pchar;
+Function DoLoadLibrary(const Name : RawByteString) : TlibHandle;
+var args : array[0..1] of PAnsiChar;
 begin
-  args[0] := pchar(Name);
+  args[0] := PAnsiChar(Name);
   args[1] := nil;
   Result:=spawnvp(P_NOWAIT,@args,nil);
 end;

+ 24 - 0
rtl/netware/rtldefs.inc

@@ -0,0 +1,24 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2012 by Free Pascal development team
+
+    This file contains platform-specific defines that are used in
+    multiple RTL units.
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+
+{ the single byte OS APIs always use UTF-8 }
+{ define FPCRTL_FILESYSTEM_UTF8}
+
+{ The OS supports a single byte file system operations API that we use }
+{$define FPCRTL_FILESYSTEM_SINGLE_BYTE_API}
+
+{ The OS supports a two byte file system operations API that we use }
+{ define FPCRTL_FILESYSTEM_TWO_BYTE_API}

+ 13 - 13
rtl/netware/sysdir.inc

@@ -17,12 +17,10 @@
                            Directory Handling
 *****************************************************************************}
 
-Procedure MkDir(s: pchar;len:sizeuint);[IOCheck, public, alias : 'FPC_SYS_MKDIR'];
+Procedure do_MkDir(s: rawbytestring);
 var
     Rc : longint;
 begin
-  If not assigned(s) or (len=0) or (InOutRes <> 0) then
-    exit;
   DoDirSeparators(s);
   Rc := _mkdir(pchar(s));
   if Rc <> 0 then
@@ -30,13 +28,14 @@ begin
 end;
 
 
-procedure RmDir(s: pchar;len:sizeuint);[IOCheck, public, alias : 'FPC_SYS_RMDIR'];
+procedure do_RmDir(s: rawbytestring);
 var Rc : longint;
 begin
-  if (len=1) and (s^ = '.' ) then
-    InOutRes := 16;
-  If not assigned(s) or (len=0) or (InOutRes <> 0) then
-    exit;
+  if s = '.' then
+    begin
+      InOutRes := 16;
+      exit;
+    end;
   DoDirSeparators(s);
   Rc := _rmdir(pchar(s));
   if Rc <> 0 then
@@ -44,17 +43,17 @@ begin
 end;
 
 
-procedure ChDir(s: pchar;len:sizeuint);[IOCheck, public, alias : 'FPC_SYS_CHDIR'];
+procedure do_ChDir(s: rawbytestring);
 var RC: longint;
 begin
-  If not assigned(s) or (len=0) or (InOutRes <> 0) then
-    exit;
+  DoDirSeparators(s);
   RC := _chdir (pchar(s));
   if Rc <> 0 then
     SetFileError(Rc);
 end;
 
-procedure getdir(drivenr : byte;var dir : shortstring);
+
+procedure do_getdir(drivenr : byte;var dir : rawbytestring);
 VAR P : ARRAY [0..255] OF CHAR;
     i : LONGINT;
 begin
@@ -63,8 +62,8 @@ begin
   i := _strlen (P);
   if i > 0 then
   begin
+    SetLength (dir, i);
     Move (P, dir[1], i);
-    BYTE(dir[0]) := i;
     DoDirSeparators(dir);
     // fix / after volume, the compiler needs that
     // normaly root of a volumes is SERVERNAME/SYS:, change that
@@ -73,6 +72,7 @@ begin
     if (i > 0) then
       if i = Length (dir) then dir := dir + '/' else
       if dir [i+1] <> '/' then insert ('/',dir,i+1);
+    SetCodePage (dir,DefaultFileSystemCodePage,false);
   END ELSE
     InOutRes := 1;
 end;

+ 3 - 3
rtl/netware/sysfile.inc

@@ -80,7 +80,7 @@ begin
     InOutRes := 0;
 end;
 
-procedure do_erase(p : pchar);
+procedure do_erase(p : pchar; pchangeable: boolean);
 VAR res : LONGINT;
 begin
   res := _unlink (p);
@@ -90,7 +90,7 @@ begin
     InOutRes := 0;
 end;
 
-procedure do_rename(p1,p2 : pchar);
+procedure do_rename(p1,p2 : pchar; p1changeable, p2changeable: boolean);
 VAR res : LONGINT;
 begin
   res := _rename (p1,p2);
@@ -189,7 +189,7 @@ begin
 end;
 
 // mostly stolen from syslinux
-procedure do_open(var f;p:pchar;flags:longint);
+procedure do_open(var f;p:pchar;flags:longint; pchangeable: boolean);
 {
   filerec and textrec have both handle and mode as the first items so
   they could use the same routine for opening/creating.

+ 61 - 67
rtl/netware/sysutils.pp

@@ -29,6 +29,11 @@ uses DOS;
 {$DEFINE HAS_SLEEP}
 {$DEFINE HAS_OSERROR}
 
+{ used OS file system APIs use ansistring }
+{$define SYSUTILS_HAS_ANSISTR_FILEUTIL_IMPL}
+{ OS has an ansistring/single byte environment variable API }
+{$define SYSUTILS_HAS_ANSISTR_ENVVAR_IMPL}
+
 TYPE
   TNetwareFindData =
   RECORD
@@ -85,35 +90,38 @@ implementation
                               File Functions
 ****************************************************************************}
 
-Function FileOpen (Const FileName : string; Mode : Integer) : THandle;
+Function FileOpen (Const FileName : rawbytestring; Mode : Integer) : THandle;
 VAR NWOpenFlags : longint;
-BEGIN
+    SystemFileName: RawByteString;
+begin
+  SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
   NWOpenFlags:=0;
   Case (Mode and 3) of
     0 : NWOpenFlags:=NWOpenFlags or O_RDONLY;
     1 : NWOpenFlags:=NWOpenFlags or O_WRONLY;
     2 : NWOpenFlags:=NWOpenFlags or O_RDWR;
   end;
-  FileOpen := _open (pchar(FileName),NWOpenFlags,0);
+  FileOpen := _open (pchar(SystemFileName),NWOpenFlags,0);
 
   //!! We need to set locking based on Mode !!
 end;
 
 
-Function FileCreate (Const FileName : String) : THandle;
-
+Function FileCreate (Const FileName : RawByteString) : THandle;
+VAR SystemFileName: RawByteString;
 begin
-  FileCreate:=_open(Pchar(FileName),O_RdWr or O_Creat or O_Trunc,0);
+  SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
+  FileCreate:=_open(Pchar(SystemFileName),O_RdWr or O_Creat or O_Trunc,0);
 end;
 
-Function FileCreate (Const FileName : String; Rights:longint) : THandle;
+Function FileCreate (Const FileName : RawByteString; Rights:longint) : THandle;
 
 begin
   FileCreate:=FileCreate (FileName);
 end;
 
 
-Function FileCreate (Const FileName : String; ShareMode: Longint; Rights:longint) : THandle;
+Function FileCreate (Const FileName : RawByteString; ShareMode: Longint; Rights:longint) : THandle;
 
 begin
   FileCreate:=FileCreate (FileName);
@@ -205,15 +213,17 @@ begin
 end;
 
 
-Function FileExists (Const FileName : String) : Boolean;
+Function FileExists (Const FileName : RawByteString) : Boolean;
 VAR Info : NWStatBufT;
+    SystemFileName: RawByteString;
 begin
-  FileExists:=(_stat(pchar(filename),Info) = 0);
+  SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
+  FileExists:=(_stat(pchar(SystemFileName),Info) = 0);
 end;
 
 
 
-PROCEDURE find_setfields (VAR f : TsearchRec);
+PROCEDURE find_setfields (VAR f : TsearchRec; VAR Name : RawByteString);
 VAR T : Dos.DateTime;
 BEGIN
   WITH F DO
@@ -225,21 +235,25 @@ BEGIN
       UnpackTime(FindData.EntryP^.d_time + (LONGINT (FindData.EntryP^.d_date) SHL 16), T);
       time := DateTimeToFileDate(EncodeDate(T.Year,T.Month,T.day)+EncodeTime(T.Hour,T.Min,T.Sec,0));
       size := FindData.EntryP^.d_size;
-      name := strpas (FindData.EntryP^.d_nameDOS);
+      name := FindData.EntryP^.d_nameDOS;
+      SetCodePage(name, DefaultFileSystemCodePage, false);
     END ELSE
     BEGIN
-      FillChar (f,SIZEOF(f),0);
+      name := '';
     END;
   END;
 END;
 
 
 
-Function FindFirst (Const Path : String; Attr : Longint; out Rslt : TSearchRec) : Longint;
+Function InternalFindFirst (Const Path : RawByteString; Attr : Longint; out Rslt : TAbstractSearchRec; var Name: RawByteString) : Longint;
+var
+  SystemEncodedPath: RawByteString;
 begin
   IF path = '' then
     exit (18);
-  Rslt.FindData.DirP := _opendir (pchar(Path));
+  SystemEncodedPath := ToSingleByteEncodedFileName (Path);
+  Rslt.FindData.DirP := _opendir (pchar(SystemEncodedPath));
   IF Rslt.FindData.DirP = NIL THEN
     exit (18);
   IF attr <> faAnyFile THEN
@@ -253,13 +267,13 @@ begin
     result := 18;
   end else
   begin
-    find_setfields (Rslt);
+    find_setfields (Rslt,Name);
     result := 0;
   end;
 end;
 
 
-Function FindNext (Var Rslt : TSearchRec) : Longint;
+Function InternalFindNext (var Rslt : TAbstractSearchRec; var Name : RawByteString) : Longint;
 
 begin
   IF Rslt.FindData.Magic <> $AD01 THEN
@@ -267,14 +281,14 @@ begin
   Rslt.FindData.EntryP := _readdir (Rslt.FindData.DirP);
   IF Rslt.FindData.EntryP = NIL THEN
     exit (18);
-  find_setfields (Rslt);
+  find_setfields (Rslt,Name);
   result := 0;
 end;
 
 
-Procedure FindClose (Var F : TSearchrec);
+Procedure InternalFindClose (var Handle: THandle; var FindData: TFindData);
 begin
-  IF F.FindData.Magic = $AD01 THEN
+  IF FindData.Magic = $AD01 THEN
   BEGIN
     IF F.FindData.DirP <> NIL THEN
       _closedir (F.FindData.DirP);
@@ -313,38 +327,48 @@ begin
 end;
 
 
-Function FileGetAttr (Const FileName : String) : Longint;
+Function FileGetAttr (Const FileName : RawByteString) : Longint;
 Var Info : NWStatBufT;
+    SystemFileName: RawByteString;
 begin
-  If _stat (pchar(FileName),Info) <> 0 then
+  SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
+  If _stat (pchar(SystemFileName),Info) <> 0 then
     Result:=-1
   Else
     Result := Info.st_attr AND $FFFF;
 end;
 
 
-Function FileSetAttr (Const Filename : String; Attr: longint) : Longint;
+Function FileSetAttr (Const Filename : RawByteString; Attr: longint) : Longint;
 VAR MS : NWModifyStructure;
+    SystemFileName: RawByteString;
 begin
+  { The Attr parameter is not used! }
+  SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
   FillChar (MS, SIZEOF (MS), 0);
-  if _ChangeDirectoryEntry (PChar (Filename), MS, MFileAtrributesBit, 0) <> 0 then
+  if _ChangeDirectoryEntry (PChar (SystemFilename), MS, MFileAtrributesBit, 0) <> 0 then
     result := -1
   else
     result := 0;
 end;
 
 
-Function DeleteFile (Const FileName : String) : Boolean;
-
+Function DeleteFile (Const FileName : RawByteString) : Boolean;
+var
+  SystemFileName: RawByteString;
 begin
-  Result:= (_UnLink (pchar(FileName)) = 0);
+  SystemFileName:=ToSingleByteFileSystemEncodedFileName(FileName);
+  Result:= (_UnLink (pchar(SystemFileName)) = 0);
 end;
 
 
-Function RenameFile (Const OldName, NewName : String) : Boolean;
-
+Function RenameFile (Const OldName, NewName : RawByteString) : Boolean;
+var
+  OldSystemFileName, NewSystemFileName: RawByteString;
 begin
-  RenameFile:=(_rename(pchar(OldName),pchar(NewName)) = 0);
+  OldSystemFileName:=ToSingleByteFileSystemEncodedFileName(OldName);
+  NewSystemFileName:=ToSingleByteFileSystemEncodedFileName(NewName);
+  RenameFile:=(_rename(pchar(OldSystemFileName),pchar(NewSystemFileName)) = 0);
 end;
 
 
@@ -416,43 +440,13 @@ Begin
 End;
 
 
-Function GetCurrentDir : String;
-begin
-  GetDir (0,Result);
-end;
-
-
-Function SetCurrentDir (Const NewDir : String) : Boolean;
-begin
-  {$I-}
-   ChDir(NewDir);
-  {$I+}
-  result := (IOResult = 0);
-end;
-
-
-Function CreateDir (Const NewDir : String) : Boolean;
-begin
-  {$I-}
-   MkDir(NewDir);
-  {$I+}
-  result := (IOResult = 0);
-end;
-
-
-Function RemoveDir (Const Dir : String) : Boolean;
-begin
-  {$I-}
-   RmDir(Dir);
-  {$I+}
-  result := (IOResult = 0);
-end;
-
-
 function DirectoryExists (const Directory: string): boolean;
-VAR Info : NWStatBufT;
+var
+  Info : NWStatBufT;
+  SystemFileName: RawByteString;
 begin
-  If _stat (pchar(Directory),Info) <> 0 then
+  SystemFileName:=ToSingleByteFileSystemEncodedFileName(Directory);
+  If _stat (pchar(SystemFileName),Info) <> 0 then
     exit(false)
   else
     Exit ((Info.st_attr and faDirectory) <> 0);
@@ -523,7 +517,7 @@ end;
 Function GetEnvironmentVariable(Const EnvVar : String) : String;
 
 begin
-  Result:=StrPas(_getenv(PChar(EnvVar)));
+  Result:=_getenv(PChar(EnvVar));
 end;
 
 Function GetEnvironmentVariableCount : Integer;
@@ -533,7 +527,7 @@ begin
   Result:=0;
 end;
 
-Function GetEnvironmentString(Index : Integer) : String;
+Function GetEnvironmentString(Index : Integer) : {$ifdef FPC_RTL_UNICODE}UnicodeString{$else}AnsiString{$endif};
 
 begin
   // Result:=FPCGetEnvStrFromP(Envp,Index);

+ 24 - 3
rtl/netwlibc/dos.pp

@@ -553,10 +553,21 @@ end;
 
 
 procedure getfattr(var f;var attr : word);
-VAR StatBuf : TStat;
+var
+  StatBuf : TStat;
+{$ifndef FPC_ANSI_TEXTFILEREC}
+  r: rawbytestring;
+{$endif not FPC_ANSI_TEXTFILEREC}
+  p: pchar;
 begin
   doserror := 0;
-  if Fpstat (@textrec(f).name, StatBuf) = 0 then
+{$ifdef FPC_ANSI_TEXTFILEREC}
+  p := @filerec(f).name;
+{$else FPC_ANSI_TEXTFILEREC}
+  r := ToSingleByteFileSystemEncodedFileName(filerec(f).name);
+  p := pchar(r);
+{$endif FPC_ANSI_TEXTFILEREC}
+  if Fpstat (p, StatBuf) = 0 then
     attr := nwattr2dosattr (StatBuf.st_mode)
   else
   begin
@@ -570,8 +581,18 @@ procedure setfattr(var f;attr : word);
 var
   StatBuf : TStat;
   newMode : longint;
+{$ifndef FPC_ANSI_TEXTFILEREC}
+  r: rawbytestring;
+{$endif not FPC_ANSI_TEXTFILEREC}
+  p: pchar;
 begin
-  if Fpstat (@textrec(f).name,StatBuf) = 0 then
+{$ifdef FPC_ANSI_TEXTFILEREC}
+  p := @filerec(f).name;
+{$else FPC_ANSI_TEXTFILEREC}
+  r := ToSingleByteFileSystemEncodedFileName(filerec(f).name);
+  p := pchar(r);
+{$endif FPC_ANSI_TEXTFILEREC}
+  if Fpstat (p,StatBuf) = 0 then
   begin
     newmode := StatBuf.st_mode and ($FFFF0000 - M_A_RDONLY-M_A_HIDDEN-M_A_SYSTEM-M_A_ARCH); {only this can be set by dos unit}
     newmode := newmode or M_A_BITS_SIGNIFICANT;  {set netware attributes}

+ 2 - 2
rtl/netwlibc/dynlibs.inc

@@ -35,10 +35,10 @@ Const
 
 uses libc;
 
-Function LoadLibrary(const Name : AnsiString) : TLibHandle;
+Function DoLoadLibrary(const Name : RawByteString) : TLibHandle;
 
 begin
-  Result:=dlopen(Pchar(Name),RTLD_LAZY);
+  Result:=dlopen(PAnsiChar(Name),RTLD_LAZY);
 end;
 
 Function GetProcedureAddress(Lib : TLibHandle; const ProcName : AnsiString) : Pointer;

Some files were not shown because too many files changed in this diff