Browse Source

* iconvenc now also with dynlinking separate. Some fixes for OS X 10.3 and Haiku ported from cwstring

git-svn-id: trunk@13038 -
marco 16 years ago
parent
commit
704c0adbd0

+ 2 - 0
.gitattributes

@@ -2770,6 +2770,8 @@ packages/iconvenc/examples/Makefile.fpc svneol=native#text/plain
 packages/iconvenc/examples/iconvtest.pp svneol=native#text/plain
 packages/iconvenc/fpmake.pp svneol=native#text/plain
 packages/iconvenc/src/iconvenc.pas svneol=native#text/plain
+packages/iconvenc/src/iconvenc_dyn.pas svneol=native#text/plain
+packages/iconvenc/src/iconvert.inc svneol=native#text/plain
 packages/imagemagick/Makefile svneol=native#text/plain
 packages/imagemagick/Makefile.fpc svneol=native#text/plain
 packages/imagemagick/examples/image.png -text svneol=unset#image/png

+ 73 - 59
packages/iconvenc/Makefile

@@ -1,5 +1,5 @@
 #
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2008/10/22]
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2009/04/25]
 #
 default: all
 MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos i386-haiku i386-netbsd i386-solaris i386-qnx i386-netware i386-openbsd i386-wdosx i386-darwin i386-emx i386-watcom i386-netwlibc i386-wince i386-embedded i386-symbian m68k-linux m68k-freebsd m68k-netbsd m68k-amiga m68k-atari m68k-openbsd m68k-palmos m68k-embedded powerpc-linux powerpc-netbsd powerpc-amiga powerpc-macos powerpc-darwin powerpc-morphos powerpc-embedded sparc-linux sparc-netbsd sparc-solaris sparc-embedded x86_64-linux x86_64-freebsd x86_64-darwin x86_64-win64 x86_64-embedded arm-linux arm-palmos arm-darwin arm-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded avr-embedded armeb-linux armeb-embedded
@@ -265,178 +265,178 @@ PACKAGESDIR:=$(wildcard $(FPCDIR) $(FPCDIR)/packages $(FPCDIR)/packages/base $(F
 override PACKAGE_NAME=iconvenc
 override PACKAGE_VERSION=2.2.2
 ifeq ($(FULL_TARGET),i386-linux)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),i386-go32v2)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),i386-win32)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),i386-os2)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),i386-freebsd)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),i386-beos)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),i386-haiku)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),i386-netbsd)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),i386-solaris)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),i386-qnx)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),i386-netware)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),i386-openbsd)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),i386-wdosx)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),i386-darwin)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),i386-emx)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),i386-watcom)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),i386-netwlibc)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),i386-wince)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),i386-embedded)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),i386-symbian)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),m68k-linux)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),m68k-freebsd)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),m68k-netbsd)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),m68k-amiga)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),m68k-atari)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),m68k-openbsd)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),m68k-palmos)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),m68k-embedded)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),powerpc-linux)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),powerpc-netbsd)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),powerpc-amiga)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),powerpc-macos)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),powerpc-darwin)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),powerpc-morphos)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),powerpc-embedded)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),sparc-linux)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),sparc-netbsd)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),sparc-solaris)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),sparc-embedded)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),x86_64-linux)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),x86_64-win64)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),x86_64-embedded)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),arm-linux)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),arm-palmos)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),arm-darwin)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),arm-wince)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),arm-gba)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),arm-nds)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),arm-embedded)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),arm-symbian)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),powerpc64-linux)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),powerpc64-darwin)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),powerpc64-embedded)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),avr-embedded)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),armeb-linux)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),armeb-embedded)
-override TARGET_UNITS+=iconvenc
+override TARGET_UNITS+=iconvenc iconvenc_dyn
 endif
 ifeq ($(FULL_TARGET),i386-linux)
 override TARGET_EXAMPLEDIRS+=examples
@@ -1213,6 +1213,7 @@ endif
 ifeq ($(OS_TARGET),go32v2)
 STATICLIBPREFIX=
 SHORTSUFFIX=dos
+IMPORTLIBPREFIX=
 endif
 ifeq ($(OS_TARGET),watcom)
 STATICLIBPREFIX=
@@ -1220,6 +1221,7 @@ OEXT=.obj
 ASMEXT=.asm
 SHAREDLIBEXT=.dll
 SHORTSUFFIX=wat
+IMPORTLIBPREFIX=
 endif
 ifeq ($(OS_TARGET),linux)
 BATCHEXT=.sh
@@ -1256,6 +1258,7 @@ STATICLIBPREFIX=
 SHAREDLIBEXT=.dll
 SHORTSUFFIX=os2
 ECHO=echo
+IMPORTLIBPREFIX=
 endif
 ifeq ($(OS_TARGET),emx)
 BATCHEXT=.cmd
@@ -1264,6 +1267,7 @@ STATICLIBPREFIX=
 SHAREDLIBEXT=.dll
 SHORTSUFFIX=emx
 ECHO=echo
+IMPORTLIBPREFIX=
 endif
 ifeq ($(OS_TARGET),amiga)
 EXEEXT=
@@ -1303,17 +1307,20 @@ ifeq ($(OS_TARGET),netware)
 EXEEXT=.nlm
 STATICLIBPREFIX=
 SHORTSUFFIX=nw
+IMPORTLIBPREFIX=imp
 endif
 ifeq ($(OS_TARGET),netwlibc)
 EXEEXT=.nlm
 STATICLIBPREFIX=
 SHORTSUFFIX=nwl
+IMPORTLIBPREFIX=imp
 endif
 ifeq ($(OS_TARGET),macos)
 BATCHEXT=
 EXEEXT=
 DEBUGSYMEXT=.xcoff
 SHORTSUFFIX=mac
+IMPORTLIBPREFIX=imp
 endif
 ifeq ($(OS_TARGET),darwin)
 BATCHEXT=.sh
@@ -1340,14 +1347,17 @@ STATICLIBEXT=.a1
 SHAREDLIBEXT=.so1
 STATICLIBPREFIX=
 SHORTSUFFIX=v1
+IMPORTLIBPREFIX=
 endif
 ifeq ($(OS_TARGET),go32v2)
 STATICLIBPREFIX=
 SHORTSUFFIX=dos
+IMPORTLIBPREFIX=
 endif
 ifeq ($(OS_TARGET),watcom)
 STATICLIBPREFIX=
 SHORTSUFFIX=wat
+IMPORTLIBPREFIX=
 endif
 ifeq ($(OS_TARGET),linux)
 BATCHEXT=.sh
@@ -1394,6 +1404,7 @@ STATICLIBEXT=.ao2
 SHAREDLIBEXT=.dll
 SHORTSUFFIX=os2
 ECHO=echo
+IMPORTLIBPREFIX=
 endif
 ifeq ($(OS_TARGET),amiga)
 EXEEXT=
@@ -1454,6 +1465,7 @@ STATICLIBEXT=.a
 SHAREDLIBEXT=.nlm
 EXEEXT=.nlm
 SHORTSUFFIX=nw
+IMPORTLIBPREFIX=imp
 endif
 ifeq ($(OS_TARGET),netwlibc)
 STATICLIBPREFIX=
@@ -1465,6 +1477,7 @@ STATICLIBEXT=.a
 SHAREDLIBEXT=.nlm
 EXEEXT=.nlm
 SHORTSUFFIX=nwl
+IMPORTLIBPREFIX=imp
 endif
 ifeq ($(OS_TARGET),macos)
 BATCHEXT=
@@ -1476,6 +1489,7 @@ STATICLIBEXT=.a
 EXEEXT=
 DEBUGSYMEXT=.xcoff
 SHORTSUFFIX=mac
+IMPORTLIBPREFIX=imp
 endif
 endif
 ifneq ($(findstring $(OS_SOURCE),$(LIMIT83fs)),)

+ 2 - 2
packages/iconvenc/Makefile.fpc

@@ -3,11 +3,11 @@
 #
 
 [package]
-name=iconvenc
+name=iconvenc 
 version=2.2.2
 
 [target]
-units=iconvenc
+units=iconvenc iconvenc_dyn
 exampledirs=examples
 
 [require]

+ 3 - 0
packages/iconvenc/fpmake.pp

@@ -28,6 +28,9 @@ begin
     P.IncludePath.Add('src');
 
     T:=P.Targets.AddUnit('iconvenc.pas');
+    T.Dependencies.AddInclude('iconvert.inc');
+    T:=P.Targets.AddUnit('iconvenc_dyn.pas');
+    T.Dependencies.AddInclude('iconvert.inc');
 
     P.ExamplePath.Add('examples');
     P.Targets.AddExampleProgram('iconvtest.pp');

+ 29 - 118
packages/iconvenc/src/iconvenc.pas

@@ -19,13 +19,9 @@ unit iconvenc;
 interface
 {$mode objfpc}{$H+}
 
-{DEFINE LOADDYNAMIC}
 
 uses
   ctypes,unixtype,baseunix,
-  {$ifdef LOADDYNAMIC}
-  dl,
-  {$endif}
   initc;
 
 const
@@ -43,135 +39,50 @@ type
    Ticonv = function(__cd: iconv_t; __inbuf: ppchar; __inbytesleft: psize_t; __outbuf: ppchar; __outbytesleft: psize_t): size_t; cdecl;
    Ticonv_close = function(__cd: iconv_t): cint; cdecl;
 
-{$IFNDEF LOADDYNAMIC}
-{$ifndef Linux}    // and other OSes with iconv in libc.
-{$linklib iconv}
+{$if not defined(linux) and not defined(solaris)}  // Linux (and maybe glibc pl
+   {$if defined(haiku)}
+    {$linklib textencoding}
+   {$else}
+    {$linklib iconv}
+   {$endif}
+ {$define useiconv}
+{$endif linux}
+          
+Const
+{$ifndef useiconv}
+  libiconvname='c';  // is in libc under Linux.
+{$else}
+  {$ifdef haiku}
+    libiconvname='textencoding';  // is in libtextencoding under Haiku
+  {$else}
+    libiconvname='iconv';
+  {$endif}
 {$endif}
-function iconv_open(__tocode: pchar; __fromcode: pchar): iconv_t; cdecl; external;
-function iconv (__cd: iconv_t; __inbuf: ppchar; __inbytesleft: psize_t; __outbuf: ppchar; __outbytesleft: psize_t): size_t; cdecl; external;
-function iconv_close (__cd: iconv_t): cint; cdecl; external;
 
-var
-  IconvLibFound: boolean = False;
+{$if defined(darwin) and defined(cpupowerpc32)}
+  iconvprefix='lib';  
+{$else}
+  iconvprefix='';
+{$endif}
+                           
+function iconv_open(__tocode: pchar; __fromcode: pchar): iconv_t; cdecl; external libiconvname name iconvprefix+'iconv_open';
+function iconv (__cd: iconv_t; __inbuf: ppchar; __inbytesleft: psize_t; __outbuf: ppchar; __outbytesleft: psize_t): size_t; cdecl; external libiconvname name iconvprefix+'iconv';
+function iconv_close (__cd: iconv_t): cint; cdecl; external libiconvname name iconvprefix+'iconv_close';
 
-{$ELSE}
 var
-  iconv_lib: pointer;
-  iconv_open: Ticonv_open;
-  iconv: Ticonv;
-  iconv_close: Ticonv_close;
-  IconvLibFound: boolean = true;
-
-function TryLoadLib(LibName: string; var error: string): boolean; // can be used to load non standard libname
-{$endif}
+  IconvLibFound: boolean = False;
 
 function Iconvert(s: string; var res: string; FromEncoding, ToEncoding: string): cint;
 function InitIconv(var error: string): boolean;
 
 implementation
 
-{$IFDEF LOADDYNAMIC}
-function TryLoadLib(LibName: string; var error: string): boolean;
-
-    function resolvesymbol (var funcptr; symbol: string): Boolean;
-    begin
-      pointer(funcptr) := pointer(dlsym(iconv_lib, pchar(symbol)));
-      result := assigned(pointer(funcptr));
-      if not result then
-        error := error+#13#10+dlerror();
-    end;
-
-var
-  res: boolean;
-begin
-  result := false;
-  Error := Error+#13#10'Trying '+LibName;
-  iconv_lib := dlopen(pchar(libname), RTLD_NOW);
-  if Assigned(iconv_lib) then
-  begin
-    result := true;
-    result := result and resolvesymbol(pointer(iconv),'iconv');
-    result := result and resolvesymbol(pointer(iconv_open),'iconv_open');
-    result := result and resolvesymbol(pointer(iconv_close),'iconv_close');
-//    if not res then
-//      dlclose(iconv_lib);
-  end else
-    error:=error+#13#10+dlerror();
-end;
-
-{$ENDIF}
-
 function InitIconv(var error: string): boolean;
 begin
   result := true;
-  {$ifdef LOADDYNAMIC}
-  error := '';
-  if not TryLoadLib('libc.so.6', error) then
-    if not TryLoadLib('libiconv.so', error) then
-      result := false; 
-  {$endif}
   iconvlibfound := iconvlibfound or result;
 end;
 
-function Iconvert(S: string; var Res: string; FromEncoding, ToEncoding: string): cint;
-var
-  InLen, OutLen, Offset: size_t;
-  Src, Dst: pchar;
-  H: iconv_t;
-  lerr: cint;
-  iconvres: size_t;
-begin
-  H := iconv_open(PChar(ToEncoding), PChar(FromEncoding));
-  if not assigned(H) then
-  begin
-    Res := S;
-    exit(-1);
-  end;
-
-  try
-    SetLength(Res, Length(S));
-    InLen := Length(S);
-    OutLen := Length(Res);
-    Src := PChar(S);
-    Dst := PChar(Res);
-
-    while InLen > 0 do
-    begin
-      iconvres := iconv(H, @Src, @InLen, @Dst, @OutLen);
-      if iconvres = size_t(-1) then
-      begin
-        lerr := cerrno;
-        if lerr = ESysEILSEQ then // unknown char, skip
-          begin
-            Dst^ := Src^;
-            Inc(Src);
-            Inc(Dst);
-            Dec(InLen);
-            Dec(OutLen);
-          end
-        else
-          if lerr = ESysE2BIG then
-            begin
-              Offset := Dst - PChar(Res);
-              SetLength(Res, Length(Res)+InLen*2+5); // 5 is minimally one utf-8 char
-              Dst := PChar(Res) + Offset;
-              OutLen := Length(Res) - Offset;
-            end
-          else
-            exit(-1)
-      end;
-    end;
-
-    // iconv has a buffer that needs flushing, specially if the last char is not #0
-    iconv(H, nil, nil, @Dst, @Outlen);
-
-    // trim output buffer
-    SetLength(Res, Length(Res) - Outlen);
-  finally
-    iconv_close(H);
-  end;
-
-  Result := 0;
-end;
+{$i iconvert.inc}
 
 end.

+ 106 - 0
packages/iconvenc/src/iconvenc_dyn.pas

@@ -0,0 +1,106 @@
+{
+    This file is part of the Free Pascal run time library.
+    Copyright (c) 2000 by Marco van de Voort([email protected])
+    member of the Free Pascal development team
+
+    libiconv header translation + a helper routine  
+    http://wiki.freepascal.org/iconvenc Dynamic version
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright. (LGPL)
+
+    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.
+
+}
+unit iconvenc_dyn;
+
+interface
+{$mode objfpc}{$H+}
+
+uses
+  ctypes,unixtype,baseunix,
+  dl,
+  initc;
+
+const
+  n = 1;
+
+{$ifdef beos}
+  ESysEILSEQ = EILSEQ;
+{$endif}
+
+type
+   piconv_t = ^iconv_t;
+   iconv_t = pointer;
+
+   Ticonv_open = function(__tocode: pchar; __fromcode: pchar): iconv_t; cdecl;
+   Ticonv = function(__cd: iconv_t; __inbuf: ppchar; __inbytesleft: psize_t; __outbuf: ppchar; __outbytesleft: psize_t): size_t; cdecl;
+   Ticonv_close = function(__cd: iconv_t): cint; cdecl;
+
+var
+  iconv_lib: pointer;
+  iconv_open: Ticonv_open;
+  iconv: Ticonv;
+  iconv_close: Ticonv_close;
+  IconvLibFound: boolean = true;
+
+function TryLoadLib(LibName: string; var error: string): boolean; // can be used to load non standard libname
+function Iconvert(s: string; var res: string; FromEncoding, ToEncoding: string): cint;
+function InitIconv(var error: string): boolean;
+
+implementation
+
+function TryLoadLib(LibName: string; var error: string): boolean;
+
+    function resolvesymbol (var funcptr; symbol: string): Boolean;
+    begin
+      pointer(funcptr) := pointer(dlsym(iconv_lib, pchar(symbol)));
+      result := assigned(pointer(funcptr));
+      if not result then
+        error := error+#13#10+dlerror();
+    end;
+
+var
+  res: boolean;
+begin
+  result := false;
+  Error := Error+#13#10'Trying '+LibName;
+  iconv_lib := dlopen(pchar(libname), RTLD_NOW);
+  if Assigned(iconv_lib) then
+  begin
+    result := true;
+    result := result and resolvesymbol(pointer(iconv),'iconv');
+    result := result and resolvesymbol(pointer(iconv_open),'iconv_open');
+    result := result and resolvesymbol(pointer(iconv_close),'iconv_close');
+    if not result then
+      begin
+        result:=true;
+        result := result and resolvesymbol(pointer(iconv),'libiconv');
+        result := result and resolvesymbol(pointer(iconv_open),'libiconv_open');
+        result := result and resolvesymbol(pointer(iconv_close),'libiconv_close');
+      end;
+//    if not res then
+//      dlclose(iconv_lib);
+  end else
+    error:=error+#13#10+dlerror();
+end;
+
+
+function InitIconv(var error: string): boolean;
+begin
+  result := true;
+  error := '';
+  if not TryLoadLib('libc.so.6', error) then
+    if not TryLoadLib('libiconv.so', error) then
+    {$if defined(haiku)}
+        if not TryLoadLib('libtextencoding.so', error) then
+      {$ifend}
+      result := false; 
+  iconvlibfound := iconvlibfound or result;
+end;
+
+{$i iconvert.inc}
+
+end.

+ 60 - 0
packages/iconvenc/src/iconvert.inc

@@ -0,0 +1,60 @@
+function Iconvert(S: string; var Res: string; FromEncoding, ToEncoding: string): cint;
+var
+  InLen, OutLen, Offset: size_t;
+  Src, Dst: pchar;
+  H: iconv_t;
+  lerr: cint;
+  iconvres: size_t;
+begin
+  H := iconv_open(PChar(ToEncoding), PChar(FromEncoding));
+  if not assigned(H) then
+  begin
+    Res := S;
+    exit(-1);
+  end;
+
+  try
+    SetLength(Res, Length(S));
+    InLen := Length(S);
+    OutLen := Length(Res);
+    Src := PChar(S);
+    Dst := PChar(Res);
+
+    while InLen > 0 do
+    begin
+      iconvres := iconv(H, @Src, @InLen, @Dst, @OutLen);
+      if iconvres = size_t(-1) then
+      begin
+        lerr := cerrno;
+        if lerr = ESysEILSEQ then // unknown char, skip
+          begin
+            Dst^ := Src^;
+            Inc(Src);
+            Inc(Dst);
+            Dec(InLen);
+            Dec(OutLen);
+          end
+        else
+          if lerr = ESysE2BIG then
+            begin
+              Offset := Dst - PChar(Res);
+              SetLength(Res, Length(Res)+InLen*2+5); // 5 is minimally one utf-8 char
+              Dst := PChar(Res) + Offset;
+              OutLen := Length(Res) - Offset;
+            end
+          else
+            exit(-1)
+      end;
+    end;
+
+    // iconv has a buffer that needs flushing, specially if the last char is not #0
+    iconv(H, nil, nil, @Dst, @Outlen);
+
+    // trim output buffer
+    SetLength(Res, Length(Res) - Outlen);
+  finally
+    iconv_close(H);
+  end;
+
+  Result := 0;
+end;