Split the build program in several files.

Renamed it 'winebuild' to avoid possible conflicts.
Cleaned up command-line parsing.
Make it understand -fPIC instead of -pic.
Merged call16.s and call32.s generated files.
This commit is contained in:
Alexandre Julliard 2000-06-23 20:15:35 +00:00
parent 22752323c5
commit e482eebf2f
20 changed files with 3561 additions and 3420 deletions

View File

@ -54,7 +54,7 @@ LINT = @LINT@
LINTFLAGS = @LINTFLAGS@
ALLLINTFLAGS = $(LINTFLAGS) $(DEFS) $(OPTIONS) $(DIVINCL)
WINAPI_CHECK = $(TOPSRCDIR)/tools/winapi_check/winapi_check
BUILD = $(TOPOBJDIR)/tools/build
BUILD = $(TOPOBJDIR)/tools/winebuild/winebuild
MAKEDEP = $(TOPOBJDIR)/tools/makedep
WRC = $(TOPOBJDIR)/tools/wrc/wrc
WRCFLAGS = -c -s -p $*
@ -183,10 +183,10 @@ DLLS = \
$(WRC) $(WRCFLAGS) $(WRCEXTRA) -bnh $<
.spec.spec.c:
$(BUILD) @BUILDFLAGS@ -o $@ -spec $<
$(BUILD) @DLLFLAGS@ -o $@ -spec $<
.c.glue.c:
$(BUILD) @BUILDFLAGS@ -o $@ -glue $<
$(BUILD) @DLLFLAGS@ -o $@ -glue $<
.c.ln:
$(LINT) -c $(ALLLINTFLAGS) $< || ( $(RM) $@ && exit 1 )
@ -212,10 +212,10 @@ $(WMC) check_wmc:
$(MAKEDEP) check_makedep:
cd $(TOPOBJDIR)/tools && $(MAKE) makedep
# Rule to rebuild the 'build' program
# Rule to rebuild the 'winebuild' program
$(BUILD) checkbuild:
cd $(TOPOBJDIR)/tools && $(MAKE) build
$(BUILD) check_winebuild:
cd $(TOPOBJDIR)/tools/winebuild && $(MAKE) winebuild
# Rule for main module

190
configure vendored
View File

@ -4484,30 +4484,28 @@ echo "$ac_t""$ac_cv_c_dll_netbsd" 1>&6
fi
DLLFLAGS=""
BUILDFLAGS=""
if test "$LIBEXT" = "so"; then
BUILDFLAGS="-pic"
DLLFLAGS="-fPIC"
DLL_LINK="-L\$(DLLDIR) \$(IMPORTS:%=-l%) -L\$(TOPOBJDIR) -lwine"
else
DLL_LINK="-L\$(DLLDIR) \$(DLLS:%=-l%) -L\$(TOPOBJDIR) -lwine \$(X_LIBS) \$(XLIB)"
echo $ac_n "checking whether the linker supports --[no]-whole-archive (Linux)""... $ac_c" 1>&6
echo "configure:4497: checking whether the linker supports --[no]-whole-archive (Linux)" >&5
echo "configure:4495: checking whether the linker supports --[no]-whole-archive (Linux)" >&5
if eval "test \"`echo '$''{'ac_cv_c_whole_archive'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
saved_cflags=$CFLAGS
CFLAGS="$CFLAGS -Wl,--whole-archive -Wl,--no-whole-archive"
cat > conftest.$ac_ext <<EOF
#line 4504 "configure"
#line 4502 "configure"
#include "confdefs.h"
int main() {
return 1
; return 0; }
EOF
if { (eval echo configure:4511: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:4509: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_c_whole_archive="yes"
else
@ -4527,21 +4525,21 @@ echo "$ac_t""$ac_cv_c_whole_archive" 1>&6
DLL_LINK="-Wl,--whole-archive $DLL_LINK -Wl,--no-whole-archive"
else
echo $ac_n "checking whether the linker supports -z {all,default}extract (Linux)""... $ac_c" 1>&6
echo "configure:4531: checking whether the linker supports -z {all,default}extract (Linux)" >&5
echo "configure:4529: checking whether the linker supports -z {all,default}extract (Linux)" >&5
if eval "test \"`echo '$''{'ac_cv_c_allextract'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
saved_cflags=$CFLAGS
CFLAGS="$CFLAGS -Wl,-z,allextract -Wl,-z,defaultextract"
cat > conftest.$ac_ext <<EOF
#line 4538 "configure"
#line 4536 "configure"
#include "confdefs.h"
int main() {
return 1
; return 0; }
EOF
if { (eval echo configure:4545: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:4543: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_c_allextract="yes"
else
@ -4569,10 +4567,9 @@ fi
wine_cv_libc_reentrant=no
echo $ac_n "checking "for reentrant libc: __errno_location"""... $ac_c" 1>&6
echo "configure:4576: checking "for reentrant libc: __errno_location"" >&5
echo "configure:4573: checking "for reentrant libc: __errno_location"" >&5
if eval "test \"`echo '$''{'wine_cv_libc_r__errno_location'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -4580,14 +4577,14 @@ else
wine_cv_libc_r__errno_location=yes
else
cat > conftest.$ac_ext <<EOF
#line 4584 "configure"
#line 4581 "configure"
#include "confdefs.h"
int myerrno = 0;
char buf[256];
int *__errno_location(){return &myerrno;}
main(){connect(0,buf,255); exit(!myerrno);}
EOF
if { (eval echo configure:4591: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
if { (eval echo configure:4588: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
wine_cv_libc_r__errno_location=yes
else
@ -4612,7 +4609,7 @@ EOF
wine_cv_libc_reentrant=__errno_location
fi
echo $ac_n "checking "for reentrant libc: __error"""... $ac_c" 1>&6
echo "configure:4616: checking "for reentrant libc: __error"" >&5
echo "configure:4613: checking "for reentrant libc: __error"" >&5
if eval "test \"`echo '$''{'wine_cv_libc_r__error'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -4620,14 +4617,14 @@ else
wine_cv_libc_r__error=yes
else
cat > conftest.$ac_ext <<EOF
#line 4624 "configure"
#line 4621 "configure"
#include "confdefs.h"
int myerrno = 0;
char buf[256];
int *__error(){return &myerrno;}
main(){connect(0,buf,255); exit(!myerrno);}
EOF
if { (eval echo configure:4631: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
if { (eval echo configure:4628: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
wine_cv_libc_r__error=yes
else
@ -4652,7 +4649,7 @@ EOF
wine_cv_libc_reentrant=__error
fi
echo $ac_n "checking "for reentrant libc: ___errno"""... $ac_c" 1>&6
echo "configure:4656: checking "for reentrant libc: ___errno"" >&5
echo "configure:4653: checking "for reentrant libc: ___errno"" >&5
if eval "test \"`echo '$''{'wine_cv_libc_r___errno'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -4660,14 +4657,14 @@ else
wine_cv_libc_r___errno=yes
else
cat > conftest.$ac_ext <<EOF
#line 4664 "configure"
#line 4661 "configure"
#include "confdefs.h"
int myerrno = 0;
char buf[256];
int *___errno(){return &myerrno;}
main(){connect(0,buf,255); exit(!myerrno);}
EOF
if { (eval echo configure:4671: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
if { (eval echo configure:4668: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
wine_cv_libc_r___errno=yes
else
@ -4692,7 +4689,7 @@ EOF
wine_cv_libc_reentrant=___errno
fi
echo $ac_n "checking "for reentrant libc: __thr_errno"""... $ac_c" 1>&6
echo "configure:4696: checking "for reentrant libc: __thr_errno"" >&5
echo "configure:4693: checking "for reentrant libc: __thr_errno"" >&5
if eval "test \"`echo '$''{'wine_cv_libc_r__thr_errno'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -4700,14 +4697,14 @@ else
wine_cv_libc_r__thr_errno=yes
else
cat > conftest.$ac_ext <<EOF
#line 4704 "configure"
#line 4701 "configure"
#include "confdefs.h"
int myerrno = 0;
char buf[256];
int *__thr_errno(){return &myerrno;}
main(){connect(0,buf,255); exit(!myerrno);}
EOF
if { (eval echo configure:4711: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
if { (eval echo configure:4708: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
wine_cv_libc_r__thr_errno=yes
else
@ -4743,7 +4740,7 @@ fi
if test "$have_x" = "yes" -a "$wine_cv_libc_reentrant" != "no"
then
echo $ac_n "checking "for reentrant X libraries"""... $ac_c" 1>&6
echo "configure:4747: checking "for reentrant X libraries"" >&5
echo "configure:4744: checking "for reentrant X libraries"" >&5
if eval "test \"`echo '$''{'wine_cv_x_reentrant'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -4789,14 +4786,14 @@ fi
echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
echo "configure:4793: checking whether byte ordering is bigendian" >&5
echo "configure:4790: checking whether byte ordering is bigendian" >&5
if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_cv_c_bigendian=unknown
# See if sys/param.h defines the BYTE_ORDER macro.
cat > conftest.$ac_ext <<EOF
#line 4800 "configure"
#line 4797 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/param.h>
@ -4807,11 +4804,11 @@ int main() {
#endif
; return 0; }
EOF
if { (eval echo configure:4811: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:4808: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
# It does; now see whether it defined to BIG_ENDIAN or not.
cat > conftest.$ac_ext <<EOF
#line 4815 "configure"
#line 4812 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/param.h>
@ -4822,7 +4819,7 @@ int main() {
#endif
; return 0; }
EOF
if { (eval echo configure:4826: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:4823: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_bigendian=yes
else
@ -4842,7 +4839,7 @@ if test "$cross_compiling" = yes; then
{ echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
else
cat > conftest.$ac_ext <<EOF
#line 4846 "configure"
#line 4843 "configure"
#include "confdefs.h"
main () {
/* Are we little or big endian? From Harbison&Steele. */
@ -4855,7 +4852,7 @@ main () {
exit (u.c[sizeof (long) - 1] == 1);
}
EOF
if { (eval echo configure:4859: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
if { (eval echo configure:4856: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_c_bigendian=no
else
@ -4883,19 +4880,19 @@ fi
# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
# for constant arguments. Useless!
echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6
echo "configure:4887: checking for working alloca.h" >&5
echo "configure:4884: checking for working alloca.h" >&5
if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 4892 "configure"
#line 4889 "configure"
#include "confdefs.h"
#include <alloca.h>
int main() {
void *p = alloca(2 * sizeof(int));
; return 0; }
EOF
if { (eval echo configure:4899: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:4896: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_header_alloca_h=yes
else
@ -4916,12 +4913,12 @@ EOF
fi
echo $ac_n "checking for alloca""... $ac_c" 1>&6
echo "configure:4920: checking for alloca" >&5
echo "configure:4917: checking for alloca" >&5
if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 4925 "configure"
#line 4922 "configure"
#include "confdefs.h"
#ifdef __GNUC__
@ -4949,7 +4946,7 @@ int main() {
char *p = (char *) alloca(1);
; return 0; }
EOF
if { (eval echo configure:4953: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:4950: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_func_alloca_works=yes
else
@ -4981,12 +4978,12 @@ EOF
echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
echo "configure:4985: checking whether alloca needs Cray hooks" >&5
echo "configure:4982: checking whether alloca needs Cray hooks" >&5
if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 4990 "configure"
#line 4987 "configure"
#include "confdefs.h"
#if defined(CRAY) && ! defined(CRAY2)
webecray
@ -5011,12 +5008,12 @@ echo "$ac_t""$ac_cv_os_cray" 1>&6
if test $ac_cv_os_cray = yes; then
for ac_func in _getb67 GETB67 getb67; do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:5015: checking for $ac_func" >&5
echo "configure:5012: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 5020 "configure"
#line 5017 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@ -5039,7 +5036,7 @@ $ac_func();
; return 0; }
EOF
if { (eval echo configure:5043: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:5040: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@ -5066,7 +5063,7 @@ done
fi
echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
echo "configure:5070: checking stack direction for C alloca" >&5
echo "configure:5067: checking stack direction for C alloca" >&5
if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -5074,7 +5071,7 @@ else
ac_cv_c_stack_direction=0
else
cat > conftest.$ac_ext <<EOF
#line 5078 "configure"
#line 5075 "configure"
#include "confdefs.h"
find_stack_direction ()
{
@ -5093,7 +5090,7 @@ main ()
exit (find_stack_direction() < 0);
}
EOF
if { (eval echo configure:5097: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
if { (eval echo configure:5094: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_c_stack_direction=1
else
@ -5145,12 +5142,12 @@ for ac_func in \
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:5149: checking for $ac_func" >&5
echo "configure:5146: checking for $ac_func" >&5
if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 5154 "configure"
#line 5151 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@ -5173,7 +5170,7 @@ $ac_func();
; return 0; }
EOF
if { (eval echo configure:5177: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
if { (eval echo configure:5174: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@ -5250,17 +5247,17 @@ for ac_hdr in \
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
echo "configure:5254: checking for $ac_hdr" >&5
echo "configure:5251: checking for $ac_hdr" >&5
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 5259 "configure"
#line 5256 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:5264: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:5261: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@ -5287,12 +5284,12 @@ fi
done
echo $ac_n "checking whether stat file-mode macros are broken""... $ac_c" 1>&6
echo "configure:5291: checking whether stat file-mode macros are broken" >&5
echo "configure:5288: checking whether stat file-mode macros are broken" >&5
if eval "test \"`echo '$''{'ac_cv_header_stat_broken'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 5296 "configure"
#line 5293 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/stat.h>
@ -5345,12 +5342,12 @@ fi
echo $ac_n "checking for working const""... $ac_c" 1>&6
echo "configure:5349: checking for working const" >&5
echo "configure:5346: checking for working const" >&5
if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 5354 "configure"
#line 5351 "configure"
#include "confdefs.h"
int main() {
@ -5399,7 +5396,7 @@ ccp = (char const *const *) p;
; return 0; }
EOF
if { (eval echo configure:5403: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:5400: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_const=yes
else
@ -5420,21 +5417,21 @@ EOF
fi
echo $ac_n "checking for inline""... $ac_c" 1>&6
echo "configure:5424: checking for inline" >&5
echo "configure:5421: checking for inline" >&5
if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
ac_cv_c_inline=no
for ac_kw in inline __inline__ __inline; do
cat > conftest.$ac_ext <<EOF
#line 5431 "configure"
#line 5428 "configure"
#include "confdefs.h"
int main() {
} int $ac_kw foo() {
; return 0; }
EOF
if { (eval echo configure:5438: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:5435: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_inline=$ac_kw; break
else
@ -5460,12 +5457,12 @@ EOF
esac
echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
echo "configure:5464: checking for ANSI C header files" >&5
echo "configure:5461: checking for ANSI C header files" >&5
if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 5469 "configure"
#line 5466 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <stdarg.h>
@ -5473,7 +5470,7 @@ else
#include <float.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
{ (eval echo configure:5477: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
{ (eval echo configure:5474: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@ -5490,7 +5487,7 @@ rm -f conftest*
if test $ac_cv_header_stdc = yes; then
# SunOS 4.x string.h does not declare mem*, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
#line 5494 "configure"
#line 5491 "configure"
#include "confdefs.h"
#include <string.h>
EOF
@ -5508,7 +5505,7 @@ fi
if test $ac_cv_header_stdc = yes; then
# ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
#line 5512 "configure"
#line 5509 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
@ -5529,7 +5526,7 @@ if test "$cross_compiling" = yes; then
:
else
cat > conftest.$ac_ext <<EOF
#line 5533 "configure"
#line 5530 "configure"
#include "confdefs.h"
#include <ctype.h>
#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@ -5540,7 +5537,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
exit (0); }
EOF
if { (eval echo configure:5544: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
if { (eval echo configure:5541: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
:
else
@ -5564,12 +5561,12 @@ EOF
fi
echo $ac_n "checking for size_t""... $ac_c" 1>&6
echo "configure:5568: checking for size_t" >&5
echo "configure:5565: checking for size_t" >&5
if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 5573 "configure"
#line 5570 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
@ -5597,7 +5594,7 @@ EOF
fi
echo $ac_n "checking size of long long""... $ac_c" 1>&6
echo "configure:5601: checking size of long long" >&5
echo "configure:5598: checking size of long long" >&5
if eval "test \"`echo '$''{'ac_cv_sizeof_long_long'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -5605,7 +5602,7 @@ else
ac_cv_sizeof_long_long=0
else
cat > conftest.$ac_ext <<EOF
#line 5609 "configure"
#line 5606 "configure"
#include "confdefs.h"
#include <stdio.h>
main()
@ -5616,7 +5613,7 @@ main()
exit(0);
}
EOF
if { (eval echo configure:5620: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
if { (eval echo configure:5617: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_sizeof_long_long=`cat conftestval`
else
@ -5639,12 +5636,12 @@ EOF
if test "$ac_cv_header_linux_joystick_h" = "yes"
then
echo $ac_n "checking "whether linux/joystick.h uses the Linux 2.2+ API"""... $ac_c" 1>&6
echo "configure:5643: checking "whether linux/joystick.h uses the Linux 2.2+ API"" >&5
echo "configure:5640: checking "whether linux/joystick.h uses the Linux 2.2+ API"" >&5
if eval "test \"`echo '$''{'wine_cv_linux_joystick_22_api'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 5648 "configure"
#line 5645 "configure"
#include "confdefs.h"
#include <sys/ioctl.h>
@ -5659,7 +5656,7 @@ int main() {
/*empty*/
; return 0; }
EOF
if { (eval echo configure:5663: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:5660: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
wine_cv_linux_joystick_22_api=yes
else
@ -5686,12 +5683,12 @@ fi
if test "$ac_cv_header_sys_vfs_h" = "yes"
then
echo $ac_n "checking "whether sys/vfs.h defines statfs"""... $ac_c" 1>&6
echo "configure:5690: checking "whether sys/vfs.h defines statfs"" >&5
echo "configure:5687: checking "whether sys/vfs.h defines statfs"" >&5
if eval "test \"`echo '$''{'wine_cv_sys_vfs_has_statfs'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 5695 "configure"
#line 5692 "configure"
#include "confdefs.h"
#include <sys/types.h>
@ -5708,7 +5705,7 @@ int main() {
; return 0; }
EOF
if { (eval echo configure:5712: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:5709: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
wine_cv_sys_vfs_has_statfs=yes
else
@ -5735,12 +5732,12 @@ fi
if test "$ac_cv_header_sys_statfs_h" = "yes"
then
echo $ac_n "checking "whether sys/statfs.h defines statfs"""... $ac_c" 1>&6
echo "configure:5739: checking "whether sys/statfs.h defines statfs"" >&5
echo "configure:5736: checking "whether sys/statfs.h defines statfs"" >&5
if eval "test \"`echo '$''{'wine_cv_sys_statfs_has_statfs'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 5744 "configure"
#line 5741 "configure"
#include "confdefs.h"
#include <sys/types.h>
@ -5755,7 +5752,7 @@ int main() {
; return 0; }
EOF
if { (eval echo configure:5759: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:5756: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
wine_cv_sys_statfs_has_statfs=yes
else
@ -5782,12 +5779,12 @@ fi
if test "$ac_cv_header_sys_mount_h" = "yes"
then
echo $ac_n "checking "whether sys/mount.h defines statfs"""... $ac_c" 1>&6
echo "configure:5786: checking "whether sys/mount.h defines statfs"" >&5
echo "configure:5783: checking "whether sys/mount.h defines statfs"" >&5
if eval "test \"`echo '$''{'wine_cv_sys_mount_has_statfs'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 5791 "configure"
#line 5788 "configure"
#include "confdefs.h"
#include <sys/types.h>
@ -5802,7 +5799,7 @@ int main() {
; return 0; }
EOF
if { (eval echo configure:5806: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:5803: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
wine_cv_sys_mount_has_statfs=yes
else
@ -5828,7 +5825,7 @@ fi
echo $ac_n "checking "for statfs.f_bfree"""... $ac_c" 1>&6
echo "configure:5832: checking "for statfs.f_bfree"" >&5
echo "configure:5829: checking "for statfs.f_bfree"" >&5
if eval "test \"`echo '$''{'wine_cv_statfs_bfree'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -5837,7 +5834,7 @@ else
wine_cv_statfs_bfree=no
else
cat > conftest.$ac_ext <<EOF
#line 5841 "configure"
#line 5838 "configure"
#include "confdefs.h"
#include <sys/types.h>
@ -5864,7 +5861,7 @@ int main() {
; return 0; }
EOF
if { (eval echo configure:5868: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:5865: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
wine_cv_statfs_bfree=yes
else
@ -5888,7 +5885,7 @@ EOF
fi
echo $ac_n "checking "for statfs.f_bavail"""... $ac_c" 1>&6
echo "configure:5892: checking "for statfs.f_bavail"" >&5
echo "configure:5889: checking "for statfs.f_bavail"" >&5
if eval "test \"`echo '$''{'wine_cv_statfs_bavail'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
@ -5897,7 +5894,7 @@ else
wine_cv_statfs_bavail=no
else
cat > conftest.$ac_ext <<EOF
#line 5901 "configure"
#line 5898 "configure"
#include "confdefs.h"
#include <sys/types.h>
@ -5924,7 +5921,7 @@ int main() {
; return 0; }
EOF
if { (eval echo configure:5928: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:5925: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
wine_cv_statfs_bavail=yes
else
@ -5949,12 +5946,12 @@ fi
echo $ac_n "checking "for msg_accrights in struct msghdr"""... $ac_c" 1>&6
echo "configure:5953: checking "for msg_accrights in struct msghdr"" >&5
echo "configure:5950: checking "for msg_accrights in struct msghdr"" >&5
if eval "test \"`echo '$''{'ac_cv_c_msg_accrights'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 5958 "configure"
#line 5955 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/socket.h>
@ -5962,7 +5959,7 @@ int main() {
struct msghdr hdr; hdr.msg_accrights=0
; return 0; }
EOF
if { (eval echo configure:5966: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:5963: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_msg_accrights="yes"
else
@ -5985,12 +5982,12 @@ fi
echo $ac_n "checking "for sun_len in struct sockaddr_un"""... $ac_c" 1>&6
echo "configure:5989: checking "for sun_len in struct sockaddr_un"" >&5
echo "configure:5986: checking "for sun_len in struct sockaddr_un"" >&5
if eval "test \"`echo '$''{'ac_cv_c_sun_len'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 5994 "configure"
#line 5991 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/socket.h>
@ -5999,7 +5996,7 @@ int main() {
static struct sockaddr_un addr; addr.sun_len = 1
; return 0; }
EOF
if { (eval echo configure:6003: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
if { (eval echo configure:6000: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_sun_len="yes"
else
@ -6022,12 +6019,12 @@ fi
echo $ac_n "checking "whether we need to define __i386__"""... $ac_c" 1>&6
echo "configure:6026: checking "whether we need to define __i386__"" >&5
echo "configure:6023: checking "whether we need to define __i386__"" >&5
if eval "test \"`echo '$''{'ac_cv_cpp_def_i386'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
#line 6031 "configure"
#line 6028 "configure"
#include "confdefs.h"
#if (defined(i386) || defined(__i386)) && !defined(__i386__)
yes
@ -6284,6 +6281,7 @@ scheduler/Makefile
server/Makefile
tools/Makefile
tools/cvdump/Makefile
tools/winebuild/Makefile
tools/wrc/Makefile
tools/wmc/Makefile
tsx11/Makefile
@ -6352,7 +6350,6 @@ s%@DGA_SRCS@%$DGA_SRCS%g
s%@DGA2_SRCS@%$DGA2_SRCS%g
s%@MESA_SRCS@%$MESA_SRCS%g
s%@DLL_LINK@%$DLL_LINK%g
s%@BUILDFLAGS@%$BUILDFLAGS%g
s%@DLLFLAGS@%$DLLFLAGS%g
s%@LDSHARED@%$LDSHARED%g
s%@LIBEXT@%$LIBEXT%g
@ -6517,6 +6514,7 @@ scheduler/Makefile
server/Makefile
tools/Makefile
tools/cvdump/Makefile
tools/winebuild/Makefile
tools/wrc/Makefile
tools/wmc/Makefile
tsx11/Makefile

View File

@ -493,10 +493,8 @@ then
fi
DLLFLAGS=""
BUILDFLAGS=""
if test "$LIBEXT" = "so"; then
BUILDFLAGS="-pic"
DLLFLAGS="-fPIC"
DLL_LINK="-L\$(DLLDIR) \$(IMPORTS:%=-l%) -L\$(TOPOBJDIR) -lwine"
else
@ -527,7 +525,6 @@ else
fi
AC_SUBST(DLL_LINK)
AC_SUBST(BUILDFLAGS)
AC_SUBST(DLLFLAGS)
AC_SUBST(LDSHARED)
AC_SUBST(LIBEXT)
@ -1083,6 +1080,7 @@ scheduler/Makefile
server/Makefile
tools/Makefile
tools/cvdump/Makefile
tools/winebuild/Makefile
tools/wrc/Makefile
tools/wmc/Makefile
tsx11/Makefile

View File

@ -1,3 +1,3 @@
Makefile
call16.s
asmrelay.s
thunk.glue.c

View File

@ -13,7 +13,7 @@ C_SRCS = \
thunk.c
GEN_ASM_SRCS = \
call16.s
asmrelay.s
GLUE = thunk.c
@ -21,7 +21,7 @@ all: $(MODULE).o
@MAKE_RULES@
call16.s: $(BUILD)
$(BUILD) @BUILDFLAGS@ -o $@ -call16
asmrelay.s: $(BUILD)
$(BUILD) @DLLFLAGS@ -o $@ -relay
### Dependencies:

View File

@ -1,2 +1 @@
Makefile
call32.s

View File

@ -12,14 +12,8 @@ C_SRCS = \
utthunk.c \
wowthunk.c
GEN_ASM_SRCS = \
call32.s
all: $(MODULE).o
@MAKE_RULES@
call32.s: $(BUILD)
$(BUILD) @BUILDFLAGS@ -o $@ -call32
### Dependencies:

View File

@ -1,5 +1,4 @@
Makefile
bin2res
build
fnt2bdf
makedep

View File

@ -4,17 +4,19 @@ TOPOBJDIR = ..
SRCDIR = @srcdir@
VPATH = @srcdir@
PROGRAMS = build makedep fnt2bdf bin2res
PROGRAMS = makedep fnt2bdf bin2res
MODULE = none
C_SRCS = build.c makedep.c fnt2bdf.c bin2res.c
C_SRCS = makedep.c fnt2bdf.c bin2res.c
SUBDIRS = \
cvdump \
winebuild \
wmc \
wrc
INSTALLSUBDIRS = \
winebuild \
wmc \
wrc
@ -24,13 +26,10 @@ EXTRASUBDIRS = \
winapi_check/win32 \
wineconf.libs
all: $(PROGRAMS) wmc wrc
all: $(PROGRAMS) winebuild wmc wrc
@MAKE_RULES@
build: build.o
$(CC) $(CFLAGS) -o build build.o
makedep: makedep.o
$(CC) $(CFLAGS) -o makedep makedep.o
@ -42,10 +41,9 @@ bin2res: bin2res.o
install:: $(PROGRAMS) $(INSTALLSUBDIRS:%=%/__install__)
[ -d $(bindir) ] || $(MKDIR) $(bindir)
$(INSTALL_PROGRAM) build $(bindir)/winebuild
$(INSTALL_PROGRAM) fnt2bdf $(bindir)/fnt2bdf
uninstall:: $(PROGRAMS) $(INSTALLSUBDIRS:%=%/__uninstall__)
$(RM) $(bindir)/winebuild $(bindir)/fnt2bdf
$(RM) $(bindir)/fnt2bdf
### Dependencies:

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,2 @@
Makefile
winebuild

View File

@ -0,0 +1,32 @@
DEFS = -D__WINE__
TOPSRCDIR = @top_srcdir@
TOPOBJDIR = ../..
SRCDIR = @srcdir@
VPATH = @srcdir@
PROGRAMS = winebuild
MODULE = none
C_SRCS = \
main.c \
parser.c \
relay.c \
spec16.c \
spec32.c \
utils.c
all: $(PROGRAMS)
@MAKE_RULES@
winebuild: $(OBJS)
$(CC) $(CFLAGS) -o winebuild $(OBJS)
install:: $(PROGRAMS)
[ -d $(bindir) ] || $(MKDIR) $(bindir)
$(INSTALL_PROGRAM) winebuild $(bindir)/winebuild
uninstall::
$(RM) $(bindir)/winebuild
### Dependencies:

View File

@ -4,10 +4,11 @@
name NAME
type win16|win32
[file WINFILENAME]
[base ORDINAL]
[mode dll|cuiexe|guiexe]
[heap SIZE]
[init FUNCTION]
[import DLL]
[rsrc PREFIX]
ORDINAL VARTYPE EXPORTNAME (DATA [DATA [DATA [...]]])
@ -31,7 +32,8 @@ General:
declarations are optional, but the default handler will print an error
message.
"base" gives the offset of the first ordinal; default is 0.
"mode" specifies whether it is the spec file for a dll or the main exe.
This is only valid for Win32 spec files.
"heap" is the size of the module local heap (only valid for Win16
modules); default is no local heap.
@ -47,6 +49,8 @@ is loaded. This is only valid for Win32 modules.
modules at the present). The import declaration can be present several
times.
"rsrc" specifies the prefix for the resource directory name.
Lines whose first character is a '#' will be ignored as comments.

174
tools/winebuild/build.h Normal file
View File

@ -0,0 +1,174 @@
/*
* Copyright 1993 Robert J. Amstadt
* Copyright 1995 Martin von Loewis
* Copyright 1995, 1996, 1997 Alexandre Julliard
* Copyright 1997 Eric Youngdale
* Copyright 1999 Ulrich Weigand
*/
#ifndef __WINE_BUILD_H
#define __WINE_BUILD_H
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#ifdef NEED_UNDERSCORE_PREFIX
# define PREFIX "_"
#else
# define PREFIX
#endif
#ifdef HAVE_ASM_STRING
# define STRING ".string"
#else
# define STRING ".ascii"
#endif
#if defined(__GNUC__) && !defined(__svr4__)
# define USE_STABS
#else
# undef USE_STABS
#endif
typedef enum
{
TYPE_BYTE, /* byte variable (Win16) */
TYPE_WORD, /* word variable (Win16) */
TYPE_LONG, /* long variable (Win16) */
TYPE_PASCAL_16, /* pascal function with 16-bit return (Win16) */
TYPE_PASCAL, /* pascal function with 32-bit return (Win16) */
TYPE_ABS, /* absolute value (Win16) */
TYPE_REGISTER, /* register function */
TYPE_INTERRUPT, /* interrupt handler function (Win16) */
TYPE_STUB, /* unimplemented stub */
TYPE_STDCALL, /* stdcall function (Win32) */
TYPE_CDECL, /* cdecl function (Win32) */
TYPE_VARARGS, /* varargs function (Win32) */
TYPE_EXTERN, /* external symbol (Win32) */
TYPE_FORWARD, /* forwarded function (Win32) */
TYPE_NBTYPES
} ORD_TYPE;
typedef enum
{
SPEC_INVALID,
SPEC_WIN16,
SPEC_WIN32
} SPEC_TYPE;
typedef enum
{
SPEC_MODE_DLL,
SPEC_MODE_GUIEXE,
SPEC_MODE_CUIEXE
} SPEC_MODE;
typedef struct
{
int n_values;
int *values;
} ORD_VARIABLE;
typedef struct
{
int n_args;
char arg_types[32];
char link_name[80];
} ORD_FUNCTION;
typedef struct
{
int value;
} ORD_ABS;
typedef struct
{
char link_name[80];
} ORD_EXTERN;
typedef struct
{
char link_name[80];
} ORD_FORWARD;
typedef struct
{
ORD_TYPE type;
int ordinal;
int offset;
int lineno;
char name[80];
union
{
ORD_VARIABLE var;
ORD_FUNCTION func;
ORD_ABS abs;
ORD_EXTERN ext;
ORD_FORWARD fwd;
} u;
} ORDDEF;
/* Offset of a structure field relative to the start of the struct */
#define STRUCTOFFSET(type,field) ((int)&((type *)0)->field)
/* Offset of register relative to the start of the CONTEXT struct */
#define CONTEXTOFFSET(reg) STRUCTOFFSET(CONTEXT86,reg)
/* Offset of register relative to the start of the STACK16FRAME struct */
#define STACK16OFFSET(reg) STRUCTOFFSET(STACK16FRAME,reg)
/* Offset of register relative to the start of the STACK32FRAME struct */
#define STACK32OFFSET(reg) STRUCTOFFSET(STACK32FRAME,reg)
/* Offset of the stack pointer relative to %fs:(0) */
#define STACKOFFSET (STRUCTOFFSET(TEB,cur_stack))
#define MAX_ORDINALS 2048
#define MAX_IMPORTS 16
/* global functions */
extern void *xmalloc (size_t size);
extern void *xrealloc (void *ptr, size_t size);
extern char *xstrdup( const char *str );
extern char *strupper(char *s);
extern void fatal_error( const char *msg, ... );
extern void dump_bytes( FILE *outfile, const unsigned char *data, int len, const char *label );
extern void BuildGlue( FILE *outfile, FILE *infile );
extern void BuildRelays( FILE *outfile );
extern void BuildSpec16File( FILE *outfile );
extern void BuildSpec32File( FILE *outfile );
extern SPEC_TYPE ParseTopLevel( FILE *file );
/* global variables */
extern int current_line;
extern int nb_entry_points;
extern int nb_names;
extern int nb_imports;
extern int Base;
extern int Limit;
extern int DLLHeapSize;
extern int UsePIC;
extern int debugging;
extern unsigned short code_selector;
extern unsigned short data_selector;
extern char DLLName[80];
extern char DLLFileName[80];
extern char DLLInitFunc[80];
extern char rsrc_name[80];
extern char *DLLImports[MAX_IMPORTS];
extern const char *input_file_name;
extern const char *output_file_name;
extern ORDDEF EntryPoints[MAX_ORDINALS];
extern ORDDEF *Ordinals[MAX_ORDINALS];
extern ORDDEF *Names[MAX_ORDINALS];
extern SPEC_MODE SpecMode;
#endif /* __WINE_BUILD_H */

221
tools/winebuild/main.c Normal file
View File

@ -0,0 +1,221 @@
/*
* Main function
*
* Copyright 1993 Robert J. Amstadt
* Copyright 1995 Martin von Loewis
* Copyright 1995, 1996, 1997 Alexandre Julliard
* Copyright 1997 Eric Youngdale
* Copyright 1999 Ulrich Weigand
*/
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include "winnt.h"
#include "build.h"
#ifdef __i386__
extern WORD __get_cs(void);
extern WORD __get_ds(void);
__ASM_GLOBAL_FUNC( __get_cs, "movw %cs,%ax\n\tret" );
__ASM_GLOBAL_FUNC( __get_ds, "movw %ds,%ax\n\tret" );
#else
static inline WORD __get_cs(void) { return 0; }
static inline WORD __get_ds(void) { return 0; }
#endif
ORDDEF EntryPoints[MAX_ORDINALS];
ORDDEF *Ordinals[MAX_ORDINALS];
ORDDEF *Names[MAX_ORDINALS];
SPEC_MODE SpecMode = SPEC_MODE_DLL;
int Base = MAX_ORDINALS;
int Limit = 0;
int DLLHeapSize = 0;
int UsePIC = 0;
int nb_entry_points = 0;
int nb_names = 0;
int nb_imports = 0;
int debugging = 1;
char DLLName[80];
char DLLFileName[80];
char DLLInitFunc[80];
char *DLLImports[MAX_IMPORTS];
char rsrc_name[80];
const char *input_file_name;
const char *output_file_name;
unsigned short code_selector;
unsigned short data_selector;
static FILE *input_file;
static FILE *output_file;
/* execution mode */
static enum { MODE_NONE, MODE_SPEC, MODE_GLUE, MODE_RELAY } exec_mode = MODE_NONE;
/* open the input file */
static void open_input( const char *name )
{
input_file_name = name;
if (!(input_file = fopen( name, "r" )))
{
fprintf( stderr, "Cannot open input file '%s'\n", name );
exit(1);
}
}
/* cleanup on program exit */
static void cleanup(void)
{
if (output_file_name) unlink( output_file_name );
}
/*******************************************************************
* command-line option handling
*/
struct option
{
const char *name;
int has_arg;
void (*func)();
const char *usage;
};
static void do_pic(void);
static void do_output( const char *arg );
static void do_usage(void);
static void do_spec( const char *arg );
static void do_glue( const char *arg );
static void do_relay(void);
static const struct option option_table[] =
{
{ "-fPIC", 0, do_pic, "-fPIC Generate PIC code" },
{ "-h", 0, do_usage, "-h Display this help message" },
{ "-o", 1, do_output, "-o name Set the output file name (default: stdout)" },
{ "-spec", 1, do_spec, "-spec file.spec Build a .c file from a spec file" },
{ "-glue", 1, do_glue, "-glue file.c Build the 16-bit glue for a .c file" },
{ "-relay", 0, do_relay, "-relay Build the relay assembly routines" },
{ NULL }
};
static void do_pic(void)
{
UsePIC = 1;
}
static void do_output( const char *arg )
{
if (!(output_file = fopen( arg, "w" )))
{
fprintf( stderr, "Unable to create output file '%s'\n", arg );
exit(1);
}
output_file_name = arg;
atexit( cleanup ); /* make sure we remove the output file on exit */
}
static void do_usage(void)
{
const struct option *opt;
fprintf( stderr, "Usage: winebuild [options]\n\n" );
fprintf( stderr, "Options:\n" );
for (opt = option_table; opt->name; opt++) fprintf( stderr, " %s\n", opt->usage );
fprintf( stderr, "\nExactly one of -spec, -glue or -relay must be specified.\n\n" );
exit(1);
}
static void do_spec( const char *arg )
{
if (exec_mode != MODE_NONE || !arg[0]) do_usage();
exec_mode = MODE_SPEC;
open_input( arg );
}
static void do_glue( const char *arg )
{
if (exec_mode != MODE_NONE || !arg[0]) do_usage();
exec_mode = MODE_GLUE;
open_input( arg );
}
static void do_relay(void)
{
if (exec_mode != MODE_NONE) do_usage();
exec_mode = MODE_RELAY;
}
/* parse options from the argv array and remove all the recognized ones */
static void parse_options( char *argv[] )
{
const struct option *opt;
int i;
for (i = 1; argv[i]; i++)
{
for (opt = option_table; opt->name; opt++)
if (!strcmp( argv[i], opt->name )) break;
if (!opt->name)
{
fprintf( stderr, "Unrecognized option '%s'\n", argv[i] );
do_usage();
}
if (opt->has_arg && argv[i+1]) opt->func( argv[++i] );
else opt->func( "" );
}
}
/*******************************************************************
* main
*/
int main(int argc, char **argv)
{
output_file = stdout;
parse_options( argv );
/* Retrieve the selector values; this assumes that we are building
* the asm files on the platform that will also run them. Probably
* a safe assumption to make.
*/
code_selector = __get_cs();
data_selector = __get_ds();
switch(exec_mode)
{
case MODE_SPEC:
switch (ParseTopLevel( input_file ))
{
case SPEC_WIN16:
BuildSpec16File( output_file );
break;
case SPEC_WIN32:
BuildSpec32File( output_file );
break;
default: assert(0);
}
break;
case MODE_GLUE:
BuildGlue( output_file, input_file );
break;
case MODE_RELAY:
BuildRelays( output_file );
break;
default:
do_usage();
break;
}
fclose( output_file );
output_file_name = NULL;
return 0;
}

495
tools/winebuild/parser.c Normal file
View File

@ -0,0 +1,495 @@
/*
* Spec file parser
*
* Copyright 1993 Robert J. Amstadt
* Copyright 1995 Martin von Loewis
* Copyright 1995, 1996, 1997 Alexandre Julliard
* Copyright 1997 Eric Youngdale
* Copyright 1999 Ulrich Weigand
*/
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "build.h"
int current_line = 0;
static SPEC_TYPE SpecType = SPEC_INVALID;
static char ParseBuffer[512];
static char *ParseNext = ParseBuffer;
static char ParseSaveChar;
static FILE *input_file;
static const char * const TypeNames[TYPE_NBTYPES] =
{
"byte", /* TYPE_BYTE */
"word", /* TYPE_WORD */
"long", /* TYPE_LONG */
"pascal16", /* TYPE_PASCAL_16 */
"pascal", /* TYPE_PASCAL */
"equate", /* TYPE_ABS */
"register", /* TYPE_REGISTER */
"interrupt", /* TYPE_INTERRUPT */
"stub", /* TYPE_STUB */
"stdcall", /* TYPE_STDCALL */
"cdecl", /* TYPE_CDECL */
"varargs", /* TYPE_VARARGS */
"extern", /* TYPE_EXTERN */
"forward" /* TYPE_FORWARD */
};
/* callback function used for stub functions */
#define STUB_CALLBACK \
((SpecType == SPEC_WIN16) ? "RELAY_Unimplemented16": "RELAY_Unimplemented32")
static int IsNumberString(char *s)
{
while (*s) if (!isdigit(*s++)) return 0;
return 1;
}
static char * GetTokenInLine(void)
{
char *p;
char *token;
if (ParseNext != ParseBuffer)
{
if (ParseSaveChar == '\0')
return NULL;
*ParseNext = ParseSaveChar;
}
/*
* Remove initial white space.
*/
for (p = ParseNext; isspace(*p); p++)
;
if ((*p == '\0') || (*p == '#'))
return NULL;
/*
* Find end of token.
*/
token = p++;
if (*token != '(' && *token != ')')
while (*p != '\0' && *p != '(' && *p != ')' && !isspace(*p))
p++;
ParseSaveChar = *p;
ParseNext = p;
*p = '\0';
return token;
}
static char * GetToken(void)
{
char *token;
while ((token = GetTokenInLine()) == NULL)
{
ParseNext = ParseBuffer;
while (1)
{
current_line++;
if (fgets(ParseBuffer, sizeof(ParseBuffer), input_file) == NULL)
return NULL;
if (ParseBuffer[0] != '#')
break;
}
}
return token;
}
/*******************************************************************
* ParseVariable
*
* Parse a variable definition.
*/
static void ParseVariable( ORDDEF *odp )
{
char *endptr;
int *value_array;
int n_values;
int value_array_size;
char *token = GetToken();
if (*token != '(') fatal_error( "Expected '(' got '%s'\n", token );
n_values = 0;
value_array_size = 25;
value_array = xmalloc(sizeof(*value_array) * value_array_size);
while ((token = GetToken()) != NULL)
{
if (*token == ')')
break;
value_array[n_values++] = strtol(token, &endptr, 0);
if (n_values == value_array_size)
{
value_array_size += 25;
value_array = xrealloc(value_array,
sizeof(*value_array) * value_array_size);
}
if (endptr == NULL || *endptr != '\0')
fatal_error( "Expected number value, got '%s'\n", token );
}
if (token == NULL)
fatal_error( "End of file in variable declaration\n" );
odp->u.var.n_values = n_values;
odp->u.var.values = xrealloc(value_array, sizeof(*value_array) * n_values);
}
/*******************************************************************
* ParseExportFunction
*
* Parse a function definition.
*/
static void ParseExportFunction( ORDDEF *odp )
{
char *token;
int i;
switch(SpecType)
{
case SPEC_WIN16:
if (odp->type == TYPE_STDCALL)
fatal_error( "'stdcall' not supported for Win16\n" );
if (odp->type == TYPE_VARARGS)
fatal_error( "'varargs' not supported for Win16\n" );
break;
case SPEC_WIN32:
if ((odp->type == TYPE_PASCAL) || (odp->type == TYPE_PASCAL_16))
fatal_error( "'pascal' not supported for Win32\n" );
break;
default:
break;
}
token = GetToken();
if (*token != '(') fatal_error( "Expected '(' got '%s'\n", token );
for (i = 0; i < sizeof(odp->u.func.arg_types)-1; i++)
{
token = GetToken();
if (*token == ')')
break;
if (!strcmp(token, "word"))
odp->u.func.arg_types[i] = 'w';
else if (!strcmp(token, "s_word"))
odp->u.func.arg_types[i] = 's';
else if (!strcmp(token, "long") || !strcmp(token, "segptr"))
odp->u.func.arg_types[i] = 'l';
else if (!strcmp(token, "ptr"))
odp->u.func.arg_types[i] = 'p';
else if (!strcmp(token, "str"))
odp->u.func.arg_types[i] = 't';
else if (!strcmp(token, "wstr"))
odp->u.func.arg_types[i] = 'W';
else if (!strcmp(token, "segstr"))
odp->u.func.arg_types[i] = 'T';
else if (!strcmp(token, "double"))
{
odp->u.func.arg_types[i++] = 'l';
odp->u.func.arg_types[i] = 'l';
}
else fatal_error( "Unknown variable type '%s'\n", token );
if (SpecType == SPEC_WIN32)
{
if (strcmp(token, "long") &&
strcmp(token, "ptr") &&
strcmp(token, "str") &&
strcmp(token, "wstr") &&
strcmp(token, "double"))
{
fatal_error( "Type '%s' not supported for Win32\n", token );
}
}
}
if ((*token != ')') || (i >= sizeof(odp->u.func.arg_types)))
fatal_error( "Too many arguments\n" );
odp->u.func.arg_types[i] = '\0';
if ((odp->type == TYPE_STDCALL) && !i)
odp->type = TYPE_CDECL; /* stdcall is the same as cdecl for 0 args */
strcpy(odp->u.func.link_name, GetToken());
}
/*******************************************************************
* ParseEquate
*
* Parse an 'equate' definition.
*/
static void ParseEquate( ORDDEF *odp )
{
char *endptr;
char *token = GetToken();
int value = strtol(token, &endptr, 0);
if (endptr == NULL || *endptr != '\0')
fatal_error( "Expected number value, got '%s'\n", token );
if (SpecType == SPEC_WIN32)
fatal_error( "'equate' not supported for Win32\n" );
odp->u.abs.value = value;
}
/*******************************************************************
* ParseStub
*
* Parse a 'stub' definition.
*/
static void ParseStub( ORDDEF *odp )
{
odp->u.func.arg_types[0] = '\0';
strcpy( odp->u.func.link_name, STUB_CALLBACK );
}
/*******************************************************************
* ParseInterrupt
*
* Parse an 'interrupt' definition.
*/
static void ParseInterrupt( ORDDEF *odp )
{
char *token;
if (SpecType == SPEC_WIN32)
fatal_error( "'interrupt' not supported for Win32\n" );
token = GetToken();
if (*token != '(') fatal_error( "Expected '(' got '%s'\n", token );
token = GetToken();
if (*token != ')') fatal_error( "Expected ')' got '%s'\n", token );
odp->u.func.arg_types[0] = '\0';
strcpy( odp->u.func.link_name, GetToken() );
}
/*******************************************************************
* ParseExtern
*
* Parse an 'extern' definition.
*/
static void ParseExtern( ORDDEF *odp )
{
if (SpecType == SPEC_WIN16) fatal_error( "'extern' not supported for Win16\n" );
strcpy( odp->u.ext.link_name, GetToken() );
}
/*******************************************************************
* ParseForward
*
* Parse a 'forward' definition.
*/
static void ParseForward( ORDDEF *odp )
{
if (SpecType == SPEC_WIN16) fatal_error( "'forward' not supported for Win16\n" );
strcpy( odp->u.fwd.link_name, GetToken() );
}
/*******************************************************************
* ParseOrdinal
*
* Parse an ordinal definition.
*/
static void ParseOrdinal(int ordinal)
{
char *token;
ORDDEF *odp = &EntryPoints[nb_entry_points++];
if (!(token = GetToken())) fatal_error( "Expected type after ordinal\n" );
for (odp->type = 0; odp->type < TYPE_NBTYPES; odp->type++)
if (TypeNames[odp->type] && !strcmp( token, TypeNames[odp->type] ))
break;
if (odp->type >= TYPE_NBTYPES)
fatal_error( "Expected type after ordinal, found '%s' instead\n", token );
if (!(token = GetToken())) fatal_error( "Expected name after type\n" );
strcpy( odp->name, token );
odp->lineno = current_line;
odp->ordinal = ordinal;
switch(odp->type)
{
case TYPE_BYTE:
case TYPE_WORD:
case TYPE_LONG:
ParseVariable( odp );
break;
case TYPE_REGISTER:
ParseExportFunction( odp );
#ifndef __i386__
/* ignore Win32 'register' routines on non-Intel archs */
if (SpecType == SPEC_WIN32)
{
nb_entry_points--;
return;
}
#endif
break;
case TYPE_PASCAL_16:
case TYPE_PASCAL:
case TYPE_STDCALL:
case TYPE_VARARGS:
case TYPE_CDECL:
ParseExportFunction( odp );
break;
case TYPE_INTERRUPT:
ParseInterrupt( odp );
break;
case TYPE_ABS:
ParseEquate( odp );
break;
case TYPE_STUB:
ParseStub( odp );
break;
case TYPE_EXTERN:
ParseExtern( odp );
break;
case TYPE_FORWARD:
ParseForward( odp );
break;
default:
assert( 0 );
}
if (ordinal != -1)
{
if (ordinal >= MAX_ORDINALS) fatal_error( "Ordinal number %d too large\n", ordinal );
if (ordinal > Limit) Limit = ordinal;
if (ordinal < Base) Base = ordinal;
odp->ordinal = ordinal;
Ordinals[ordinal] = odp;
}
if (!strcmp( odp->name, "@" ))
{
if (ordinal == -1)
fatal_error( "Nameless function needs an explicit ordinal number\n" );
if (SpecType != SPEC_WIN32)
fatal_error( "Nameless functions not supported for Win16\n" );
odp->name[0] = 0;
}
else Names[nb_names++] = odp;
}
/*******************************************************************
* ParseTopLevel
*
* Parse a spec file.
*/
SPEC_TYPE ParseTopLevel( FILE *file )
{
char *token;
input_file = file;
current_line = 1;
while ((token = GetToken()) != NULL)
{
if (strcmp(token, "name") == 0)
{
strcpy(DLLName, GetToken());
}
else if (strcmp(token, "file") == 0)
{
strcpy(DLLFileName, GetToken());
strupper(DLLFileName);
}
else if (strcmp(token, "type") == 0)
{
token = GetToken();
if (!strcmp(token, "win16" )) SpecType = SPEC_WIN16;
else if (!strcmp(token, "win32" )) SpecType = SPEC_WIN32;
else fatal_error( "Type must be 'win16' or 'win32'\n" );
}
else if (strcmp(token, "mode") == 0)
{
token = GetToken();
if (!strcmp(token, "dll" )) SpecMode = SPEC_MODE_DLL;
else if (!strcmp(token, "guiexe" )) SpecMode = SPEC_MODE_GUIEXE;
else if (!strcmp(token, "cuiexe" )) SpecMode = SPEC_MODE_CUIEXE;
else fatal_error( "Mode must be 'dll', 'guiexe' or 'cuiexe'\n" );
}
else if (strcmp(token, "heap") == 0)
{
token = GetToken();
if (!IsNumberString(token)) fatal_error( "Expected number after heap\n" );
DLLHeapSize = atoi(token);
}
else if (strcmp(token, "init") == 0)
{
strcpy(DLLInitFunc, GetToken());
if (SpecType == SPEC_WIN16)
fatal_error( "init cannot be used for Win16 spec files\n" );
if (!DLLInitFunc[0])
fatal_error( "Expected function name after init\n" );
if (!strcmp(DLLInitFunc, "main"))
fatal_error( "The init function cannot be named 'main'\n" );
}
else if (strcmp(token, "import") == 0)
{
if (nb_imports >= MAX_IMPORTS)
fatal_error( "Too many imports (limit %d)\n", MAX_IMPORTS );
if (SpecType != SPEC_WIN32)
fatal_error( "Imports not supported for Win16\n" );
DLLImports[nb_imports++] = xstrdup(GetToken());
}
else if (strcmp(token, "rsrc") == 0)
{
strcpy( rsrc_name, GetToken() );
strcat( rsrc_name, "_ResourceDescriptor" );
}
else if (strcmp(token, "@") == 0)
{
if (SpecType != SPEC_WIN32)
fatal_error( "'@' ordinals not supported for Win16\n" );
ParseOrdinal( -1 );
}
else if (IsNumberString(token))
{
ParseOrdinal( atoi(token) );
}
else
fatal_error( "Expected name, id, length or ordinal\n" );
}
if (!DLLFileName[0])
{
if (SpecMode == SPEC_MODE_DLL)
sprintf( DLLFileName, "%s.dll", DLLName );
else
sprintf( DLLFileName, "%s.exe", DLLName );
}
if (SpecType == SPEC_INVALID) fatal_error( "Missing 'type' declaration\n" );
current_line = 0; /* no longer parsing the input file */
return SpecType;
}

1194
tools/winebuild/relay.c Normal file

File diff suppressed because it is too large Load Diff

780
tools/winebuild/spec16.c Normal file
View File

@ -0,0 +1,780 @@
/*
* 16-bit spec files
*
* Copyright 1993 Robert J. Amstadt
* Copyright 1995 Martin von Loewis
* Copyright 1995, 1996, 1997 Alexandre Julliard
* Copyright 1997 Eric Youngdale
* Copyright 1999 Ulrich Weigand
*/
#include <assert.h>
#include <ctype.h>
#include "builtin16.h"
#include "module.h"
#include "neexe.h"
#include "stackframe.h"
#include "build.h"
/*******************************************************************
* StoreVariableCode
*
* Store a list of ints into a byte array.
*/
static int StoreVariableCode( unsigned char *buffer, int size, ORDDEF *odp )
{
int i;
switch(size)
{
case 1:
for (i = 0; i < odp->u.var.n_values; i++)
buffer[i] = odp->u.var.values[i];
break;
case 2:
for (i = 0; i < odp->u.var.n_values; i++)
((unsigned short *)buffer)[i] = odp->u.var.values[i];
break;
case 4:
for (i = 0; i < odp->u.var.n_values; i++)
((unsigned int *)buffer)[i] = odp->u.var.values[i];
break;
}
return odp->u.var.n_values * size;
}
/*******************************************************************
* BuildModule16
*
* Build the in-memory representation of a 16-bit NE module, and dump it
* as a byte stream into the assembly code.
*/
static int BuildModule16( FILE *outfile, int max_code_offset,
int max_data_offset )
{
int i;
char *buffer;
NE_MODULE *pModule;
SEGTABLEENTRY *pSegment;
OFSTRUCT *pFileInfo;
BYTE *pstr;
WORD *pword;
ET_BUNDLE *bundle = 0;
ET_ENTRY *entry = 0;
/* Module layout:
* NE_MODULE Module
* OFSTRUCT File information
* SEGTABLEENTRY Segment 1 (code)
* SEGTABLEENTRY Segment 2 (data)
* WORD[2] Resource table (empty)
* BYTE[2] Imported names (empty)
* BYTE[n] Resident names table
* BYTE[n] Entry table
*/
buffer = xmalloc( 0x10000 );
pModule = (NE_MODULE *)buffer;
memset( pModule, 0, sizeof(*pModule) );
pModule->magic = IMAGE_OS2_SIGNATURE;
pModule->count = 1;
pModule->next = 0;
pModule->flags = NE_FFLAGS_SINGLEDATA | NE_FFLAGS_BUILTIN | NE_FFLAGS_LIBMODULE;
pModule->dgroup = 2;
pModule->heap_size = DLLHeapSize;
pModule->stack_size = 0;
pModule->ip = 0;
pModule->cs = 0;
pModule->sp = 0;
pModule->ss = 0;
pModule->seg_count = 2;
pModule->modref_count = 0;
pModule->nrname_size = 0;
pModule->modref_table = 0;
pModule->nrname_fpos = 0;
pModule->moveable_entries = 0;
pModule->alignment = 0;
pModule->truetype = 0;
pModule->os_flags = NE_OSFLAGS_WINDOWS;
pModule->misc_flags = 0;
pModule->dlls_to_init = 0;
pModule->nrname_handle = 0;
pModule->min_swap_area = 0;
pModule->expected_version = 0;
pModule->module32 = 0;
pModule->self = 0;
pModule->self_loading_sel = 0;
/* File information */
pFileInfo = (OFSTRUCT *)(pModule + 1);
pModule->fileinfo = (int)pFileInfo - (int)pModule;
memset( pFileInfo, 0, sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName) );
pFileInfo->cBytes = sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName)
+ strlen(DLLFileName);
strcpy( pFileInfo->szPathName, DLLFileName );
pstr = (char *)pFileInfo + pFileInfo->cBytes + 1;
#ifdef __i386__ /* FIXME: Alignment problems! */
/* Segment table */
pSegment = (SEGTABLEENTRY *)pstr;
pModule->seg_table = (int)pSegment - (int)pModule;
pSegment->filepos = 0;
pSegment->size = max_code_offset;
pSegment->flags = 0;
pSegment->minsize = max_code_offset;
pSegment->hSeg = 0;
pSegment++;
pModule->dgroup_entry = (int)pSegment - (int)pModule;
pSegment->filepos = 0;
pSegment->size = max_data_offset;
pSegment->flags = NE_SEGFLAGS_DATA;
pSegment->minsize = max_data_offset;
pSegment->hSeg = 0;
pSegment++;
/* Resource table */
pword = (WORD *)pSegment;
pModule->res_table = (int)pword - (int)pModule;
*pword++ = 0;
*pword++ = 0;
/* Imported names table */
pstr = (char *)pword;
pModule->import_table = (int)pstr - (int)pModule;
*pstr++ = 0;
*pstr++ = 0;
/* Resident names table */
pModule->name_table = (int)pstr - (int)pModule;
/* First entry is module name */
*pstr = strlen(DLLName );
strcpy( pstr + 1, DLLName );
pstr += *pstr + 1;
*(WORD *)pstr = 0;
pstr += sizeof(WORD);
/* Store all ordinals */
for (i = 1; i <= Limit; i++)
{
ORDDEF *odp = Ordinals[i];
if (!odp || !odp->name[0]) continue;
*pstr = strlen( odp->name );
strcpy( pstr + 1, odp->name );
strupper( pstr + 1 );
pstr += *pstr + 1;
*(WORD *)pstr = i;
pstr += sizeof(WORD);
}
*pstr++ = 0;
/* Entry table */
pModule->entry_table = (int)pstr - (int)pModule;
for (i = 1; i <= Limit; i++)
{
int selector = 0;
ORDDEF *odp = Ordinals[i];
if (!odp) continue;
switch (odp->type)
{
case TYPE_CDECL:
case TYPE_PASCAL:
case TYPE_PASCAL_16:
case TYPE_REGISTER:
case TYPE_INTERRUPT:
case TYPE_STUB:
selector = 1; /* Code selector */
break;
case TYPE_BYTE:
case TYPE_WORD:
case TYPE_LONG:
selector = 2; /* Data selector */
break;
case TYPE_ABS:
selector = 0xfe; /* Constant selector */
break;
default:
selector = 0; /* Invalid selector */
break;
}
if ( !selector )
continue;
if ( bundle && bundle->last+1 == i )
bundle->last++;
else
{
if ( bundle )
bundle->next = (char *)pstr - (char *)pModule;
bundle = (ET_BUNDLE *)pstr;
bundle->first = i-1;
bundle->last = i;
bundle->next = 0;
pstr += sizeof(ET_BUNDLE);
}
/* FIXME: is this really correct ?? */
entry = (ET_ENTRY *)pstr;
entry->type = 0xff; /* movable */
entry->flags = 3; /* exported & public data */
entry->segnum = selector;
entry->offs = odp->offset;
pstr += sizeof(ET_ENTRY);
}
*pstr++ = 0;
#endif
/* Dump the module content */
dump_bytes( outfile, (char *)pModule, (int)pstr - (int)pModule, "Module" );
return (int)pstr - (int)pModule;
}
/*******************************************************************
* BuildCallFrom16Func
*
* Build a 16-bit-to-Wine callback glue function.
*
* The generated routines are intended to be used as argument conversion
* routines to be called by the CallFrom16... core. Thus, the prototypes of
* the generated routines are (see also CallFrom16):
*
* extern WORD WINAPI PREFIX_CallFrom16_C_word_xxx( FARPROC func, LPBYTE args );
* extern LONG WINAPI PREFIX_CallFrom16_C_long_xxx( FARPROC func, LPBYTE args );
* extern void WINAPI PREFIX_CallFrom16_C_regs_xxx( FARPROC func, LPBYTE args,
* CONTEXT86 *context );
* extern void WINAPI PREFIX_CallFrom16_C_intr_xxx( FARPROC func, LPBYTE args,
* CONTEXT86 *context );
*
* where 'C' is the calling convention ('p' for pascal or 'c' for cdecl),
* and each 'x' is an argument ('w'=word, 's'=signed word, 'l'=long,
* 'p'=linear pointer, 't'=linear pointer to null-terminated string,
* 'T'=segmented pointer to null-terminated string).
*
* The generated routines fetch the arguments from the 16-bit stack (pointed
* to by 'args'); the offsets of the single argument values are computed
* according to the calling convention and the argument types. Then, the
* 32-bit entry point is called with these arguments.
*
* For register functions, the arguments (if present) are converted just
* the same as for normal functions, but in addition the CONTEXT86 pointer
* filled with the current register values is passed to the 32-bit routine.
* (An 'intr' interrupt handler routine is treated exactly like a register
* routine, except that upon return, the flags word pushed onto the stack
* by the interrupt is removed by the 16-bit call stub.)
*
*/
static void BuildCallFrom16Func( FILE *outfile, char *profile, char *prefix, int local )
{
int i, pos, argsize = 0;
int short_ret = 0;
int reg_func = 0;
int usecdecl = 0;
char *args = profile + 7;
char *ret_type;
/* Parse function type */
if (!strncmp( "c_", profile, 2 )) usecdecl = 1;
else if (strncmp( "p_", profile, 2 ))
{
fprintf( stderr, "Invalid function name '%s', ignored\n", profile );
return;
}
if (!strncmp( "word_", profile + 2, 5 )) short_ret = 1;
else if (!strncmp( "regs_", profile + 2, 5 )) reg_func = 1;
else if (!strncmp( "intr_", profile + 2, 5 )) reg_func = 2;
else if (strncmp( "long_", profile + 2, 5 ))
{
fprintf( stderr, "Invalid function name '%s', ignored\n", profile );
return;
}
for ( i = 0; args[i]; i++ )
switch ( args[i] )
{
case 'w': /* word */
case 's': /* s_word */
argsize += 2;
break;
case 'l': /* long or segmented pointer */
case 'T': /* segmented pointer to null-terminated string */
case 'p': /* linear pointer */
case 't': /* linear pointer to null-terminated string */
argsize += 4;
break;
}
ret_type = reg_func? "void" : short_ret? "WORD" : "LONG";
fprintf( outfile, "typedef %s WINAPI (*proc_%s_t)( ",
ret_type, profile );
args = profile + 7;
for ( i = 0; args[i]; i++ )
{
if ( i ) fprintf( outfile, ", " );
switch (args[i])
{
case 'w': fprintf( outfile, "WORD" ); break;
case 's': fprintf( outfile, "INT16" ); break;
case 'l': case 'T': fprintf( outfile, "LONG" ); break;
case 'p': case 't': fprintf( outfile, "LPVOID" ); break;
}
}
if ( reg_func )
fprintf( outfile, "%sstruct _CONTEXT86 *", i? ", " : "" );
else if ( !i )
fprintf( outfile, "void" );
fprintf( outfile, " );\n" );
fprintf( outfile, "%s%s WINAPI %s_CallFrom16_%s( FARPROC proc, LPBYTE args%s )\n{\n",
local? "static " : "", ret_type, prefix, profile,
reg_func? ", struct _CONTEXT86 *context" : "" );
fprintf( outfile, " %s((proc_%s_t) proc) (\n",
reg_func? "" : "return ", profile );
args = profile + 7;
pos = !usecdecl? argsize : 0;
for ( i = 0; args[i]; i++ )
{
if ( i ) fprintf( outfile, ",\n" );
fprintf( outfile, " " );
switch (args[i])
{
case 'w': /* word */
if ( !usecdecl ) pos -= 2;
fprintf( outfile, "*(WORD *)(args+%d)", pos );
if ( usecdecl ) pos += 2;
break;
case 's': /* s_word */
if ( !usecdecl ) pos -= 2;
fprintf( outfile, "*(INT16 *)(args+%d)", pos );
if ( usecdecl ) pos += 2;
break;
case 'l': /* long or segmented pointer */
case 'T': /* segmented pointer to null-terminated string */
if ( !usecdecl ) pos -= 4;
fprintf( outfile, "*(LONG *)(args+%d)", pos );
if ( usecdecl ) pos += 4;
break;
case 'p': /* linear pointer */
case 't': /* linear pointer to null-terminated string */
if ( !usecdecl ) pos -= 4;
fprintf( outfile, "PTR_SEG_TO_LIN( *(SEGPTR *)(args+%d) )", pos );
if ( usecdecl ) pos += 4;
break;
default:
fprintf( stderr, "Unknown arg type '%c'\n", args[i] );
}
}
if ( reg_func )
fprintf( outfile, "%s context", i? ",\n" : "" );
fprintf( outfile, " );\n}\n\n" );
}
/*******************************************************************
* BuildCallTo16Func
*
* Build a Wine-to-16-bit callback glue function.
*
* Prototypes for the CallTo16 functions:
* extern WORD CALLBACK PREFIX_CallTo16_word_xxx( FARPROC16 func, args... );
* extern LONG CALLBACK PREFIX_CallTo16_long_xxx( FARPROC16 func, args... );
*
* These routines are provided solely for convenience; they simply
* write the arguments onto the 16-bit stack, and call the appropriate
* CallTo16... core routine.
*
* If you have more sophisticated argument conversion requirements than
* are provided by these routines, you might as well call the core
* routines by yourself.
*
*/
static void BuildCallTo16Func( FILE *outfile, char *profile, char *prefix )
{
char *args = profile + 5;
int i, argsize = 0, short_ret = 0;
if (!strncmp( "word_", profile, 5 )) short_ret = 1;
else if (strncmp( "long_", profile, 5 ))
{
fprintf( stderr, "Invalid function name '%s'.\n", profile );
exit(1);
}
fprintf( outfile, "%s %s_CallTo16_%s( FARPROC16 proc",
short_ret? "WORD" : "LONG", prefix, profile );
args = profile + 5;
for ( i = 0; args[i]; i++ )
{
fprintf( outfile, ", " );
switch (args[i])
{
case 'w': fprintf( outfile, "WORD" ); argsize += 2; break;
case 'l': fprintf( outfile, "LONG" ); argsize += 4; break;
}
fprintf( outfile, " arg%d", i+1 );
}
fprintf( outfile, " )\n{\n" );
if ( argsize > 0 )
fprintf( outfile, " LPBYTE args = (LPBYTE)CURRENT_STACK16;\n" );
args = profile + 5;
for ( i = 0; args[i]; i++ )
{
switch (args[i])
{
case 'w': fprintf( outfile, " args -= sizeof(WORD); *(WORD" ); break;
case 'l': fprintf( outfile, " args -= sizeof(LONG); *(LONG" ); break;
default: fprintf( stderr, "Unexpected case '%c' in BuildCallTo16Func\n",
args[i] );
}
fprintf( outfile, " *)args = arg%d;\n", i+1 );
}
fprintf( outfile, " return CallTo16%s( proc, %d );\n}\n\n",
short_ret? "Word" : "Long", argsize );
}
/*******************************************************************
* Spec16TypeCompare
*/
static int Spec16TypeCompare( const void *e1, const void *e2 )
{
const ORDDEF *odp1 = *(const ORDDEF **)e1;
const ORDDEF *odp2 = *(const ORDDEF **)e2;
int type1 = (odp1->type == TYPE_CDECL) ? 0
: (odp1->type == TYPE_REGISTER) ? 3
: (odp1->type == TYPE_INTERRUPT) ? 4
: (odp1->type == TYPE_PASCAL_16) ? 1 : 2;
int type2 = (odp2->type == TYPE_CDECL) ? 0
: (odp2->type == TYPE_REGISTER) ? 3
: (odp2->type == TYPE_INTERRUPT) ? 4
: (odp2->type == TYPE_PASCAL_16) ? 1 : 2;
int retval = type1 - type2;
if ( !retval )
retval = strcmp( odp1->u.func.arg_types, odp2->u.func.arg_types );
return retval;
}
/*******************************************************************
* BuildSpec16File
*
* Build a Win16 assembly file from a spec file.
*/
void BuildSpec16File( FILE *outfile )
{
ORDDEF **type, **typelist;
int i, nFuncs, nTypes;
int code_offset, data_offset, module_size;
unsigned char *data;
/* File header */
fprintf( outfile, "/* File generated automatically from %s; do not edit! */\n\n",
input_file_name );
fprintf( outfile, "#define __FLATCS__ 0x%04x\n", code_selector );
fprintf( outfile, "#include \"builtin16.h\"\n\n" );
data = (unsigned char *)xmalloc( 0x10000 );
memset( data, 0, 16 );
data_offset = 16;
strupper( DLLName );
/* Build sorted list of all argument types, without duplicates */
typelist = (ORDDEF **)calloc( Limit+1, sizeof(ORDDEF *) );
for (i = nFuncs = 0; i <= Limit; i++)
{
ORDDEF *odp = Ordinals[i];
if (!odp) continue;
switch (odp->type)
{
case TYPE_REGISTER:
case TYPE_INTERRUPT:
case TYPE_CDECL:
case TYPE_PASCAL:
case TYPE_PASCAL_16:
case TYPE_STUB:
typelist[nFuncs++] = odp;
default:
break;
}
}
qsort( typelist, nFuncs, sizeof(ORDDEF *), Spec16TypeCompare );
i = nTypes = 0;
while ( i < nFuncs )
{
typelist[nTypes++] = typelist[i++];
while ( i < nFuncs && Spec16TypeCompare( typelist + i, typelist + nTypes-1 ) == 0 )
i++;
}
/* Output CallFrom16 routines needed by this .spec file */
for ( i = 0; i < nTypes; i++ )
{
char profile[101];
sprintf( profile, "%s_%s_%s",
(typelist[i]->type == TYPE_CDECL) ? "c" : "p",
(typelist[i]->type == TYPE_REGISTER) ? "regs" :
(typelist[i]->type == TYPE_INTERRUPT) ? "intr" :
(typelist[i]->type == TYPE_PASCAL_16) ? "word" : "long",
typelist[i]->u.func.arg_types );
BuildCallFrom16Func( outfile, profile, DLLName, TRUE );
}
/* Output the DLL functions prototypes */
for (i = 0; i <= Limit; i++)
{
ORDDEF *odp = Ordinals[i];
if (!odp) continue;
switch(odp->type)
{
case TYPE_REGISTER:
case TYPE_INTERRUPT:
case TYPE_CDECL:
case TYPE_PASCAL:
case TYPE_PASCAL_16:
fprintf( outfile, "extern void %s();\n", odp->u.func.link_name );
break;
default:
break;
}
}
/* Output code segment */
fprintf( outfile, "\nstatic struct\n{\n CALLFROM16 call[%d];\n"
" ENTRYPOINT16 entry[%d];\n} Code_Segment = \n{\n {\n",
nTypes, nFuncs );
code_offset = 0;
for ( i = 0; i < nTypes; i++ )
{
char profile[101], *arg;
int argsize = 0;
sprintf( profile, "%s_%s_%s",
(typelist[i]->type == TYPE_CDECL) ? "c" : "p",
(typelist[i]->type == TYPE_REGISTER) ? "regs" :
(typelist[i]->type == TYPE_INTERRUPT) ? "intr" :
(typelist[i]->type == TYPE_PASCAL_16) ? "word" : "long",
typelist[i]->u.func.arg_types );
if ( typelist[i]->type != TYPE_CDECL )
for ( arg = typelist[i]->u.func.arg_types; *arg; arg++ )
switch ( *arg )
{
case 'w': /* word */
case 's': /* s_word */
argsize += 2;
break;
case 'l': /* long or segmented pointer */
case 'T': /* segmented pointer to null-terminated string */
case 'p': /* linear pointer */
case 't': /* linear pointer to null-terminated string */
argsize += 4;
break;
}
if ( typelist[i]->type == TYPE_INTERRUPT )
argsize += 2;
fprintf( outfile, " CF16_%s( %s_CallFrom16_%s, %d, \"%s\" ),\n",
( typelist[i]->type == TYPE_REGISTER
|| typelist[i]->type == TYPE_INTERRUPT)? "REGS":
typelist[i]->type == TYPE_PASCAL_16? "WORD" : "LONG",
DLLName, profile, argsize, profile );
code_offset += sizeof(CALLFROM16);
}
fprintf( outfile, " },\n {\n" );
for (i = 0; i <= Limit; i++)
{
ORDDEF *odp = Ordinals[i];
if (!odp) continue;
switch (odp->type)
{
case TYPE_ABS:
odp->offset = LOWORD(odp->u.abs.value);
break;
case TYPE_BYTE:
odp->offset = data_offset;
data_offset += StoreVariableCode( data + data_offset, 1, odp);
break;
case TYPE_WORD:
odp->offset = data_offset;
data_offset += StoreVariableCode( data + data_offset, 2, odp);
break;
case TYPE_LONG:
odp->offset = data_offset;
data_offset += StoreVariableCode( data + data_offset, 4, odp);
break;
case TYPE_REGISTER:
case TYPE_INTERRUPT:
case TYPE_CDECL:
case TYPE_PASCAL:
case TYPE_PASCAL_16:
case TYPE_STUB:
type = bsearch( &odp, typelist, nTypes, sizeof(ORDDEF *), Spec16TypeCompare );
assert( type );
fprintf( outfile, " /* %s.%d */ ", DLLName, i );
fprintf( outfile, "EP( %s, %d /* %s_%s_%s */ ),\n",
odp->u.func.link_name,
(type-typelist)*sizeof(CALLFROM16) -
(code_offset + sizeof(ENTRYPOINT16)),
(odp->type == TYPE_CDECL) ? "c" : "p",
(odp->type == TYPE_REGISTER) ? "regs" :
(odp->type == TYPE_INTERRUPT) ? "intr" :
(odp->type == TYPE_PASCAL_16) ? "word" : "long",
odp->u.func.arg_types );
odp->offset = code_offset;
code_offset += sizeof(ENTRYPOINT16);
break;
default:
fprintf(stderr,"build: function type %d not available for Win16\n",
odp->type);
exit(1);
}
}
fprintf( outfile, " }\n};\n" );
/* Output data segment */
dump_bytes( outfile, data, data_offset, "Data_Segment" );
/* Build the module */
module_size = BuildModule16( outfile, code_offset, data_offset );
/* Output the DLL descriptor */
if (rsrc_name[0]) fprintf( outfile, "extern const char %s[];\n\n", rsrc_name );
fprintf( outfile, "\nstatic const BUILTIN16_DESCRIPTOR descriptor = \n{\n" );
fprintf( outfile, " \"%s\",\n", DLLName );
fprintf( outfile, " Module,\n" );
fprintf( outfile, " sizeof(Module),\n" );
fprintf( outfile, " (BYTE *)&Code_Segment,\n" );
fprintf( outfile, " (BYTE *)Data_Segment,\n" );
fprintf( outfile, " %s\n", rsrc_name[0] ? rsrc_name : "0" );
fprintf( outfile, "};\n" );
/* Output the DLL constructor */
fprintf( outfile, "#ifdef __GNUC__\n" );
fprintf( outfile, "static void %s_init(void) __attribute__((constructor));\n", DLLName );
fprintf( outfile, "#else /* defined(__GNUC__) */\n" );
fprintf( outfile, "static void __asm__dummy_dll_init(void) {\n" );
fprintf( outfile, "asm(\"\\t.section\t.init ,\\\"ax\\\"\\n\"\n" );
fprintf( outfile, " \"\\tcall %s_init\\n\"\n", DLLName );
fprintf( outfile, " \"\\t.previous\\n\");\n" );
fprintf( outfile, "}\n" );
fprintf( outfile, "#endif /* defined(__GNUC__) */\n" );
fprintf( outfile, "static void %s_init(void) { BUILTIN_RegisterDLL( &descriptor ); }\n",
DLLName );
}
/*******************************************************************
* BuildGlue
*
* Build the 16-bit-to-Wine/Wine-to-16-bit callback glue code
*/
void BuildGlue( FILE *outfile, FILE *infile )
{
char buffer[1024];
/* File header */
fprintf( outfile, "/* File generated automatically from %s; do not edit! */\n\n",
input_file_name );
fprintf( outfile, "#include \"builtin16.h\"\n" );
fprintf( outfile, "#include \"stackframe.h\"\n\n" );
/* Build the callback glue functions */
while (fgets( buffer, sizeof(buffer), infile ))
{
if (strstr( buffer, "### start build ###" )) break;
}
while (fgets( buffer, sizeof(buffer), infile ))
{
char *p;
if ( (p = strstr( buffer, "CallFrom16_" )) != NULL )
{
char *q, *profile = p + strlen( "CallFrom16_" );
for (q = profile; (*q == '_') || isalpha(*q); q++ )
;
*q = '\0';
for (q = p-1; q > buffer && ((*q == '_') || isalnum(*q)); q-- )
;
if ( ++q < p ) p[-1] = '\0'; else q = "";
BuildCallFrom16Func( outfile, profile, q, FALSE );
}
if ( (p = strstr( buffer, "CallTo16_" )) != NULL )
{
char *q, *profile = p + strlen( "CallTo16_" );
for (q = profile; (*q == '_') || isalpha(*q); q++ )
;
*q = '\0';
for (q = p-1; q > buffer && ((*q == '_') || isalnum(*q)); q-- )
;
if ( ++q < p ) p[-1] = '\0'; else q = "";
BuildCallTo16Func( outfile, profile, q );
}
if (strstr( buffer, "### stop build ###" )) break;
}
fclose( infile );
}

467
tools/winebuild/spec32.c Normal file
View File

@ -0,0 +1,467 @@
/*
* 32-bit spec files
*
* Copyright 1993 Robert J. Amstadt
* Copyright 1995 Martin von Loewis
* Copyright 1995, 1996, 1997 Alexandre Julliard
* Copyright 1997 Eric Youngdale
* Copyright 1999 Ulrich Weigand
*/
#include <assert.h>
#include <unistd.h>
#include "winbase.h"
#include "build.h"
static int name_compare( const void *name1, const void *name2 )
{
ORDDEF *odp1 = *(ORDDEF **)name1;
ORDDEF *odp2 = *(ORDDEF **)name2;
return strcmp( odp1->name, odp2->name );
}
/*******************************************************************
* AssignOrdinals
*
* Assign ordinals to all entry points.
*/
static void AssignOrdinals(void)
{
int i, ordinal;
if ( !nb_names ) return;
/* sort the list of names */
qsort( Names, nb_names, sizeof(Names[0]), name_compare );
/* check for duplicate names */
for (i = 0; i < nb_names - 1; i++)
{
if (!strcmp( Names[i]->name, Names[i+1]->name ))
{
current_line = max( Names[i]->lineno, Names[i+1]->lineno );
fatal_error( "'%s' redefined (previous definition at line %d)\n",
Names[i]->name, min( Names[i]->lineno, Names[i+1]->lineno ) );
}
}
/* start assigning from Base, or from 1 if no ordinal defined yet */
if (Base == MAX_ORDINALS) Base = 1;
for (i = 0, ordinal = Base; i < nb_names; i++)
{
if (Names[i]->ordinal != -1) continue; /* already has an ordinal */
while (Ordinals[ordinal]) ordinal++;
if (ordinal >= MAX_ORDINALS)
{
current_line = Names[i]->lineno;
fatal_error( "Too many functions defined (max %d)\n", MAX_ORDINALS );
}
Names[i]->ordinal = ordinal;
Ordinals[ordinal] = Names[i];
}
if (ordinal > Limit) Limit = ordinal;
}
/*******************************************************************
* output_exports
*
* Output the export table for a Win32 module.
*/
static void output_exports( FILE *outfile, int nr_exports, int nr_names, int fwd_size )
{
int i, fwd_pos = 0;
if (!nr_exports) return;
fprintf( outfile, "\n\n/* exports */\n\n" );
fprintf( outfile, "typedef void (*func_ptr)();\n" );
fprintf( outfile, "static struct {\n" );
fprintf( outfile, " struct {\n" );
fprintf( outfile, " unsigned int Characteristics;\n" );
fprintf( outfile, " unsigned int TimeDateStamp;\n" );
fprintf( outfile, " unsigned short MajorVersion;\n" );
fprintf( outfile, " unsigned short MinorVersion;\n" );
fprintf( outfile, " const char *Name;\n" );
fprintf( outfile, " unsigned int Base;\n" );
fprintf( outfile, " unsigned int NumberOfFunctions;\n" );
fprintf( outfile, " unsigned int NumberOfNames;\n" );
fprintf( outfile, " func_ptr *AddressOfFunctions;\n" );
fprintf( outfile, " const char **AddressOfNames;\n" );
fprintf( outfile, " unsigned short *AddressOfNameOrdinals;\n" );
fprintf( outfile, " func_ptr functions[%d];\n", nr_exports );
if (nb_names)
{
fprintf( outfile, " const char *names[%d];\n", nb_names );
fprintf( outfile, " unsigned short ordinals[%d];\n", nb_names );
if (nb_names % 2) fprintf( outfile, " unsigned short pad1;\n" );
}
if (fwd_size)
{
fprintf( outfile, " char forwards[%d];\n", (fwd_size + 3) & ~3 );
}
fprintf( outfile, " } exp;\n" );
#ifdef __i386__
fprintf( outfile, " struct {\n" );
fprintf( outfile, " unsigned char jmp;\n" );
fprintf( outfile, " unsigned char addr[4];\n" );
fprintf( outfile, " unsigned char ret;\n" );
fprintf( outfile, " unsigned short args;\n" );
fprintf( outfile, " func_ptr orig;\n" );
fprintf( outfile, " unsigned int argtypes;\n" );
fprintf( outfile, " } relay[%d];\n", nr_exports );
#endif /* __i386__ */
fprintf( outfile, "} exports = {\n {\n" );
fprintf( outfile, " 0,\n" ); /* Characteristics */
fprintf( outfile, " 0,\n" ); /* TimeDateStamp */
fprintf( outfile, " 0,\n" ); /* MajorVersion */
fprintf( outfile, " 0,\n" ); /* MinorVersion */
fprintf( outfile, " dllname,\n" ); /* Name */
fprintf( outfile, " %d,\n", Base ); /* Base */
fprintf( outfile, " %d,\n", nr_exports ); /* NumberOfFunctions */
fprintf( outfile, " %d,\n", nb_names ); /* NumberOfNames */
fprintf( outfile, " exports.exp.functions,\n" ); /* AddressOfFunctions */
if (nb_names)
{
fprintf( outfile, " exports.exp.names,\n" ); /* AddressOfNames */
fprintf( outfile, " exports.exp.ordinals,\n" ); /* AddressOfNameOrdinals */
}
else
{
fprintf( outfile, " 0,\n" ); /* AddressOfNames */
fprintf( outfile, " 0,\n" ); /* AddressOfNameOrdinals */
}
/* output the function addresses */
fprintf( outfile, " {\n " );
for (i = Base; i <= Limit; i++)
{
ORDDEF *odp = Ordinals[i];
if (!odp) fprintf( outfile, "0" );
else switch(odp->type)
{
case TYPE_EXTERN:
fprintf( outfile, "%s", odp->u.ext.link_name );
break;
case TYPE_STDCALL:
case TYPE_VARARGS:
case TYPE_CDECL:
fprintf( outfile, "%s", odp->u.func.link_name);
break;
case TYPE_STUB:
fprintf( outfile, "__stub_%d", i );
break;
case TYPE_REGISTER:
fprintf( outfile, "__regs_%d", i );
break;
case TYPE_FORWARD:
fprintf( outfile, "(func_ptr)&exports.exp.forwards[%d] /* %s */",
fwd_pos, odp->u.fwd.link_name );
fwd_pos += strlen(odp->u.fwd.link_name) + 1;
break;
default:
assert(0);
}
if (i < Limit) fprintf( outfile, ",\n " );
else fprintf( outfile, "\n },\n" );
}
if (nb_names)
{
/* output the function names */
fprintf( outfile, " {\n" );
for (i = 0; i < nb_names; i++)
{
if (i) fprintf( outfile, ",\n" );
fprintf( outfile, " \"%s\"", Names[i]->name );
}
fprintf( outfile, "\n },\n" );
/* output the function ordinals */
fprintf( outfile, " {\n " );
for (i = 0; i < nb_names; i++)
{
fprintf( outfile, "%4d", Names[i]->ordinal - Base );
if (i < nb_names-1)
{
fputc( ',', outfile );
if ((i % 8) == 7) fprintf( outfile, "\n " );
}
}
fprintf( outfile, "\n },\n" );
if (nb_names % 2) fprintf( outfile, " 0,\n" );
}
/* output forwards */
if (fwd_size)
{
for (i = Base; i <= Limit; i++)
{
ORDDEF *odp = Ordinals[i];
if (odp && odp->type == TYPE_FORWARD)
fprintf( outfile, " \"%s\\0\"\n", odp->u.fwd.link_name );
}
}
/* output relays */
#ifdef __i386__
fprintf( outfile, " },\n {\n" );
for (i = Base; i <= Limit; i++)
{
ORDDEF *odp = Ordinals[i];
if (odp && ((odp->type == TYPE_STDCALL) ||
(odp->type == TYPE_CDECL) ||
(odp->type == TYPE_REGISTER)))
{
unsigned int j, mask = 0;
for (j = 0; odp->u.func.arg_types[j]; j++)
{
if (odp->u.func.arg_types[j] == 't') mask |= 1<< (j*2);
if (odp->u.func.arg_types[j] == 'W') mask |= 2<< (j*2);
}
switch(odp->type)
{
case TYPE_STDCALL:
fprintf( outfile, " { 0xe9, { 0,0,0,0 }, 0xc2, 0x%04x, %s, 0x%08x }",
strlen(odp->u.func.arg_types) * sizeof(int),
odp->u.func.link_name, mask );
break;
case TYPE_CDECL:
fprintf( outfile, " { 0xe9, { 0,0,0,0 }, 0xc3, 0x%04x, %s, 0x%08x }",
strlen(odp->u.func.arg_types) * sizeof(int),
odp->u.func.link_name, mask );
break;
case TYPE_REGISTER:
fprintf( outfile, " { 0xe9, { 0,0,0,0 }, 0xc3, 0x%04x, __regs_%d, 0x%08x }",
0x8000 | (strlen(odp->u.func.arg_types) * sizeof(int)), i, mask );
break;
default:
assert(0);
}
}
else fprintf( outfile, " { 0, }" );
if (i < Limit) fprintf( outfile, ",\n" );
}
#endif /* __i386__ */
fprintf( outfile, " }\n};\n" );
}
/*******************************************************************
* BuildSpec32File
*
* Build a Win32 C file from a spec file.
*/
void BuildSpec32File( FILE *outfile )
{
ORDDEF *odp;
int i, fwd_size = 0, have_regs = FALSE;
int nr_exports;
const char *init_func;
DWORD page_size;
#ifdef HAVE_GETPAGESIZE
page_size = getpagesize();
#else
# ifdef __svr4__
page_size = sysconf(_SC_PAGESIZE);
# else
# error Cannot get the page size on this platform
# endif
#endif
AssignOrdinals();
nr_exports = Base <= Limit ? Limit - Base + 1 : 0;
fprintf( outfile, "/* File generated automatically from %s; do not edit! */\n\n",
input_file_name );
fprintf( outfile, "#include \"builtin32.h\"\n\n" );
/* Reserve some space for the PE header */
fprintf( outfile, "extern char pe_header[];\n" );
fprintf( outfile, "asm(\".section .text\\n\\t\"\n" );
fprintf( outfile, " \".align %ld\\n\"\n", page_size );
fprintf( outfile, " \"pe_header:\\t.fill %ld,1,0\\n\\t\");\n", page_size );
fprintf( outfile, "static const char dllname[] = \"%s\";\n", DLLName );
/* Output the DLL functions prototypes */
for (i = 0, odp = EntryPoints; i < nb_entry_points; i++, odp++)
{
switch(odp->type)
{
case TYPE_EXTERN:
fprintf( outfile, "extern void %s();\n", odp->u.ext.link_name );
break;
case TYPE_STDCALL:
case TYPE_VARARGS:
case TYPE_CDECL:
fprintf( outfile, "extern void %s();\n", odp->u.func.link_name );
break;
case TYPE_FORWARD:
fwd_size += strlen(odp->u.fwd.link_name) + 1;
break;
case TYPE_REGISTER:
fprintf( outfile, "extern void __regs_%d();\n", odp->ordinal );
have_regs = TRUE;
break;
case TYPE_STUB:
if (odp->name[0])
fprintf( outfile,
"static void __stub_%d() { BUILTIN32_Unimplemented(dllname,\"%s\"); }\n",
odp->ordinal, odp->name );
else
fprintf( outfile,
"static void __stub_%d() { BUILTIN32_Unimplemented(dllname,\"%d\"); }\n",
odp->ordinal, odp->ordinal );
break;
default:
fprintf(stderr,"build: function type %d not available for Win32\n",
odp->type);
exit(1);
}
}
/* Output code for all register functions */
if ( have_regs )
{
fprintf( outfile, "#ifndef __GNUC__\n" );
fprintf( outfile, "static void __asm__dummy(void) {\n" );
fprintf( outfile, "#endif /* !defined(__GNUC__) */\n" );
for (i = 0, odp = EntryPoints; i < nb_entry_points; i++, odp++)
{
if (odp->type != TYPE_REGISTER) continue;
fprintf( outfile,
"asm(\".align 4\\n\\t\"\n"
" \".type " PREFIX "__regs_%d,@function\\n\\t\"\n"
" \"" PREFIX "__regs_%d:\\n\\t\"\n"
" \"call " PREFIX "CALL32_Regs\\n\\t\"\n"
" \".long " PREFIX "%s\\n\\t\"\n"
" \".byte %d,%d\");\n",
odp->ordinal, odp->ordinal, odp->u.func.link_name,
4 * strlen(odp->u.func.arg_types),
4 * strlen(odp->u.func.arg_types) );
}
fprintf( outfile, "#ifndef __GNUC__\n" );
fprintf( outfile, "}\n" );
fprintf( outfile, "#endif /* !defined(__GNUC__) */\n" );
}
/* Output the exports and relay entry points */
output_exports( outfile, nr_exports, nb_names, fwd_size );
/* Output the DLL imports */
if (nb_imports)
{
fprintf( outfile, "static const char * const Imports[%d] =\n{\n", nb_imports );
for (i = 0; i < nb_imports; i++)
{
fprintf( outfile, " \"%s\"", DLLImports[i] );
if (i < nb_imports-1) fprintf( outfile, ",\n" );
}
fprintf( outfile, "\n};\n\n" );
}
/* Output LibMain function */
init_func = DLLInitFunc[0] ? DLLInitFunc : NULL;
switch(SpecMode)
{
case SPEC_MODE_DLL:
if (init_func) fprintf( outfile, "extern void %s();\n", init_func );
break;
case SPEC_MODE_GUIEXE:
if (!init_func) init_func = "WinMain";
fprintf( outfile,
"\n#include <winbase.h>\n"
"static void exe_main(void)\n"
"{\n"
" extern int PASCAL %s(HINSTANCE,HINSTANCE,LPCSTR,INT);\n"
" STARTUPINFOA info;\n"
" const char *cmdline = GetCommandLineA();\n"
" while (*cmdline && *cmdline != ' ') cmdline++;\n"
" if (*cmdline) cmdline++;\n"
" GetStartupInfoA( &info );\n"
" if (!(info.dwFlags & STARTF_USESHOWWINDOW)) info.wShowWindow = 1;\n"
" ExitProcess( %s( GetModuleHandleA(0), 0, cmdline, info.wShowWindow ) );\n"
"}\n\n", init_func, init_func );
fprintf( outfile,
"int main( int argc, char *argv[] )\n"
"{\n"
" extern void PROCESS_InitWinelib( int, char ** );\n"
" PROCESS_InitWinelib( argc, argv );\n"
" return 1;\n"
"}\n\n" );
init_func = "exe_main";
break;
case SPEC_MODE_CUIEXE:
if (!init_func) init_func = "wine_main";
fprintf( outfile,
"\n#include <winbase.h>\n"
"static void exe_main(void)\n"
"{\n"
" extern int %s( int argc, char *argv[] );\n"
" extern int _ARGC;\n"
" extern char **_ARGV;\n"
" ExitProcess( %s( _ARGC, _ARGV ) );\n"
"}\n\n", init_func, init_func );
fprintf( outfile,
"int main( int argc, char *argv[] )\n"
"{\n"
" extern void PROCESS_InitWinelib( int, char ** );\n"
" PROCESS_InitWinelib( argc, argv );\n"
" return 1;\n"
"}\n\n" );
init_func = "exe_main";
break;
}
/* Output the DLL descriptor */
if (rsrc_name[0]) fprintf( outfile, "extern char %s[];\n\n", rsrc_name );
fprintf( outfile, "static const BUILTIN32_DESCRIPTOR descriptor =\n{\n" );
fprintf( outfile, " \"%s\",\n", DLLFileName );
fprintf( outfile, " %d,\n", nb_imports );
fprintf( outfile, " pe_header,\n" );
fprintf( outfile, " %s,\n", nr_exports ? "&exports" : "0" );
fprintf( outfile, " %s,\n", nr_exports ? "sizeof(exports.exp)" : "0" );
fprintf( outfile, " %s,\n", nb_imports ? "Imports" : "0" );
fprintf( outfile, " %s,\n", init_func ? init_func : "0" );
fprintf( outfile, " %d,\n", SpecMode == SPEC_MODE_DLL ? IMAGE_FILE_DLL : 0 );
fprintf( outfile, " %s\n", rsrc_name[0] ? rsrc_name : "0" );
fprintf( outfile, "};\n" );
/* Output the DLL constructor */
fprintf( outfile, "#ifdef __GNUC__\n" );
fprintf( outfile, "static void %s_init(void) __attribute__((constructor));\n", DLLName );
fprintf( outfile, "#else /* defined(__GNUC__) */\n" );
fprintf( outfile, "static void __asm__dummy_dll_init(void) {\n" );
fprintf( outfile, "asm(\"\\t.section\t.init ,\\\"ax\\\"\\n\"\n" );
fprintf( outfile, " \"\\tcall %s_init\\n\"\n", DLLName );
fprintf( outfile, " \"\\t.previous\\n\");\n" );
fprintf( outfile, "}\n" );
fprintf( outfile, "#endif /* defined(__GNUC__) */\n" );
fprintf( outfile, "static void %s_init(void) { BUILTIN32_RegisterDLL( &descriptor ); }\n",
DLLName );
}

79
tools/winebuild/utils.c Normal file
View File

@ -0,0 +1,79 @@
/* small utility functions for winebuild */
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "build.h"
void *xmalloc (size_t size)
{
void *res;
res = malloc (size ? size : 1);
if (res == NULL)
{
fprintf (stderr, "Virtual memory exhausted.\n");
exit (1);
}
return res;
}
void *xrealloc (void *ptr, size_t size)
{
void *res = realloc (ptr, size);
if (res == NULL)
{
fprintf (stderr, "Virtual memory exhausted.\n");
exit (1);
}
return res;
}
char *xstrdup( const char *str )
{
char *res = strdup( str );
if (!res)
{
fprintf (stderr, "Virtual memory exhausted.\n");
exit (1);
}
return res;
}
char *strupper(char *s)
{
char *p;
for (p = s; *p; p++) *p = toupper(*p);
return s;
}
void fatal_error( const char *msg, ... )
{
va_list valist;
va_start( valist, msg );
if (input_file_name && current_line)
fprintf( stderr, "%s:%d: ", input_file_name, current_line );
vfprintf( stderr, msg, valist );
va_end( valist );
exit(1);
}
/* dump a byte stream into the assembly code */
void dump_bytes( FILE *outfile, const unsigned char *data, int len, const char *label )
{
int i;
fprintf( outfile, "\nstatic unsigned char %s[] = \n{", label );
for (i = 0; i < len; i++)
{
if (!(i & 0x0f)) fprintf( outfile, "\n " );
fprintf( outfile, "%d", *data++ );
if (i < len - 1) fprintf( outfile, ", " );
}
fprintf( outfile, "\n};\n" );
}