Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
5cb97d83
Commit
5cb97d83
authored
Sep 21, 2005
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Generate 16-bit spec files as assembly code too.
parent
331e09c2
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
562 additions
and
734 deletions
+562
-734
Make.rules.in
Make.rules.in
+5
-4
Makefile.in
Makefile.in
+2
-2
Makedll.rules.in
dlls/Makedll.rules.in
+5
-5
Makefile.in
dlls/gdi/Makefile.in
+2
-2
Makefile.in
dlls/kernel/Makefile.in
+5
-10
Makefile.in
dlls/ntdll/Makefile.in
+3
-8
Makefile.in
dlls/shell32/Makefile.in
+2
-2
Makefile.in
dlls/user/Makefile.in
+6
-6
build.h
tools/winebuild/build.h
+2
-8
res16.c
tools/winebuild/res16.c
+41
-137
spec16.c
tools/winebuild/spec16.c
+489
-550
No files found.
Make.rules.in
View file @
5cb97d83
...
...
@@ -59,6 +59,7 @@ EXTRACFLAGS = @EXTRACFLAGS@
ALLCFLAGS = $(INCLUDES) $(DEFS) $(DLLFLAGS) $(EXTRACFLAGS) $(CPPFLAGS) $(CFLAGS) $(MODCFLAGS)
ALLLINTFLAGS = $(INCLUDES) $(DEFS) $(LINTFLAGS)
IDLFLAGS = $(INCLUDES) $(DEFS) $(EXTRAIDLFLAGS)
WINEBUILDFLAGS = $(DLLFLAGS) --as-cmd "$(AS)"
MKINSTALLDIRS= $(TOPSRCDIR)/tools/mkinstalldirs -m 755
WINAPI_CHECK = $(TOPSRCDIR)/tools/winapi/winapi_check
WINEWRAPPER = $(TOPSRCDIR)/tools/winewrapper
...
...
@@ -107,7 +108,7 @@ prog_manext = 1
api_manext = 3w
conf_manext = 5
CLEAN_FILES = *.o *.a *.so *.ln *.$(LIBEXT) \\\#*\\\# *~ *% .\\\#* *.bak *.orig *.rej \
*.flc *.
spec.c *.
dbg.c *.tab.c *.tab.h @LEX_OUTPUT_ROOT@.c core
*.flc *.dbg.c *.tab.c *.tab.h @LEX_OUTPUT_ROOT@.c core
OBJS = $(C_SRCS:.c=.o) $(EXTRA_OBJS)
...
...
@@ -116,7 +117,7 @@ LINTS = $(C_SRCS:.c=.ln)
# Implicit rules
.SUFFIXES: .mc .rc .mc.rc .res .res.o .spec .spec.
c
.idl .tlb .h .ok .sfd .ttf
.SUFFIXES: .mc .rc .mc.rc .res .res.o .spec .spec.
o
.idl .tlb .h .ok .sfd .ttf
.c.o:
$(CC) -c $(ALLCFLAGS) -o $@ $<
...
...
@@ -133,8 +134,8 @@ LINTS = $(C_SRCS:.c=.ln)
.res.res.o:
$(WINDRES) -i $< -o $@
.spec.spec.
c
:
$(WINEBUILD) $(
DEF
S) --dll -o $@ --main-module $(MODULE) --export $<
.spec.spec.
o
:
$(WINEBUILD) $(
WINEBUILDFLAG
S) --dll -o $@ --main-module $(MODULE) --export $<
.idl.h:
$(WIDL) $(IDLFLAGS) -h -H $@ $<
...
...
Makefile.in
View file @
5cb97d83
...
...
@@ -136,10 +136,10 @@ $(TESTSUBDIRS:%=%/__crosstest__): tools include
# Misc rules
TAGS etags
:
find
$(TOPSRCDIR)
-name
'*.[ch]'
-a
-not
-name
'*.
spec.c'
-a
-not
-name
'*.
dbg.c'
-print
| etags -
find
$(TOPSRCDIR)
-name
'*.[ch]'
-a
-not
-name
'*.dbg.c'
-print
| etags -
tags ctags
:
find
$(TOPSRCDIR)
-name
'*.[ch]'
-a
-not
-name
'*.
spec.c'
-a
-not
-name
'*.
dbg.c'
-print
| ctags
--c-types
=
+px
-L
-
find
$(TOPSRCDIR)
-name
'*.[ch]'
-a
-not
-name
'*.dbg.c'
-print
| ctags
--c-types
=
+px
-L
-
manpages htmlpages sgmlpages
:
cd
documentation
&&
$(MAKE)
$@
...
...
dlls/Makedll.rules.in
View file @
5cb97d83
...
...
@@ -67,7 +67,7 @@ lib$(BASEMODULE).a: $(SPEC_DEF) $(IMPLIB_OBJS)
$(WIN16_FILES:%=__checklink16__%): checklink16
checklink16:: $(MAINSPEC).o $(OBJS) $(MODULE).dbg.o dummy
$(CC) -o checklink -Wl,-rpath,$(TOPOBJDIR)/libs $(TOPSRCDIR)/dlls/checklink.c $(MAINSPEC).o $(OBJS) $(MODULE).dbg.o -L$(DLLDIR) $(ALL_LIBS) -lwinecrt0 -lm && $(RM) checklink $(MAINSPEC).
s $(MAINSPEC).
o
$(CC) -o checklink -Wl,-rpath,$(TOPOBJDIR)/libs $(TOPSRCDIR)/dlls/checklink.c $(MAINSPEC).o $(OBJS) $(MODULE).dbg.o -L$(DLLDIR) $(ALL_LIBS) -lwinecrt0 -lm && $(RM) checklink $(MAINSPEC).o
checklink:: $(WIN16_FILES:%=__checklink16__%)
...
...
@@ -77,10 +77,10 @@ check test:: $(SUBDIRS:%=%/__test__)
crosstest:: $(SUBDIRS:%=%/__crosstest__)
# Rule to explicitly generate the .spec.
c
for debugging
# Rule to explicitly generate the .spec.
s
for debugging
$(MAINSPEC).s: $(MAINSPEC) $(ALL_OBJS)
$(WINEBUILD) $(
DEFS) $(DLL
FLAGS) --dll -o $@ --export $(SRCDIR)/$(MAINSPEC) $(SUBSYSTEM:%=--subsystem %) $(ALL_OBJS) $(DLL_LDPATH) $(ALL_IMPORTS:%=-l%) $(DELAYIMPORTS:%=-d%) $(DLLDIR)/libwinecrt0.a
$(MAINSPEC).s
$(MAINSPEC).o
: $(MAINSPEC) $(ALL_OBJS)
$(WINEBUILD) $(
WINEBUILD
FLAGS) --dll -o $@ --export $(SRCDIR)/$(MAINSPEC) $(SUBSYSTEM:%=--subsystem %) $(ALL_OBJS) $(DLL_LDPATH) $(ALL_IMPORTS:%=-l%) $(DELAYIMPORTS:%=-d%) $(DLLDIR)/libwinecrt0.a
# Rules for auto documentation
...
...
@@ -137,6 +137,6 @@ uninstall::
clean::
$(RM) $(SPEC_DEF)
$(SPEC_DEF) $(SPEC_SRCS16:.spec=.spec.
c
): $(WINEBUILD)
$(SPEC_DEF) $(SPEC_SRCS16:.spec=.spec.
o
): $(WINEBUILD)
# End of global dll rules
dlls/gdi/Makefile.in
View file @
5cb97d83
...
...
@@ -71,8 +71,8 @@ EXTRASUBDIRS = \
# Special rules for 16-bit resource and spec files
gdi.exe.spec.
c
:
gdi.exe.spec version16.res
$(WINEBUILD)
$(
DEFS)
$(DLL
FLAGS)
--dll
-o
$@
--heap
65520
--main-module
$(MODULE)
--res
version16.res
--export
$(SRCDIR)
/gdi.exe.spec
gdi.exe.spec.
o
:
gdi.exe.spec version16.res
$(WINEBUILD)
$(
WINEBUILD
FLAGS)
--dll
-o
$@
--heap
65520
--main-module
$(MODULE)
--res
version16.res
--export
$(SRCDIR)
/gdi.exe.spec
version16.res
:
version16.rc
$(LDPATH)
$(RC16)
$(RC16FLAGS)
-fo
$@
$(SRCDIR)
/version16.rc
...
...
dlls/kernel/Makefile.in
View file @
5cb97d83
...
...
@@ -84,8 +84,6 @@ C_SRCS16 = \
toolhelp16.c
\
win87em.c
ASM_SRCS
=
relay16asm.s
RC_SRCS
=
kernel.rc
RC_SRCS16
=
\
...
...
@@ -94,7 +92,7 @@ RC_SRCS16 = \
MC_SRCS
=
\
messages/winerr_enu.mc
EXTRA_OBJS
=
$
(
ASM_SRCS:.s
=
.o
)
EXTRA_OBJS
=
relay16asm.o
SUBDIRS
=
tests
EXTRASUBDIRS
=
messages nls
...
...
@@ -102,18 +100,15 @@ EXTRASUBDIRS = messages nls
kernel.res
:
$(MC_SRCS:.mc=.mc.rc)
relay16asm.
s
:
$(WINEBUILD)
$(WINEBUILD)
$(
DEFS)
$(DLL
FLAGS)
-o
$@
--relay16
relay16asm.
o
:
$(WINEBUILD)
$(WINEBUILD)
$(
WINEBUILD
FLAGS)
-o
$@
--relay16
# Special rules for 16-bit resource and spec files
krnl386.exe.spec.
c
:
krnl386.exe.spec version16.res
$(WINEBUILD)
$(
DEFS)
$(DLL
FLAGS)
--dll
-o
$@
--dll-name
kernel
--main-module
$(MODULE)
--res
version16.res
--export
$(SRCDIR)
/krnl386.exe.spec
krnl386.exe.spec.
o
:
krnl386.exe.spec version16.res
$(WINEBUILD)
$(
WINEBUILD
FLAGS)
--dll
-o
$@
--dll-name
kernel
--main-module
$(MODULE)
--res
version16.res
--export
$(SRCDIR)
/krnl386.exe.spec
version16.res
:
version16.rc
$(LDPATH)
$(RC16)
$(RC16FLAGS)
-fo
$@
$(SRCDIR)
/version16.rc
clean
::
$(RM)
$(ASM_SRCS)
### Dependencies:
dlls/ntdll/Makefile.in
View file @
5cb97d83
...
...
@@ -49,18 +49,13 @@ C_SRCS = \
virtual.c
\
wcstring.c
ASM_SRCS
=
relay32.s
EXTRA_OBJS
=
$
(
ASM_SRCS:.s
=
.o
)
EXTRA_OBJS
=
relay32.o
SUBDIRS
=
tests
@MAKE_DLL_RULES@
relay32.s
:
$(WINEBUILD)
$(WINEBUILD)
$(DEFS)
$(DLLFLAGS)
-o
$@
--relay32
clean
::
$(RM)
$(ASM_SRCS)
relay32.o
:
$(WINEBUILD)
$(WINEBUILD)
$(WINEBUILDFLAGS)
-o
$@
--relay32
### Dependencies:
dlls/shell32/Makefile.in
View file @
5cb97d83
...
...
@@ -81,8 +81,8 @@ SUBDIRS = tests
version16.res
:
version16.rc
$(LDPATH)
$(RC16)
$(RC16FLAGS)
-fo
$@
$(SRCDIR)
/version16.rc
shell.spec.
c
:
shell.spec version16.res
$(WINEBUILD)
$(
DEFS)
$(DLL
FLAGS)
--dll
-o
$@
--main-module
$(MODULE)
--res
version16.res
--export
$(SRCDIR)
/shell.spec
shell.spec.
o
:
shell.spec version16.res
$(WINEBUILD)
$(
WINEBUILD
FLAGS)
--dll
-o
$@
--main-module
$(MODULE)
--res
version16.res
--export
$(SRCDIR)
/shell.spec
authors.c
:
$(TOPSRCDIR)/AUTHORS
(
LC_ALL
=
C
;
export
LC_ALL
;
echo
'const char * const SHELL_Authors[] = {'
&&
\
...
...
dlls/user/Makefile.in
View file @
5cb97d83
...
...
@@ -152,14 +152,14 @@ EXTRASUBDIRS = resources
# Special rules for 16-bit resource and spec files
user.exe.spec.
c
:
user.exe.spec resources/version16.res
$(WINEBUILD)
$(
DEFS)
$(DLL
FLAGS)
--dll
-o
$@
--heap
65520
--main-module
$(MODULE)
--res
resources/version16.res
--export
$(SRCDIR)
/user.exe.spec
user.exe.spec.
o
:
user.exe.spec resources/version16.res
$(WINEBUILD)
$(
WINEBUILD
FLAGS)
--dll
-o
$@
--heap
65520
--main-module
$(MODULE)
--res
resources/version16.res
--export
$(SRCDIR)
/user.exe.spec
display.drv.spec.
c
:
display.drv.spec resources/display.res
$(WINEBUILD)
$(
DEFS)
$(DLL
FLAGS)
--dll
-o
$@
--main-module
$(MODULE)
--res
resources/display.res
--export
$(SRCDIR)
/display.drv.spec
display.drv.spec.
o
:
display.drv.spec resources/display.res
$(WINEBUILD)
$(
WINEBUILD
FLAGS)
--dll
-o
$@
--main-module
$(MODULE)
--res
resources/display.res
--export
$(SRCDIR)
/display.drv.spec
mouse.drv.spec.
c
:
mouse.drv.spec resources/mouse.res
$(WINEBUILD)
$(
DEFS)
$(DLL
FLAGS)
--dll
-o
$@
--main-module
$(MODULE)
--res
resources/mouse.res
--export
$(SRCDIR)
/mouse.drv.spec
mouse.drv.spec.
o
:
mouse.drv.spec resources/mouse.res
$(WINEBUILD)
$(
WINEBUILD
FLAGS)
--dll
-o
$@
--main-module
$(MODULE)
--res
resources/mouse.res
--export
$(SRCDIR)
/mouse.drv.spec
resources/display.res
:
resources/display.rc
$(LDPATH)
$(RC16)
$(RC16FLAGS)
-fo
$@
$(SRCDIR)
/resources/display.rc
...
...
tools/winebuild/build.h
View file @
5cb97d83
...
...
@@ -70,7 +70,6 @@ typedef struct
{
ORD_TYPE
type
;
int
ordinal
;
int
offset
;
int
lineno
;
int
flags
;
char
*
name
;
/* public name of this function */
...
...
@@ -206,13 +205,8 @@ extern void output_imports( FILE *outfile, DLLSPEC *spec );
extern
int
load_res32_file
(
const
char
*
name
,
DLLSPEC
*
spec
);
extern
void
output_resources
(
FILE
*
outfile
,
DLLSPEC
*
spec
);
extern
void
load_res16_file
(
const
char
*
name
,
DLLSPEC
*
spec
);
extern
unsigned
int
get_res16_data_size
(
DLLSPEC
*
spec
,
unsigned
int
res_offset
,
unsigned
int
alignment
);
extern
unsigned
int
output_res16_data
(
unsigned
char
**
ret_buf
,
DLLSPEC
*
spec
,
unsigned
int
res_offset
,
unsigned
int
alignment
);
extern
unsigned
int
get_res16_directory_size
(
DLLSPEC
*
spec
);
extern
unsigned
int
output_res16_directory
(
unsigned
char
**
ret_buf
,
DLLSPEC
*
spec
,
unsigned
int
res_offset
,
unsigned
int
alignment
);
extern
void
output_res16_data
(
FILE
*
outfile
,
DLLSPEC
*
spec
);
extern
void
output_res16_directory
(
FILE
*
outfile
,
DLLSPEC
*
spec
,
const
char
*
header_name
);
extern
void
output_dll_init
(
FILE
*
outfile
,
const
char
*
constructor
,
const
char
*
destructor
);
extern
void
BuildRelays16
(
FILE
*
outfile
);
...
...
tools/winebuild/res16.c
View file @
5cb97d83
...
...
@@ -241,189 +241,93 @@ static void free_resource_tree( struct res_tree *tree )
free
(
tree
);
}
inline
static
void
put_byte
(
unsigned
char
**
buffer
,
unsigned
char
val
)
{
*
(
*
buffer
)
++
=
val
;
}
inline
static
void
put_word
(
unsigned
char
**
buffer
,
WORD
val
)
{
#ifdef WORDS_BIGENDIAN
put_byte
(
buffer
,
HIBYTE
(
val
)
);
put_byte
(
buffer
,
LOBYTE
(
val
)
);
#else
put_byte
(
buffer
,
LOBYTE
(
val
)
);
put_byte
(
buffer
,
HIBYTE
(
val
)
);
#endif
}
/* output a string preceded by its length */
static
void
output_string
(
unsigned
char
**
buffer
,
const
char
*
str
)
static
void
output_string
(
FILE
*
outfile
,
const
char
*
str
)
{
int
len
=
strlen
(
str
);
put_byte
(
buffer
,
len
);
while
(
len
--
)
put_byte
(
buffer
,
*
str
++
);
}
/* get the resource data total size */
unsigned
int
get_res16_data_size
(
DLLSPEC
*
spec
,
unsigned
int
res_offset
,
unsigned
int
alignment
)
{
const
struct
resource
*
res
;
unsigned
int
i
,
total
;
unsigned
int
align_mask
=
(
1
<<
alignment
)
-
1
;
if
(
!
spec
->
nb_resources
)
return
0
;
/* add padding at the beginning if needed so that resources are properly aligned */
total
=
((
res_offset
+
align_mask
)
&
~
align_mask
)
-
res_offset
;
for
(
i
=
0
,
res
=
spec
->
resources
;
i
<
spec
->
nb_resources
;
i
++
,
res
++
)
total
+=
(
res
->
data_size
+
align_mask
)
&
~
align_mask
;
return
total
;
unsigned
int
i
,
len
=
strlen
(
str
);
fprintf
(
outfile
,
"
\t
.byte 0x%02x"
,
len
);
for
(
i
=
0
;
i
<
len
;
i
++
)
fprintf
(
outfile
,
",0x%02x"
,
(
unsigned
char
)
str
[
i
]
);
fprintf
(
outfile
,
" /* %s */
\n
"
,
str
);
}
/* output the resource data */
unsigned
int
output_res16_data
(
unsigned
char
**
ret_buf
,
DLLSPEC
*
spec
,
unsigned
int
res_offset
,
unsigned
int
alignment
)
void
output_res16_data
(
FILE
*
outfile
,
DLLSPEC
*
spec
)
{
const
struct
resource
*
res
;
unsigned
char
*
p
;
unsigned
int
i
,
total
,
padding
;
unsigned
int
align_mask
=
(
1
<<
alignment
)
-
1
;
if
(
!
spec
->
nb_resources
)
return
0
;
/* add padding at the beginning if needed so that resources are properly aligned */
padding
=
((
res_offset
+
align_mask
)
&
~
align_mask
)
-
res_offset
;
unsigned
int
i
;
for
(
i
=
total
=
0
,
res
=
spec
->
resources
;
i
<
spec
->
nb_resources
;
i
++
,
res
++
)
total
+=
(
res
->
data_size
+
align_mask
)
&
~
align_mask
;
if
(
!
spec
->
nb_resources
)
return
;
*
ret_buf
=
p
=
xmalloc
(
total
+
padding
);
memset
(
p
,
0
,
padding
);
p
+=
padding
;
for
(
i
=
0
,
res
=
spec
->
resources
;
i
<
spec
->
nb_resources
;
i
++
,
res
++
)
{
unsigned
int
size
=
(
res
->
data_size
+
align_mask
)
&
~
align_mask
;
memcpy
(
p
,
res
->
data
,
res
->
data_size
);
memset
(
p
+
res
->
data_size
,
0
,
size
-
res
->
data_size
);
p
+=
size
;
fprintf
(
outfile
,
".L__wine_spec_resource_%u:
\n
"
,
i
);
dump_bytes
(
outfile
,
res
->
data
,
res
->
data_size
);
fprintf
(
outfile
,
".L__wine_spec_resource_%u_end:
\n
"
,
i
);
}
return
total
;
}
/* get the resource definitions total size */
unsigned
int
get_res16_directory_size
(
DLLSPEC
*
spec
)
{
unsigned
int
i
,
j
,
total_size
;
struct
res_tree
*
tree
;
const
struct
res_type
*
type
;
const
struct
resource
*
res
;
tree
=
build_resource_tree
(
spec
);
total_size
=
4
;
/* alignment + terminator */
total_size
+=
tree
->
nb_types
*
8
;
/* typeinfo structures */
total_size
+=
spec
->
nb_resources
*
12
;
/* nameinfo structures */
for
(
i
=
0
,
type
=
tree
->
types
;
i
<
tree
->
nb_types
;
i
++
,
type
++
)
{
if
(
type
->
type
->
str
)
total_size
+=
strlen
(
type
->
type
->
str
)
+
1
;
for
(
j
=
0
,
res
=
type
->
res
;
j
<
type
->
nb_names
;
j
++
,
res
++
)
if
(
res
->
name
.
str
)
total_size
+=
strlen
(
res
->
name
.
str
)
+
1
;
}
total_size
++
;
/* final terminator */
if
(
total_size
&
1
)
total_size
++
;
return
total_size
;
}
/* output the resource definitions */
unsigned
int
output_res16_directory
(
unsigned
char
**
ret_buf
,
DLLSPEC
*
spec
,
unsigned
int
res_offset
,
unsigned
int
alignment
)
void
output_res16_directory
(
FILE
*
outfile
,
DLLSPEC
*
spec
,
const
char
*
header_name
)
{
int
offset
;
unsigned
int
i
,
j
,
total_size
;
unsigned
int
align_mask
=
(
1
<<
alignment
)
-
1
;
unsigned
int
i
,
j
;
struct
res_tree
*
tree
;
const
struct
res_type
*
type
;
const
struct
resource
*
res
;
unsigned
char
*
buffer
;
tree
=
build_resource_tree
(
spec
);
/* make sure data offset is properly aligned */
res_offset
=
(
res_offset
+
align_mask
)
&
~
align_mask
;
/* first compute total size */
offset
=
4
;
/* alignment + terminator */
offset
+=
tree
->
nb_types
*
8
;
/* typeinfo structures */
offset
+=
spec
->
nb_resources
*
12
;
/* nameinfo structures */
total_size
=
offset
;
for
(
i
=
0
,
type
=
tree
->
types
;
i
<
tree
->
nb_types
;
i
++
,
type
++
)
{
if
(
type
->
type
->
str
)
total_size
+=
strlen
(
type
->
type
->
str
)
+
1
;
for
(
j
=
0
,
res
=
type
->
res
;
j
<
type
->
nb_names
;
j
++
,
res
++
)
if
(
res
->
name
.
str
)
total_size
+=
strlen
(
res
->
name
.
str
)
+
1
;
}
total_size
++
;
/* final terminator */
if
(
total_size
&
1
)
total_size
++
;
*
ret_buf
=
buffer
=
xmalloc
(
total_size
);
put_word
(
&
buffer
,
alignment
);
fprintf
(
outfile
,
"
\n
.L__wine_spec_ne_rsrctab:
\n
"
);
fprintf
(
outfile
,
"
\t
%s 0
\n
"
,
get_asm_short_keyword
()
);
/* alignment */
/* type and name structures */
for
(
i
=
0
,
type
=
tree
->
types
;
i
<
tree
->
nb_types
;
i
++
,
type
++
)
{
if
(
type
->
type
->
str
)
{
put_word
(
&
buffer
,
offset
);
offset
+=
strlen
(
type
->
type
->
str
)
+
1
;
}
fprintf
(
outfile
,
"
\t
%s .L__wine_spec_restype_%u-.L__wine_spec_ne_rsrctab
\n
"
,
get_asm_short_keyword
(),
i
);
else
put_word
(
&
buffer
,
type
->
type
->
id
|
0x8000
);
fprintf
(
outfile
,
"
\t
%s 0x%04x
\n
"
,
get_asm_short_keyword
()
,
type
->
type
->
id
|
0x8000
);
put_word
(
&
buffer
,
type
->
nb_names
);
put_word
(
&
buffer
,
0
);
put_word
(
&
buffer
,
0
);
fprintf
(
outfile
,
"
\t
%s %u,0,0
\n
"
,
get_asm_short_keyword
(),
type
->
nb_names
);
for
(
j
=
0
,
res
=
type
->
res
;
j
<
type
->
nb_names
;
j
++
,
res
++
)
{
put_word
(
&
buffer
,
res_offset
>>
alignment
);
put_word
(
&
buffer
,
(
res
->
data_size
+
align_mask
)
>>
alignment
);
put_word
(
&
buffer
,
res
->
memopt
);
fprintf
(
outfile
,
"
\t
%s .L__wine_spec_resource_%u-%s
\n
"
,
get_asm_short_keyword
(),
res
-
spec
->
resources
,
header_name
);
fprintf
(
outfile
,
"
\t
%s .L__wine_spec_resource_%u_end-.L__wine_spec_resource_%u
\n
"
,
get_asm_short_keyword
(),
res
-
spec
->
resources
,
res
-
spec
->
resources
);
fprintf
(
outfile
,
"
\t
%s 0x%04x
\n
"
,
get_asm_short_keyword
(),
res
->
memopt
);
if
(
res
->
name
.
str
)
{
put_word
(
&
buffer
,
offset
);
offset
+=
strlen
(
res
->
name
.
str
)
+
1
;
}
fprintf
(
outfile
,
"
\t
%s .L__wine_spec_resname_%u_%u-.L__wine_spec_ne_rsrctab
\n
"
,
get_asm_short_keyword
(),
i
,
j
);
else
put_word
(
&
buffer
,
res
->
name
.
id
|
0x8000
);
put_word
(
&
buffer
,
0
);
put_word
(
&
buffer
,
0
);
res_offset
+=
(
res
->
data_size
+
align_mask
)
&
~
align_mask
;
fprintf
(
outfile
,
"
\t
%s 0x%04x
\n
"
,
get_asm_short_keyword
(),
res
->
name
.
id
|
0x8000
);
fprintf
(
outfile
,
"
\t
%s 0,0
\n
"
,
get_asm_short_keyword
()
);
}
}
put_word
(
&
buffer
,
0
);
/* terminator */
fprintf
(
outfile
,
"
\t
%s 0
\n
"
,
get_asm_short_keyword
()
);
/* terminator */
/* name strings */
for
(
i
=
0
,
type
=
tree
->
types
;
i
<
tree
->
nb_types
;
i
++
,
type
++
)
{
if
(
type
->
type
->
str
)
output_string
(
&
buffer
,
type
->
type
->
str
);
if
(
type
->
type
->
str
)
{
fprintf
(
outfile
,
".L__wine_spec_restype_%u:
\n
"
,
i
);
output_string
(
outfile
,
type
->
type
->
str
);
}
for
(
j
=
0
,
res
=
type
->
res
;
j
<
type
->
nb_names
;
j
++
,
res
++
)
{
if
(
res
->
name
.
str
)
output_string
(
&
buffer
,
res
->
name
.
str
);
if
(
res
->
name
.
str
)
{
fprintf
(
outfile
,
".L__wine_spec_resname_%u_%u:
\n
"
,
i
,
j
);
output_string
(
outfile
,
res
->
name
.
str
);
}
}
}
put_byte
(
&
buffer
,
0
);
/* names terminator */
if
((
buffer
-
*
ret_buf
)
&
1
)
put_byte
(
&
buffer
,
0
);
/* align on word boundary */
assert
(
buffer
-
*
ret_buf
==
total_size
);
fprintf
(
outfile
,
"
\t
.byte 0
\n
"
);
/* names terminator */
free_resource_tree
(
tree
);
return
total_size
;
}
tools/winebuild/spec16.c
View file @
5cb97d83
...
...
@@ -32,40 +32,72 @@
#include "build.h"
/* sequences of nops to fill a certain number of words */
static
const
char
*
const
nop_sequence
[
4
]
=
{
".byte 0x89,0xf6"
,
/* mov %esi,%esi */
".byte 0x8d,0x74,0x26,0x00"
,
/* lea 0x00(%esi),%esi */
".byte 0x8d,0xb6,0x00,0x00,0x00,0x00"
,
/* lea 0x00000000(%esi),%esi */
".byte 0x8d,0x74,0x26,0x00,0x8d,0x74,0x26,0x00"
/* lea 0x00(%esi),%esi; lea 0x00(%esi),%esi */
};
static
inline
int
is_function
(
const
ORDDEF
*
odp
)
{
return
(
odp
->
type
==
TYPE_CDECL
||
odp
->
type
==
TYPE_PASCAL
||
odp
->
type
==
TYPE_VARARGS
||
odp
->
type
==
TYPE_STUB
);
}
/*******************************************************************
* output_
file_header
* output_
entries
*
* Output
a file header with the common declarations we need
.
* Output
entries for individual symbols in the entry table
.
*/
static
void
output_
file_header
(
FILE
*
outfile
)
static
void
output_
entries
(
FILE
*
outfile
,
DLLSPEC
*
spec
,
int
first
,
int
count
)
{
output_standard_file_header
(
outfile
);
fprintf
(
outfile
,
"extern struct
\n
{
\n
"
);
fprintf
(
outfile
,
" void *base[8192];
\n
"
);
fprintf
(
outfile
,
" unsigned long limit[8192];
\n
"
);
fprintf
(
outfile
,
" unsigned char flags[8192];
\n
"
);
fprintf
(
outfile
,
"} wine_ldt_copy;
\n\n
"
);
fprintf
(
outfile
,
"#define __stdcall __attribute__((__stdcall__))
\n\n
"
);
int
i
;
for
(
i
=
0
;
i
<
count
;
i
++
)
{
ORDDEF
*
odp
=
spec
->
ordinals
[
first
+
i
];
fprintf
(
outfile
,
"
\t
.byte 0x03
\n
"
);
/* flags: exported & public data */
switch
(
odp
->
type
)
{
case
TYPE_CDECL
:
case
TYPE_PASCAL
:
case
TYPE_VARARGS
:
case
TYPE_STUB
:
fprintf
(
outfile
,
"
\t
%s .L__wine_%s_%u-.L__wine_spec_code_segment
\n
"
,
get_asm_short_keyword
(),
make_c_identifier
(
spec
->
dll_name
),
first
+
i
);
break
;
case
TYPE_VARIABLE
:
fprintf
(
outfile
,
"
\t
%s .L__wine_%s_%u-.L__wine_spec_data_segment
\n
"
,
get_asm_short_keyword
(),
make_c_identifier
(
spec
->
dll_name
),
first
+
i
);
break
;
case
TYPE_ABS
:
fprintf
(
outfile
,
"
\t
%s 0x%04x /* %s */
\n
"
,
get_asm_short_keyword
(),
odp
->
u
.
abs
.
value
,
odp
->
name
);
break
;
default:
assert
(
0
);
}
}
}
/*******************************************************************
* output_entry_table
*/
static
int
output_entry_table
(
unsigned
char
**
ret_buff
,
DLLSPEC
*
spec
)
static
void
output_entry_table
(
FILE
*
outfile
,
DLLSPEC
*
spec
)
{
int
i
,
prev
=
0
,
prev_sel
=
-
1
;
unsigned
char
*
pstr
,
*
buffer
;
unsigned
char
*
bundle
=
NULL
;
buffer
=
xmalloc
(
spec
->
limit
*
5
);
/* we use at most 5 bytes per entry-point */
pstr
=
buffer
;
int
i
,
prev
=
0
,
prev_sel
=
-
1
,
bundle_count
=
0
;
for
(
i
=
1
;
i
<=
spec
->
limit
;
i
++
)
{
int
selector
=
0
;
WORD
offset
;
ORDDEF
*
odp
=
spec
->
ordinals
[
i
];
if
(
!
odp
)
continue
;
...
...
@@ -87,64 +119,145 @@ static int output_entry_table( unsigned char **ret_buff, DLLSPEC *spec )
continue
;
}
if
(
!
bundle
||
prev
+
1
!=
i
||
prev_sel
!=
selector
||
*
bundle
==
255
)
if
(
prev
+
1
!=
i
||
prev_sel
!=
selector
||
bundle_count
==
255
)
{
/* need to start a new bundle */
/* flush previous bundle */
if
(
bundle_count
)
{
fprintf
(
outfile
,
"
\t
/* %s.%d - %s.%d */
\n
"
,
spec
->
dll_name
,
prev
-
bundle_count
+
1
,
spec
->
dll_name
,
prev
);
fprintf
(
outfile
,
"
\t
.byte 0x%02x,0x%02x
\n
"
,
bundle_count
,
prev_sel
);
output_entries
(
outfile
,
spec
,
prev
-
bundle_count
+
1
,
bundle_count
);
}
if
(
prev
+
1
!=
i
)
{
int
skip
=
i
-
(
prev
+
1
);
while
(
skip
>
255
)
{
*
pstr
++
=
255
;
*
pstr
++
=
0
;
fprintf
(
outfile
,
"
\t
.byte 0xff,0x00
\n
"
);
skip
-=
255
;
}
*
pstr
++
=
skip
;
*
pstr
++
=
0
;
fprintf
(
outfile
,
"
\t
.byte 0x%02x,0x00
\n
"
,
skip
);
}
bundle
=
pstr
;
*
pstr
++
=
0
;
*
pstr
++
=
selector
;
bundle_count
=
0
;
prev_sel
=
selector
;
}
/* output the entry */
*
pstr
++
=
3
;
/* flags: exported & public data */
offset
=
odp
->
offset
;
memcpy
(
pstr
,
&
offset
,
sizeof
(
WORD
)
);
pstr
+=
sizeof
(
WORD
);
(
*
bundle
)
++
;
/* increment bundle entry count */
bundle_count
++
;
prev
=
i
;
}
*
pstr
++
=
0
;
if
((
pstr
-
buffer
)
&
1
)
*
pstr
++
=
0
;
*
ret_buff
=
xrealloc
(
buffer
,
pstr
-
buffer
);
return
pstr
-
buffer
;
/* flush last bundle */
if
(
bundle_count
)
{
fprintf
(
outfile
,
"
\t
.byte 0x%02x,0x%02x
\n
"
,
bundle_count
,
prev_sel
);
output_entries
(
outfile
,
spec
,
prev
-
bundle_count
+
1
,
bundle_count
);
}
fprintf
(
outfile
,
"
\t
.byte 0x00
\n
"
);
}
/*******************************************************************
* output_resident_name
*/
static
void
output_resident_name
(
FILE
*
outfile
,
const
char
*
string
,
int
ordinal
)
{
unsigned
int
i
,
len
=
strlen
(
string
);
fprintf
(
outfile
,
"
\t
.byte 0x%02x"
,
len
);
for
(
i
=
0
;
i
<
len
;
i
++
)
fprintf
(
outfile
,
",0x%02x"
,
(
unsigned
char
)
toupper
(
string
[
i
])
);
fprintf
(
outfile
,
" /* %s */
\n
"
,
string
);
fprintf
(
outfile
,
"
\t
%s %u
\n
"
,
get_asm_short_keyword
(),
ordinal
);
}
/*******************************************************************
* get_callfrom16_name
*/
static
const
char
*
get_callfrom16_name
(
const
ORDDEF
*
odp
)
{
static
char
buffer
[
80
];
sprintf
(
buffer
,
"%s_%s_%s"
,
(
odp
->
type
==
TYPE_PASCAL
)
?
"p"
:
(
odp
->
type
==
TYPE_VARARGS
)
?
"v"
:
"c"
,
(
odp
->
flags
&
FLAG_REGISTER
)
?
"regs"
:
(
odp
->
flags
&
FLAG_RET16
)
?
"word"
:
"long"
,
odp
->
u
.
func
.
arg_types
);
return
buffer
;
}
/*******************************************************************
* get_relay_name
*/
static
const
char
*
get_relay_name
(
const
ORDDEF
*
odp
)
{
static
char
buffer
[
80
];
char
*
p
;
switch
(
odp
->
type
)
{
case
TYPE_PASCAL
:
strcpy
(
buffer
,
"p_"
);
break
;
case
TYPE_VARARGS
:
strcpy
(
buffer
,
"v_"
);
break
;
case
TYPE_CDECL
:
case
TYPE_STUB
:
strcpy
(
buffer
,
"c_"
);
break
;
default:
assert
(
0
);
}
strcat
(
buffer
,
odp
->
u
.
func
.
arg_types
);
for
(
p
=
buffer
+
2
;
*
p
;
p
++
)
{
/* map string types to the corresponding plain pointer type */
if
(
*
p
==
't'
)
*
p
=
'p'
;
else
if
(
*
p
==
'T'
)
*
p
=
'l'
;
}
if
(
odp
->
flags
&
FLAG_REGISTER
)
strcat
(
buffer
,
"_regs"
);
return
buffer
;
}
/*******************************************************************
*
output_bytes
*
get_function_argsize
*/
static
void
output_bytes
(
FILE
*
outfile
,
const
void
*
buffer
,
unsigned
int
size
)
static
int
get_function_argsize
(
const
ORDDEF
*
odp
)
{
unsigned
int
i
;
const
unsigned
char
*
ptr
=
buffer
;
const
char
*
args
;
int
argsize
=
0
;
fprintf
(
outfile
,
" {"
);
for
(
i
=
0
;
i
<
size
;
i
++
)
for
(
args
=
odp
->
u
.
func
.
arg_types
;
*
args
;
args
++
)
{
switch
(
*
args
)
{
if
(
!
(
i
&
7
))
fprintf
(
outfile
,
"
\n
"
);
fprintf
(
outfile
,
" 0x%02x"
,
*
ptr
++
);
if
(
i
<
size
-
1
)
fprintf
(
outfile
,
","
);
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
;
default:
assert
(
0
);
}
}
fprintf
(
outfile
,
"
\n
},
\n
"
)
;
return
argsize
;
}
/*******************************************************************
*
BuildCallFrom16Func
*
output_call16_function
*
* Build a 16-bit-to-Wine callback glue function.
*
...
...
@@ -152,10 +265,9 @@ static void output_bytes( FILE *outfile, const void *buffer, unsigned int size )
* 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 WORD WINAPI __wine_spec_call16_C_xxx( FARPROC func, LPBYTE args );
* extern LONG WINAPI __wine_spec_call16_C_xxx( FARPROC func, LPBYTE args );
* extern void WINAPI __wine_spec_call16_C_xxx_regs( 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,
...
...
@@ -171,144 +283,106 @@ static void output_bytes( FILE *outfile, const void *buffer, unsigned int size )
* 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.
*/
static
void
BuildCallFrom16Func
(
FILE
*
outfile
,
const
char
*
profile
,
const
char
*
prefix
)
static
void
output_call16_function
(
FILE
*
outfile
,
ORDDEF
*
odp
)
{
int
i
,
pos
,
argsize
=
0
;
int
short_ret
=
0
;
int
reg_func
=
0
;
int
usecdecl
=
0
;
int
varargs
=
0
;
const
char
*
args
=
profile
+
7
;
const
char
*
ret_type
;
char
name
[
256
];
int
i
,
pos
;
const
char
*
args
=
odp
->
u
.
func
.
arg_types
;
int
argsize
=
get_function_argsize
(
odp
);
int
needs_ldt
=
strchr
(
args
,
'p'
)
||
strchr
(
args
,
't'
);
/* Parse function type */
sprintf
(
name
,
".L__wine_spec_call16_%s"
,
get_relay_name
(
odp
)
);
if
(
!
strncmp
(
"c_"
,
profile
,
2
))
usecdecl
=
1
;
else
if
(
!
strncmp
(
"v_"
,
profile
,
2
))
varargs
=
usecdecl
=
1
;
else
if
(
strncmp
(
"p_"
,
profile
,
2
))
fprintf
(
outfile
,
"
\t
.align %d
\n
"
,
get_alignment
(
4
)
);
fprintf
(
outfile
,
"
\t
%s
\n
"
,
func_declaration
(
name
)
);
fprintf
(
outfile
,
"%s:
\n
"
,
name
);
fprintf
(
outfile
,
"
\t
pushl %%ebp
\n
"
);
fprintf
(
outfile
,
"
\t
movl %%esp,%%ebp
\n
"
);
if
(
needs_ldt
)
{
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
(
"long_"
,
profile
+
2
,
5
))
fprintf
(
outfile
,
"
\t
pushl %%esi
\n
"
);
if
(
UsePIC
)
{
fprintf
(
stderr
,
"Invalid function name '%s', ignored
\n
"
,
profile
);
return
;
fprintf
(
outfile
,
"
\t
call 1f
\n
"
);
fprintf
(
outfile
,
"1:
\t
popl %%eax
\n
"
);
fprintf
(
outfile
,
"
\t
movl wine_ldt_copy_ptr-1b(%%eax),%%esi
\n
"
);
}
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
;
else
fprintf
(
outfile
,
"
\t
movl $%s,%%esi
\n
"
,
asm_name
(
"wine_ldt_copy"
)
);
}
ret_type
=
reg_func
?
"void"
:
short_ret
?
"unsigned short"
:
"unsigned int"
;
if
(
args
[
0
]
||
odp
->
type
==
TYPE_VARARGS
)
fprintf
(
outfile
,
"
\t
movl 12(%%ebp),%%ecx
\n
"
);
/* args */
fprintf
(
outfile
,
"typedef %s (%s*proc_%s_t)( "
,
ret_type
,
usecdecl
?
""
:
"__stdcall "
,
profile
);
args
=
profile
+
7
;
for
(
i
=
0
;
args
[
i
];
i
++
)
if
(
odp
->
flags
&
FLAG_REGISTER
)
{
if
(
i
)
fprintf
(
outfile
,
", "
);
switch
(
args
[
i
])
{
case
'w'
:
fprintf
(
outfile
,
"unsigned short"
);
break
;
case
's'
:
fprintf
(
outfile
,
"short"
);
break
;
case
'l'
:
case
'T'
:
fprintf
(
outfile
,
"unsigned int"
);
break
;
case
'p'
:
case
't'
:
fprintf
(
outfile
,
"void *"
);
break
;
fprintf
(
outfile
,
"
\t
pushl 16(%%ebp)
\n
"
);
/* context */
}
else
if
(
odp
->
type
==
TYPE_VARARGS
)
{
fprintf
(
outfile
,
"
\t
leal %d(%%ecx),%%eax
\n
"
,
argsize
);
fprintf
(
outfile
,
"
\t
pushl %%eax
\n
"
);
/* va_list16 */
}
if
(
reg_func
||
varargs
)
fprintf
(
outfile
,
"%svoid *"
,
i
?
", "
:
""
);
else
if
(
!
i
)
fprintf
(
outfile
,
"void"
);
fprintf
(
outfile
,
" );
\n
"
);
fprintf
(
outfile
,
"static %s __wine_%s_CallFrom16_%s( proc_%s_t proc, unsigned char *args%s )
\n
"
,
ret_type
,
make_c_identifier
(
prefix
),
profile
,
profile
,
reg_func
?
", void *context"
:
""
);
fprintf
(
outfile
,
"{
\n
%sproc(
\n
"
,
reg_func
?
""
:
"return "
);
args
=
profile
+
7
;
pos
=
!
usecdecl
?
argsize
:
0
;
for
(
i
=
0
;
args
[
i
];
i
++
)
pos
=
(
odp
->
type
==
TYPE_PASCAL
)
?
0
:
argsize
;
for
(
i
=
strlen
(
args
)
-
1
;
i
>=
0
;
i
--
)
{
if
(
i
)
fprintf
(
outfile
,
",
\n
"
);
fprintf
(
outfile
,
" "
);
switch
(
args
[
i
])
{
case
'w'
:
/* word */
if
(
!
usecdecl
)
pos
-=
2
;
fprintf
(
outfile
,
"*(unsigned short *)(args+%d)"
,
pos
);
if
(
usecdecl
)
pos
+=
2
;
if
(
odp
->
type
!=
TYPE_PASCAL
)
pos
-=
2
;
fprintf
(
outfile
,
"
\t
movzwl %d(%%ecx),%%eax
\n
"
,
pos
);
fprintf
(
outfile
,
"
\t
pushl %%eax
\n
"
);
if
(
odp
->
type
==
TYPE_PASCAL
)
pos
+=
2
;
break
;
case
's'
:
/* s_word */
if
(
!
usecdecl
)
pos
-=
2
;
fprintf
(
outfile
,
"*(short *)(args+%d)"
,
pos
);
if
(
usecdecl
)
pos
+=
2
;
if
(
odp
->
type
!=
TYPE_PASCAL
)
pos
-=
2
;
fprintf
(
outfile
,
"
\t
movswl %d(%%ecx),%%eax
\n
"
,
pos
);
fprintf
(
outfile
,
"
\t
pushl %%eax
\n
"
);
if
(
odp
->
type
==
TYPE_PASCAL
)
pos
+=
2
;
break
;
case
'l'
:
/* long or segmented pointer */
case
'T'
:
/* segmented pointer to null-terminated string */
if
(
!
usecdecl
)
pos
-=
4
;
fprintf
(
outfile
,
"
*(unsigned int *)(args+%d)
"
,
pos
);
if
(
usecdecl
)
pos
+=
4
;
if
(
odp
->
type
!=
TYPE_PASCAL
)
pos
-=
4
;
fprintf
(
outfile
,
"
\t
pushl %d(%%ecx)
\n
"
,
pos
);
if
(
odp
->
type
==
TYPE_PASCAL
)
pos
+=
4
;
break
;
case
'p'
:
/* linear pointer */
case
't'
:
/* linear pointer to null-terminated string */
if
(
!
usecdecl
)
pos
-=
4
;
fprintf
(
outfile
,
"((char*)wine_ldt_copy.base[*(unsigned short*)(args+%d) >> 3] + *(unsigned short*)(args+%d))"
,
pos
+
2
,
pos
);
if
(
usecdecl
)
pos
+=
4
;
if
(
odp
->
type
!=
TYPE_PASCAL
)
pos
-=
4
;
fprintf
(
outfile
,
"
\t
movzwl %d(%%ecx),%%edx
\n
"
,
pos
+
2
);
/* sel */
fprintf
(
outfile
,
"
\t
shr $3,%%edx
\n
"
);
fprintf
(
outfile
,
"
\t
movzwl %d(%%ecx),%%eax
\n
"
,
pos
);
/* offset */
fprintf
(
outfile
,
"
\t
addl (%%esi,%%edx,4),%%eax
\n
"
);
fprintf
(
outfile
,
"
\t
pushl %%eax
\n
"
);
if
(
odp
->
type
==
TYPE_PASCAL
)
pos
+=
4
;
break
;
default:
fprintf
(
stderr
,
"Unknown arg type '%c'
\n
"
,
args
[
i
]
);
assert
(
0
);
}
}
if
(
reg_func
)
fprintf
(
outfile
,
"%s context"
,
i
?
",
\n
"
:
""
);
else
if
(
varargs
)
fprintf
(
outfile
,
"%s args + %d"
,
i
?
",
\n
"
:
""
,
argsize
);
fprintf
(
outfile
,
" );
\n
}
\n\n
"
);
}
fprintf
(
outfile
,
"
\t
call *8(%%ebp)
\n
"
);
/*******************************************************************
* get_function_name
*/
static
const
char
*
get_function_name
(
const
ORDDEF
*
odp
)
{
static
char
buffer
[
80
];
if
(
needs_ldt
)
fprintf
(
outfile
,
"
\t
movl -4(%%ebp),%%esi
\n
"
);
if
(
odp
->
flags
&
FLAG_RET16
)
fprintf
(
outfile
,
"
\t
movzwl %%ax,%%eax
\n
"
);
sprintf
(
buffer
,
"%s_%s_%s"
,
(
odp
->
type
==
TYPE_PASCAL
)
?
"p"
:
(
odp
->
type
==
TYPE_VARARGS
)
?
"v"
:
"c"
,
(
odp
->
flags
&
FLAG_REGISTER
)
?
"regs"
:
(
odp
->
flags
&
FLAG_RET16
)
?
"word"
:
"long"
,
odp
->
u
.
func
.
arg_types
);
return
buffer
;
fprintf
(
outfile
,
"
\t
leave
\n
"
);
fprintf
(
outfile
,
"
\t
ret
\n
"
);
output_function_size
(
outfile
,
name
);
}
/*******************************************************************
* Spec16TypeCompare
* callfrom16_type_compare
*
* Compare two callfrom16 sequences.
*/
static
int
Spec16TypeC
ompare
(
const
void
*
e1
,
const
void
*
e2
)
static
int
callfrom16_type_c
ompare
(
const
void
*
e1
,
const
void
*
e2
)
{
const
ORDDEF
*
odp1
=
*
(
const
ORDDEF
*
const
*
)
e1
;
const
ORDDEF
*
odp2
=
*
(
const
ORDDEF
*
const
*
)
e2
;
...
...
@@ -331,412 +405,284 @@ static int Spec16TypeCompare( const void *e1, const void *e2 )
/*******************************************************************
*
output_stub_funcs
*
relay_type_compare
*
*
Output the functions for stub entry points
*/
static
void
output_stub_funcs
(
FILE
*
outfile
,
const
DLLSPEC
*
spec
)
*
Same as callfrom16_type_compare but ignores differences that don't affect the resulting relay function.
*/
static
int
relay_type_compare
(
const
void
*
e1
,
const
void
*
e2
)
{
int
i
;
char
*
p
;
const
ORDDEF
*
odp1
=
*
(
const
ORDDEF
*
const
*
)
e1
;
const
ORDDEF
*
odp2
=
*
(
const
ORDDEF
*
const
*
)
e2
;
char
name1
[
80
];
for
(
i
=
0
;
i
<=
spec
->
limit
;
i
++
)
{
ORDDEF
*
odp
=
spec
->
ordinals
[
i
];
if
(
!
odp
||
odp
->
type
!=
TYPE_STUB
)
continue
;
fprintf
(
outfile
,
"#ifdef __GNUC__
\n
"
);
fprintf
(
outfile
,
"extern void __wine_spec_unimplemented_stub( const char *module, const char *func ) __attribute__((noreturn));
\n
"
);
fprintf
(
outfile
,
"#else
\n
"
);
fprintf
(
outfile
,
"extern void __wine_spec_unimplemented_stub( const char *module, const char *func );
\n
"
);
fprintf
(
outfile
,
"#endif
\n\n
"
);
break
;
}
for
(
i
=
0
;
i
<=
spec
->
limit
;
i
++
)
{
ORDDEF
*
odp
=
spec
->
ordinals
[
i
];
if
(
!
odp
||
odp
->
type
!=
TYPE_STUB
)
continue
;
odp
->
link_name
=
xrealloc
(
odp
->
link_name
,
strlen
(
odp
->
name
)
+
13
);
strcpy
(
odp
->
link_name
,
"__wine_stub_"
);
strcat
(
odp
->
link_name
,
odp
->
name
);
for
(
p
=
odp
->
link_name
;
*
p
;
p
++
)
if
(
!
isalnum
(
*
p
))
*
p
=
'_'
;
fprintf
(
outfile
,
"static void %s(void) { __wine_spec_unimplemented_stub(__wine_spec16_file_name,
\"
%s
\"
); }
\n
"
,
odp
->
link_name
,
odp
->
name
);
}
strcpy
(
name1
,
get_relay_name
(
odp1
)
);
return
strcmp
(
name1
,
get_relay_name
(
odp2
)
);
}
/*******************************************************************
*
BuildSpec16File
*
sort_func_list
*
*
Build a Win16 assembly file from a spec file
.
*
Sort a list of functions, removing duplicates
.
*/
void
BuildSpec16File
(
FILE
*
outfile
,
DLLSPEC
*
spec
)
static
int
sort_func_list
(
ORDDEF
**
list
,
int
count
,
int
(
*
compare
)(
const
void
*
,
const
void
*
)
)
{
ORDDEF
**
type
,
**
typelist
;
int
i
,
nFuncs
,
nTypes
;
unsigned
char
*
resdir_buffer
,
*
resdata_buffer
,
*
et_buffer
,
*
data_buffer
;
char
string
[
256
];
unsigned
int
ne_offset
,
segtable_offset
,
impnames_offset
;
unsigned
int
entrypoint_size
,
callfrom_size
;
unsigned
int
code_size
,
code_offset
;
unsigned
int
data_size
,
data_offset
;
unsigned
int
resnames_size
,
resnames_offset
;
unsigned
int
resdir_size
,
resdir_offset
;
unsigned
int
resdata_size
,
resdata_offset
,
resdata_align
;
unsigned
int
et_size
,
et_offset
;
char
constructor
[
100
],
destructor
[
100
];
/* File header */
int
i
,
j
;
output_file_header
(
outfile
);
fprintf
(
outfile
,
"static const char __wine_spec16_file_name[] =
\"
%s
\"
;
\n
"
,
spec
->
file_name
);
qsort
(
list
,
count
,
sizeof
(
*
list
),
compare
);
data_buffer
=
xmalloc
(
0x10000
);
memset
(
data_buffer
,
0
,
16
);
data_size
=
16
;
if
(
!
spec
->
dll_name
)
/* set default name from file name */
for
(
i
=
j
=
0
;
i
<
count
;
i
++
)
{
char
*
p
;
spec
->
dll_name
=
xstrdup
(
spec
->
file_name
);
if
((
p
=
strrchr
(
spec
->
dll_name
,
'.'
)))
*
p
=
0
;
if
(
compare
(
&
list
[
j
],
&
list
[
i
]
))
list
[
++
j
]
=
list
[
i
];
}
return
j
+
1
;
}
output_stub_funcs
(
outfile
,
spec
);
/* Build sorted list of all argument types, without duplicates */
/*******************************************************************
* output_init_code
*
* Output the dll initialization code.
*/
static
void
output_init_code
(
FILE
*
outfile
,
const
DLLSPEC
*
spec
,
const
char
*
header_name
)
{
char
name
[
80
];
typelist
=
(
ORDDEF
**
)
calloc
(
spec
->
limit
+
1
,
sizeof
(
ORDDEF
*
)
);
sprintf
(
name
,
".L__wine_spec_%s_init"
,
make_c_identifier
(
spec
->
dll_name
)
);
for
(
i
=
nFuncs
=
0
;
i
<=
spec
->
limit
;
i
++
)
{
ORDDEF
*
odp
=
spec
->
ordinals
[
i
];
if
(
!
odp
)
continue
;
switch
(
odp
->
type
)
fprintf
(
outfile
,
"
\n
/* dll initialization code */
\n\n
"
);
fprintf
(
outfile
,
"
\t
.text
\n
"
);
fprintf
(
outfile
,
"
\t
.align 4
\n
"
);
fprintf
(
outfile
,
"
\t
%s
\n
"
,
func_declaration
(
name
)
);
fprintf
(
outfile
,
"%s:
\n
"
,
name
);
if
(
UsePIC
)
{
case
TYPE_CDECL
:
case
TYPE_PASCAL
:
case
TYPE_VARARGS
:
case
TYPE_STUB
:
typelist
[
nFuncs
++
]
=
odp
;
default:
break
;
fprintf
(
outfile
,
"
\t
call %s
\n
"
,
asm_name
(
"__wine_spec_get_pc_thunk_eax"
)
);
fprintf
(
outfile
,
"1:
\t
leal .L__wine_spec_file_name-1b(%%eax),%%ecx
\n
"
);
fprintf
(
outfile
,
"
\t
pushl %%ecx
\n
"
);
fprintf
(
outfile
,
"
\t
leal %s-1b(%%eax),%%ecx
\n
"
,
header_name
);
fprintf
(
outfile
,
"
\t
pushl %%ecx
\n
"
);
}
else
{
fprintf
(
outfile
,
"
\t
pushl $.L__wine_spec_file_name
\n
"
);
fprintf
(
outfile
,
"
\t
pushl $%s
\n
"
,
header_name
);
}
fprintf
(
outfile
,
"
\t
call %s
\n
"
,
asm_name
(
"__wine_dll_register_16"
)
);
fprintf
(
outfile
,
"
\t
addl $8,%%esp
\n
"
);
fprintf
(
outfile
,
"
\t
ret
\n
"
);
output_function_size
(
outfile
,
name
);
qsort
(
typelist
,
nFuncs
,
sizeof
(
ORDDEF
*
),
Spec16TypeCompare
);
sprintf
(
name
,
".L__wine_spec_%s_fini"
,
make_c_identifier
(
spec
->
dll_name
)
);
i
=
nTypes
=
0
;
while
(
i
<
nFuncs
)
fprintf
(
outfile
,
"
\t
.align 4
\n
"
);
fprintf
(
outfile
,
"
\t
%s
\n
"
,
func_declaration
(
name
)
);
fprintf
(
outfile
,
"%s:
\n
"
,
name
);
if
(
UsePIC
)
{
typelist
[
nTypes
++
]
=
typelist
[
i
++
]
;
while
(
i
<
nFuncs
&&
Spec16TypeCompare
(
typelist
+
i
,
typelist
+
nTypes
-
1
)
==
0
)
i
++
;
fprintf
(
outfile
,
"
\t
call %s
\n
"
,
asm_name
(
"__wine_spec_get_pc_thunk_eax"
)
)
;
fprintf
(
outfile
,
"1:
\t
leal %s-1b(%%eax),%%ecx
\n
"
,
header_name
);
fprintf
(
outfile
,
"
\t
pushl %%ecx
\n
"
)
;
}
/* Output CallFrom16 routines needed by this .spec file */
for
(
i
=
0
;
i
<
nTypes
;
i
++
)
else
{
char
profile
[
101
];
strcpy
(
profile
,
get_function_name
(
typelist
[
i
]
));
BuildCallFrom16Func
(
outfile
,
profile
,
spec
->
file_name
);
fprintf
(
outfile
,
"
\t
pushl $%s
\n
"
,
header_name
);
}
fprintf
(
outfile
,
"
\t
call %s
\n
"
,
asm_name
(
"__wine_dll_unregister_16"
)
);
fprintf
(
outfile
,
"
\t
addl $4,%%esp
\n
"
);
fprintf
(
outfile
,
"
\t
ret
\n
"
);
output_function_size
(
outfile
,
name
);
/* compute code and data sizes, set offsets, and output prototypes */
entrypoint_size
=
2
+
5
+
4
;
/* pushw bp + pushl target + call */
callfrom_size
=
5
+
7
+
10
+
2
+
8
;
/* pushl relay + lcall cs:glue + ret sequence + movl + args */
code_size
=
nTypes
*
callfrom_size
;
for
(
i
=
0
;
i
<=
spec
->
limit
;
i
++
)
if
(
target_platform
==
PLATFORM_APPLE
)
{
ORDDEF
*
odp
=
spec
->
ordinals
[
i
];
if
(
!
odp
)
continue
;
switch
(
odp
->
type
)
{
case
TYPE_ABS
:
odp
->
offset
=
LOWORD
(
odp
->
u
.
abs
.
value
);
break
;
case
TYPE_VARIABLE
:
odp
->
offset
=
data_size
;
memcpy
(
data_buffer
+
data_size
,
odp
->
u
.
var
.
values
,
odp
->
u
.
var
.
n_values
*
sizeof
(
int
)
);
data_size
+=
odp
->
u
.
var
.
n_values
*
sizeof
(
int
);
break
;
case
TYPE_CDECL
:
case
TYPE_PASCAL
:
case
TYPE_VARARGS
:
fprintf
(
outfile
,
"extern void %s();
\n
"
,
odp
->
link_name
);
/* fall through */
case
TYPE_STUB
:
odp
->
offset
=
code_size
;
code_size
+=
entrypoint_size
;
break
;
default:
assert
(
0
);
break
;
fprintf
(
outfile
,
"
\t
.mod_init_func
\n
"
);
fprintf
(
outfile
,
"
\t
.align %d
\n
"
,
get_alignment
(
4
)
);
fprintf
(
outfile
,
"
\t
.long .L__wine_spec_%s_init
\n
"
,
make_c_identifier
(
spec
->
dll_name
)
);
fprintf
(
outfile
,
"
\t
.mod_term_func
\n
"
);
fprintf
(
outfile
,
"
\t
.align %d
\n
"
,
get_alignment
(
4
)
);
fprintf
(
outfile
,
"
\t
.long .L__wine_spec_%s_fini
\n
"
,
make_c_identifier
(
spec
->
dll_name
)
);
}
else
{
fprintf
(
outfile
,
"
\t
.section
\"
.init
\"
,
\"
ax
\"\n
"
);
fprintf
(
outfile
,
"
\t
call .L__wine_spec_%s_init
\n
"
,
make_c_identifier
(
spec
->
dll_name
)
);
fprintf
(
outfile
,
"
\t
.section
\"
.fini
\"
,
\"
ax
\"\n
"
);
fprintf
(
outfile
,
"
\t
call .L__wine_spec_%s_fini
\n
"
,
make_c_identifier
(
spec
->
dll_name
)
);
}
data_buffer
=
xrealloc
(
data_buffer
,
data_size
);
/* free unneeded data */
}
/* Output the module structure */
/* DOS header */
fprintf
(
outfile
,
"
\n
#pragma pack(1)
\n
"
);
fprintf
(
outfile
,
"static const struct module_data
\n
{
\n
"
);
fprintf
(
outfile
,
" struct
\n
{
\n
"
);
fprintf
(
outfile
,
" unsigned short e_magic;
\n
"
);
fprintf
(
outfile
,
" unsigned short e_cblp;
\n
"
);
fprintf
(
outfile
,
" unsigned short e_cp;
\n
"
);
fprintf
(
outfile
,
" unsigned short e_crlc;
\n
"
);
fprintf
(
outfile
,
" unsigned short e_cparhdr;
\n
"
);
fprintf
(
outfile
,
" unsigned short e_minalloc;
\n
"
);
fprintf
(
outfile
,
" unsigned short e_maxalloc;
\n
"
);
fprintf
(
outfile
,
" unsigned short e_ss;
\n
"
);
fprintf
(
outfile
,
" unsigned short e_sp;
\n
"
);
fprintf
(
outfile
,
" unsigned short e_csum;
\n
"
);
fprintf
(
outfile
,
" unsigned short e_ip;
\n
"
);
fprintf
(
outfile
,
" unsigned short e_cs;
\n
"
);
fprintf
(
outfile
,
" unsigned short e_lfarlc;
\n
"
);
fprintf
(
outfile
,
" unsigned short e_ovno;
\n
"
);
fprintf
(
outfile
,
" unsigned short e_res[4];
\n
"
);
fprintf
(
outfile
,
" unsigned short e_oemid;
\n
"
);
fprintf
(
outfile
,
" unsigned short e_oeminfo;
\n
"
);
fprintf
(
outfile
,
" unsigned short e_res2[10];
\n
"
);
fprintf
(
outfile
,
" unsigned int e_lfanew;
\n
"
);
fprintf
(
outfile
,
" } dos_header;
\n
"
);
/* NE header */
ne_offset
=
64
;
fprintf
(
outfile
,
" struct
\n
{
\n
"
);
fprintf
(
outfile
,
" unsigned short ne_magic;
\n
"
);
fprintf
(
outfile
,
" unsigned char ne_ver;
\n
"
);
fprintf
(
outfile
,
" unsigned char ne_rev;
\n
"
);
fprintf
(
outfile
,
" unsigned short ne_enttab;
\n
"
);
fprintf
(
outfile
,
" unsigned short ne_cbenttab;
\n
"
);
fprintf
(
outfile
,
" int ne_crc;
\n
"
);
fprintf
(
outfile
,
" unsigned short ne_flags;
\n
"
);
fprintf
(
outfile
,
" unsigned short ne_autodata;
\n
"
);
fprintf
(
outfile
,
" unsigned short ne_heap;
\n
"
);
fprintf
(
outfile
,
" unsigned short ne_stack;
\n
"
);
fprintf
(
outfile
,
" unsigned int ne_csip;
\n
"
);
fprintf
(
outfile
,
" unsigned int ne_sssp;
\n
"
);
fprintf
(
outfile
,
" unsigned short ne_cseg;
\n
"
);
fprintf
(
outfile
,
" unsigned short ne_cmod;
\n
"
);
fprintf
(
outfile
,
" unsigned short ne_cbnrestab;
\n
"
);
fprintf
(
outfile
,
" unsigned short ne_segtab;
\n
"
);
fprintf
(
outfile
,
" unsigned short ne_rsrctab;
\n
"
);
fprintf
(
outfile
,
" unsigned short ne_restab;
\n
"
);
fprintf
(
outfile
,
" unsigned short ne_modtab;
\n
"
);
fprintf
(
outfile
,
" unsigned short ne_imptab;
\n
"
);
fprintf
(
outfile
,
" unsigned int ne_nrestab;
\n
"
);
fprintf
(
outfile
,
" unsigned short ne_cmovent;
\n
"
);
fprintf
(
outfile
,
" unsigned short ne_align;
\n
"
);
fprintf
(
outfile
,
" unsigned short ne_cres;
\n
"
);
fprintf
(
outfile
,
" unsigned char ne_exetyp;
\n
"
);
fprintf
(
outfile
,
" unsigned char ne_flagsothers;
\n
"
);
fprintf
(
outfile
,
" unsigned short ne_pretthunks;
\n
"
);
fprintf
(
outfile
,
" unsigned short ne_psegrefbytes;
\n
"
);
fprintf
(
outfile
,
" unsigned short ne_swaparea;
\n
"
);
fprintf
(
outfile
,
" unsigned short ne_expver;
\n
"
);
fprintf
(
outfile
,
" } os2_header;
\n
"
);
/*******************************************************************
* BuildSpec16File
*
* Build a Win16 assembly file from a spec file.
*/
void
BuildSpec16File
(
FILE
*
outfile
,
DLLSPEC
*
spec
)
{
ORDDEF
**
typelist
;
int
i
,
j
,
nb_funcs
;
char
header_name
[
256
];
/*
segment table
*/
/*
File header
*/
segtable_offset
=
64
;
fprintf
(
outfile
,
" struct
\n
{
\n
"
);
fprintf
(
outfile
,
" unsigned short filepos;
\n
"
);
fprintf
(
outfile
,
" unsigned short size;
\n
"
);
fprintf
(
outfile
,
" unsigned short flags;
\n
"
);
fprintf
(
outfile
,
" unsigned short minsize;
\n
"
);
fprintf
(
outfile
,
" } segtable[2];
\n
"
);
output_standard_file_header
(
outfile
);
/* resource directory */
if
(
!
spec
->
dll_name
)
/* set default name from file name */
{
char
*
p
;
spec
->
dll_name
=
xstrdup
(
spec
->
file_name
);
if
((
p
=
strrchr
(
spec
->
dll_name
,
'.'
)))
*
p
=
0
;
}
resdir_offset
=
segtable_offset
+
2
*
8
;
resdir_size
=
get_res16_directory_size
(
spec
);
fprintf
(
outfile
,
" unsigned char resdir[%d];
\n
"
,
resdir_size
);
/* Build sorted list of all argument types, without duplicates */
/* resident names table */
typelist
=
xmalloc
(
(
spec
->
limit
+
1
)
*
sizeof
(
*
typelist
)
);
resnames_offset
=
resdir_offset
+
resdir_size
;
fprintf
(
outfile
,
" struct
\n
{
\n
"
);
fprintf
(
outfile
,
" struct { unsigned char len; char name[%d]; unsigned short ord; } name_0;
\n
"
,
strlen
(
spec
->
dll_name
)
);
resnames_size
=
3
+
strlen
(
spec
->
dll_name
);
for
(
i
=
1
;
i
<=
spec
->
limit
;
i
++
)
for
(
i
=
nb_funcs
=
0
;
i
<=
spec
->
limit
;
i
++
)
{
ORDDEF
*
odp
=
spec
->
ordinals
[
i
];
if
(
!
odp
||
!
odp
->
name
[
0
])
continue
;
fprintf
(
outfile
,
" struct { unsigned char len; char name[%d]; unsigned short ord; } name_%d;
\n
"
,
strlen
(
odp
->
name
),
i
);
resnames_size
+=
3
+
strlen
(
odp
->
name
);
if
(
!
odp
)
continue
;
if
(
is_function
(
odp
))
typelist
[
nb_funcs
++
]
=
odp
;
}
fprintf
(
outfile
,
" unsigned char name_last[%d];
\n
"
,
2
-
(
resnames_size
&
1
)
);
resnames_size
=
(
resnames_size
+
2
)
&
~
1
;
fprintf
(
outfile
,
" } resnames;
\n
"
);
/* imported names table */
impnames_offset
=
resnames_offset
+
resnames_size
;
fprintf
(
outfile
,
" unsigned char impnames[2];
\n
"
);
/* entry table */
et_offset
=
impnames_offset
+
2
;
et_size
=
output_entry_table
(
&
et_buffer
,
spec
);
fprintf
(
outfile
,
" unsigned char entry_table[%d];
\n
"
,
et_size
);
/* code segment */
code_offset
=
et_offset
+
et_size
;
fprintf
(
outfile
,
" struct {
\n
"
);
fprintf
(
outfile
,
" unsigned char pushl;
\n
"
);
/* pushl $relay */
fprintf
(
outfile
,
" void *relay;
\n
"
);
fprintf
(
outfile
,
" unsigned char lcall;
\n
"
);
/* lcall __FLATCS__:glue */
fprintf
(
outfile
,
" void *glue;
\n
"
);
fprintf
(
outfile
,
" unsigned short flatcs;
\n
"
);
fprintf
(
outfile
,
" unsigned short ret[5];
\n
"
);
/* return sequence */
fprintf
(
outfile
,
" unsigned short movl;
\n
"
);
/* movl arg_types[1],arg_types[0](%esi) */
fprintf
(
outfile
,
" unsigned int arg_types[2];
\n
"
);
fprintf
(
outfile
,
" } call[%d];
\n
"
,
nTypes
);
fprintf
(
outfile
,
" struct {
\n
"
);
fprintf
(
outfile
,
" unsigned short pushw_bp;
\n
"
);
/* pushw %bp */
fprintf
(
outfile
,
" unsigned char pushl;
\n
"
);
/* pushl $target */
fprintf
(
outfile
,
" void (*target)();
\n
"
);
fprintf
(
outfile
,
" unsigned short call;
\n
"
);
/* call CALLFROM16 */
fprintf
(
outfile
,
" short callfrom16;
\n
"
);
fprintf
(
outfile
,
" } entry[%d];
\n
"
,
nFuncs
);
nb_funcs
=
sort_func_list
(
typelist
,
nb_funcs
,
callfrom16_type_compare
);
/* data segment */
data_offset
=
code_offset
+
code_size
;
fprintf
(
outfile
,
" unsigned char data_segment[%d];
\n
"
,
data_size
);
if
(
data_offset
+
data_size
>=
0x10000
)
fatal_error
(
"Not supported yet: 16-bit module data larger than 64K
\n
"
);
/* resource data */
resdata_offset
=
ne_offset
+
data_offset
+
data_size
;
for
(
resdata_align
=
0
;
resdata_align
<
16
;
resdata_align
++
)
{
unsigned
int
size
=
get_res16_data_size
(
spec
,
resdata_offset
,
resdata_align
);
if
((
resdata_offset
+
size
)
>>
resdata_align
<=
0xffff
)
break
;
}
output_res16_directory
(
&
resdir_buffer
,
spec
,
resdata_offset
,
resdata_align
);
resdata_size
=
output_res16_data
(
&
resdata_buffer
,
spec
,
resdata_offset
,
resdata_align
);
if
(
resdata_size
)
fprintf
(
outfile
,
" unsigned char resources[%d];
\n
"
,
resdata_size
);
/* Output the module structure */
/* Output the module data */
sprintf
(
header_name
,
"__wine_spec_%s_dos_header"
,
make_c_identifier
(
spec
->
dll_name
)
);
fprintf
(
outfile
,
"
\n
/* module data */
\n\n
"
);
fprintf
(
outfile
,
"
\t
.data
\n
"
);
fprintf
(
outfile
,
"
\t
.align %d
\n
"
,
get_alignment
(
4
)
);
fprintf
(
outfile
,
"%s:
\n
"
,
header_name
);
fprintf
(
outfile
,
"
\t
%s 0x%04x
\n
"
,
get_asm_short_keyword
(),
/* e_magic */
IMAGE_DOS_SIGNATURE
);
fprintf
(
outfile
,
"
\t
%s 0
\n
"
,
get_asm_short_keyword
()
);
/* e_cblp */
fprintf
(
outfile
,
"
\t
%s 0
\n
"
,
get_asm_short_keyword
()
);
/* e_cp */
fprintf
(
outfile
,
"
\t
%s 0
\n
"
,
get_asm_short_keyword
()
);
/* e_crlc */
fprintf
(
outfile
,
"
\t
%s 0
\n
"
,
get_asm_short_keyword
()
);
/* e_cparhdr */
fprintf
(
outfile
,
"
\t
%s 0
\n
"
,
get_asm_short_keyword
()
);
/* e_minalloc */
fprintf
(
outfile
,
"
\t
%s 0
\n
"
,
get_asm_short_keyword
()
);
/* e_maxalloc */
fprintf
(
outfile
,
"
\t
%s 0
\n
"
,
get_asm_short_keyword
()
);
/* e_ss */
fprintf
(
outfile
,
"
\t
%s 0
\n
"
,
get_asm_short_keyword
()
);
/* e_sp */
fprintf
(
outfile
,
"
\t
%s 0
\n
"
,
get_asm_short_keyword
()
);
/* e_csum */
fprintf
(
outfile
,
"
\t
%s 0
\n
"
,
get_asm_short_keyword
()
);
/* e_ip */
fprintf
(
outfile
,
"
\t
%s 0
\n
"
,
get_asm_short_keyword
()
);
/* e_cs */
fprintf
(
outfile
,
"
\t
%s 0
\n
"
,
get_asm_short_keyword
()
);
/* e_lfarlc */
fprintf
(
outfile
,
"
\t
%s 0
\n
"
,
get_asm_short_keyword
()
);
/* e_ovno */
fprintf
(
outfile
,
"
\t
%s 0,0,0,0
\n
"
,
get_asm_short_keyword
()
);
/* e_res */
fprintf
(
outfile
,
"
\t
%s 0
\n
"
,
get_asm_short_keyword
()
);
/* e_oemid */
fprintf
(
outfile
,
"
\t
%s 0
\n
"
,
get_asm_short_keyword
()
);
/* e_oeminfo */
fprintf
(
outfile
,
"
\t
%s 0,0,0,0,0,0,0,0,0,0
\n
"
,
get_asm_short_keyword
()
);
/* e_res2 */
fprintf
(
outfile
,
"
\t
.long .L__wine_spec_ne_header-%s
\n
"
,
header_name
);
/* e_lfanew */
fprintf
(
outfile
,
".L__wine_spec_ne_header:
\n
"
);
fprintf
(
outfile
,
"
\t
%s 0x%04x
\n
"
,
get_asm_short_keyword
(),
/* ne_magic */
IMAGE_OS2_SIGNATURE
);
fprintf
(
outfile
,
"
\t
.byte 0
\n
"
);
/* ne_ver */
fprintf
(
outfile
,
"
\t
.byte 0
\n
"
);
/* ne_rev */
fprintf
(
outfile
,
"
\t
%s .L__wine_spec_ne_enttab-.L__wine_spec_ne_header
\n
"
,
/* ne_enttab */
get_asm_short_keyword
()
);
fprintf
(
outfile
,
"
\t
%s .L__wine_spec_ne_enttab_end-.L__wine_spec_ne_enttab
\n
"
,
/* ne_cbenttab */
get_asm_short_keyword
()
);
fprintf
(
outfile
,
"
\t
.long 0
\n
"
);
/* ne_crc */
fprintf
(
outfile
,
"
\t
%s 0x%04x
\n
"
,
get_asm_short_keyword
(),
/* ne_flags */
NE_FFLAGS_SINGLEDATA
|
NE_FFLAGS_LIBMODULE
);
fprintf
(
outfile
,
"
\t
%s 2
\n
"
,
get_asm_short_keyword
()
);
/* ne_autodata */
fprintf
(
outfile
,
"
\t
%s %u
\n
"
,
get_asm_short_keyword
(),
spec
->
heap_size
);
/* ne_heap */
fprintf
(
outfile
,
"
\t
%s 0
\n
"
,
get_asm_short_keyword
()
);
/* ne_stack */
fprintf
(
outfile
,
"
\t
.long 0
\n
"
);
/* ne_csip */
fprintf
(
outfile
,
"
\t
.long 0
\n
"
);
/* ne_sssp */
fprintf
(
outfile
,
"
\t
%s 2
\n
"
,
get_asm_short_keyword
()
);
/* ne_cseg */
fprintf
(
outfile
,
"
\t
%s 0
\n
"
,
get_asm_short_keyword
()
);
/* ne_cmod */
fprintf
(
outfile
,
"
\t
%s 0
\n
"
,
get_asm_short_keyword
()
);
/* ne_cbnrestab */
fprintf
(
outfile
,
"
\t
%s .L__wine_spec_ne_segtab-.L__wine_spec_ne_header
\n
"
,
/* ne_segtab */
get_asm_short_keyword
()
);
fprintf
(
outfile
,
"
\t
%s .L__wine_spec_ne_rsrctab-.L__wine_spec_ne_header
\n
"
,
/* ne_rsrctab */
get_asm_short_keyword
()
);
fprintf
(
outfile
,
"
\t
%s .L__wine_spec_ne_restab-.L__wine_spec_ne_header
\n
"
,
/* ne_restab */
get_asm_short_keyword
()
);
fprintf
(
outfile
,
"
\t
%s .L__wine_spec_ne_modtab-.L__wine_spec_ne_header
\n
"
,
/* ne_modtab */
get_asm_short_keyword
()
);
fprintf
(
outfile
,
"
\t
%s .L__wine_spec_ne_imptab-.L__wine_spec_ne_header
\n
"
,
/* ne_imptab */
get_asm_short_keyword
()
);
fprintf
(
outfile
,
"
\t
.long 0
\n
"
);
/* ne_nrestab */
fprintf
(
outfile
,
"
\t
%s 0
\n
"
,
get_asm_short_keyword
()
);
/* ne_cmovent */
fprintf
(
outfile
,
"
\t
%s 0
\n
"
,
get_asm_short_keyword
()
);
/* ne_align */
fprintf
(
outfile
,
"
\t
%s 0
\n
"
,
get_asm_short_keyword
()
);
/* ne_cres */
fprintf
(
outfile
,
"
\t
.byte 0x%02x
\n
"
,
NE_OSFLAGS_WINDOWS
);
/* ne_exetyp */
fprintf
(
outfile
,
"
\t
.byte 0x%02x
\n
"
,
NE_AFLAGS_FASTLOAD
);
/* ne_flagsothers */
fprintf
(
outfile
,
"
\t
%s 0
\n
"
,
get_asm_short_keyword
()
);
/* ne_pretthunks */
fprintf
(
outfile
,
"
\t
%s 0
\n
"
,
get_asm_short_keyword
()
);
/* ne_psegrefbytes */
fprintf
(
outfile
,
"
\t
%s 0
\n
"
,
get_asm_short_keyword
()
);
/* ne_swaparea */
fprintf
(
outfile
,
"
\t
%s 0
\n
"
,
get_asm_short_keyword
()
);
/* ne_expver */
/*
DOS header
*/
/*
segment table
*/
fprintf
(
outfile
,
"} module =
\n
{
\n
{
\n
"
);
fprintf
(
outfile
,
" 0x%04x,
\n
"
,
IMAGE_DOS_SIGNATURE
);
/* e_magic */
fprintf
(
outfile
,
" 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
\n
"
);
fprintf
(
outfile
,
" { 0, 0, 0, 0, }, 0, 0,
\n
"
);
fprintf
(
outfile
,
" { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
\n
"
);
fprintf
(
outfile
,
" sizeof(module.dos_header)
\n
"
);
/* e_lfanew */
fprintf
(
outfile
,
"
\n
.L__wine_spec_ne_segtab:
\n
"
);
/*
NE header
*/
/*
code segment entry
*/
fprintf
(
outfile
,
" },
\n
{
\n
"
);
fprintf
(
outfile
,
" 0x%04x,
\n
"
,
IMAGE_OS2_SIGNATURE
);
/* ne_magic */
fprintf
(
outfile
,
" 0, 0,
\n
"
);
fprintf
(
outfile
,
" %d,
\n
"
,
et_offset
);
/* ne_enttab */
fprintf
(
outfile
,
" sizeof(module.entry_table),
\n
"
);
/* ne_cbenttab */
fprintf
(
outfile
,
" 0,
\n
"
);
/* ne_crc */
fprintf
(
outfile
,
" 0x%04x,
\n
"
,
/* ne_flags */
NE_FFLAGS_SINGLEDATA
|
NE_FFLAGS_LIBMODULE
);
fprintf
(
outfile
,
" 2,
\n
"
);
/* ne_autodata */
fprintf
(
outfile
,
" %d,
\n
"
,
spec
->
heap_size
);
/* ne_heap */
fprintf
(
outfile
,
" 0, 0, 0,
\n
"
);
fprintf
(
outfile
,
" 2,
\n
"
);
/* ne_cseg */
fprintf
(
outfile
,
" 0,
\n
"
);
/* ne_cmod */
fprintf
(
outfile
,
" 0,
\n
"
);
/* ne_cbnrestab */
fprintf
(
outfile
,
" %d,
\n
"
,
segtable_offset
);
/* ne_segtab */
fprintf
(
outfile
,
" %d,
\n
"
,
resdir_offset
);
/* ne_rsrctab */
fprintf
(
outfile
,
" %d,
\n
"
,
resnames_offset
);
/* ne_restab */
fprintf
(
outfile
,
" %d,
\n
"
,
impnames_offset
);
/* ne_modtab */
fprintf
(
outfile
,
" %d,
\n
"
,
impnames_offset
);
/* ne_imptab */
fprintf
(
outfile
,
" 0,
\n
"
);
/* ne_nrestab */
fprintf
(
outfile
,
" 0,
\n
"
);
/* ne_cmovent */
fprintf
(
outfile
,
" 0,
\n
"
);
/* ne_align */
fprintf
(
outfile
,
" 0,
\n
"
);
/* ne_cres */
fprintf
(
outfile
,
" 0x%04x,
\n
"
,
NE_OSFLAGS_WINDOWS
);
/* ne_exetyp */
fprintf
(
outfile
,
" 0x%04x,
\n
"
,
NE_AFLAGS_FASTLOAD
);
/* ne_flagsothers */
fprintf
(
outfile
,
" 0,
\n
"
);
/* ne_pretthunks */
fprintf
(
outfile
,
" 0,
\n
"
);
/* ne_psegrefbytes */
fprintf
(
outfile
,
" 0,
\n
"
);
/* ne_swaparea */
fprintf
(
outfile
,
" 0
\n
"
);
/* ne_expver */
fprintf
(
outfile
,
" },
\n
"
);
fprintf
(
outfile
,
"
\t
%s .L__wine_spec_code_segment-%s
\n
"
,
/* filepos */
get_asm_short_keyword
(),
header_name
);
fprintf
(
outfile
,
"
\t
%s .L__wine_spec_code_segment_end-.L__wine_spec_code_segment
\n
"
,
/* size */
get_asm_short_keyword
()
);
fprintf
(
outfile
,
"
\t
%s 0x%04x
\n
"
,
get_asm_short_keyword
(),
NE_SEGFLAGS_32BIT
);
/* flags */
fprintf
(
outfile
,
"
\t
%s .L__wine_spec_code_segment_end-.L__wine_spec_code_segment
\n
"
,
/* minsize */
get_asm_short_keyword
()
);
/*
segment table
*/
/*
data segment entry
*/
fprintf
(
outfile
,
" {
\n
"
);
fprintf
(
outfile
,
" { %d, %d, 0x%04x, %d },
\n
"
,
ne_offset
+
code_offset
,
code_size
,
NE_SEGFLAGS_32BIT
,
code_size
);
fprintf
(
outfile
,
" { %d, %d, 0x%04x, %d },
\n
"
,
ne_offset
+
data_offset
,
data_size
,
NE_SEGFLAGS_DATA
,
data_size
);
fprintf
(
outfile
,
" },
\n
"
);
fprintf
(
outfile
,
"
\t
%s .L__wine_spec_data_segment-%s
\n
"
,
/* filepos */
get_asm_short_keyword
(),
header_name
);
fprintf
(
outfile
,
"
\t
%s .L__wine_spec_data_segment_end-.L__wine_spec_data_segment
\n
"
,
/* size */
get_asm_short_keyword
()
);
fprintf
(
outfile
,
"
\t
%s 0x%04x
\n
"
,
get_asm_short_keyword
(),
NE_SEGFLAGS_DATA
);
/* flags */
fprintf
(
outfile
,
"
\t
%s .L__wine_spec_data_segment_end-.L__wine_spec_data_segment
\n
"
,
/* minsize */
get_asm_short_keyword
()
);
/* resource directory */
output_bytes
(
outfile
,
resdir_buffer
,
resdir_size
);
free
(
resdir_buffer
);
output_res16_directory
(
outfile
,
spec
,
header_name
);
/* resident names table */
fprintf
(
outfile
,
"
{
\n
"
);
strcpy
(
string
,
spec
->
dll_name
);
fprintf
(
outfile
,
" { %d,
\"
%s
\"
, 0 },
\n
"
,
strlen
(
string
),
strupper
(
string
)
);
fprintf
(
outfile
,
"
\n\t
.align %d
\n
"
,
get_alignment
(
2
)
);
fprintf
(
outfile
,
".L__wine_spec_ne_restab:
\n
"
);
output_resident_name
(
outfile
,
spec
->
dll_name
,
0
);
for
(
i
=
1
;
i
<=
spec
->
limit
;
i
++
)
{
ORDDEF
*
odp
=
spec
->
ordinals
[
i
];
if
(
!
odp
||
!
odp
->
name
[
0
])
continue
;
strcpy
(
string
,
odp
->
name
);
fprintf
(
outfile
,
" { %d,
\"
%s
\"
, %d },
\n
"
,
strlen
(
string
),
strupper
(
string
),
i
);
output_resident_name
(
outfile
,
odp
->
name
,
i
);
}
fprintf
(
outfile
,
"
{ 0 }
\n
},
\n
"
);
fprintf
(
outfile
,
"
\t
.byte 0
\n
"
);
/* imported names table */
fprintf
(
outfile
,
" { 0, 0 },
\n
"
);
fprintf
(
outfile
,
"
\n\t
.align %d
\n
"
,
get_alignment
(
2
)
);
fprintf
(
outfile
,
".L__wine_spec_ne_modtab:
\n
"
);
fprintf
(
outfile
,
".L__wine_spec_ne_imptab:
\n
"
);
fprintf
(
outfile
,
"
\t
.byte 0,0
\n
"
);
/* entry table */
output_bytes
(
outfile
,
et_buffer
,
et_size
);
free
(
et_buffer
);
fprintf
(
outfile
,
"
\n
.L__wine_spec_ne_enttab:
\n
"
);
output_entry_table
(
outfile
,
spec
);
fprintf
(
outfile
,
".L__wine_spec_ne_enttab_end:
\n
"
);
/* code segment */
fprintf
(
outfile
,
" {
\n
"
);
for
(
i
=
0
;
i
<
nTypes
;
i
++
)
fprintf
(
outfile
,
"
\n\t
.align %d
\n
"
,
get_alignment
(
2
)
);
fprintf
(
outfile
,
".L__wine_spec_code_segment:
\n
"
);
for
(
i
=
0
;
i
<
nb_funcs
;
i
++
)
{
char
profile
[
101
],
*
arg
;
unsigned
int
arg_types
[
2
];
int
j
,
argsize
=
0
;
int
j
,
nop_words
,
argsize
=
0
;
strcpy
(
profile
,
get_function_name
(
typelist
[
i
]
));
if
(
typelist
[
i
]
->
type
==
TYPE_PASCAL
)
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
;
}
argsize
=
get_function_argsize
(
typelist
[
i
]
);
/* build the arg types bit fields */
arg_types
[
0
]
=
arg_types
[
1
]
=
0
;
...
...
@@ -756,107 +702,100 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
}
if
(
typelist
[
i
]
->
type
==
TYPE_VARARGS
)
arg_types
[
j
/
10
]
|=
ARG_VARARG
<<
(
3
*
(
j
%
10
));
fprintf
(
outfile
,
" { 0x68, __wine_%s_CallFrom16_%s, 0x9a, 0, 0,
\n
"
,
make_c_identifier
(
spec
->
file_name
),
profile
);
fprintf
(
outfile
,
".L__wine_spec_callfrom16_%s:
\n
"
,
get_callfrom16_name
(
typelist
[
i
])
);
fprintf
(
outfile
,
"
\t
pushl $.L__wine_spec_call16_%s
\n
"
,
get_relay_name
(
typelist
[
i
])
);
fprintf
(
outfile
,
"
\t
lcall $0,$0
\n
"
);
if
(
typelist
[
i
]
->
flags
&
FLAG_REGISTER
)
{
/* ret sequence: ret $n; nop */
if
(
argsize
)
fprintf
(
outfile
,
"{ 0xca66, %d, 0xb68d, 0x0000, 0x0000 },"
,
argsize
);
else
fprintf
(
outfile
,
"{ 0xcb66, 0x748d, 0x0026, 0x748d, 0x0026 },"
);
nop_words
=
4
;
}
else
if
(
typelist
[
i
]
->
flags
&
FLAG_RET16
)
{
/* ret sequence: orl %eax,%eax; ret $n; nop */
if
(
argsize
)
fprintf
(
outfile
,
"{ 0xc009, 0xca66, %d, 0x748d, 0x0026 },"
,
argsize
);
else
fprintf
(
outfile
,
"{ 0xc009, 0xcb66, 0xb68d, 0x0000, 0x0000 },"
);
fprintf
(
outfile
,
"
\t
orw %%ax,%%ax
\n
"
);
fprintf
(
outfile
,
"
\t
nop
\n
"
);
/* so that the lretw is aligned */
nop_words
=
2
;
}
else
{
/* ret sequence: shld $16,%eax,%edx; orl %eax,%eax; ret $n [; nop] */
fprintf
(
outfile
,
"shld $16,%%eax,%%edx
\n
"
);
fprintf
(
outfile
,
"orl %%eax,%%eax
\n
"
);
nop_words
=
1
;
}
if
(
argsize
)
fprintf
(
outfile
,
"{ 0xa40f, 0x10c2, 0xc009, 0xca66, %d },"
,
argsize
);
else
fprintf
(
outfile
,
"{ 0xa40f, 0x10c2, 0xc009, 0xcb66, 0xf689 },"
)
;
{
fprintf
(
outfile
,
"lretw $%u
\n
"
,
argsize
);
nop_words
--
;
}
else
fprintf
(
outfile
,
"lretw
\n
"
);
if
(
nop_words
)
fprintf
(
outfile
,
"
\t
%s
\n
"
,
nop_sequence
[
nop_words
-
1
]
);
/* the movl is here so that the code contains only valid instructions, */
/* it's never actually executed, we only care about the arg_types[] values */
fprintf
(
outfile
,
" 0x86c7, { 0x%08x, 0x%08x } },
\n
"
,
arg_types
[
0
],
arg_types
[
1
]
);
fprintf
(
outfile
,
"
\t
%s 0x86c7
\n
"
,
get_asm_short_keyword
()
);
fprintf
(
outfile
,
"
\t
.long 0x%08x,0x%08x
\n
"
,
arg_types
[
0
],
arg_types
[
1
]
);
}
fprintf
(
outfile
,
" },
\n
{
\n
"
);
for
(
i
=
0
;
i
<=
spec
->
limit
;
i
++
)
{
ORDDEF
*
odp
=
spec
->
ordinals
[
i
];
if
(
!
odp
)
continue
;
switch
(
odp
->
type
)
{
case
TYPE_CDECL
:
case
TYPE_PASCAL
:
case
TYPE_VARARGS
:
case
TYPE_STUB
:
type
=
bsearch
(
&
odp
,
typelist
,
nTypes
,
sizeof
(
ORDDEF
*
),
Spec16TypeCompare
);
assert
(
type
);
fprintf
(
outfile
,
" /* %s.%d */ "
,
spec
->
dll_name
,
i
);
fprintf
(
outfile
,
"{ 0x5566, 0x68, %s, 0xe866, %d /* %s */ },
\n
"
,
odp
->
link_name
,
(
type
-
typelist
)
*
callfrom_size
-
(
odp
->
offset
+
entrypoint_size
),
get_function_name
(
odp
)
);
break
;
default:
break
;
if
(
!
odp
||
!
is_function
(
odp
))
continue
;
fprintf
(
outfile
,
".L__wine_%s_%u:
\n
"
,
make_c_identifier
(
spec
->
dll_name
),
i
);
fprintf
(
outfile
,
"
\t
pushw %%bp
\n
"
);
fprintf
(
outfile
,
"
\t
pushl $%s
\n
"
,
asm_name
(
odp
->
type
==
TYPE_STUB
?
get_stub_name
(
odp
,
spec
)
:
odp
->
link_name
));
fprintf
(
outfile
,
"
\t
callw .L__wine_spec_callfrom16_%s
\n
"
,
get_callfrom16_name
(
odp
)
);
}
}
fprintf
(
outfile
,
" },
\n
"
);
fprintf
(
outfile
,
".L__wine_spec_code_segment_end:
\n
"
);
/* data
_
segment */
/* data
segment */
output_bytes
(
outfile
,
data_buffer
,
data_size
);
free
(
data_buffer
);
fprintf
(
outfile
,
"
\n
.L__wine_spec_data_segment:
\n
"
);
fprintf
(
outfile
,
"
\t
.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
\n
"
);
/* instance data */
for
(
i
=
0
;
i
<=
spec
->
limit
;
i
++
)
{
ORDDEF
*
odp
=
spec
->
ordinals
[
i
];
if
(
!
odp
||
odp
->
type
!=
TYPE_VARIABLE
)
continue
;
fprintf
(
outfile
,
".L__wine_%s_%u:
\n
"
,
make_c_identifier
(
spec
->
dll_name
),
i
);
fprintf
(
outfile
,
"
\t
.long "
);
for
(
j
=
0
;
j
<
odp
->
u
.
var
.
n_values
-
1
;
j
++
)
fprintf
(
outfile
,
"0x%08x,"
,
odp
->
u
.
var
.
values
[
j
]
);
fprintf
(
outfile
,
"0x%08x
\n
"
,
odp
->
u
.
var
.
values
[
j
]
);
}
fprintf
(
outfile
,
".L__wine_spec_data_segment_end:
\n
"
);
/* resource data */
if
(
resdata_size
)
if
(
spec
->
nb_resources
)
{
output_bytes
(
outfile
,
resdata_buffer
,
resdata_size
);
free
(
resdata_buffer
);
fprintf
(
outfile
,
"
\n
.L__wine_spec_resource_data:
\n
"
);
output_res16_data
(
outfile
,
spec
);
}
fprintf
(
outfile
,
"};
\n
"
);
fprintf
(
outfile
,
"#pragma pack()
\n\n
"
);
/* Output the DLL constructor */
fprintf
(
outfile
,
"
\t
.byte 0
\n
"
);
/* make sure the last symbol points to something */
sprintf
(
constructor
,
"__wine_spec_%s_init"
,
make_c_identifier
(
spec
->
file_name
)
);
sprintf
(
destructor
,
"__wine_spec_%s_fini"
,
make_c_identifier
(
spec
->
file_name
)
);
/* relay functions */
fprintf
(
outfile
,
"void %s(void)
\n
"
"{
\n
"
" extern void __wine_dll_register_16( const struct module_data *, const char * );
\n
"
" __wine_dll_register_16( &module,
\"
%s
\"
);
\n
"
"}
\n
"
,
constructor
,
spec
->
file_name
);
fprintf
(
outfile
,
"void %s(void)
\n
"
"{
\n
"
" extern void __wine_dll_unregister_16( const struct module_data * );
\n
"
" __wine_dll_unregister_16( &module );
\n
"
"}
\n
"
,
destructor
);
nb_funcs
=
sort_func_list
(
typelist
,
nb_funcs
,
relay_type_compare
);
if
(
nb_funcs
)
{
fprintf
(
outfile
,
"
\n
/* relay functions */
\n\n
"
);
fprintf
(
outfile
,
"
\t
.text
\n
"
);
for
(
i
=
0
;
i
<
nb_funcs
;
i
++
)
output_call16_function
(
outfile
,
typelist
[
i
]
);
fprintf
(
outfile
,
"
\t
.data
\n
"
);
fprintf
(
outfile
,
"wine_ldt_copy_ptr:
\n
"
);
fprintf
(
outfile
,
"
\t
.long %s
\n
"
,
asm_name
(
"wine_ldt_copy"
)
);
}
fprintf
(
outfile
,
"
#ifndef __GNUC__
\n
"
);
fprintf
(
outfile
,
"
static void __asm__dummy_dll_init(void) {
\n
"
);
fprintf
(
outfile
,
"
#endif
\n
"
);
fprintf
(
outfile
,
"
\n\t
%s
\n
"
,
get_asm_string_section
()
);
fprintf
(
outfile
,
"
.L__wine_spec_file_name:
\n
"
);
fprintf
(
outfile
,
"
\t
%s
\"
%s
\"\n
"
,
get_asm_string_keyword
(),
spec
->
file_name
);
output_dll_init
(
outfile
,
constructor
,
destructor
);
output_stubs
(
outfile
,
spec
);
output_get_pc_thunk
(
outfile
);
output_init_code
(
outfile
,
spec
,
header_name
);
fprintf
(
outfile
,
"#ifndef __GNUC__
\n
"
);
fprintf
(
outfile
,
"}
\n
"
);
fprintf
(
outfile
,
"#endif
\n
"
);
free
(
typelist
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment