515 lines
16 KiB
Plaintext
515 lines
16 KiB
Plaintext
![]() |
<chapter id="codingpractice">
|
||
|
<title>Coding Practice</title>
|
||
|
|
||
|
<para>
|
||
|
This chapter describes the relevant coding practices in Wine,
|
||
|
that you should be aware of before doing any serious development
|
||
|
in Wine.
|
||
|
</para>
|
||
|
<sect1 id="patch-format">
|
||
|
<title>Patch Format</title>
|
||
|
|
||
|
<para>
|
||
|
Patches are submitted via email to the Wine patches mailing
|
||
|
list, <email>wine-patches@winehq.org</email>. Your patch
|
||
|
should include:
|
||
|
</para>
|
||
|
|
||
|
<itemizedlist>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
A meaningful subject (very short description of patch)
|
||
|
</para>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
A long (paragraph) description of what was wrong and what
|
||
|
is now better. (recommended)
|
||
|
</para>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
A change log entry (short description of what was
|
||
|
changed).
|
||
|
</para>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
The patch in <command>diff -u</command> format
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</itemizedlist>
|
||
|
|
||
|
<para></para>
|
||
|
|
||
|
<para>
|
||
|
<command>cvs diff -u</command> works great for the common case
|
||
|
where a file is edited. However, if you add or remove a file
|
||
|
<command>cvs diff</command> will not report that correctly so
|
||
|
make sure you explicitly take care of this rare case.
|
||
|
</para>
|
||
|
<para>
|
||
|
For additions simply include them by appending the
|
||
|
<command>diff -u /dev/null /my/new/file</command> output of
|
||
|
them to any <command>cvs diff -u</command> output you may
|
||
|
have. Alternatively, use <command>diff -Nu olddir/
|
||
|
newdir/</command> in case of multiple new files to add.
|
||
|
</para>
|
||
|
<para>
|
||
|
For removals, clearly list the files in the description of the
|
||
|
patch.
|
||
|
</para>
|
||
|
<para>
|
||
|
Since wine is constantly changing due to development it is
|
||
|
strongly recommended that you use cvs for patches, if you
|
||
|
cannot use cvs for some reason, you can submit patches against
|
||
|
the latest tarball. To do this make a copy of the files that
|
||
|
you will be modifying and <command>diff -u</command> against
|
||
|
the old file. I.E.
|
||
|
</para>
|
||
|
<screen>
|
||
|
diff -u file.old file.c > file.txt
|
||
|
</screen>
|
||
|
</sect1>
|
||
|
|
||
|
<sect1 id="Style-notes">
|
||
|
<title>Some notes about style</title>
|
||
|
|
||
|
<para>
|
||
|
There are a few conventions that about coding style that have
|
||
|
been adopted over the years of development. The rational for
|
||
|
these <quote>rules</quote> is explained for each one.
|
||
|
</para>
|
||
|
<itemizedlist>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
No HTML mail, since patches should be in-lined and HTML
|
||
|
turns the patch into garbage. Also it is considered bad
|
||
|
etiquette as it uglifies the message, and is not viewable
|
||
|
by many of the subscribers.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Only one change set per patch. Patches should address only
|
||
|
one bug/problem at a time. If a lot of changes need to be
|
||
|
made then it is preferred to break it into a series of
|
||
|
patches. This makes it easier to find regressions.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Tabs are not forbidden but discouraged. A tab is defined
|
||
|
as 8 characters and the usual amount of indentation is 4
|
||
|
characters.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
C++ style comments are discouraged since some compilers
|
||
|
choke on them.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Commenting out a block of code is usually done by
|
||
|
enclosing it in <command>#if 0 ... #endif</command>
|
||
|
Statements. For example.
|
||
|
</para>
|
||
|
<screen>
|
||
|
/* note about reason for commenting block */
|
||
|
#if 0
|
||
|
code
|
||
|
code /* comments */
|
||
|
code
|
||
|
#endif
|
||
|
</screen>
|
||
|
<para>
|
||
|
The reason for using this method is that it does not
|
||
|
require that you edit comments that may be inside the
|
||
|
block of code.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Patches should be in-lined (if you can configure your
|
||
|
email client to not wrap lines), or attached as plain text
|
||
|
attachments so they can be read inline. This may mean some
|
||
|
more work for you. However it allows others to review your
|
||
|
patch easily and decreases the chances of it being
|
||
|
overlooked or forgotten.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Code is usually limited to 80 columns. This helps prevent
|
||
|
mailers mangling patches by line wrap. Also it generally
|
||
|
makes code easier to read.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
If the patch fixes a bug in Bugzilla please provide a link
|
||
|
to the bug in the comments of the patch. This will make it
|
||
|
easier for the maintainers of Bugzilla.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</itemizedlist>
|
||
|
<sect2 id="Inline-Attachments-with-OE">
|
||
|
<title>Inline attachments with Outlook Express</title>
|
||
|
<para>
|
||
|
Outlook Express is notorious for mangling
|
||
|
attachments. Giving the patch a <filename>.txt</filename>
|
||
|
extension and attaching will solve the problem for most
|
||
|
mailers including Outlook. Also, there is a way to enable
|
||
|
Outlook Express send <filename>.diff</filename>
|
||
|
attachments.
|
||
|
</para>
|
||
|
<para>
|
||
|
You need following two things to make it work.
|
||
|
</para>
|
||
|
<orderedlist>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Make sure that <filename>.diff</filename> files have
|
||
|
\r\n line ends, because if OE detects that there is no
|
||
|
\r\n line endings it switches to quoted-printable format
|
||
|
attachments.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
Using regedit add key "Content Type"
|
||
|
with value "text/plain" to the
|
||
|
<filename>.diff</filename> extension under
|
||
|
HKEY_CLASSES_ROOT (same as for <filename>.txt</filename>
|
||
|
extension). This tells OE to use
|
||
|
Content-Type: text/plain instead of
|
||
|
application/octet-stream.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</orderedlist>
|
||
|
<para>
|
||
|
Item #1 is important. After you hit "Send" button, go to
|
||
|
"Outbox" and using "Properties" verify the message source to
|
||
|
make sure that the mail has correct format. You might want
|
||
|
to send several test emails to yourself too.
|
||
|
</para>
|
||
|
</sect2>
|
||
|
<sect2 id="Alexandre-Bottom-Line">
|
||
|
<title>Alexandre's Bottom Line</title>
|
||
|
<para>
|
||
|
<quote>The basic rules are: no attachments, no MIME crap, no
|
||
|
line wrapping, a single patch per mail. Basically if I can't
|
||
|
do <command>"cat raw_mail | patch -p0"</command> it's in the
|
||
|
wrong format.</quote>
|
||
|
</para>
|
||
|
</sect2>
|
||
|
</sect1>
|
||
|
|
||
|
<sect1 id="patch-quality">
|
||
|
<title>Quality Assurance</title>
|
||
|
|
||
|
<para>
|
||
|
(Or, "How do I get Alexandre to apply my patch quickly so I
|
||
|
can build on it and it will not go stale?")
|
||
|
</para>
|
||
|
<para>
|
||
|
Make sure your patch applies to the current CVS head
|
||
|
revisions. If a bunch of patches are committed to CVS that may
|
||
|
affect whether your patch will apply cleanly then verify that
|
||
|
your patch does apply! <command>cvs update</command> is your
|
||
|
friend!
|
||
|
</para>
|
||
|
<para>
|
||
|
Save yourself some embarrassment and run your patched code
|
||
|
against more than just your current test example. Experience
|
||
|
will tell you how much effort to apply here. If there are
|
||
|
any conformance tests for the code you're working on, run them
|
||
|
and make sure they still pass after your patch is applied. Running
|
||
|
tests can be done by running <command>make test</command>. You may
|
||
|
need to run <command>make testclean</command> to undo the results
|
||
|
of a previous test run. See the <quote>testing</quote> guide for
|
||
|
more details on Wine's conformance tests.
|
||
|
</para>
|
||
|
|
||
|
</sect1>
|
||
|
<sect1 id="porting">
|
||
|
<title>Porting Wine to new Platforms</title>
|
||
|
<para>
|
||
|
This document provides a few tips on porting Wine to your
|
||
|
favorite (UNIX-based) operating system.
|
||
|
</para>
|
||
|
|
||
|
<sect2>
|
||
|
<title>
|
||
|
Why <symbol>#ifdef MyOS</symbol> is probably a mistake.
|
||
|
</title>
|
||
|
|
||
|
<para>
|
||
|
Operating systems change. Maybe yours doesn't have the
|
||
|
<filename>foo.h</filename> header, but maybe a future
|
||
|
version will have it. If you want to <symbol>#include
|
||
|
<foo.h></symbol>, it doesn't matter what operating
|
||
|
system you are using; it only matters whether
|
||
|
<filename>foo.h</filename> is there.
|
||
|
</para>
|
||
|
<para>
|
||
|
Furthermore, operating systems change names or "fork" into
|
||
|
several ones. An <symbol>#ifdef MyOs</symbol> will break
|
||
|
over time.
|
||
|
</para>
|
||
|
<para>
|
||
|
If you use the feature of <command>autoconf</command> -- the
|
||
|
Gnu auto-configuration utility -- wisely, you will help
|
||
|
future porters automatically because your changes will test
|
||
|
for <emphasis>features</emphasis>, not names of operating
|
||
|
systems. A feature can be many things:
|
||
|
</para>
|
||
|
|
||
|
<itemizedlist>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
existence of a header file
|
||
|
</para>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
existence of a library function
|
||
|
</para>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
existence of libraries
|
||
|
</para>
|
||
|
</listitem>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
bugs in header files, library functions, the compiler, ...
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</itemizedlist>
|
||
|
<para>
|
||
|
You will need Gnu Autoconf, which you can get from your
|
||
|
friendly Gnu mirror. This program takes Wine's
|
||
|
<filename>configure.ac</filename> file and produces a
|
||
|
<filename>configure</filename> shell script that users use
|
||
|
to configure Wine to their system.
|
||
|
</para>
|
||
|
<para>
|
||
|
There <emphasis>are</emphasis> exceptions to the "avoid
|
||
|
<symbol>#ifdef MyOS</symbol>" rule. Wine, for example, needs
|
||
|
the internals of the signal stack -- that cannot easily be
|
||
|
described in terms of features. Moreover, you can not use
|
||
|
<filename>autoconf</filename>'s <symbol>HAVE_*</symbol>
|
||
|
symbols in Wine's headers, as these may be used by Winelib
|
||
|
users who may not be using a <filename>configure</filename>
|
||
|
script.
|
||
|
</para>
|
||
|
<para>
|
||
|
Let's now turn to specific porting problems and how to solve
|
||
|
them.
|
||
|
</para>
|
||
|
</sect2>
|
||
|
|
||
|
<sect2>
|
||
|
<title>
|
||
|
MyOS doesn't have the <filename>foo.h</filename> header!
|
||
|
</title>
|
||
|
|
||
|
<para>
|
||
|
This first step is to make <command>autoconf</command> check
|
||
|
for this header. In <filename>configure.in</filename> you
|
||
|
add a segment like this in the section that checks for
|
||
|
header files (search for "header files"):
|
||
|
</para>
|
||
|
<programlisting>
|
||
|
AC_CHECK_HEADER(foo.h, AC_DEFINE(HAVE_FOO_H))
|
||
|
</programlisting>
|
||
|
<para>
|
||
|
If your operating system supports a header file with the
|
||
|
same contents but a different name, say
|
||
|
<filename>bar.h</filename>, add a check for that also.
|
||
|
</para>
|
||
|
<para>
|
||
|
Now you can change
|
||
|
</para>
|
||
|
<programlisting>
|
||
|
#include <foo.h>
|
||
|
</programlisting>
|
||
|
<para>
|
||
|
to
|
||
|
</para>
|
||
|
<programlisting>
|
||
|
#ifdef HAVE_FOO_H
|
||
|
#include <foo.h>
|
||
|
#elif defined (HAVE_BAR_H)
|
||
|
#include <bar.h>
|
||
|
#endif
|
||
|
</programlisting>
|
||
|
<para>
|
||
|
If your system doesn't have a corresponding header file even
|
||
|
though it has the library functions being used, you might
|
||
|
have to add an <symbol>#else</symbol> section to the
|
||
|
conditional. Avoid this if you can.
|
||
|
</para>
|
||
|
<para>
|
||
|
You will also need to add <symbol>#undef HAVE_FOO_H</symbol>
|
||
|
(etc.) to <filename>include/config.h.in</filename>
|
||
|
</para>
|
||
|
<para>
|
||
|
Finish up with <command>make configure</command> and
|
||
|
<command>./configure</command>.
|
||
|
</para>
|
||
|
</sect2>
|
||
|
|
||
|
<sect2>
|
||
|
<title>
|
||
|
MyOS doesn't have the <function>bar</function> function!
|
||
|
</title>
|
||
|
|
||
|
<para>
|
||
|
A typical example of this is the <function>memmove</function>
|
||
|
function. To solve this problem you would add
|
||
|
<function>memmove</function> to the list of functions that
|
||
|
<command>autoconf</command> checks for. In
|
||
|
<filename>configure.in</filename> you search for
|
||
|
<function>AC_CHECK_FUNCS</function> and add
|
||
|
<function>memmove</function>. (You will notice that someone
|
||
|
already did this for this particular function.)
|
||
|
</para>
|
||
|
<para>
|
||
|
Secondly, you will also need to add
|
||
|
<symbol>#undef HAVE_BAR</symbol> to
|
||
|
<filename>include/config.h.in</filename>
|
||
|
</para>
|
||
|
<para>
|
||
|
The next step depends on the nature of the missing function.
|
||
|
</para>
|
||
|
|
||
|
<variablelist>
|
||
|
<varlistentry>
|
||
|
<term>Case 1:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
It's easy to write a complete implementation of the
|
||
|
function. (<function>memmove</function> belongs to
|
||
|
this case.)
|
||
|
</para>
|
||
|
<para>
|
||
|
You add your implementation in
|
||
|
<filename>misc/port.c</filename> surrounded by
|
||
|
<symbol>#ifndef HAVE_MEMMOVE</symbol> and
|
||
|
<symbol>#endif</symbol>.
|
||
|
</para>
|
||
|
<para>
|
||
|
You might have to add a prototype for your function.
|
||
|
If so, <filename>include/miscemu.h</filename> might be
|
||
|
the place. Don't forget to protect that definition by
|
||
|
<symbol>#ifndef HAVE_MEMMOVE</symbol> and
|
||
|
<symbol>#endif</symbol> also!
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
<varlistentry>
|
||
|
<term>Case 2:</term>
|
||
|
<listitem>
|
||
|
<para>
|
||
|
A general implementation is hard, but Wine is only
|
||
|
using a special case.
|
||
|
</para>
|
||
|
<para>
|
||
|
An example is the various <function>wait</function>
|
||
|
calls used in <function>SIGNAL_child</function> from
|
||
|
<filename>loader/signal.c</filename>. Here we have a
|
||
|
multi-branch case on features:
|
||
|
</para>
|
||
|
<programlisting>
|
||
|
#ifdef HAVE_THIS
|
||
|
...
|
||
|
#elif defined (HAVE_THAT)
|
||
|
...
|
||
|
#elif defined (HAVE_SOMETHING_ELSE)
|
||
|
...
|
||
|
#endif
|
||
|
</programlisting>
|
||
|
<para>
|
||
|
Note that this is very different from testing on
|
||
|
operating systems. If a new version of your operating
|
||
|
systems comes out and adds a new function, this code
|
||
|
will magically start using it.
|
||
|
</para>
|
||
|
</listitem>
|
||
|
</varlistentry>
|
||
|
</variablelist>
|
||
|
<para>
|
||
|
Finish up with <command>make configure</command> and
|
||
|
<command>./configure</command>.
|
||
|
</para>
|
||
|
</sect2>
|
||
|
</sect1>
|
||
|
|
||
|
<sect1 id="adding-languages">
|
||
|
<title>Adding New Languages</title>
|
||
|
|
||
|
<para>
|
||
|
This file documents the necessary procedure for adding a new
|
||
|
language to the list of languages that Wine can display system
|
||
|
menus and forms in. Adding new translations is not hard as it
|
||
|
requires no programming knowledge or special skills.
|
||
|
</para>
|
||
|
|
||
|
<para>
|
||
|
Language dependent resources reside in files
|
||
|
named <filename>somefile_Xx.rc</filename> or
|
||
|
<filename>Xx.rc</filename>, where <literal>Xx</literal>
|
||
|
is your language abbreviation (look for it in
|
||
|
<filename>include/winnls.h</filename>). These are included
|
||
|
in a master file named <filename>somefile.rc</filename> or
|
||
|
<filename>rsrc.rc</filename>, located in the same
|
||
|
directory as the language files.
|
||
|
</para>
|
||
|
|
||
|
<para>
|
||
|
To add a new language to one of these resources you
|
||
|
need to make a copy of the English resource (located
|
||
|
in the <filename>somefile_En.rc</filename> file) over to
|
||
|
your <filename>somefile_Xx.rc</filename> file, include this
|
||
|
file in the master <filename>somefile.rc</filename> file,
|
||
|
and edit the new file to translate the English text.
|
||
|
You may also need to rearrange some of the controls
|
||
|
to better fit the newly translated strings. Test your changes
|
||
|
to make sure they properly layout on the screen.
|
||
|
</para>
|
||
|
|
||
|
<para>
|
||
|
In menus, the character "&" means that the next
|
||
|
character will be highlighted and that pressing that
|
||
|
letter will select the item. You should place these
|
||
|
"&" characters suitably for your language, not just
|
||
|
copy the positions from English. In particular,
|
||
|
items within one menu should have different highlighted
|
||
|
letters.
|
||
|
</para>
|
||
|
|
||
|
<para>
|
||
|
To get a list of the files that need translating,
|
||
|
run the following command in the root of your Wine tree:
|
||
|
<command>find -name "*En.rc"</command>.
|
||
|
</para>
|
||
|
|
||
|
<para>
|
||
|
When adding a new language, also make sure the parameters
|
||
|
defined in <filename>./dlls/kernel/nls/*.nls</filename>
|
||
|
fit your local habits and language.
|
||
|
</para>
|
||
|
</sect1>
|
||
|
</chapter>
|
||
|
|
||
|
<!-- Keep this comment at the end of the file
|
||
|
Local variables:
|
||
|
mode: sgml
|
||
|
sgml-parent-document:("wine-devel.sgml" "set" "book" "part" "chapter" "")
|
||
|
End:
|
||
|
-->
|