Explorar o código

* New version from Giulio Bernardi

git-svn-id: branches/resources@9695 -
michael %!s(int64=17) %!d(string=hai) anos
pai
achega
07c4889131

+ 4 - 5
.gitattributes

@@ -9051,12 +9051,11 @@ utils/fpcm/makefile.exm -text
 utils/fpcm/readme.txt svneol=native#text/plain
 utils/fpcres/Makefile svneol=native#text/plain
 utils/fpcres/Makefile.fpc svneol=native#text/plain
-utils/fpcres/elfbfd.pas svneol=native#text/plain
-utils/fpcres/elfres.pas svneol=native#text/plain
-utils/fpcres/elfresfix.pas svneol=native#text/plain
-utils/fpcres/fpcres.lpi svneol=native#text/plain
 utils/fpcres/fpcres.pas svneol=native#text/plain
-utils/fpcres/resptrs.as -text
+utils/fpcres/msghandler.pas svneol=native#text/plain
+utils/fpcres/paramparser.pas svneol=native#text/plain
+utils/fpcres/sourcehandler.pas svneol=native#text/plain
+utils/fpcres/target.pas svneol=native#text/plain
 utils/fpdoc/COPYING -text
 utils/fpdoc/Makefile svneol=native#text/plain
 utils/fpdoc/Makefile.fpc svneol=native#text/plain

+ 249 - 4
utils/fpcres/Makefile

@@ -1,5 +1,5 @@
 #
-# Don't edit, this file is generated by FPCMake Version 2.0.0 [2007/11/08]
+# Don't edit, this file is generated by FPCMake Version 2.0.0 [2007/11/14]
 #
 default: all
 MAKEFILETARGETS=i386-linux i386-go32v2 i386-win32 i386-os2 i386-freebsd i386-beos 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-wince arm-gba arm-nds arm-embedded arm-symbian powerpc64-linux powerpc64-darwin powerpc64-embedded
@@ -400,6 +400,165 @@ ifeq ($(FULL_TARGET),powerpc64-embedded)
 override TARGET_PROGRAMS+=fpcres
 endif
 ifeq ($(FULL_TARGET),i386-linux)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),i386-go32v2)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),i386-win32)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),i386-os2)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),i386-freebsd)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),i386-beos)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),i386-netbsd)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),i386-solaris)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),i386-qnx)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),i386-netware)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),i386-openbsd)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),i386-wdosx)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),i386-darwin)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),i386-emx)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),i386-watcom)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),i386-netwlibc)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),i386-wince)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),i386-embedded)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),i386-symbian)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),m68k-linux)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),m68k-freebsd)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),m68k-netbsd)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),m68k-amiga)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),m68k-atari)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),m68k-openbsd)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),m68k-palmos)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),m68k-embedded)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),powerpc-linux)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),powerpc-netbsd)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),powerpc-amiga)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),powerpc-macos)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),powerpc-darwin)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),powerpc-morphos)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),powerpc-embedded)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),sparc-linux)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),sparc-netbsd)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),sparc-solaris)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),sparc-embedded)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),x86_64-linux)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),x86_64-freebsd)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),x86_64-darwin)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),x86_64-win64)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),x86_64-embedded)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),arm-linux)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),arm-palmos)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),arm-wince)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),arm-gba)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),arm-nds)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),arm-embedded)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),arm-symbian)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),powerpc64-linux)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),powerpc64-darwin)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),powerpc64-embedded)
+override TARGET_UNITS+=msghandler paramparser sourcehandler  target
+endif
+ifeq ($(FULL_TARGET),i386-linux)
 override TARGET_RSTS+=fpcres fpcresfix elfres
 endif
 ifeq ($(FULL_TARGET),i386-go32v2)
@@ -1465,165 +1624,218 @@ else
 TAROPT=vz
 TAREXT=.tar.gz
 endif
-override REQUIRE_PACKAGES=rtl rtl
+override REQUIRE_PACKAGES=rtl rtl fcl-res
 ifeq ($(FULL_TARGET),i386-linux)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),i386-go32v2)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),i386-win32)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),i386-os2)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),i386-freebsd)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),i386-beos)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),i386-netbsd)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),i386-solaris)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),i386-qnx)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),i386-netware)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),i386-openbsd)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),i386-wdosx)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),i386-darwin)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),i386-emx)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),i386-watcom)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),i386-netwlibc)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),i386-wince)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),i386-embedded)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),i386-symbian)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),m68k-linux)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),m68k-freebsd)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),m68k-netbsd)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),m68k-amiga)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),m68k-atari)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),m68k-openbsd)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),m68k-palmos)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),m68k-embedded)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),powerpc-linux)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),powerpc-netbsd)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),powerpc-amiga)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),powerpc-macos)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),powerpc-darwin)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),powerpc-morphos)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),powerpc-embedded)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),sparc-linux)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),sparc-netbsd)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),sparc-solaris)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),sparc-embedded)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),x86_64-linux)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),x86_64-freebsd)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),x86_64-darwin)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),x86_64-win64)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),x86_64-embedded)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),arm-linux)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),arm-palmos)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),arm-wince)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),arm-gba)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),arm-nds)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),arm-embedded)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),arm-symbian)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),powerpc64-linux)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),powerpc64-darwin)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifeq ($(FULL_TARGET),powerpc64-embedded)
 REQUIRE_PACKAGES_RTL=1
+REQUIRE_PACKAGES_FCL-RES=1
 endif
 ifdef REQUIRE_PACKAGES_RTL
 PACKAGEDIR_RTL:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /rtl/Makefile.fpc,$(PACKAGESDIR))))))
@@ -1651,6 +1863,32 @@ ifdef UNITDIR_RTL
 override COMPILER_UNITDIR+=$(UNITDIR_RTL)
 endif
 endif
+ifdef REQUIRE_PACKAGES_FCL-RES
+PACKAGEDIR_FCL-RES:=$(firstword $(subst /Makefile.fpc,,$(strip $(wildcard $(addsuffix /fcl-res/Makefile.fpc,$(PACKAGESDIR))))))
+ifneq ($(PACKAGEDIR_FCL-RES),)
+ifneq ($(wildcard $(PACKAGEDIR_FCL-RES)/units/$(TARGETSUFFIX)),)
+UNITDIR_FCL-RES=$(PACKAGEDIR_FCL-RES)/units/$(TARGETSUFFIX)
+else
+UNITDIR_FCL-RES=$(PACKAGEDIR_FCL-RES)
+endif
+ifdef CHECKDEPEND
+$(PACKAGEDIR_FCL-RES)/$(FPCMADE):
+	$(MAKE) -C $(PACKAGEDIR_FCL-RES) $(FPCMADE)
+override ALLDEPENDENCIES+=$(PACKAGEDIR_FCL-RES)/$(FPCMADE)
+endif
+else
+PACKAGEDIR_FCL-RES=
+UNITDIR_FCL-RES:=$(subst /Package.fpc,,$(strip $(wildcard $(addsuffix /fcl-res/Package.fpc,$(UNITSDIR)))))
+ifneq ($(UNITDIR_FCL-RES),)
+UNITDIR_FCL-RES:=$(firstword $(UNITDIR_FCL-RES))
+else
+UNITDIR_FCL-RES=
+endif
+endif
+ifdef UNITDIR_FCL-RES
+override COMPILER_UNITDIR+=$(UNITDIR_FCL-RES)
+endif
+endif
 ifndef NOCPUDEF
 override FPCOPTDEF=$(CPU_TARGET)
 endif
@@ -1804,6 +2042,15 @@ EXECPPAS:=@$(PPAS)
 endif
 endif
 endif
+.PHONY: fpc_units
+ifneq ($(TARGET_UNITS),)
+override ALLTARGET+=fpc_units
+override UNITPPUFILES=$(addsuffix $(PPUEXT),$(TARGET_UNITS))
+override IMPLICITUNITPPUFILES=$(addsuffix $(PPUEXT),$(TARGET_IMPLICITUNITS))
+override INSTALLPPUFILES+=$(UNITPPUFILES) $(IMPLICITUNITPPUFILES)
+override CLEANPPUFILES+=$(UNITPPUFILES) $(IMPLICITUNITPPUFILES)
+endif
+fpc_units: $(COMPILER_UNITTARGETDIR) $(UNITPPUFILES)
 .PHONY: fpc_exes
 ifndef CROSSINSTALL
 ifneq ($(TARGET_PROGRAMS),)
@@ -2166,5 +2413,3 @@ makefiles: fpc_makefiles
 ifneq ($(wildcard fpcmake.loc),)
 include fpcmake.loc
 endif
-.NOTPARALLEL:
-fpcmake$(EXEEXT): fpcresfix.pas elfbfd.pas elfres.pas fpcres.pas

+ 2 - 3
utils/fpcres/Makefile.fpc

@@ -4,13 +4,14 @@
 
 [target]
 programs=fpcres
+units=msghandler paramparser sourcehandler  target
 rsts=fpcres fpcresfix elfres
 
 [clean]
 units=fpcresfix elfbfd elfres
 
 [require]
-packages=rtl
+packages=rtl fcl-res
 
 [install]
 fpcpackage=y
@@ -19,5 +20,3 @@ fpcpackage=y
 fpcdir=../..
 
 [rules]
-.NOTPARALLEL:
-fpcmake$(EXEEXT): fpcresfix.pas elfbfd.pas elfres.pas fpcres.pas

+ 0 - 150
utils/fpcres/elfbfd.pas

@@ -1,150 +0,0 @@
-{$ifdef fpc}
-{$mode objfpc}
-{$endif}
-{$H+}
-unit elfbfd;
-
-{ELF Binary Format Description. 32/64 bit definitions }
-
-interface
-
-const
-  SHT_NULL     = 0;
-  SHT_PROGBITS = 1;
-  SHT_SYMTAB   = 2;
-  SHT_STRTAB   = 3;
-  SHT_RELA     = 4;
-  SHT_HASH     = 5;
-  SHT_DYNAMIC  = 6;
-  SHT_NOTE     = 7;
-  SHT_NOBITS   = 8;
-  SHT_REL      = 9;
-  SHT_SHLIB    = 10;
-  SHT_DYNSYM   = 11;
-  SHF_WRITE     = 1;
-  SHF_ALLOC     = 2;
-  SHF_EXECINSTR = 4;
-
-  PT_NULL       = 0;
-  PT_LOAD 	= 1;
-  PT_DYNAMIC 	= 2;
-  PT_INTERP 	= 3;
-  PT_NOTE 	= 4;
-  PT_SHLIB 	= 5;
-  PT_PHDR 	= 6;
-  PT_LOOS 	= $60000000;
-  PT_HIOS 	= $6fffffff;
-  PT_LOPROC 	= $70000000;
-  PT_HIPROC 	= $7fffffff;
-
-Type
-  TElf32header = packed record
-    magic0123: longint;
-    file_class: byte;
-    data_encoding: byte;
-    file_version: byte;
-    padding: array[$07..$0F] of byte;
-    e_type: word;
-    e_machine: word;
-    e_version: longint;
-    e_entry: longint; { entrypoint }
-    e_phoff: longint; { program header offset }
-    e_shoff: longint; { sections header offset }
-    e_flags: longint;
-    e_ehsize: word; { elf header size in bytes }
-    e_phentsize: word; { size of an entry in the program header array }
-    e_phnum: word; { 0..e_phnum-1 of entrys }
-    e_shentsize: word; { size of an entry in sections header array }
-    e_shnum: word; { 0..e_shnum-1 of entrys }
-    e_shstrndx: word; { index of string section header }
-  end;
-
-  TElf64header = packed record
-    magic0123: longint;
-    file_class: byte;
-    data_encoding: byte;
-    file_version: byte;
-    padding: array[$07..$0F] of byte;
-    e_type: word;
-    e_machine: word;
-    e_version: longint;
-    e_entry: int64; { entrypoint }
-    e_phoff: int64; { program header offset }
-    e_shoff: int64; { sections header offset }
-    e_flags: longint;
-    e_ehsize: word; { elf header size in bytes }
-    e_phentsize: word; { size of an entry in the program header array }
-    e_phnum: word; { 0..e_phnum-1 of entrys }
-    e_shentsize: word; { size of an entry in sections header array }
-    e_shnum: word; { 0..e_shnum-1 of entrys }
-    e_shstrndx: word; { index of string section header }
-  end;
-
-  TElf32sechdr = packed record
-    sh_name: longint;
-    sh_type: longint;
-    sh_flags: longint;
-    sh_addr: longint;
-    sh_offset: longint;
-    sh_size: longint;
-    sh_link: longint;
-    sh_info: longint;
-    sh_addralign: longint;
-    sh_entsize: longint;
-  end;
-
-  TElf64sechdr = packed record
-    sh_name: longint;
-    sh_type: longint;
-    sh_flags: longint;
-    sh_addr: int64;
-    sh_offset: int64;
-    sh_size: int64;
-    sh_link: longint;
-    sh_info: longint;
-    sh_addralign: int64;
-    sh_entsize: int64;
-  end;
-  
-  { FPC resources }
-  
-  TELF32ResourceSectionInfo = packed record
-    ptr: longint;
-    size: longint;
-  end;
-
-  TELF64ResourceSectionInfo = packed record
-    ptr: int64;
-    size: int64;
-  end;
-
-  TELF32ResourceInfo = packed record
-    reshash: longint; // always 32bit, contains an ELF hash of the resource entries name
-    restype: longint; // always 32bit, contains the resource type ID compatible with Windows RES IDs
-    ptr:     longint; // Byte offset to the resource inside the resdata section.
-    name:    longint; // Byte offset to the the resource name inside the ressym section.
-    size:    longint; // The size of the resource entry
-  end;
-
-  TELF64ResourceInfo = packed record
-    reshash: longint; // always 32bit, contains an ELF hash of the resource entries name
-    restype: longint; // always 32bit, contains the resource type ID compatible with Windows RES IDs
-    ptr:     int64;   // Byte offset to the resource inside the resdata section.
-    name:    int64;   // Byte offset to the the resource name inside the ressym section.
-    size:    int64;   // The size of the resource entry
-  end;
-
-  TELF32ResourceSectionTable = packed record
-    version: integer;
-    resentries: integer;
-    ressym: TELF32ResourceSectionInfo;
-    reshash: TELF32ResourceSectionInfo;
-    resdata: TELF32ResourceSectionInfo;
-    resspare: TELF32ResourceSectionInfo;
-    resstr: TELF32ResourceSectionInfo;
-  end;
-
-implementation
-
-end.
-

+ 0 - 604
utils/fpcres/elfres.pas

@@ -1,604 +0,0 @@
-{ *********************************************************************** }
-{                                                                         }
-{  fpcres2elf - Free Pascal Resource to ELF object compiler               }
-{  Part of the Free Pascal and CrossFPC distributions                     }
-{                                                                         }
-{  Copyright (C) 2005 Simon Kissel                                        }
-{                                                                         }
-{  See the file COPYING.FPC, included in the FPC 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.                   }
-{                                                                         }
-{ *********************************************************************** }
-
-{
-This unit will compile an ELF object file out of a supplied .res resource
-file. Optionally, Delphi/Kylix dfm/xfm form files are also accepted as
-input. These will automatically be converted into resources internally.
-
-fpcres2elf builds with Delphi, Kylix and FPC.
-
-Currently this only works on 32Bit targets, but support for 64Bit targets
-is in the works. Support for big endian systems is completely missing,
-though.
-
-Format used for the various resource sections:
-
- .fpc.resptrs:  This section is contained in resptrs.o and always linked to the executable by
-                FPC. It containes an exported label fpcrespointers, which is used at runtime
-                to find the resptrs section in memory. The resptrs contains pointers to all the
-                sections and their sizes. These are updated in a post-precessing step by the
-                compiler and by the external resource embedder when applied to an ELF file.
-                This section always is 128 Bytes long and initially filled with zeros.
-                The first integer (32/64 Bit) value in this section contains the version
-                number of the resource system. Currently this value is 1.
-                The second integer (32/64 Bit) value in this section contains the number of
-                resources.
-                After this follows a version-defined number of TFPCResourceSectionInfo entries.
- .fpc.ressym:   Contains the resource names. This simply is a stream of zero-terminated strings.
-                Only textual names are supported, numeric IDs get autoconverted to #ID's.
-                The reshash table has got a byte index into ressym to quickly get that data if needed
- .fpc.reshash:  n TFPCResourceInfo records. (number of entries is defined in fpc.resptrs)
- .fpc.resdata:  Contains the plain resource data stream. A byte index into the data stream
-                is given for each resource entry in TResourceInfo
- .fpc.resspare: An empty section which is resized to make room if the size of any of the previous
-                sections gets changed. NOT USED IN VERSION 1 (SIZE WILL BE 0)
- .fpc.resstr:   This section is completely seperated from the rest and contains a block of
-                resourcestrings in internal FPC format.
-
-resptr TFPCResourceSectionInfo list for FPC resources version 1:
-
-Index   Pointer to
-0       ressym
-1       reshash
-2       resdata
-3       resspare
-4       resstr
-5       reserved for future extension (stabs)
-6       reserved for future extension
-}
-{$ifdef fpc}
-{$mode objfpc}
-{$endif}
-{$h+}
-
-unit elfres;
-
-interface
-
-uses
-  elfbfd,
-  SysUtils,
-  Classes;
-
-const fpcres2elf_version=1;
-
-type
-  TSectionKind = (skSymtab, skStrtab, skShstrtab, skText, skData, skBss, skFpcRessym, skFpcResstr,
-                  skFpcReshash, skFpcResdata, skFpcResspare);
-
-// Do not change the following consts, they are dummy tables to generate an .o that makes ld happy
-const symtab =   #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00+
-                 #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$03#$00#$01#$00+
-                 #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$03#$00#$02#$00+
-                 #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$03#$00#$03#$00+
-                 #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$03#$00#$04#$00+
-                 #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$03#$00#$05#$00+
-                 #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$03#$00#$06#$00+
-                 #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$03#$00#$07#$00+
-                 #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$03#$00#$08#$00;
-      strtab =   #$00#$00; // this actually is just one byte long
-      zeros  =   #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00;
-
-      // header of a windows 32 bit .res file (16 bytes)
-      reshdr =   #$00#$00#$00#$00#$20#$00#$00#$00#$FF#$FF#$00#$00#$FF#$FF#$00#$00+
-                 #$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00#$00;
-
-      FilerSignature: array[1..4] of Char = 'TPF0';
-
-      SDefaultExtension = '.or';
-      
-Type
-  { TElfResCreator }
-
-  TElfResCreator = Class(TObject)
-  private
-    FDestFileName: String;
-    FExtension: string;
-    FSourceFileName: String;
-    FOverwrite: Boolean;
-    FVerbose: Boolean;
-    FVersion: Integer;
-    FShStrTab: string;
-    FShStrOffsets: array[TSectionKind] of Longint;
-  Protected
-    FSectionStream: TMemoryStream;
-    FDataStream: TMemoryStream;
-    FSymStream: TMemoryStream;
-    FHashStream: TMemoryStream;
-    sectionheader_ofs: integer;
-    shstrtab_ofs: integer;
-    CurrentResource:integer;
-    resheader: string;
-    Signature: byte;
-    Procedure AllocateData; virtual;
-    Procedure FreeData; virtual;
-    Procedure DoAlign(const a: integer);
-  Public
-    Constructor Create;
-    Procedure Convert(Const Source,Destination : String);
-    Procedure ConvertStreams(Source,Dest : TStream);
-    Procedure DoConvertStreams(Source,Dest : TStream); virtual;Abstract;
-    Property  Verbose : Boolean Read FVerbose Write FVerbose;
-    Property  SourceFileName : String Read FSourceFileName;
-    Property  DestFileName : String Read FDestFileName;
-    Property  Overwrite : Boolean Read FOverwrite Write FOverWrite;
-    Property  Version : Integer Read FVersion Write FVersion;
-    Property  Extension : string Read FExtension Write FExtension;
-  end;
-  
-  { TElf32ResCreator }
-
-  TElf32ResCreator = Class(TElfResCreator)
-  Private
-    ResourceEntries: array of TELF32ResourceInfo;
-  Protected
-    Procedure AllocateData; override;
-    Procedure FreeData; override;
-    procedure AddSection(aKind: TSectionKind; atype, aflags, aaddr, aoffset, asize, alink, ainfo, aaddralign, aentsize: longint);
-  public
-    procedure LoadBinaryDFMEntry(const rs:TStream; const DataStream:TMemoryStream; const SymStream:TMemoryStream; var resinfo:TELF32ResourceInfo);
-    procedure LoadTextDFMEntry(const rs:TStream; const DataStream:TMemoryStream; const SymStream:TMemoryStream; var resinfo:TELF32ResourceInfo);
-    procedure LoadRESEntry(const rs:TStream; const DataStream:TMemoryStream; const SymStream:TMemoryStream; var resinfo:TELF32ResourceInfo);
-    Procedure DoConvertStreams(Source,Dest : TStream); override;
-  end;
-  
-  { TElf64Creator }
-
-  TElf64ResCreator = Class(TElfResCreator)
-    Procedure DoConvertStreams(Source,Dest : TStream); override;
-  end;
-
-  EElfResError = Class(Exception);
-
-implementation
-
-resourcestring
-  SErrUnrecognizedFormat = 'Unrecognized file format for input file "%s"';
-
-Procedure DoError (Msg : String);
-
-begin
-  Raise EElfResError.Create(Msg);
-end;
-
-Procedure DoErrorFmt (Msg : String; Args : Array of const);
-
-begin
-  Raise EElfResError.CreateFmt(Msg,Args);
-end;
-
-function HashELF(const S : string) : longint;
-{Note: this hash function is described in "Practical Algorithms For
-       Programmers" by Andrew Binstock and John Rex, Addison Wesley,
-       with modifications in Dr Dobbs Journal, April 1996}
-var
-  G : longint;
-  i : integer;
-begin
-  Result := 0;
-  for i := 1 to length(S) do begin
-    Result := (Result shl 4) + ord(S[i]);
-    G := Result and $F0000000;
-    if (G <> 0) then
-      Result := Result xor (G shr 24);
-    Result := Result and (not G);
-  end;
-end;
-
-{ TElfResCreator }
-
-const
-  sectionNames: array[TSectionKind] of PChar = (
-    '.symtab',
-    '.strtab',
-    '.shstrtab',
-    '.text',
-    '.data',
-    '.bss',
-    '.fpc.ressym',
-    '.fpc.resstr',
-    '.fpc.reshash',
-    '.fpc.resdata',
-    '.fpc.resspare'
-  );
-
-procedure TElfResCreator.AllocateData;
-var
-  i: TSectionKind;
-begin
-  FSectionStream:=TMemoryStream.Create;
-  FDataStream:=TMemoryStream.Create;
-  FSymStream:=TMemoryStream.Create;
-  FHashStream:=TMemoryStream.Create;
-  for i := Low(TSectionKind) to High(TSectionKind) do
-  begin
-    FShStrOffsets[i] := Length(FShStrTab) + 1;
-    FShStrTab := FShStrTab + #0 + string(sectionNames[i]);
-  end;
-  FShStrTab := FShStrTab + #0#0;
-end;
-
-procedure TElfResCreator.FreeData;
-begin
-  FreeAndNil(FSectionStream);
-  FreeAndNil(FDataStream);
-  FreeAndNil(FSymStream);
-  FreeAndNil(FHashStream);
-end;
-
-constructor TElfResCreator.Create;
-begin
-  FVersion:=fpcres2elf_version;
-  FOverwrite:=True;
-  FVerbose:=False;
-  FExtension:=SDefaultExtension;
-end;
-
-// fill the memorystream so it is aligned, max supported align is 16
-procedure TElfResCreator.DoAlign(const a: integer);
-var i: integer;
-begin
-  i:=(4 - (FSectionStream.position MOD a)) MOD a;
-  if (i>0) then FSectionStream.Write(zeros[1],i);
-end;
-
-procedure TElfResCreator.Convert(const Source, Destination: String);
-
-Var
-  Src,Dest : TFileStream;
-
-begin
-  FSourceFileName:=Source;
-  FDestFileName:=Destination;
-  if FDestFileName='' then
-    FDestFileName:=ChangeFileExt(Source,FExtension);
-  Src:=TFileStream.Create(FSourceFileName,fmOpenRead or fmShareDenyWrite);
-  try
-    Dest:=TFileStream.Create(FDestFileName,fmCreate or fmShareDenyWrite);
-    Try
-      ConvertStreams(Src,Dest);
-    Finally
-      Dest.Free;
-    end;
-  Finally
-    Src.Free;
-  end;
-end;
-
-procedure TElfResCreator.ConvertStreams(Source, Dest: TStream);
-begin
-  AllocateData;
-  Try
-    DoConvertStreams(Source,Dest);
-  Finally
-    FreeData;
-  end;
-end;
-
-{ ---------------------------------------------------------------------
-  TElf32ResCreator
-  ---------------------------------------------------------------------}
-
-procedure TElf32ResCreator.AllocateData;
-begin
-  inherited AllocateData;
-  // reserve space for 1024 resource entries for now
-  SetLength(ResourceEntries,1024);
-  CurrentResource:=0;
-end;
-
-procedure TElf32ResCreator.FreeData;
-begin
-  inherited FreeData;
-  SetLength(ResourceEntries,0);
-end;
-
-procedure TElf32ResCreator.LoadRESEntry(const rs:TStream; const DataStream:TMemoryStream; const SymStream:TMemoryStream; var resinfo:TELF32ResourceInfo);
-var l:longint;
-    w:word;
-    ws:WideString;
-    wc:WideChar;
-    name:string;
-    i,nl: integer;
-    headersize:integer;
-    headerstart:integer;
-begin
-  headerstart:=rs.Position;
-  resinfo.ptr:=DataStream.Position;
-  rs.Read(resinfo.size,4);
-  rs.Read(headersize,4);
-  rs.Read(l,4); // Type
-  if (l AND $0000FFFF)=$0000FFFF then
-  begin // Type is stored as ID
-    resinfo.restype:=(l AND $FFFF0000) shr 16; // kill the marker, we always use IDs
-  end
-  else
-  begin
-    // we don't support text IDs for now, skip until we have reached the end
-    // of the widestring, and set rcdata (10) in this case.
-    repeat
-      rs.Read(w,2);
-    until w=0;
-    resinfo.restype:=10;
-  end;
-
-  rs.Read(l,4); // Name
-  if (l AND $0000FFFF)=$0000FFFF then
-  begin // Name is stored as ID.
-    l:=(l AND $FFFF0000) shr 16; // kill the marker
-    // We don't want to support integer names, we'll instead convert them to a #id string
-    // which is more common.
-    name:='#'+inttostr(l);
-  end
-  else
-  begin
-    // Ok, it's a widestring ID
-    ws:=widechar(l AND $0000FFFF);
-    ws:=ws+widechar((l AND $FFFF0000) shr 16);
-    // get the rest of it
-    repeat
-      rs.Read(wc,2);
-      if wc<>#0 then ws:=ws+wc;
-    until wc=#0;
-    // convert to ANSI
-    name:=ws;
-  end;
-
-  // create a hash of the name
-  resinfo.reshash:=HashELF(name);
-  // save the name plus a trailing #0 to the SymStream, also save
-  // the position of this name in the SymStream
-  resinfo.name:=SymStream.Position;
-  name:=name+#0;
-  nl:=length(name);
-  SymStream.Write(name[1],length(name));
-
-  // We don't care about the rest of the header
-  rs.Seek(headersize-(rs.position-headerstart),soFromCurrent);
-
-  // Now copy over the resource data into our internal memory stream
-  DataStream.CopyFrom(rs,resinfo.size);
-
-  // Align the resource stream on a dword boundary
-  i:=(4 - (rs.Position MOD 4)) MOD 4;
-  if (i>0) then rs.Seek(i,soFromCurrent);
-
-
-  // Align the data stream on a dword boundary
-  i:=(4 - (DataStream.Position MOD 4)) MOD 4;
-  if (i>0) then DataStream.Write(zeros[1],i);
-end;
-
-procedure TElf32ResCreator.LoadBinaryDFMEntry(const rs:TStream; const DataStream:TMemoryStream; const SymStream:TMemoryStream; var resinfo:TELF32ResourceInfo);
-var name: string;
-    i: integer;
-begin
-  resinfo.ptr:=0;
-  resinfo.restype:=10; // RCDATA
-
-  // Skip the header
-  rs.Position:=3;
-
-  // Read the name
-  setlength(name,64); // Component names can be 64 chars at max
-  rs.Read(name[1],64);
-
-  // Find end of name
-  i:=pos(#0,name);
-  name:=copy(name,1,i-1);
-
-  // Seek to after the name and skip other crap
-  rs.Position:=i+9;
-
-  resinfo.size:=rs.Size-rs.Position;
-
-  // ...this is followed by the data.
-
-  // create a hash of the name
-  resinfo.reshash:=HashELF(name);
-
-  // save the name plus a trailing #0 to the SymStream, also save
-  // the position of this name in the SymStream
-  resinfo.name:=SymStream.Position;
-  name:=name+#0;
-  SymStream.Write(name[1],length(name));
-
-  // Now copy over the resource data into our internal memory stream
-  DataStream.CopyFrom(rs,resinfo.size);
-
-  // Align the data stream on a dword boundary
-  i:=(4 - (DataStream.Position MOD 4)) MOD 4;
-  if (i>0) then DataStream.Write(zeros,i);
-end;
-
-procedure TElf32ResCreator.LoadTextDFMEntry(const rs:TStream; const DataStream:TMemoryStream; const SymStream:TMemoryStream; var resinfo:TELF32ResourceInfo);
-var ms:TMemoryStream;
-begin
-  ms:=nil;
-  try
-    ms:=TMemoryStream.Create;
-    ObjectTextToResource(rs,ms);
-    LoadBinaryDFMEntry(ms, DataStream, SymStream, resinfo);
-  finally
-    ms.free;
-  end;
-end;
-
-procedure TElf32ResCreator.AddSection(aKind: TSectionKind; atype, aflags, aaddr, aoffset, asize, alink, ainfo, aaddralign, aentsize: longint);
-var
-  sechdr: TElf32sechdr;
-begin
-  sechdr.sh_name := FShStrOffsets[aKind];
-  sechdr.sh_type := atype;
-  sechdr.sh_flags := aflags;
-  sechdr.sh_addr := aaddr;
-  sechdr.sh_offset := aoffset;
-  sechdr.sh_size := asize;
-  sechdr.sh_link := alink;
-  sechdr.sh_info := ainfo;
-  sechdr.sh_addralign := aaddralign;
-  sechdr.sh_entsize := aentsize;
-  FSectionStream.Write(sechdr, sizeOf(sechdr));
-end;
-
-procedure TElf32ResCreator.DoConvertStreams(Source, Dest: TStream);
-
-Var
-  I : Integer;
-  ElfHeader: TElf32Header;
-  SectionHeader: TElf32sechdr;
-  ressym: TELF32ResourceSectionInfo;
-  resstr: TELF32ResourceSectionInfo;
-  reshash: TELF32ResourceSectionInfo;
-  resdata: TELF32ResourceSectionInfo;
-  resspare: TELF32ResourceSectionInfo;
-  
-begin
-  // Read and check the header of the input file. First check if it's a 32bit resource
-  // file...
-  SetLength(resheader,32);
-  Source.Read(resheader[1],32);
-  if (resheader<>reshdr) then
-    begin
-    // ...not a 32Bit resource file. Now let's see if it's a text or binary dfm/xfm/lfm file.
-    Source.Position:=0;
-    Source.Read(Signature,1);
-    if (Signature=$FF) then
-      begin
-      Source.Position:=0;
-      LoadBinaryDFMEntry(Source, FDataStream, FSymStream, ResourceEntries[CurrentResource]);
-      end
-    else if char(Signature) in ['o','O','i','I',' ',#13,#11,#9] then
-      begin
-      Source.Position:=0;
-      LoadTextDFMEntry(Source, FDataStream, FSymStream, ResourceEntries[CurrentResource]);
-      end
-    else
-      DoErrorFmt(SErrUnrecognizedFormat,[SourceFileName]);
-    inc(CurrentResource,1);
-    end
-  else // ...yes, it's a resource file.
-    while Source.Position<Source.Size do
-      begin
-      // Load Resource info, and copy the resource data into the DataStream
-      LoadRESEntry(Source, FDataStream, FSymStream, ResourceEntries[CurrentResource]);
-      inc(CurrentResource,1);
-      // if we hit the current limit of allocated ResourceEntries in the
-      // array, allocate some more space
-      if (CurrentResource>=length(ResourceEntries)) then
-        setlength(ResourceEntries,length(ResourceEntries)+1024);
-      end;
-
-  // downsize the ResourceEntries to the really needed size
-  SetLength(ResourceEntries,CurrentResource);
-
-  // Write the symbol table - ressym
-  ressym.ptr:=FSectionStream.Position+sizeof(TElf32Header);
-  FSymStream.Position:=0;
-  FSectionStream.CopyFrom(FSymStream,FSymStream.Size);
-
-  // resstr
-  resstr.ptr:=FSectionStream.Position+sizeof(TElf32Header);
-  resstr.size:=0;
-  // TODO: Load string data here
-  doalign(4);
-
-  // Now write the ResourceInfos.
-  reshash.ptr:=FSectionStream.Position+sizeof(TElf32Header);
-  for i:=0 to high(ResourceEntries) do
-  begin
-    FSectionStream.Write(ResourceEntries[i],sizeof(TELF32ResourceInfo));
-  end;
-  doalign(4);
-
-  // Next write the resource data stream
-  resdata.ptr:=FSectionStream.Position+sizeof(TElf32Header);
-  FDataStream.Position:=0;
-  FSectionStream.CopyFrom(FDataStream,FDataStream.Size);
-  doalign(4);
-
-  // resspare
-  resspare.ptr:=FSectionStream.Position+sizeof(TElf32Header);
-  // don't write anything, this is an empty section
-
-  // shstrtab - this is not aligned
-  shstrtab_ofs:=FSectionStream.Position+sizeof(TElf32Header);
-  FSectionStream.Write(FShStrtab[1], length(FShStrtab));
-
-  // Write 12 section headers. The headers itself don't need to be aligned,
-  // as their size can be divided by 4. As shstrtab is uneven and not aligned,
-  // we however need to align the start of the section header table
-  doalign(4);
-  sectionheader_ofs:=FSectionStream.Position+sizeof(TElf32Header);;
-
-  // empty one
-  fillchar(SectionHeader,sizeof(SectionHeader),0);
-  FSectionStream.Write(SectionHeader,sizeOf(SectionHeader));
-
-  AddSection(skText,        SHT_PROGBITS, 6 {AX}, 0, sizeof(TElf32Header), 0, 0, 0, 4, 0);
-  AddSection(skData,        SHT_PROGBITS, 3 {WA}, 0, sizeof(TElf32Header), 0, 0, 0, 4, 0);
-  AddSection(skBss,         SHT_NOBITS,   3 {WA}, 0, sizeof(TElf32Header), 0, 0, 0, 4, 0);
-  AddSection(skFpcRessym,   SHT_PROGBITS, 2 {A},  0, ressym.ptr, FSymStream.Size, 0, 0, 1, 0);
-  AddSection(skFpcResstr,   SHT_PROGBITS, 2 {A},  0, resstr.ptr, 0, 0, 0, 4, 0);
-  AddSection(skFpcReshash,  SHT_PROGBITS, 2 {A},  0, reshash.ptr, length(ResourceEntries)*sizeof(TELF32ResourceInfo), 0, 0, 4, 0);
-  AddSection(skFpcResdata,  SHT_PROGBITS, 2 {A},  0, resdata.ptr, FDataStream.Size, 0, 0, 4, 0);
-  AddSection(skFpcResspare, SHT_NOBITS,   2 {A},  0, resspare.ptr, 0, 0, 0, 4, 0);
-  AddSection(skShstrtab,    SHT_STRTAB,   0,      0, shstrtab_ofs, length(FShStrtab), 0, 0, 1, 0);
-  AddSection(skSymtab,      SHT_SYMTAB,   0,      0, FSectionStream.Position+sizeof(TElf32Header) + 2 * sizeof(SectionHeader), length(symtab), $0B, $09, 4, $10);
-  AddSection(skStrtab,      SHT_STRTAB,   0,      0, FSectionStream.Position+sizeof(TElf32Header) + sizeof(SectionHeader) + length(symtab), 1, 0, 0, 1, 0);
-
-  // now write the symbol table
-  FSectionStream.Write(symtab[1],length(symtab));
-  // We don't need to align it, as it's $90 in size
-
-  // now write the string table, it's just a single byte
-  FSectionStream.Write(strtab[1],1);
-
-  // Ok, we are done, now let's really write something to disk...
-
-  // First write the ELF header
-
-  fillchar(ElfHeader,sizeof(ElfHeader),0);
-  ElfHeader.magic0123:=$464c457f; { = #127'ELF' }
-  ElfHeader.file_class:=1;
-  ElfHeader.data_encoding:=1;
-  ElfHeader.file_version:=1;
-  ElfHeader.e_type:=1;
-  ElfHeader.e_machine:=3;
-  ElfHeader.e_version:=1;
-  ElfHeader.e_shoff:=sectionheader_ofs;
-  ElfHeader.e_shstrndx:=9;
-  ElfHeader.e_shnum:=12;
-  ElfHeader.e_ehsize:=sizeof(TElf32header);
-  ElfHeader.e_shentsize:=sizeof(TElf32sechdr);
-
-  Dest.Write(ElfHeader,sizeof(TElf32header));
-
-  // And now let's dump our whole memorystream into it.
-  FSectionStream.Position:=0;
-  Dest.CopyFrom(FSectionStream,FsectionStream.Size);
-end;
-
-
-{ TElf64Creator }
-
-procedure TElf64ResCreator.DoConvertStreams(Source, Dest: TStream);
-begin
-  DoError('64 bits resources not yet supported')
-end;
-
-end.

+ 0 - 312
utils/fpcres/elfresfix.pas

@@ -1,312 +0,0 @@
-
-{ *********************************************************************** }
-{                                                                         }
-{  elfresfix - Free Pascal Resource to ELF object compiler - fixup tool   }
-{  Part of the Free Pascal and CrossFPC distributions                     }
-{                                                                         }
-{  Copyright (C) 2005 Simon Kissel                                        }
-{                                                                         }
-{  See the file COPYING.FPC, included in the FPC 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.                   }
-{                                                                         }
-{ *********************************************************************** }
-
-{
-This tool will update the .fpc.resptrs section of an ELF executable to point
-to the various resource sections in the file. This is done so that the FPC
-RTL at runtime is able to get pointers to these sections.
-
-This tool is automatically run on any fpc compiled ELF executable that
-contains ELF resources.
-
-fpcresfix builds with Delphi, Kylix and FPC.
-
-Currently this only works on 32Bit targets, but support for 64Bit targets
-is in the works. Support for big endian systems is completely missing,
-though.
-}
-{$ifdef fpc}
-{$mode objfpc}
-{$endif}
-{$h+}
-
-unit elfresfix;
-
-interface
-
-uses
-  SysUtils, Classes, elfbfd;
-  
-Type
-
-  TLogEvent = Procedure(Const Msg : String) of object;
-  
-  { TElfResourceFixer }
-
-  TElfResourceFixer = Class(TObject)
-  private
-    FFileName: String;
-    FOnVerbose: TLogEvent;
-    FVerbose: Boolean;
-    Procedure DoVerbose(Msg : String);
-  public
-    Procedure FixFile(AFileName : String);
-    Procedure DoFixStream(Stream : TStream); virtual; abstract;
-    Property Verbose : Boolean read FVerbose write FVerbose;
-    Property FileName : String Read FFileName;
-    Property Onverbose : TLogEvent Read FOnVerbose Write FOnVerbose;
-  end;
-  
-  { TElf32ResourceFixer }
-
-  TElf32ResourceFixer = Class(TElfResourceFixer)
-    Procedure DoFixStream(Stream : TStream); override;
-  end;
-  
-  { TElf64ResourceFixer }
-
-  TElf64ResourceFixer = Class(TElfResourceFixer)
-    Procedure DoFixStream(Stream : TStream); override;
-  end;
-
-  EElfResFixError = Class(Exception);
-
-Implementation
-
-ResourceString
-  SCheckingHeader           = 'Checking ELF Header... ';
-  SReadingSectionHeaders    = 'Reading Section Headers...';
-  SHeaderOK                 = 'ELF Header is OK';
-  SCheckingHeaderTable      = 'Checking Section Header table...';
-  SStrTabFound              = 'Found strtab...';
-  SProcessingSection        = 'Processing section: ';
-  SUpdatingResptrs          = 'Updating resptrs section...';
-  SFileFixed                = 'File fixed successfully!';
-  SNothingToFix             = 'There was nothing to fix in this file.';
-  
-  SErrUnsupportedHeaderSize = 'Unsupported Section Header size.';
-  SErrInvalidELFHeader      = 'Not a valid linux ELF binary.';
-  SErrResPtrsNotFound       = 'Unable to find resptrs section.';
-  
-Procedure DoError (Msg : String);
-
-begin
-  Raise EElfResFixError.Create(Msg);
-end;
-
-Procedure DoErrorFmt (Msg : String; Args : Array of const);
-
-begin
-  Raise EElfResFixError.CreateFmt(Msg,Args);
-end;
-
-{ TElfResourceFixer }
-
-procedure TElfResourceFixer.DoVerbose(Msg: String);
-begin
-  If FVerbose and Assigned(FOnVerbose) then
-    FOnVerbose(Msg);
-end;
-
-procedure TElfResourceFixer.FixFile(AFileName: String);
-
-Var
-  F : TStream;
-
-begin
-  FFileName:=AFileName;
-  F:=TFileStream.Create(AFilename,fmOpenReadWrite or fmShareDenyWrite);
-  Try
-    DoFixStream(F);
-  Finally
-    F.Free;
-  end;
-end;
-
-{ TElf32ResourceFixer }
-
-procedure TElf32ResourceFixer.DoFixStream(Stream: TStream);
-var
-  ElfHeader:TElf32header;
-  ResourceSectionTable: TElf32ResourceSectionTable;
-  SectionHeaders: array of TElf32sechdr;
-
-  i:integer;
-  sn:string;
-  SectionHeaderOffset:integer;
-  fixed: boolean;
-  strtab:string;
-  SectionName: string;
-  ResPtrsSection: integer;
-  ResHashSection: integer;
-  ResSymSection: integer;
-
-  ResourceInfo: TELF32ResourceInfo;
-  DataIndex, StringIndex: integer;
-  SymString: string;
-
-  procedure DoAlign(var value:integer; const a: integer);
-  var i: integer;
-  begin
-    i:=(4 - (value MOD a)) MOD a;
-    if (i>0) then inc(value,i);
-  end;
-
-begin
-  Fixed:=False;
-  Stream.Read(ElfHeader,sizeof(TElf32header));
-  DoVerbose(SCheckingHeader);
-  if (ElfHeader.magic0123<>$464C457F) then
-    DoError(SErrInvalidELFheader);
-  if ElfHeader.e_shentsize=sizeof(TElf32sechdr) then
-    DoVerbose(SHeaderOK)
-  else
-    DoError(SErrUnSupportedHeaderSize);
-  DoVerbose(SReadingSectionHeaders);
-
-  setlength(SectionHeaders,ElfHeader.e_shnum);
-  SectionHeaderOffset:=ElfHeader.e_shoff;
-  Stream.Position:=SectionHeaderOffset;
-
-  for i:=0 to ElfHeader.e_shnum-1 do
-    begin
-    Stream.Read(SectionHeaders[i],sizeof(TElf32sechdr));
-    end;
-
-  DoVerbose(SCheckingHeaderTable);
-
-  // Get the section header strtab
-  i:=ElfHeader.e_shstrndx;
-  if SectionHeaders[i].sh_type=SHT_STRTAB then
-    begin
-    DoVerbose(SStrTabFound);
-    // read the strtab
-    Stream.Position:=SectionHeaders[i].sh_offset;
-    setlength(strtab,SectionHeaders[i].sh_size);
-    Stream.Read(strtab[1],SectionHeaders[i].sh_size);
-  end
-  else
-  begin
-    writeln('Error: Unable to find strtab.');
-    halt(5);
-  end;
-
-  ResPtrsSection:=-1;
-  ResHashSection:=-1;
-  FillChar(ResourceSectionTable, sizeof(ResourceSectionTable), 0);
-  ResourceSectionTable.version:=1;
-
-  // Next cycle through all sections to gather pointers to all the resource
-  // sections, and note the index of the resptrs section
-  for i:=0 to ElfHeader.e_shnum-1 do
-    begin
-    SectionName:=copy(strtab,SectionHeaders[i].sh_name+1,32);
-    SectionName:=copy(SectionName,1,pos(#0,SectionName)-1);
-    DoVerbose(SProcessingSection+SectionName);
-    sn:=Copy(SectionName,1,5);
-    // FPC section ?
-    if (sn='.fpc.') then
-      begin
-      sn:=SectionName;
-      Delete(SN,1,5);
-      if SN='resptrs' then
-        begin
-        ResPtrsSection:=i;
-        end
-      else if sn='ressym' then
-        begin
-        ResSymSection:=i;
-        ResourceSectionTable.ressym.ptr:=SectionHeaders[i].sh_addr;
-        ResourceSectionTable.ressym.size:=SectionHeaders[i].sh_size;
-        end
-      else if sn='reshash' then
-        begin
-        ResHashSection:=i;
-        ResourceSectionTable.reshash.ptr:=SectionHeaders[i].sh_addr;
-        ResourceSectionTable.reshash.size:=SectionHeaders[i].sh_size;
-        ResourceSectionTable.resentries:=SectionHeaders[i].sh_size DIV sizeof(TELF32ResourceInfo);
-        end
-      else if sn='resdata' then
-        begin
-        ResourceSectionTable.resdata.ptr:=SectionHeaders[i].sh_addr;
-        ResourceSectionTable.resdata.size:=SectionHeaders[i].sh_size;
-        end
-      else if sn='resspare' then
-        begin
-        ResourceSectionTable.resspare.ptr:=SectionHeaders[i].sh_addr;
-        ResourceSectionTable.resspare.size:=SectionHeaders[i].sh_size;
-        end
-      else if SectionName='resstr' then
-        begin
-        ResourceSectionTable.resstr.ptr:=SectionHeaders[i].sh_addr;
-        ResourceSectionTable.resstr.size:=SectionHeaders[i].sh_size;
-        end;
-      end
-  end;
-
-  // Ok, we now have pointers to all resource sections and also
-  // know the number of resources.
-  // Now update the resptrs table
-  if (ResPtrsSection>-1) and (ResHashSection>-1) and (ResSymSection>-1) then
-  begin
-    Doverbose(SUpdatingResPtrs);
-    Stream.Position:=SectionHeaders[ResPtrsSection].sh_offset;
-    Stream.Write(ResourceSectionTable,sizeof(TELF32ResourceSectionTable));
-
-    // LD might have merged the sections of several linked .or together
-    // Therefore our data and stringtable offsets might be messed up and need to recalculated
-
-    // First get the symbol string
-    Stream.Position:=SectionHeaders[ResSymSection].sh_offset;
-    setlength(SymString, SectionHeaders[ResSymSection].sh_size);
-    Stream.Read(SymString[1], SectionHeaders[ResSymSection].sh_size);
-
-    DataIndex:=0;
-    StringIndex:=0;
-    Stream.Position:=SectionHeaders[ResHashSection].sh_offset;
-
-    for i:=0 to ResourceSectionTable.resentries-1 do
-    begin
-      Stream.Position:=SectionHeaders[ResHashSection].sh_offset+i*sizeof(TELF32ResourceInfo);
-      Stream.Read(ResourceInfo, sizeof(TELF32ResourceInfo));
-      ResourceInfo.ptr:=DataIndex;
-      ResourceInfo.name:=StringIndex;
-
-      // advance for next entry
-      DataIndex:=DataIndex+ResourceInfo.size;
-      DoAlign(DataIndex,4); // The data blocks are 32bit aligned
-
-      // find end of current string
-      while SymString[StringIndex+1]<>#0 do
-        inc(StringIndex,1);
-      inc(StringIndex,1);
-      // this should be the start of the next string
-
-      // write back the entry
-      Stream.Position:=SectionHeaders[ResHashSection].sh_offset+i*sizeof(TELF32ResourceInfo);
-      Stream.Write(ResourceInfo, sizeof(TELF32ResourceInfo));
-    end;
-    fixed:=true;
-  end
-  else
-    DoError(SErrREsptrsNotFound);
-
-
-  if fixed then
-    DoVerbose(SFileFixed)
-  else
-    writeln(SNothingToFix);
-end;
-
-{ TElf64ResourceFixer }
-
-procedure TElf64ResourceFixer.DoFixStream(Stream: TStream);
-begin
-  DoError('64-bit resources not yet supported');
-end;
-
-end.

+ 0 - 171
utils/fpcres/fpcres.lpi

@@ -1,171 +0,0 @@
-<?xml version="1.0"?>
-<CONFIG>
-  <ProjectOptions>
-    <PathDelim Value="/"/>
-    <Version Value="5"/>
-    <General>
-      <Flags>
-        <MainUnitHasUsesSectionForAllUnits Value="False"/>
-        <MainUnitHasCreateFormStatements Value="False"/>
-        <MainUnitHasTitleStatement Value="False"/>
-      </Flags>
-      <MainUnit Value="0"/>
-      <ActiveEditorIndexAtStart Value="0"/>
-      <IconPath Value="./"/>
-      <TargetFileExt Value=""/>
-    </General>
-    <JumpHistory Count="18" HistoryIndex="17">
-      <Position1>
-        <Filename Value="fpcres.pas"/>
-        <Caret Line="175" Column="14" TopLine="138"/>
-      </Position1>
-      <Position2>
-        <Filename Value="fpcres.pas"/>
-        <Caret Line="144" Column="11" TopLine="122"/>
-      </Position2>
-      <Position3>
-        <Filename Value="fpcres.pas"/>
-        <Caret Line="143" Column="5" TopLine="122"/>
-      </Position3>
-      <Position4>
-        <Filename Value="fpcres.pas"/>
-        <Caret Line="148" Column="29" TopLine="126"/>
-      </Position4>
-      <Position5>
-        <Filename Value="fpcres.pas"/>
-        <Caret Line="152" Column="5" TopLine="130"/>
-      </Position5>
-      <Position6>
-        <Filename Value="fpcres.pas"/>
-        <Caret Line="162" Column="8" TopLine="140"/>
-      </Position6>
-      <Position7>
-        <Filename Value="fpcres.pas"/>
-        <Caret Line="162" Column="8" TopLine="140"/>
-      </Position7>
-      <Position8>
-        <Filename Value="fpcres.pas"/>
-        <Caret Line="163" Column="3" TopLine="141"/>
-      </Position8>
-      <Position9>
-        <Filename Value="fpcres.pas"/>
-        <Caret Line="162" Column="34" TopLine="141"/>
-      </Position9>
-      <Position10>
-        <Filename Value="fpcres.pas"/>
-        <Caret Line="170" Column="25" TopLine="148"/>
-      </Position10>
-      <Position11>
-        <Filename Value="fpcres.pas"/>
-        <Caret Line="170" Column="25" TopLine="148"/>
-      </Position11>
-      <Position12>
-        <Filename Value="fpcres.pas"/>
-        <Caret Line="170" Column="25" TopLine="148"/>
-      </Position12>
-      <Position13>
-        <Filename Value="fpcres.pas"/>
-        <Caret Line="148" Column="17" TopLine="148"/>
-      </Position13>
-      <Position14>
-        <Filename Value="fpcres.pas"/>
-        <Caret Line="67" Column="16" TopLine="67"/>
-      </Position14>
-      <Position15>
-        <Filename Value="fpcres.pas"/>
-        <Caret Line="70" Column="1" TopLine="28"/>
-      </Position15>
-      <Position16>
-        <Filename Value="fpcres.pas"/>
-        <Caret Line="233" Column="27" TopLine="190"/>
-      </Position16>
-      <Position17>
-        <Filename Value="fpcres.pas"/>
-        <Caret Line="143" Column="5" TopLine="121"/>
-      </Position17>
-      <Position18>
-        <Filename Value="fpcres.pas"/>
-        <Caret Line="137" Column="1" TopLine="137"/>
-      </Position18>
-    </JumpHistory>
-    <Units Count="5">
-      <Unit0>
-        <CursorPos X="18" Y="4"/>
-        <EditorIndex Value="0"/>
-        <Filename Value="fpcres.pas"/>
-        <IsPartOfProject Value="True"/>
-        <Loaded Value="True"/>
-        <TopLine Value="1"/>
-        <UnitName Value="fpcres"/>
-        <UsageCount Value="32"/>
-      </Unit0>
-      <Unit1>
-        <CursorPos X="1" Y="235"/>
-        <EditorIndex Value="1"/>
-        <Filename Value="elfres.pas"/>
-        <IsPartOfProject Value="True"/>
-        <Loaded Value="True"/>
-        <TopLine Value="206"/>
-        <UnitName Value="elfres"/>
-        <UsageCount Value="32"/>
-      </Unit1>
-      <Unit2>
-        <CursorPos X="1" Y="1"/>
-        <Filename Value="/home/michael/cmdline.pp"/>
-        <TopLine Value="1"/>
-        <UsageCount Value="10"/>
-      </Unit2>
-      <Unit3>
-        <CursorPos X="1" Y="1"/>
-        <EditorIndex Value="3"/>
-        <Filename Value="elfbfd.pas"/>
-        <IsPartOfProject Value="True"/>
-        <Loaded Value="True"/>
-        <TopLine Value="1"/>
-        <UnitName Value="elfbfd"/>
-        <UsageCount Value="25"/>
-      </Unit3>
-      <Unit4>
-        <CursorPos X="1" Y="121"/>
-        <EditorIndex Value="2"/>
-        <Filename Value="elfresfix.pas"/>
-        <IsPartOfProject Value="True"/>
-        <Loaded Value="True"/>
-        <TopLine Value="109"/>
-        <UnitName Value="elfresfix"/>
-        <UsageCount Value="25"/>
-      </Unit4>
-    </Units>
-    <PublishOptions>
-      <Version Value="2"/>
-      <IgnoreBinaries Value="False"/>
-      <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
-      <ExcludeFileFilter Value="*.(bak|ppu|ppw|o|so);*~;backup"/>
-    </PublishOptions>
-    <RunParams>
-      <local>
-        <FormatVersion Value="1"/>
-        <LaunchingApplication PathPlusParams="/usr/X11R6/bin/xterm -T 'Lazarus Run Output' -e $(LazarusDir)/tools/runwait.sh $(TargetCmdLine)"/>
-      </local>
-    </RunParams>
-  </ProjectOptions>
-  <CompilerOptions>
-    <Version Value="5"/>
-    <CodeGeneration>
-      <Generate Value="Faster"/>
-    </CodeGeneration>
-    <Other>
-      <CompilerPath Value="$(CompPath)"/>
-    </Other>
-  </CompilerOptions>
-  <Debugging>
-    <Exceptions Count="2">
-      <Item1>
-        <Name Value="ECodetoolError"/>
-      </Item1>
-      <Item2>
-        <Name Value="EFOpenError"/>
-      </Item2>
-    </Exceptions>
-  </Debugging>
-</CONFIG>

+ 297 - 229
utils/fpcres/fpcres.pas

@@ -1,277 +1,345 @@
-{$ifdef fpc}
-{$mode objfpc}
-{$endif}
-{$apptype console}
-{$H+}
+{
+
+    FPCRes - Free Pascal Resource Converter
+    Part of the Free Pascal distribution
+    Copyright (C) 2008 by Giulio Bernardi
+
+    See the file COPYING, 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.
+}
+
+{ Note: This program is not the old fpcres by Simon Kissel }
+
 program fpcres;
 
+{$MODE OBJFPC} {$H+}
+
 uses
-  Classes, SysUtils, elfres, elfresfix;
-
-resourcestring
-  SError           = 'Error:';
-  SErrUnknownParam = 'Unknown command-line parameter : %s';
-  SErrNeedArgument = 'Option at pos %d (%s) needs an argument.';
-  SErrNoInputFile  = 'No input filename was specified';
-  SErrNoOutputFile = 'Outputfile is not allowed when multiple input files are given';
-  SErrOutputFileIllegal = 'Outputfile not allowed when fixing headers.';
-
-  SUsage010 = 'fpcres - Free Pascal Resource to ELF object compiler';
-  SUsage020 = 'Part of the Free Pascal and CrossFPC distributions';
-  SUsage030 = 'Copyright (C) 2005 Simon Kissel';
-  SUsage040 = '--------------------------------------------------------';
-  SUsage050 = 'Usage: fpcres [options] -i inputfile [-i inputfile] [-o outputfile]';
-  SUsage055 = ' where options are one or more of:';
-  SUsage060 = ' -i --input=inputfile';
-  SUsage065 = '                   A file in windows .res resource format, ';
-  SUsage070 = '                   or a Delphi/Kylix form file in dfm/xfm  ';
-  SUsage080 = '                   format (binary or text).';
-  SUSage085 = '                   More than one inputfile may be specified.';
-  SUsage090 = ' -o --output=outputfile';
-  SUsage095 = '                   Name of the object file to generate. If ';
-  SUsage100 = '                   omitted, the name of the input file will';
-  SUsage110 = '                   be used, with .or as extension.';
-  SUSage115 = '                   (not allowed with multiple input files.)';
-  SUsage116 = ' -e --extension=ext';
-  SUsage117 = '                   use ext as the extension for output filenames';
-  SUsage120 = ' -h --help         show this help message.';
-  SUsage130 = ' -f --fixheader    fix resource block header.';
-  SUsage140 = ' -6 --64bit        Use 64-bit elf resources.';
-  SUsage150 = ' -v --verbose      be verbose.';
-
-
-Type
-  TRunMode = (rmCreateElfRes,rmFixHeader);
-
-Var
-  RunMode        : TRunMode;
-  InputFiles     : TStringList;
-  OutputFileName : String;
-  Use64bit       : Boolean;
-  BeVerbose      : Boolean;
-  UseExt         : String;
-
-Procedure Usage(ExitStatus : Word);
+  SysUtils, Classes, paramparser, target, msghandler, sourcehandler,
+  resource,
+//readers
+  resreader, coffreader, winpeimagereader, elfreader, machoreader,
+  externalreader, dfmreader,
+//writers
+  reswriter, coffwriter, elfwriter, machowriter, externalwriter,
+//misc
+  elfconsts, cofftypes, machotypes, externaltypes
+  ;
+  
+const
+  halt_no_err = 0;
+  halt_param_err = 1;
+  halt_read_err = 2;
+  halt_write_err = 3;
+
+  progname = 'fpcres';
+  progversion = '2.0'; //to distinguish from the old fpcres
+
+  fpcversion = {$INCLUDE %FPCVERSION%};
+  host_arch = {$INCLUDE %FPCTARGETCPU%};
+  host_os = {$INCLUDE %FPCTARGETOS%};
+  build_date = {$INCLUDE %DATE%};
 
+var
+  params : TParameters = nil;
+  resources : TResources = nil;
+  sourcefiles : TSourceFiles = nil;
+
+procedure ShowVersion;
 begin
-  Writeln(SUsage010);
-  Writeln(SUsage020);
-  Writeln(SUsage030);
-  Writeln(SUsage040);
-  Writeln(SUsage050);
-  Writeln(SUsage055);
-  Writeln(SUsage060);
-  Writeln(SUsage065);
-  Writeln(SUsage070);
-  Writeln(SUsage080);
-  Writeln(SUSage085);
-  Writeln(SUsage090);
-  Writeln(SUsage095);
-  Writeln(SUsage100);
-  Writeln(SUsage110);
-  Writeln(SUSage115);
-  Writeln(SUSage116);
-  Writeln(SUSage117);
-  Writeln(SUsage120);
-  Writeln(SUsage130);
-  Writeln(SUsage140);
-  Writeln(SUsage150);
-  Halt(ExitStatus);
+  writeln(progname+' - resource file converter, version '+progversion+' ['+build_date+'], FPC '+fpcversion);
+  writeln('Host platform: '+host_os+' - '+host_arch);
+  writeln('Copyright (c) 2008 by Giulio Bernardi.');
 end;
 
-Procedure DoError(Msg : String; Args : Array of const);
-
+procedure ShowHelp;
 begin
-  Writeln(SError,' ',Format(Msg,Args));
-  Usage(1);
+  ShowVersion;
+  writeln('Syntax: '+progname+' [options] <inputfile> [<inputfile>...] [-o <outputfile>]');
+  writeln;
+  writeln('Options:');
+  writeln('  --help, -h, -?     Show this screen.');
+  writeln('  --version, -V      Show program version.');
+  writeln('  --verbose, -v      Be verbose.');
+  writeln('  --input, -i <x>    Ignored for compatibility.');
+  writeln('  --output, -o <x>   Set the output file name.');
+  writeln('  -of <format>       Set the output file format. Supported formats:');
+  writeln('                       res, elf, coff, mach-o, external');
+  writeln('  --arch, -a <name>  Set object file architecture. Supported architectures:');
+  writeln('                       i386, x86_64, arm (coff)');
+  writeln('                       i386, x86_64, powerpc, powerpc64, arm, armeb, m68k,');
+  writeln('                       sparc, alpha, ia64 (elf)');
+  writeln('                       i386, x86_64, powerpc, powerpc64 (mach-o)');
+  writeln('                       bigendian, littleendian (external)');
+  writeln('  @<file>            Read more options from file <file>');
+  writeln('Default output target: '+TargetToStr(currenttarget));
 end;
 
-Procedure AnalyzeParams;
+const
+  SOutputFileAlreadySet = 'Output file name already set.';
+  SUnknownParameter = 'Unknown parameter ''%s''';
+  SArgumentMissing = 'Argument missing for option ''%s''';
+  SUnknownObjFormat = 'Unknown file format ''%s''';
+  SUnknownMachine = 'Unknown architecture ''%s''';
+  SFormatArchMismatch = 'Architecture %s is not available for %s format';
+  SNoInputFiles = 'No input files';
+  SNoOutputFile = 'No output file name specified';
+  SCannotReadConfFile ='Can''t read config file ''%s''';
+  
+  SCantOpenFile = 'Can''t open file ''%s''';
+  SUnknownInputFormat = 'No known file format detected for file ''%s''';
+  
+  SCantCreateFile = 'Can''t create file ''%s''';
 
-  Function CheckOption(Index : Integer;Short,Long : String): Boolean;
+function GetCurrentTimeMsec : longint;
+var h,m,s,ms : word;
+begin
+  DecodeTime(Time,h,m,s,ms);
+  Result:=h*3600*1000 + m*60*1000 + s*1000 + ms;
+end;
 
-  var
-    O : String;
+procedure CheckTarget;
+begin
+  //if user explicitally set a format, use it
+  if params.Target.objformat<>ofNone then
+    CurrentTarget.objformat:=params.Target.objformat;
+  //if no machine was specified, check if current is ok for this format,
+  //otherwise pick the default one for that format
+  if params.Target.machine=mtNone then
+  begin
+    if not (CurrentTarget.machine in ObjFormats[CurrentTarget.objformat].machines) then
+      CurrentTarget.machine:=GetDefaultMachineForFormat(CurrentTarget.objformat);
+  end
+  else CurrentTarget.machine:=params.Target.machine;
 
+  if not (CurrentTarget.machine in ObjFormats[CurrentTarget.objformat].machines) then
   begin
-    O:=Paramstr(Index);
-    Result:=(O='-'+short) or (copy(O,1,Length(Long)+3)=('--'+long+'='));
+    Messages.DoError(Format(SFormatArchMismatch,[
+     MachineToStr(CurrentTarget.machine),ObjFormatToStr(CurrentTarget.objformat)]));
+    halt(halt_param_err);
   end;
+  Messages.DoVerbose('target set to '+TargetToStr(CurrentTarget));
+end;
 
-  Function OptionArg(Var Index : Integer) : String;
-
-  Var
-    P : Integer;
-
+procedure CheckInputFiles;
+begin
+  if params.InputFiles.Count=0 then
   begin
-    if (Length(ParamStr(Index))>1) and (Paramstr(Index)[2]<>'-') then
-      begin
-      If Index<ParamCount then
-        begin
-        Inc(Index);
-        Result:=Paramstr(Index);
-        end
-      else
-        DoError(SErrNeedArgument,[Index,ParamStr(Index)]);
-      end
-    else If length(ParamStr(Index))>2 then
-      begin
-      P:=Pos('=',Paramstr(Index));
-      If (P=0) then
-        DoError(SErrNeedArgument,[Index,ParamStr(Index)])
-      else
-        begin
-        Result:=Paramstr(Index);
-        Delete(Result,1,P);
-        end;
-      end;
+    Messages.DoError(SNoInputFiles);
+    halt(halt_param_err);
   end;
+end;
 
-Var
-  I : Integer;
-  P : String;
-  
+procedure CheckOutputFile;
+var tmp : string;
 begin
-  RunMode:=rmCreateElfres;
-  Use64bit:=False;
-  BeVerbose:=False;
-  I:=0;
-  While (I<ParamCount) do
-    begin
-    Inc(I);
-    // Values.
-    If Checkoption(I,'o','output') then
-      OutPutFileName:=OptionArg(I)
-    else if Checkoption(I,'i','input') then
-      InputFiles.Add(OptionArg(I))
-    else If Checkoption(I,'e','extension') then
-      UseExt:=OptionArg(I)
-    else if CheckOption(I,'f','fixheader') then
-      RunMode:=rmFixHeader
-    else if CheckOption(I,'6','64bit') then
-      Use64bit:=True
-    else if CheckOption(I,'h','help') then
-      Usage(0)
-    else if CheckOption(I,'v','verbose') then
-      BeVerbose:=True
-    else
-      begin
-      P:=ParamStr(I);
-      if (Length(P)>0) and (P[1]<>'-') then
-        begin
-        if (I=ParamCount) then
-          OutputFileName:=P
-        else
-          InputFiles.Add(P)
-        end
-      else
-        begin
-        DoError(SErrUnknownParam,[P]);
-        Usage(1);
-        end;
-      end;
-    end;
-  If (InputFiles.Count=0) then
-    DoError(SErrNoInputFile,[]);
-  If (InputFiles.Count>1) and (OutputFileName<>'') then
-    DoError(SErrNoOutputFile,[]);
-  If (RunMode=rmFixHeader) and (OutputFileName<>'') then
-    DoError(SErrOutputFileIllegal,[])
+  if params.OutputFile<>'' then exit;
+  if params.InputFiles.Count>1 then
+  begin
+    Messages.DoError(SNoOutputFile);
+    halt(halt_param_err);
+  end;
+  tmp:=ChangeFileExt(ExtractFileName(params.InputFiles[0]),
+    ObjFormats[CurrentTarget.objformat].ext);
+  if lowercase(tmp)=lowercase(params.InputFiles[0]) then
+    tmp:=tmp+ObjFormats[CurrentTarget.objformat].ext;
+  params.OutputFile:=tmp;
 end;
 
-Type
-  TLogger = Class(TObject)
-    Procedure Log(Const Msg : String);
+procedure ParseParams;
+var msg : string;
+begin
+  Messages.DoVerbose('parsing command line parameters');
+  msg:='';
+  if ParamCount = 0 then
+  begin
+    ShowHelp;
+    halt(halt_no_err);
+  end;
+  params:=TParameters.Create;
+  try
+    params.Parse;
+  except
+    on e : EOutputFileAlreadySetException do msg:=SOutputFileAlreadySet;
+    on e : EUnknownParameterException do msg:=Format(SUnknownParameter,[e.Message]);
+    on e : EArgumentMissingException do msg:=Format(SArgumentMissing,[e.Message]);
+    on e : EUnknownObjFormatException do msg:=Format(SUnknownObjFormat,[e.Message]);
+    on e : EUnknownMachineException do msg:=Format(SUnknownMachine,[e.Message]);
+    on e : ECannotReadConfFile do msg:=Format(SCannotReadConfFile,[e.Message]);
+  end;
+  Messages.Verbose:=params.Verbose;
+  if msg<>'' then
+  begin
+    Messages.DoError(msg);
+    halt(halt_param_err);
+  end;
+  if params.Version then
+  begin
+    ShowVersion;
+    halt(halt_no_err);
+  end;
+  if params.Help then
+  begin
+    ShowHelp;
+    halt(halt_no_err);
   end;
 
-Procedure TLogger.Log(Const Msg : string);
+  CheckTarget;
+  CheckInputFiles;
+  CheckOutputFile;
 
-begin
-  Writeln(Msg);
+  Messages.DoVerbose('finished parsing command line parameters');
 end;
 
-Procedure FixHeader(AFileName : String);
-
-Var
-  F : TElfResourceFixer;
-  O : TLogger;
-  
+procedure LoadSourceFiles;
+var msg : string;
 begin
-  if Use64bit then
-    F:=TElf64ResourceFixer.Create
-  else
-    F:=TElf32ResourceFixer.Create;
+  msg:='';
+  resources:=TResources.Create;
+  sourcefiles:=TSourceFiles.Create;
+  sourcefiles.FileList.AddStrings(params.InputFiles);
   try
-    F.Verbose:=BeVerbose;
-    if BeVerbose then
-      begin
-      O:=TLogger.Create;
-      F.OnVerbose:={$ifdef fpc}@{$endif}O.Log;
-      end
-    else
-      O:=Nil;
-    Try
-      F.FixFile(AFileName);
-    Finally
-      O.Free;
+    sourcefiles.Load(resources);
+  except
+    on e : ECantOpenFileException do msg:=Format(SCantOpenFile,[e.Message]);
+    on e : EUnknownInputFormatException do msg:=Format(SUnknownInputFormat,[e.Message]);
+    on e : Exception do
+    begin
+      if e.Message='' then msg:=e.ClassName
+      else msg:=e.Message;
     end;
-  Finally
-    F.Free;
+  end;
+  if msg<>'' then
+  begin
+    Messages.DoError(msg);
+    halt(halt_read_err);
   end;
 end;
 
-Procedure CreateRes(AFileName : String);
+function SetUpResWriter : TResResourceWriter;
+begin
+  Result:=TResResourceWriter.Create;
+end;
 
-Var
-  C : TElfResCreator;
+function SetUpElfWriter : TElfResourceWriter;
+begin
+  Result:=TElfResourceWriter.Create;
+  case CurrentTarget.machine of
+//    mtnone :
+    mti386 : Result.MachineType:=emti386;
+    mtx86_64 : Result.MachineType:=emtx86_64;
+    mtppc : Result.MachineType:=emtppc;
+    mtppc64 : Result.MachineType:=emtppc64;
+    mtarm : Result.MachineType:=emtarm;
+    mtarmeb : Result.MachineType:=emtarmeb;
+    mtm68k : Result.MachineType:=emtm68k;
+    mtsparc : Result.MachineType:=emtsparc;
+    mtalpha : Result.MachineType:=emtalpha;
+    mtia64 : Result.MachineType:=emtia64;
+  end;
+end;
 
+function SetUpCoffWriter : TCoffResourceWriter;
 begin
-  If Use64Bit then
-    C:=TElf64ResCreator.Create
-  else
-    C:=TElf32ResCreator.Create;
-  With C do
-    Try
-      Verbose:=BeVerbose;
-      If (UseExt<>'') then
-        Extension:=UseExt;
-      Convert(AFileName,OutputFileName);
-    Finally
-      Free;
-    end;
+  Result:=TCoffResourceWriter.Create;
+  case CurrentTarget.machine of
+//    mtnone :
+    mti386 : Result.MachineType:=cmti386;
+    mtarm : Result.MachineType:=cmtarm;
+    mtx86_64 : Result.MachineType:=cmtx8664;
+  end;
 end;
 
-Procedure Run;
+function SetUpMachOWriter : TMachOResourceWriter;
+begin
+  Result:=TMachOResourceWriter.Create;
+  case CurrentTarget.machine of
+//    mtnone :
+    mti386 : Result.MachineType:=mmti386;
+    mtx86_64 : Result.MachineType:=mmtx86_64;
+    mtppc : Result.MachineType:=mmtpowerpc;
+    mtppc64 : Result.MachineType:=mmtpowerpc64;
+  end;
+end;
 
-Var
-  I : Integer;
-  
+
+function SetUpExternalWriter : TExternalResourceWriter;
 begin
-  Try
-    Case RunMode of
-      rmFixHeader:
-        For I:=0 to InputFiles.Count-1 do
-          FixHeader(InputFiles[i]);
-      rmCreateElfRes:
-        For I:=0 to InputFiles.Count-1 do
-          CreateRes(InputFiles[i]);
-    end;
+  Result:=TExternalResourceWriter.Create;
+  case CurrentTarget.machine of
+//    mtnone :
+    mtBigEndian : Result.Endianess:=EXT_ENDIAN_BIG;
+    mtLittleEndian : Result.Endianess:=EXT_ENDIAN_LITTLE;
+  end;
+end;
+
+procedure WriteOutputFile;
+var aStream : TFileStream;
+    aWriter : TAbstractResourceWriter;
+    msg : string;
+begin
+  Messages.DoVerbose(Format('Trying to create output file %s...',[params.OutputFile]));
+  try
+    aStream:=TFileStream.Create(params.OutputFile,fmCreate or fmShareDenyWrite);
   except
-    On E : Exception do
-      begin
-      Writeln(SError,' ',E.Message);
-      Halt(1);
+    Messages.DoError(Format(SCantCreateFile,[params.OutputFile]));
+    halt(halt_write_err);
+  end;
+  try
+    Messages.DoVerbose('Setting up resource writer...');
+    case CurrentTarget.objformat of
+      ofRes   : aWriter:=SetUpResWriter;
+      ofElf   : aWriter:=SetUpElfWriter;
+      ofCoff  : aWriter:=SetUpCoffWriter;
+      ofMachO : aWriter:=SetUpMachOWriter;
+      ofExt   : aWriter:=SetUpExternalWriter;
+    end;
+    try
+      Messages.DoVerbose(Format('Writing output file %s...',[params.OutputFile]));
+      try
+        resources.WriteToStream(aStream,aWriter);
+      except
+        on e : Exception do
+        begin
+          if e.Message='' then msg:=e.ClassName
+          else msg:=e.Message;
+          Messages.DoError(msg);
+          halt(halt_write_err);
+        end;
       end;
+      Messages.DoVerbose(Format('Output file %s written',[params.OutputFile]));
+    finally
+      aWriter.Free;
+    end;
+  finally
+    aStream.Free;
   end;
 end;
 
+procedure Cleanup;
+begin
+  Messages.DoVerbose('Cleaning up');
+  if Resources<>nil then Resources.Free;
+  if SourceFiles<>nil then SourceFiles.Free;
+  if Params<>nil then Params.Free;
+end;
+
+var before, elapsed : longint;
+
 begin
-  InputFiles:=TStringList.Create;
-  Try
-    AnalyzeParams;
-    Run;
-  Finally
-    FreeAndNil(InputFiles);
+  try
+    before:=GetCurrentTimeMsec;
+    ParseParams;
+    LoadSourceFiles;
+    WriteOutputFile;
+    elapsed:=GetCurrentTimeMsec-before;
+    if elapsed<0 then elapsed:=24*3600*1000 + elapsed;
+    Messages.DoVerbose(Format('Time elapsed: %d.%d seconds',[elapsed div 1000,(elapsed mod 1000) div 10]));
+  finally
+    Cleanup;
   end;
 end.
-

+ 105 - 0
utils/fpcres/msghandler.pas

@@ -0,0 +1,105 @@
+{
+
+    FPCRes - Free Pascal Resource Converter
+    Part of the Free Pascal distribution
+    Copyright (C) 2008 by Giulio Bernardi
+
+    Output messages handler
+
+    See the file COPYING, 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.
+}
+
+unit msghandler;
+
+{$MODE OBJFPC}
+
+interface
+
+uses
+  Classes, SysUtils;
+
+type
+
+  { TMessages }
+
+  TMessages = class
+  private
+    fVerboseSet : boolean;
+    fVerbose : boolean;
+    fVerbCache : TStringList;
+    fStdOut : text;
+    fStdErr : text;
+    procedure SetVerbose(const aValue : boolean);
+  protected
+  public
+    constructor Create;
+    destructor Destroy; override;
+    procedure DoError(const aMsg : string);
+    procedure DoVerbose(const aMsg : string);
+    property Verbose : boolean read fVerbose write SetVerbose;
+  end;
+  
+var Messages : TMessages;
+
+implementation
+
+{ TMessages }
+
+procedure TMessages.SetVerbose(const aValue: boolean);
+var i : integer;
+begin
+  fVerbose:=aValue;
+  if fVerboseSet then exit;
+
+  fVerboseSet:=true;
+  if fVerbose then //output all verbose messages we didn't output before
+    for i:=0 to fVerbCache.Count-1 do
+      writeln(fStdOut,'Debug: '+fVerbCache[i]);
+
+  FreeAndNil(fVerbCache);
+end;
+
+constructor TMessages.Create;
+begin
+  fVerbose:=false;
+  fVerboseSet:=false;
+  fVerbCache:=TStringList.Create;
+  fStdOut:=stdout;
+  fStdErr:=stderr;
+end;
+
+destructor TMessages.Destroy;
+begin
+  if fVerbCache<>nil then
+    fVerbCache.Free;
+end;
+
+procedure TMessages.DoError(const aMsg: string);
+begin
+  writeln(fStdErr,'Error: '+aMsg);
+end;
+
+procedure TMessages.DoVerbose(const aMsg: string);
+begin
+  if not fVerboseSet then
+  begin
+    fVerbCache.Add(aMsg);
+    exit;
+  end;
+  if fVerbose then
+    writeln(fStdOut,'Debug: '+aMsg);
+end;
+
+initialization
+  Messages:=TMessages.Create;
+
+
+finalization
+  Messages.Free;
+
+end.

+ 367 - 0
utils/fpcres/paramparser.pas

@@ -0,0 +1,367 @@
+{
+
+    FPCRes - Free Pascal Resource Converter
+    Part of the Free Pascal distribution
+    Copyright (C) 2008 by Giulio Bernardi
+    
+    Handles the parsing of parameters
+
+    See the file COPYING, 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.
+}
+
+unit paramparser;
+
+{$MODE OBJFPC} {$H+}
+
+interface
+
+uses
+  Classes, SysUtils, target;
+
+type
+  EParametersException = class(Exception);
+  EOutputFileAlreadySetException = class(EParametersException);
+  EUnknownParameterException = class(EParametersException);
+  EArgumentMissingException = class(EParametersException);
+  EUnknownObjFormatException = class(EParametersException);
+  EUnknownMachineException = class(EParametersException);
+  ECannotReadConfFile = class(EParametersException);
+
+type
+
+  { TParameters }
+
+  TParameters = class
+  private
+    fHelp : boolean;
+    fVersion : boolean;
+    fVerbose : boolean;
+    fInputFiles : TStringList;
+    fOutputFile : string;
+    fTarget : TResTarget;
+
+    procedure ParseInputFiles(aList : TStringList; var index : integer; const parname : string);
+    procedure ParseOutputFile(aList : TStringList; var index : integer; const parname : string);
+    procedure ParseOutputFormat(aList : TStringList; var index : integer; const parname : string);
+    procedure ParseArchitecture(aList : TStringList; var index : integer; const parname : string);
+    procedure ParseConfigFile(aList : TStringList; var index : integer; const parname : string);
+    function DoOptionalArgument(aList : TStringList; const i : integer) : string;
+    function DoMandatoryArgument(aList : TStringList; const i : integer) : string;
+    function IsParameter(const s : string) : boolean;
+    function ParamsToStrList : TStringList;
+  protected
+  public
+    constructor Create;
+    destructor Destroy; override;
+    procedure Parse;
+    property Help : boolean read fHelp;
+    property Version : boolean read fVersion;
+    property Verbose : boolean read fVerbose;
+    property InputFiles : TStringList read fInputFiles;
+    property OutputFile : string read fOutputFile write fOutputFile;
+    property Target : TResTarget read fTarget;
+  end;
+
+implementation
+
+uses
+  msghandler;
+
+type
+
+  { TConfFileParser }
+
+  TConfFileParser = class
+  private
+    fConfFile : TStringList;
+    fParList : TStringList;
+    fInsPos : integer;
+
+    procedure ParseLine(idx : integer);
+    function GetParameter(pc : pchar; var i : integer) : string;
+    function GetString(pc : pchar; var i : integer) : string;
+  protected
+  public
+    constructor Create(aFileName : string; aParList : TStringList; aInsPos : integer);
+    procedure Parse;
+    destructor Destroy; override;
+  end;
+
+{ TConfFileParser }
+
+procedure TConfFileParser.ParseLine(idx: integer);
+var pc : pchar;
+    tmp : string;
+    i : integer;
+begin
+  pc:=pchar(fConfFile[idx]);
+  i:=0;
+  while pc[i]<>#0 do
+  begin
+    case pc[i] of
+      ' ',#9,#13,#10 : inc(i);
+      '#' : break
+    else
+      begin
+        tmp:=GetParameter(pc,i);
+        if tmp<>'' then
+        begin
+          fParList.Insert(fInsPos,tmp);
+          inc(fInsPos);
+        end;
+      end;
+    end;
+  end;
+end;
+
+function TConfFileParser.GetParameter(pc : pchar; var i : integer): string;
+begin
+  Result:='';
+  while pc[i]<>#0 do
+  begin
+    case pc[i] of
+      ' ',#9,#13,#10 : exit;
+      '#' : exit;
+      '"' : Result:=Result+GetString(pc,i);
+      else
+        Result:=Result+pc[i];
+    end;
+    inc(i);
+  end;
+end;
+
+function TConfFileParser.GetString(pc: pchar; var i: integer): string;
+begin
+  Result:='';
+  inc(i);
+  while pc[i]<>#0 do
+  begin
+    if pc[i] = '"' then
+      exit
+    else
+      Result:=Result+pc[i];
+    inc(i);
+  end;
+  dec(i);
+end;
+
+constructor TConfFileParser.Create(aFileName: string; aParList: TStringList; aInsPos : integer);
+begin
+  fInsPos:=aInsPos+1;
+  fConfFile:=TStringList.Create;
+  fParList:=aParList;
+  try
+    fConfFile.LoadFromFile(aFileName);
+  except
+    raise ECannotReadConfFile.Create(aFileName);
+  end;
+end;
+
+procedure TConfFileParser.Parse;
+var i : integer;
+begin
+  for i:=0 to fConfFile.Count-1 do
+    ParseLine(i);
+end;
+
+destructor TConfFileParser.Destroy;
+begin
+  fConfFile.Free;
+end;
+
+{ TParameters }
+
+//for compatibility allow -i <inputfiles>
+procedure TParameters.ParseInputFiles(aList: TStringList; var index: integer;
+  const parname : string);
+var tmp : string;
+begin
+  tmp:=DoMandatoryArgument(aList,index+1);
+  if tmp='' then
+    raise EArgumentMissingException.Create(parname);
+
+  while tmp<>'' do
+  begin
+    inc(index);
+    fInputFiles.Add(tmp);
+    tmp:=DoOptionalArgument(aList,index+1);
+  end;
+end;
+
+procedure TParameters.ParseOutputFile(aList: TStringList; var index: integer;
+  const parname : string);
+begin
+  if fOutputFile<>'' then
+    raise EOutputFileAlreadySetException.Create('');
+  inc(index);
+  fOutputFile:=DoMandatoryArgument(aList,index);
+  if fOutputFile='' then
+    raise EArgumentMissingException.Create(parname);
+end;
+
+procedure TParameters.ParseOutputFormat(aList: TStringList; var index: integer;
+  const parname: string);
+var tmp : string;
+    aFormat : TObjFormat;
+begin
+  inc(index);
+  tmp:=DoMandatoryArgument(aList,index);
+  if tmp='' then
+    raise EArgumentMissingException.Create(parname);
+
+  for aFormat:=low(TObjFormat) to high(TObjFormat) do
+  begin
+    if ObjFormats[aFormat].name=tmp then
+    begin
+      fTarget.objformat:=aFormat;
+      exit;
+    end;
+  end;
+  
+  raise EUnknownObjFormatException.Create(tmp);
+
+end;
+
+procedure TParameters.ParseArchitecture(aList: TStringList; var index: integer;
+  const parname: string);
+var tmp : string;
+    aMachine : TMachineType;
+begin
+  inc(index);
+  tmp:=DoMandatoryArgument(aList,index);
+  if tmp='' then
+    raise EArgumentMissingException.Create(parname);
+
+  for aMachine:=low(TMachineType) to high(TMachineType) do
+  begin
+    if Machines[aMachine].name=tmp then
+    begin
+      fTarget.machine:=aMachine;
+      exit;
+    end;
+  end;
+
+  raise EUnknownMachineException.Create(tmp);
+
+end;
+
+procedure TParameters.ParseConfigFile(aList: TStringList; var index: integer;
+  const parname : string);
+var tmp : string;
+    cp : TConfFileParser;
+begin
+  tmp:=copy(parname,2,length(parname)-1);
+  if tmp='' then
+    raise EArgumentMissingException.Create(parname);
+  cp:=TConfFileParser.Create(tmp,aList,index);
+  try
+    cp.Parse;
+  finally
+    cp.Free;
+  end;
+end;
+
+function TParameters.DoOptionalArgument(aList: TStringList; const i: integer
+  ): string;
+begin
+  Result:='';
+  if aList.Count>i then
+  begin
+    if not IsParameter(aList[i]) then
+      Result:=aList[i];
+  end;
+end;
+
+function TParameters.DoMandatoryArgument(aList: TStringList; const i: integer
+  ): string;
+begin
+  Result:='';
+  if aList.count>i then
+    Result:=aList[i];
+end;
+
+function TParameters.IsParameter(const s: string): boolean;
+begin
+  Result:=false;
+  if length(s)<=1 then exit;
+  if copy(s,1,1)='-' then Result:=true;
+end;
+
+function TParameters.ParamsToStrList: TStringList;
+var i : integer;
+begin
+  Result:=TStringList.Create;
+  try
+    for i:=1 to ParamCount do
+      Result.Add(ParamStr(i));
+  except
+    Result.Free;
+    raise;
+  end;
+end;
+
+procedure TParameters.Parse;
+var fList : TStringList;
+    tmp : string;
+    i : integer;
+begin
+  fList:=ParamsToStrList;
+  try
+    i:=0;
+    while i<fList.Count do
+    begin
+      tmp:=fList[i];
+      Messages.DoVerbose(Format('parsing parameter ''%s''',[tmp]));
+      if IsParameter(tmp) then
+      begin
+        if ((tmp='--help') or (tmp='-h') or (tmp='-?')) then
+          fHelp:=true
+        else if ((tmp='--version') or (tmp='-V')) then
+          fVersion:=true
+        else if ((tmp='--verbose') or (tmp='-v')) then
+          fVerbose:=true
+        else if ((tmp='-i') or (tmp='--input')) then
+          ParseInputFiles(fList,i,tmp)
+        else if ((tmp='-o') or (tmp='--output')) then
+          ParseOutputFile(fList,i,tmp)
+        else if (tmp='-of') then
+          ParseOutputFormat(fList,i,tmp)
+        else if ((tmp='-a') or (tmp='--arch')) then
+          ParseArchitecture(fList,i,tmp)
+        else
+          raise EUnknownParameterException.Create(tmp);
+      end
+      else
+        if copy(tmp,1,1)='@' then
+          ParseConfigFile(fList,i,tmp)
+      else
+        fInputFiles.Add(tmp); //assume it is an input file
+      inc(i);
+    end;
+  finally
+    fList.Free;
+  end;
+end;
+
+constructor TParameters.Create;
+begin
+  fHelp:=false;
+  fVersion:=false;
+  fVerbose:=false;
+  fInputFiles:=TStringList.Create;
+  fOutputFile:='';
+  fTarget.machine:=mtnone;
+  fTarget.objformat:=ofnone;
+end;
+
+destructor TParameters.Destroy;
+begin
+  fInputFiles.Free;
+end;
+
+end.

+ 0 - 38
utils/fpcres/resptrs.as

@@ -1,38 +0,0 @@
-.section fpc.resptrs, "a", @progbits
-        .balign 4
-.globl  FPC_RESSYMBOL
-        .type FPC_RESSYMBOL,@object
-FPC_RESSYMBOL:
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-        .long 0
-

+ 107 - 0
utils/fpcres/sourcehandler.pas

@@ -0,0 +1,107 @@
+{
+
+    FPCRes - Free Pascal Resource Converter
+    Part of the Free Pascal distribution
+    Copyright (C) 2008 by Giulio Bernardi
+
+    Source files handling
+
+    See the file COPYING, 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.
+}
+
+unit sourcehandler;
+
+{$MODE OBJFPC} {$H+}
+
+interface
+
+uses
+  Classes, SysUtils, resource;
+
+type
+  ESourceFilesException = class(Exception);
+  ECantOpenFileException = class(ESourceFilesException);
+  EUnknownInputFormatException = class(ESourceFilesException);
+  
+type
+
+  { TSourceFiles }
+
+  TSourceFiles = class
+  private
+    fFileList : TStringList;
+    fStreamList : TFPList;
+  protected
+  public
+    constructor Create;
+    destructor Destroy; override;
+    procedure Load(aResources : TResources);
+    property FileList : TStringList read fFileList;
+  end;
+  
+implementation
+
+uses msghandler;
+
+{ TSourceFiles }
+
+constructor TSourceFiles.Create;
+begin
+  fFileList:=TStringList.Create;
+  fStreamList:=TFPList.Create;
+end;
+
+destructor TSourceFiles.Destroy;
+var i : integer;
+begin
+  fFileList.Free;
+  for i:=0 to fStreamList.Count-1 do
+    TStream(fStreamList[i]).Free;
+  fStreamList.Free;
+end;
+
+procedure TSourceFiles.Load(aResources: TResources);
+var aReader : TAbstractResourceReader;
+    aStream : TFileStream;
+    i : integer;
+    tmpres : TResources;
+begin
+  tmpres:=TResources.Create;
+  try
+    for i:=0 to fFileList.Count-1 do
+    begin
+      Messages.DoVerbose(Format('Trying to open file %s...',[fFileList[i]]));
+      try
+        aStream:=TFileStream.Create(fFileList[i],fmOpenRead or fmShareDenyWrite);
+      except
+        raise ECantOpenFileException.Create(fFileList[i]);
+      end;
+      fStreamList.Add(aStream);
+      try
+        aReader:=TResources.FindReader(aStream);
+      except
+        raise EUnknownInputFormatException.Create(fFileList[i]);
+      end;
+      Messages.DoVerbose(Format('Chosen reader: %s',[aReader.Description]));
+      try
+        Messages.DoVerbose('Reading resource information...');
+        tmpres.LoadFromStream(aStream,aReader);
+        aResources.MoveFrom(tmpres);
+        Messages.DoVerbose('Resource information read');
+      finally
+        aReader.Free;
+      end;
+    end;
+    Messages.DoVerbose(Format('%d resources read.',[aResources.Count]));
+  finally
+    tmpres.Free;
+  end;
+end;
+
+end.
+

+ 179 - 0
utils/fpcres/target.pas

@@ -0,0 +1,179 @@
+{
+
+    FPCRes - Free Pascal Resource Converter
+    Part of the Free Pascal distribution
+    Copyright (C) 2008 by Giulio Bernardi
+
+    Target selection and definitions
+
+    See the file COPYING, 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.
+}
+
+unit target;
+
+{$MODE OBJFPC}
+
+interface
+
+type
+  TMachineType = (mtnone, mti386,mtx86_64,mtppc,mtppc64,mtarm,mtarmeb,mtm68k,
+                  mtsparc,mtalpha,mtia64,mtBigEndian,mtLittleEndian);
+  TMachineTypes = set of TMachineType;
+
+  TObjFormat = (ofNone, ofRes, ofElf, ofCoff, ofMachO, ofExt);
+  TObjFormats = set of TObjFormat;
+  
+
+  TMachineInfo = record
+    name : string;
+    formats : TObjFormats;
+  end;
+  
+  TFormatInfo = record
+    name : string;
+    ext : string;
+    machines : TMachineTypes;
+  end;
+
+  TResTarget = record
+    machine : TMachineType;
+    objformat : TObjFormat;
+  end;
+
+function GetDefaultMachineForFormat(aFormat : TObjFormat) : TMachineType;
+function TargetToStr(const aTarget : TResTarget) : string;
+function MachineToStr(const aMachine : TMachineType) : string;
+function ObjFormatToStr(const aFormat : TObjFormat) : string;
+
+var
+  Machines : array[TMachineType] of TMachineInfo =
+  (
+    (name : '';             formats : [ofRes]),                  //mtnone
+    (name : 'i386';         formats : [ofElf, ofCoff, ofMachO]), //mti386
+    (name : 'x86_64';       formats : [ofElf, ofCoff, ofMachO]), //mtx86_64
+    (name : 'powerpc';      formats : [ofElf, ofMachO]),         //mtppc
+    (name : 'powerpc64';    formats : [ofElf, ofMachO]),         //mtppc64
+    (name : 'arm';          formats : [ofElf, ofCoff]),          //mtarm
+    (name : 'armeb';        formats : [ofElf]),                  //mtarmeb
+    (name : 'm68k';         formats : [ofElf]),                  //mtm68k
+    (name : 'sparc';        formats : [ofElf]),                  //mtsparc
+    (name : 'alpha';        formats : [ofElf]),                  //mtalpha
+    (name : 'ia64';         formats : [ofElf]),                  //mtia64
+    (name : 'bigendian';    formats : [ofExt]),                  //mtBigEndian
+    (name : 'littleendian'; formats : [ofExt])                   //mtLittleEndian
+  );
+  
+  ObjFormats : array[TObjFormat] of TFormatInfo =
+  (
+    (name : '';         ext : '';        machines : []),
+    (name : 'res';      ext : '.res';    machines : [mtnone]),
+    (name : 'elf';      ext : '.or';     machines : [mti386,mtx86_64,mtppc,
+                                                     mtppc64,mtarm,mtarmeb,
+                                                     mtm68k,mtsparc,mtalpha,
+                                                     mtia64]),
+    (name : 'coff';     ext : '.o';      machines : [mti386,mtx86_64,mtarm]),
+    (name : 'mach-o';   ext : '.or';     machines : [mti386,mtx86_64,mtppc,
+                                                     mtppc64]),
+    (name : 'external'; ext : '.fpcres'; machines : [mtBigEndian,mtLittleEndian])
+  );
+
+
+  CurrentTarget : TResTarget =
+  (
+  {$IFDEF CPUI386}
+    machine : mti386;
+  {$ELSE}
+  {$IFDEF CPUX86_64}
+    machine : mtx86_64;
+  {$ELSE}
+  {$IFDEF CPUPOWERPC32}
+    machine : mtppc;
+  {$ELSE}
+  {$IFDEF CPUPOWERPC64}
+    machine : mtppc64;
+  {$ELSE}
+  {$IFDEF CPUARM}
+    {$IFDEF ENDIAN_LITTLE}
+    machine : mtarm;
+    {$ELSE}
+    machine : mtarmeb;
+    {$ENDIF}
+  {$ELSE}
+  {$IFDEF CPU68K}
+    machine : mtm68k;
+  {$ELSE}
+  {$IFDEF CPUSPARC}
+    machine : mtsparc;
+  {$ELSE}
+  {$IFDEF CPUALPHA}
+    machine : mtalpha;
+  {$ELSE}
+  {$IFDEF CPUIA64}
+    machine : mtia64;
+  {$ELSE}
+    machine : mti386;  //default i386
+  {$ENDIF}
+  {$ENDIF}
+  {$ENDIF}
+  {$ENDIF}
+  {$ENDIF}
+  {$ENDIF}
+  {$ENDIF}
+  {$ENDIF}
+  {$ENDIF}
+
+  {$IFDEF WINDOWS}
+    objformat : ofCoff;
+  {$ELSE}
+    {$IFDEF DARWIN}
+      objformat : ofMachO;
+    {$ELSE}
+      objformat : ofElf;
+    {$ENDIF}
+  {$ENDIF}
+  );
+
+
+implementation
+
+function GetDefaultMachineForFormat(aFormat : TObjFormat) : TMachineType;
+begin
+  case aFormat of
+    ofNone : Result:=mtnone;
+    ofRes  : Result:=mtnone;
+    ofElf  : Result:=mti386;
+    ofCoff : Result:=mti386;
+    ofMachO: Result:=mti386;
+    {$IFDEF ENDIAN_BIG}
+    ofExt  : Result:=mtBigEndian;
+    {$ELSE}
+    ofExt  : Result:=mtLittleEndian;
+    {$ENDIF}
+  end;
+end;
+
+function MachineToStr(const aMachine : TMachineType) : string;
+begin
+  Result:=Machines[aMachine].name;
+end;
+
+function ObjFormatToStr(const aFormat : TObjFormat) : string;
+begin
+  Result:=ObjFormats[aFormat].name;
+end;
+
+function TargetToStr(const aTarget : TResTarget) : string;
+var s1, s2 : string;
+begin
+  s1:=MachineToStr(aTarget.machine);
+  s2:=ObjFormatToStr(aTarget.objformat);
+  if (s1='') or (s2='') then Result:=s1+s2
+  else Result:=s1+' - '+s2;
+end;
+
+end.