summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Alexey Yakovenko <wakeroid@gmail.com>2010-05-30 15:48:40 +0200
committerGravatar Alexey Yakovenko <wakeroid@gmail.com>2010-05-30 15:48:40 +0200
commit754fc088625e95ec3266d2db5a148cc95db51557 (patch)
treef694659121e9afc6f99e0293fd85f17cd01c5890
parent52332cffdbbe27776b125061a17e14a47dfa55be (diff)
parent288ad1d3a653383c59c0e1f1b088ef652a6c2149 (diff)
Merge branch 'i18n' into devel
Conflicts: configure.ac
-rw-r--r--ABOUT-NLS1327
-rw-r--r--Makefile.am21
-rw-r--r--README.transifex11
-rwxr-xr-xconfig.rpath672
-rw-r--r--configure.ac12
-rw-r--r--deadbeef.desktop.in5
-rw-r--r--gettext.h15
-rw-r--r--intl/ChangeLog4
-rw-r--r--intl/Makefile.in659
-rw-r--r--intl/VERSION1
-rw-r--r--intl/bindtextdom.c340
-rwxr-xr-xintl/config.charset684
-rw-r--r--intl/dcgettext.c56
-rw-r--r--intl/dcigettext.c1705
-rw-r--r--intl/dcngettext.c57
-rw-r--r--intl/dgettext.c58
-rw-r--r--intl/dngettext.c59
-rw-r--r--intl/eval-plural.h108
-rw-r--r--intl/explodename.c135
-rw-r--r--intl/export.h6
-rw-r--r--intl/finddomain.c212
-rw-r--r--intl/gettext.c63
-rw-r--r--intl/gettextP.h307
-rw-r--r--intl/gmo.h152
-rw-r--r--intl/hash-string.c51
-rw-r--r--intl/hash-string.h36
-rw-r--r--intl/intl-compat.c133
-rw-r--r--intl/intl-exports.c36
-rw-r--r--intl/l10nflist.c400
-rw-r--r--intl/langprefs.c355
-rw-r--r--intl/libgnuintl.h.in460
-rw-r--r--intl/libintl.rc38
-rw-r--r--intl/loadinfo.h132
-rw-r--r--intl/loadmsgcat.c1333
-rw-r--r--intl/localcharset.c549
-rw-r--r--intl/localcharset.h42
-rw-r--r--intl/locale.alias77
-rw-r--r--intl/localealias.c439
-rw-r--r--intl/localename.c2959
-rw-r--r--intl/lock.c1059
-rw-r--r--intl/lock.h928
-rw-r--r--intl/log.c128
-rw-r--r--intl/ngettext.c65
-rw-r--r--intl/os2compat.c98
-rw-r--r--intl/os2compat.h46
-rw-r--r--intl/osdep.c26
-rw-r--r--intl/plural-exp.c155
-rw-r--r--intl/plural-exp.h129
-rw-r--r--intl/plural.c1961
-rw-r--r--intl/plural.y385
-rw-r--r--intl/printf-args.c188
-rw-r--r--intl/printf-args.h155
-rw-r--r--intl/printf-parse.c628
-rw-r--r--intl/printf-parse.h75
-rw-r--r--intl/printf.c429
-rw-r--r--intl/ref-add.sin31
-rw-r--r--intl/ref-del.sin26
-rw-r--r--intl/relocatable.c493
-rw-r--r--intl/relocatable.h83
-rw-r--r--intl/setlocale.c1015
-rw-r--r--intl/textdomain.c127
-rw-r--r--intl/threadlib.c75
-rw-r--r--intl/tsearch.c684
-rw-r--r--intl/tsearch.h83
-rw-r--r--intl/vasnprintf.c5568
-rw-r--r--intl/vasnprintf.h78
-rw-r--r--intl/vasnwprintf.h46
-rw-r--r--intl/version.c26
-rw-r--r--intl/wprintf-parse.h75
-rw-r--r--intl/xsize.h109
-rw-r--r--intltool-extract.in0
-rw-r--r--intltool-merge.in0
-rw-r--r--intltool-update.in0
-rw-r--r--main.c39
-rw-r--r--playlist.c8
-rw-r--r--plugins.c3
-rw-r--r--plugins/gtkui/callbacks.c25
-rw-r--r--plugins/gtkui/ddbtabstrip.c8
-rw-r--r--plugins/gtkui/deadbeef.glade30
-rw-r--r--plugins/gtkui/deadbeef.gladep1
-rw-r--r--plugins/gtkui/eq.c26
-rw-r--r--plugins/gtkui/gtkui.c27
-rw-r--r--plugins/gtkui/interface.c324
-rw-r--r--plugins/gtkui/mainplaylist.c14
-rw-r--r--plugins/gtkui/plcommon.c38
-rw-r--r--plugins/gtkui/pluginconf.c5
-rw-r--r--plugins/gtkui/prefwin.c22
-rw-r--r--plugins/gtkui/progress.c6
-rw-r--r--plugins/gtkui/search.c9
-rw-r--r--plugins/gtkui/support.c4
-rw-r--r--plugins/gtkui/support.h25
-rw-r--r--plugins/gtkui/trkproperties.c24
-rw-r--r--plugins/notify/notify.c3
-rw-r--r--po/ChangeLog5
-rw-r--r--po/LINGUAS8
-rw-r--r--po/Makefile.in.in217
-rw-r--r--po/POTFILES.in21
-rw-r--r--po/deadbeef.pot1086
-rw-r--r--po/el.po1103
-rw-r--r--po/es.po1106
-rw-r--r--po/he.po1109
-rw-r--r--po/hr.po982
-rw-r--r--po/nl.po1086
-rw-r--r--po/ru.po1124
-rw-r--r--po/sv.po1122
-rw-r--r--po/uk.po1113
106 files changed, 39112 insertions, 294 deletions
diff --git a/ABOUT-NLS b/ABOUT-NLS
new file mode 100644
index 00000000..4f50fb5f
--- /dev/null
+++ b/ABOUT-NLS
@@ -0,0 +1,1327 @@
+1 Notes on the Free Translation Project
+***************************************
+
+Free software is going international! The Free Translation Project is
+a way to get maintainers of free software, translators, and users all
+together, so that free software will gradually become able to speak many
+languages. A few packages already provide translations for their
+messages.
+
+ If you found this `ABOUT-NLS' file inside a distribution, you may
+assume that the distributed package does use GNU `gettext' internally,
+itself available at your nearest GNU archive site. But you do _not_
+need to install GNU `gettext' prior to configuring, installing or using
+this package with messages translated.
+
+ Installers will find here some useful hints. These notes also
+explain how users should proceed for getting the programs to use the
+available translations. They tell how people wanting to contribute and
+work on translations can contact the appropriate team.
+
+ When reporting bugs in the `intl/' directory or bugs which may be
+related to internationalization, you should tell about the version of
+`gettext' which is used. The information can be found in the
+`intl/VERSION' file, in internationalized packages.
+
+1.1 Quick configuration advice
+==============================
+
+If you want to exploit the full power of internationalization, you
+should configure it using
+
+ ./configure --with-included-gettext
+
+to force usage of internationalizing routines provided within this
+package, despite the existence of internationalizing capabilities in the
+operating system where this package is being installed. So far, only
+the `gettext' implementation in the GNU C library version 2 provides as
+many features (such as locale alias, message inheritance, automatic
+charset conversion or plural form handling) as the implementation here.
+It is also not possible to offer this additional functionality on top
+of a `catgets' implementation. Future versions of GNU `gettext' will
+very likely convey even more functionality. So it might be a good idea
+to change to GNU `gettext' as soon as possible.
+
+ So you need _not_ provide this option if you are using GNU libc 2 or
+you have installed a recent copy of the GNU gettext package with the
+included `libintl'.
+
+1.2 INSTALL Matters
+===================
+
+Some packages are "localizable" when properly installed; the programs
+they contain can be made to speak your own native language. Most such
+packages use GNU `gettext'. Other packages have their own ways to
+internationalization, predating GNU `gettext'.
+
+ By default, this package will be installed to allow translation of
+messages. It will automatically detect whether the system already
+provides the GNU `gettext' functions. If not, the included GNU
+`gettext' library will be used. This library is wholly contained
+within this package, usually in the `intl/' subdirectory, so prior
+installation of the GNU `gettext' package is _not_ required.
+Installers may use special options at configuration time for changing
+the default behaviour. The commands:
+
+ ./configure --with-included-gettext
+ ./configure --disable-nls
+
+will, respectively, bypass any pre-existing `gettext' to use the
+internationalizing routines provided within this package, or else,
+_totally_ disable translation of messages.
+
+ When you already have GNU `gettext' installed on your system and run
+configure without an option for your new package, `configure' will
+probably detect the previously built and installed `libintl.a' file and
+will decide to use this. This might not be desirable. You should use
+the more recent version of the GNU `gettext' library. I.e. if the file
+`intl/VERSION' shows that the library which comes with this package is
+more recent, you should use
+
+ ./configure --with-included-gettext
+
+to prevent auto-detection.
+
+ The configuration process will not test for the `catgets' function
+and therefore it will not be used. The reason is that even an
+emulation of `gettext' on top of `catgets' could not provide all the
+extensions of the GNU `gettext' library.
+
+ Internationalized packages usually have many `po/LL.po' files, where
+LL gives an ISO 639 two-letter code identifying the language. Unless
+translations have been forbidden at `configure' time by using the
+`--disable-nls' switch, all available translations are installed
+together with the package. However, the environment variable `LINGUAS'
+may be set, prior to configuration, to limit the installed set.
+`LINGUAS' should then contain a space separated list of two-letter
+codes, stating which languages are allowed.
+
+1.3 Using This Package
+======================
+
+As a user, if your language has been installed for this package, you
+only have to set the `LANG' environment variable to the appropriate
+`LL_CC' combination. If you happen to have the `LC_ALL' or some other
+`LC_xxx' environment variables set, you should unset them before
+setting `LANG', otherwise the setting of `LANG' will not have the
+desired effect. Here `LL' is an ISO 639 two-letter language code, and
+`CC' is an ISO 3166 two-letter country code. For example, let's
+suppose that you speak German and live in Germany. At the shell
+prompt, merely execute `setenv LANG de_DE' (in `csh'),
+`export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash').
+This can be done from your `.login' or `.profile' file, once and for
+all.
+
+ You might think that the country code specification is redundant.
+But in fact, some languages have dialects in different countries. For
+example, `de_AT' is used for Austria, and `pt_BR' for Brazil. The
+country code serves to distinguish the dialects.
+
+ The locale naming convention of `LL_CC', with `LL' denoting the
+language and `CC' denoting the country, is the one use on systems based
+on GNU libc. On other systems, some variations of this scheme are
+used, such as `LL' or `LL_CC.ENCODING'. You can get the list of
+locales supported by your system for your language by running the
+command `locale -a | grep '^LL''.
+
+ Not all programs have translations for all languages. By default, an
+English message is shown in place of a nonexistent translation. If you
+understand other languages, you can set up a priority list of languages.
+This is done through a different environment variable, called
+`LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG'
+for the purpose of message handling, but you still need to have `LANG'
+set to the primary language; this is required by other parts of the
+system libraries. For example, some Swedish users who would rather
+read translations in German than English for when Swedish is not
+available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'.
+
+ Special advice for Norwegian users: The language code for Norwegian
+bokma*l changed from `no' to `nb' recently (in 2003). During the
+transition period, while some message catalogs for this language are
+installed under `nb' and some older ones under `no', it's recommended
+for Norwegian users to set `LANGUAGE' to `nb:no' so that both newer and
+older translations are used.
+
+ In the `LANGUAGE' environment variable, but not in the `LANG'
+environment variable, `LL_CC' combinations can be abbreviated as `LL'
+to denote the language's main dialect. For example, `de' is equivalent
+to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT'
+(Portuguese as spoken in Portugal) in this context.
+
+1.4 Translating Teams
+=====================
+
+For the Free Translation Project to be a success, we need interested
+people who like their own language and write it well, and who are also
+able to synergize with other translators speaking the same language.
+Each translation team has its own mailing list. The up-to-date list of
+teams can be found at the Free Translation Project's homepage,
+`http://translationproject.org/', in the "Teams" area.
+
+ If you'd like to volunteer to _work_ at translating messages, you
+should become a member of the translating team for your own language.
+The subscribing address is _not_ the same as the list itself, it has
+`-request' appended. For example, speakers of Swedish can send a
+message to `sv-request@li.org', having this message body:
+
+ subscribe
+
+ Keep in mind that team members are expected to participate
+_actively_ in translations, or at solving translational difficulties,
+rather than merely lurking around. If your team does not exist yet and
+you want to start one, or if you are unsure about what to do or how to
+get started, please write to `coordinator@translationproject.org' to
+reach the coordinator for all translator teams.
+
+ The English team is special. It works at improving and uniformizing
+the terminology in use. Proven linguistic skills are praised more than
+programming skills, here.
+
+1.5 Available Packages
+======================
+
+Languages are not equally supported in all packages. The following
+matrix shows the current state of internationalization, as of May 2010.
+The matrix shows, in regard of each package, for which languages PO
+files have been submitted to translation coordination, with a
+translation percentage of at least 50%.
+
+ Ready PO files af am ar as ast az be be@latin bg bn_IN bs ca crh
+ +---------------------------------------------------+
+ a2ps | [] [] |
+ aegis | |
+ ant-phone | |
+ anubis | |
+ aspell | [] [] |
+ bash | |
+ bfd | |
+ bibshelf | [] |
+ binutils | |
+ bison | |
+ bison-runtime | [] |
+ bluez-pin | [] [] |
+ bombono-dvd | |
+ buzztard | |
+ cflow | |
+ clisp | |
+ coreutils | [] [] |
+ cpio | |
+ cppi | |
+ cpplib | [] |
+ cryptsetup | |
+ dfarc | |
+ dialog | [] [] |
+ dico | |
+ diffutils | [] |
+ dink | |
+ doodle | |
+ e2fsprogs | [] |
+ enscript | [] |
+ exif | |
+ fetchmail | [] |
+ findutils | [] |
+ flex | [] |
+ freedink | |
+ gas | |
+ gawk | [] [] |
+ gcal | [] |
+ gcc | |
+ gettext-examples | [] [] [] [] |
+ gettext-runtime | [] [] [] |
+ gettext-tools | [] [] |
+ gip | [] |
+ gjay | |
+ gliv | [] |
+ glunarclock | [] [] |
+ gnubiff | |
+ gnucash | [] |
+ gnuedu | |
+ gnulib | |
+ gnunet | |
+ gnunet-gtk | |
+ gnutls | |
+ gold | |
+ gpe-aerial | |
+ gpe-beam | |
+ gpe-bluetooth | |
+ gpe-calendar | |
+ gpe-clock | [] |
+ gpe-conf | |
+ gpe-contacts | |
+ gpe-edit | |
+ gpe-filemanager | |
+ gpe-go | |
+ gpe-login | |
+ gpe-ownerinfo | [] |
+ gpe-package | |
+ gpe-sketchbook | |
+ gpe-su | [] |
+ gpe-taskmanager | [] |
+ gpe-timesheet | [] |
+ gpe-today | [] |
+ gpe-todo | |
+ gphoto2 | |
+ gprof | [] |
+ gpsdrive | |
+ gramadoir | |
+ grep | |
+ grub | [] [] |
+ gsasl | |
+ gss | |
+ gst-plugins-bad | [] |
+ gst-plugins-base | [] |
+ gst-plugins-good | [] |
+ gst-plugins-ugly | [] |
+ gstreamer | [] [] [] |
+ gtick | |
+ gtkam | [] |
+ gtkorphan | [] |
+ gtkspell | [] [] [] |
+ gutenprint | |
+ hello | [] |
+ help2man | |
+ hylafax | |
+ idutils | |
+ indent | [] [] |
+ iso_15924 | |
+ iso_3166 | [] [] [] [] [] [] [] [] |
+ iso_3166_2 | |
+ iso_4217 | |
+ iso_639 | [] [] [] [] [] |
+ iso_639_3 | [] |
+ jwhois | |
+ kbd | |
+ keytouch | [] |
+ keytouch-editor | |
+ keytouch-keyboa... | [] |
+ klavaro | [] |
+ latrine | |
+ ld | [] |
+ leafpad | [] [] |
+ libc | [] [] |
+ libexif | () |
+ libextractor | |
+ libgnutls | |
+ libgpewidget | |
+ libgpg-error | |
+ libgphoto2 | |
+ libgphoto2_port | |
+ libgsasl | |
+ libiconv | [] |
+ libidn | |
+ lifelines | |
+ liferea | [] [] |
+ lilypond | |
+ linkdr | [] |
+ lordsawar | |
+ lprng | |
+ lynx | [] |
+ m4 | |
+ mailfromd | |
+ mailutils | |
+ make | |
+ man-db | |
+ man-db-manpages | |
+ minicom | |
+ mkisofs | |
+ myserver | |
+ nano | [] [] |
+ opcodes | |
+ parted | |
+ pies | |
+ popt | |
+ psmisc | |
+ pspp | [] |
+ pwdutils | |
+ radius | [] |
+ recode | [] [] |
+ rosegarden | |
+ rpm | |
+ rush | |
+ sarg | |
+ screem | |
+ scrollkeeper | [] [] [] |
+ sed | [] [] |
+ sharutils | [] [] |
+ shishi | |
+ skencil | |
+ solfege | |
+ solfege-manual | |
+ soundtracker | |
+ sp | |
+ sysstat | |
+ tar | [] |
+ texinfo | |
+ tin | |
+ unicode-han-tra... | |
+ unicode-transla... | |
+ util-linux-ng | [] |
+ vice | |
+ vmm | |
+ vorbis-tools | |
+ wastesedge | |
+ wdiff | |
+ wget | [] [] |
+ wyslij-po | |
+ xchat | [] [] [] [] |
+ xdg-user-dirs | [] [] [] [] [] [] [] [] [] |
+ xkeyboard-config | [] [] [] |
+ +---------------------------------------------------+
+ af am ar as ast az be be@latin bg bn_IN bs ca crh
+ 6 0 2 3 19 1 11 3 28 3 1 38 5
+
+ cs da de el en en_GB en_ZA eo es et eu fa fi
+ +-------------------------------------------------+
+ a2ps | [] [] [] [] [] [] [] [] |
+ aegis | [] [] [] |
+ ant-phone | [] () |
+ anubis | [] [] [] |
+ aspell | [] [] [] [] [] |
+ bash | [] [] [] [] |
+ bfd | [] [] |
+ bibshelf | [] [] [] [] |
+ binutils | [] [] |
+ bison | [] [] [] |
+ bison-runtime | [] [] [] [] [] |
+ bluez-pin | [] [] [] [] [] [] [] |
+ bombono-dvd | [] [] |
+ buzztard | [] [] [] |
+ cflow | [] [] [] |
+ clisp | [] [] [] [] |
+ coreutils | [] [] [] [] |
+ cpio | [] |
+ cppi | [] |
+ cpplib | [] [] [] |
+ cryptsetup | [] |
+ dfarc | [] [] [] [] |
+ dialog | [] [] [] [] [] |
+ dico | |
+ diffutils | [] [] [] [] [] [] [] |
+ dink | [] [] [] |
+ doodle | [] |
+ e2fsprogs | [] [] [] |
+ enscript | [] [] [] |
+ exif | () [] [] [] |
+ fetchmail | [] [] () [] [] [] |
+ findutils | [] [] [] [] |
+ flex | [] [] [] |
+ freedink | [] [] [] [] |
+ gas | [] |
+ gawk | [] [] [] |
+ gcal | [] |
+ gcc | [] [] |
+ gettext-examples | [] [] [] [] [] |
+ gettext-runtime | [] [] [] [] [] |
+ gettext-tools | [] [] [] |
+ gip | [] [] [] [] [] |
+ gjay | [] [] |
+ gliv | [] [] [] [] |
+ glunarclock | [] [] [] |
+ gnubiff | () |
+ gnucash | [] () () () () () |
+ gnuedu | [] [] |
+ gnulib | [] [] [] |
+ gnunet | |
+ gnunet-gtk | [] |
+ gnutls | [] [] |
+ gold | [] [] |
+ gpe-aerial | [] [] [] [] [] |
+ gpe-beam | [] [] [] [] [] |
+ gpe-bluetooth | [] [] [] |
+ gpe-calendar | [] [] |
+ gpe-clock | [] [] [] [] [] |
+ gpe-conf | [] [] [] [] |
+ gpe-contacts | [] [] [] [] |
+ gpe-edit | [] [] [] |
+ gpe-filemanager | [] [] [] [] |
+ gpe-go | [] [] [] [] [] |
+ gpe-login | [] [] [] |
+ gpe-ownerinfo | [] [] [] [] [] |
+ gpe-package | [] [] [] [] |
+ gpe-sketchbook | [] [] [] [] [] |
+ gpe-su | [] [] [] [] [] |
+ gpe-taskmanager | [] [] [] [] [] |
+ gpe-timesheet | [] [] [] [] [] |
+ gpe-today | [] [] [] [] [] |
+ gpe-todo | [] [] [] [] |
+ gphoto2 | [] [] () [] [] [] [] |
+ gprof | [] [] [] [] |
+ gpsdrive | [] [] [] |
+ gramadoir | [] [] [] |
+ grep | [] [] |
+ grub | [] [] [] |
+ gsasl | [] [] |
+ gss | [] |
+ gst-plugins-bad | [] [] [] [] [] [] |
+ gst-plugins-base | [] [] [] [] [] [] |
+ gst-plugins-good | [] [] [] [] [] [] [] |
+ gst-plugins-ugly | [] [] [] [] [] [] [] |
+ gstreamer | [] [] [] [] [] [] |
+ gtick | [] () [] [] |
+ gtkam | [] [] () [] [] |
+ gtkorphan | [] [] [] [] |
+ gtkspell | [] [] [] [] [] [] [] [] |
+ gutenprint | [] [] [] [] |
+ hello | [] [] [] [] [] |
+ help2man | [] [] |
+ hylafax | [] [] |
+ idutils | [] [] [] |
+ indent | [] [] [] [] [] [] [] [] |
+ iso_15924 | [] () [] [] [] |
+ iso_3166 | [] [] [] () [] [] [] () [] |
+ iso_3166_2 | () |
+ iso_4217 | [] [] [] () [] [] [] |
+ iso_639 | [] [] [] () [] [] [] |
+ iso_639_3 | |
+ jwhois | [] [] |
+ kbd | [] [] [] [] [] |
+ keytouch | [] [] [] |
+ keytouch-editor | [] [] [] |
+ keytouch-keyboa... | [] [] |
+ klavaro | [] [] [] [] |
+ latrine | [] () [] |
+ ld | [] [] [] |
+ leafpad | [] [] [] [] [] [] [] |
+ libc | [] [] [] [] [] |
+ libexif | [] [] () |
+ libextractor | |
+ libgnutls | [] |
+ libgpewidget | [] [] [] |
+ libgpg-error | [] [] |
+ libgphoto2 | [] () |
+ libgphoto2_port | [] () [] |
+ libgsasl | [] |
+ libiconv | [] [] [] [] [] [] |
+ libidn | [] [] [] [] |
+ lifelines | [] () |
+ liferea | [] [] [] [] [] |
+ lilypond | [] [] [] [] |
+ linkdr | [] [] [] [] |
+ lordsawar | [] |
+ lprng | |
+ lynx | [] [] [] [] |
+ m4 | [] [] [] [] [] |
+ mailfromd | |
+ mailutils | [] |
+ make | [] [] [] [] |
+ man-db | |
+ man-db-manpages | |
+ minicom | [] [] [] [] [] |
+ mkisofs | [] |
+ myserver | |
+ nano | [] [] [] [] |
+ opcodes | [] [] [] |
+ parted | [] [] |
+ pies | |
+ popt | [] [] [] [] [] [] |
+ psmisc | [] [] [] [] |
+ pspp | [] |
+ pwdutils | [] |
+ radius | [] |
+ recode | [] [] [] [] [] [] [] |
+ rosegarden | () () () () |
+ rpm | [] [] [] |
+ rush | |
+ sarg | |
+ screem | |
+ scrollkeeper | [] [] [] [] [] [] |
+ sed | [] [] [] [] [] [] [] |
+ sharutils | [] [] [] [] [] |
+ shishi | |
+ skencil | [] () [] |
+ solfege | [] [] [] [] |
+ solfege-manual | [] [] |
+ soundtracker | [] [] [] |
+ sp | [] |
+ sysstat | [] [] [] [] |
+ tar | [] [] [] [] [] |
+ texinfo | [] [] [] |
+ tin | [] [] |
+ unicode-han-tra... | |
+ unicode-transla... | |
+ util-linux-ng | [] [] [] [] [] |
+ vice | () () |
+ vmm | [] |
+ vorbis-tools | [] [] |
+ wastesedge | [] |
+ wdiff | [] [] [] |
+ wget | [] [] [] [] |
+ wyslij-po | [] |
+ xchat | [] [] [] [] [] [] |
+ xdg-user-dirs | [] [] [] [] [] [] [] [] [] |
+ xkeyboard-config | [] [] [] [] [] [] |
+ +-------------------------------------------------+
+ cs da de el en en_GB en_ZA eo es et eu fa fi
+ 64 105 117 18 1 8 0 28 89 18 19 0 104
+
+ fr ga gl gu he hi hr hu hy id is it ja ka kn
+ +------------------------------------------------+
+ a2ps | [] [] [] |
+ aegis | [] [] |
+ ant-phone | [] [] |
+ anubis | [] [] [] |
+ aspell | [] [] [] [] |
+ bash | [] [] [] |
+ bfd | [] [] |
+ bibshelf | [] [] [] [] |
+ binutils | [] [] |
+ bison | [] [] [] |
+ bison-runtime | [] [] [] [] [] |
+ bluez-pin | [] [] [] [] [] [] [] |
+ bombono-dvd | |
+ buzztard | [] |
+ cflow | [] [] |
+ clisp | [] |
+ coreutils | [] [] [] [] [] |
+ cpio | [] [] [] |
+ cppi | [] |
+ cpplib | [] [] |
+ cryptsetup | [] [] [] |
+ dfarc | [] [] |
+ dialog | [] [] [] [] [] [] [] |
+ dico | |
+ diffutils | [] [] [] [] [] [] [] [] |
+ dink | [] |
+ doodle | [] [] |
+ e2fsprogs | [] [] |
+ enscript | [] [] [] [] |
+ exif | [] [] [] [] [] |
+ fetchmail | [] [] [] [] |
+ findutils | [] [] [] [] [] |
+ flex | [] [] |
+ freedink | [] [] |
+ gas | [] [] |
+ gawk | [] [] [] [] () [] |
+ gcal | [] |
+ gcc | [] |
+ gettext-examples | [] [] [] [] [] [] |
+ gettext-runtime | [] [] [] [] [] |
+ gettext-tools | [] [] [] [] |
+ gip | [] [] [] [] [] |
+ gjay | |
+ gliv | () |
+ glunarclock | [] [] [] |
+ gnubiff | () [] () |
+ gnucash | () () () () [] |
+ gnuedu | [] [] |
+ gnulib | [] [] [] [] [] |
+ gnunet | |
+ gnunet-gtk | [] |
+ gnutls | [] [] |
+ gold | [] |
+ gpe-aerial | [] [] |
+ gpe-beam | [] [] [] |
+ gpe-bluetooth | [] [] [] |
+ gpe-calendar | [] |
+ gpe-clock | [] [] [] [] |
+ gpe-conf | [] [] [] |
+ gpe-contacts | [] [] [] |
+ gpe-edit | [] [] |
+ gpe-filemanager | [] [] [] |
+ gpe-go | [] [] [] [] |
+ gpe-login | [] [] |
+ gpe-ownerinfo | [] [] [] [] |
+ gpe-package | [] [] |
+ gpe-sketchbook | [] [] [] |
+ gpe-su | [] [] [] [] [] |
+ gpe-taskmanager | [] [] [] [] |
+ gpe-timesheet | [] [] [] [] |
+ gpe-today | [] [] [] [] [] [] |
+ gpe-todo | [] [] |
+ gphoto2 | [] [] [] [] [] |
+ gprof | [] [] [] |
+ gpsdrive | [] [] [] |
+ gramadoir | [] [] [] |
+ grep | [] |
+ grub | [] [] [] |
+ gsasl | [] [] [] [] |
+ gss | [] [] [] [] |
+ gst-plugins-bad | [] [] [] [] |
+ gst-plugins-base | [] [] [] [] [] |
+ gst-plugins-good | [] [] [] [] [] |
+ gst-plugins-ugly | [] [] [] [] [] |
+ gstreamer | [] [] [] [] |
+ gtick | [] [] [] [] |
+ gtkam | [] [] [] [] [] |
+ gtkorphan | [] [] [] |
+ gtkspell | [] [] [] [] [] [] [] [] |
+ gutenprint | [] [] [] |
+ hello | [] [] |
+ help2man | [] |
+ hylafax | [] |
+ idutils | [] [] [] [] [] |
+ indent | [] [] [] [] [] [] [] |
+ iso_15924 | () [] [] |
+ iso_3166 | () [] [] [] [] [] [] [] [] [] [] |
+ iso_3166_2 | () [] [] [] |
+ iso_4217 | () [] [] [] [] |
+ iso_639 | () [] [] [] [] [] [] [] |
+ iso_639_3 | () [] [] |
+ jwhois | [] [] [] [] |
+ kbd | [] [] |
+ keytouch | [] [] [] [] [] |
+ keytouch-editor | [] [] [] [] |
+ keytouch-keyboa... | [] [] [] [] |
+ klavaro | [] [] |
+ latrine | [] [] |
+ ld | [] [] [] |
+ leafpad | [] [] [] [] [] [] () |
+ libc | [] [] [] [] |
+ libexif | |
+ libextractor | |
+ libgnutls | [] [] |
+ libgpewidget | [] [] [] |
+ libgpg-error | [] [] |
+ libgphoto2 | [] [] [] |
+ libgphoto2_port | [] [] [] |
+ libgsasl | [] [] [] [] |
+ libiconv | [] [] [] [] [] |
+ libidn | [] [] [] |
+ lifelines | () |
+ liferea | [] [] [] [] |
+ lilypond | [] |
+ linkdr | [] [] [] [] |
+ lordsawar | |
+ lprng | [] |
+ lynx | [] [] [] [] [] |
+ m4 | [] [] [] [] [] |
+ mailfromd | |
+ mailutils | [] [] |
+ make | [] [] [] [] [] [] [] [] |
+ man-db | [] [] |
+ man-db-manpages | [] |
+ minicom | [] [] [] [] |
+ mkisofs | [] [] [] |
+ myserver | |
+ nano | [] [] [] [] [] |
+ opcodes | [] [] [] |
+ parted | [] [] [] [] |
+ pies | |
+ popt | [] [] [] [] [] [] [] [] |
+ psmisc | [] [] |
+ pspp | |
+ pwdutils | [] [] |
+ radius | [] [] |
+ recode | [] [] [] [] [] [] [] |
+ rosegarden | () () () () |
+ rpm | [] [] |
+ rush | |
+ sarg | [] |
+ screem | [] [] |
+ scrollkeeper | [] [] [] |
+ sed | [] [] [] [] [] [] [] |
+ sharutils | [] [] [] [] [] [] |
+ shishi | [] |
+ skencil | [] |
+ solfege | [] [] [] |
+ solfege-manual | [] [] |
+ soundtracker | [] [] |
+ sp | [] () |
+ sysstat | [] [] [] [] |
+ tar | [] [] [] [] [] [] |
+ texinfo | [] [] [] [] |
+ tin | [] |
+ unicode-han-tra... | |
+ unicode-transla... | [] [] |
+ util-linux-ng | [] [] [] [] [] |
+ vice | () () () |
+ vmm | [] |
+ vorbis-tools | [] |
+ wastesedge | () () |
+ wdiff | |
+ wget | [] [] [] [] [] [] [] |
+ wyslij-po | [] [] |
+ xchat | [] [] [] [] [] [] [] [] |
+ xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] [] |
+ xkeyboard-config | [] [] [] [] |
+ +------------------------------------------------+
+ fr ga gl gu he hi hr hu hy id is it ja ka kn
+ 121 53 20 4 8 2 5 53 2 120 5 83 66 0 4
+
+ ko ku ky lg lt lv mk ml mn mr ms mt nb nds ne
+ +-----------------------------------------------+
+ a2ps | [] |
+ aegis | |
+ ant-phone | |
+ anubis | [] [] |
+ aspell | [] |
+ bash | |
+ bfd | |
+ bibshelf | [] [] |
+ binutils | |
+ bison | [] |
+ bison-runtime | [] [] [] [] [] |
+ bluez-pin | [] [] [] [] [] |
+ bombono-dvd | |
+ buzztard | |
+ cflow | |
+ clisp | |
+ coreutils | [] |
+ cpio | |
+ cppi | |
+ cpplib | |
+ cryptsetup | |
+ dfarc | [] |
+ dialog | [] [] [] [] [] |
+ dico | |
+ diffutils | [] [] |
+ dink | |
+ doodle | |
+ e2fsprogs | |
+ enscript | |
+ exif | [] |
+ fetchmail | |
+ findutils | |
+ flex | |
+ freedink | [] |
+ gas | |
+ gawk | |
+ gcal | |
+ gcc | |
+ gettext-examples | [] [] [] [] |
+ gettext-runtime | [] |
+ gettext-tools | [] |
+ gip | [] [] |
+ gjay | |
+ gliv | |
+ glunarclock | [] |
+ gnubiff | |
+ gnucash | () () () () |
+ gnuedu | |
+ gnulib | |
+ gnunet | |
+ gnunet-gtk | |
+ gnutls | [] |
+ gold | |
+ gpe-aerial | [] |
+ gpe-beam | [] |
+ gpe-bluetooth | [] [] |
+ gpe-calendar | [] |
+ gpe-clock | [] [] [] [] [] |
+ gpe-conf | [] [] |
+ gpe-contacts | [] [] |
+ gpe-edit | [] |
+ gpe-filemanager | [] [] |
+ gpe-go | [] [] [] |
+ gpe-login | [] |
+ gpe-ownerinfo | [] [] |
+ gpe-package | [] [] |
+ gpe-sketchbook | [] [] |
+ gpe-su | [] [] [] [] [] [] |
+ gpe-taskmanager | [] [] [] [] [] [] |
+ gpe-timesheet | [] [] |
+ gpe-today | [] [] [] [] |
+ gpe-todo | [] [] |
+ gphoto2 | |
+ gprof | [] |
+ gpsdrive | |
+ gramadoir | |
+ grep | |
+ grub | |
+ gsasl | |
+ gss | |
+ gst-plugins-bad | [] [] |
+ gst-plugins-base | [] [] |
+ gst-plugins-good | [] [] |
+ gst-plugins-ugly | [] [] [] [] [] |
+ gstreamer | |
+ gtick | |
+ gtkam | [] |
+ gtkorphan | [] [] |
+ gtkspell | [] [] [] [] [] [] [] |
+ gutenprint | |
+ hello | [] [] [] |
+ help2man | |
+ hylafax | |
+ idutils | |
+ indent | |
+ iso_15924 | [] [] |
+ iso_3166 | [] [] () [] [] [] [] [] |
+ iso_3166_2 | |
+ iso_4217 | [] [] |
+ iso_639 | [] [] |
+ iso_639_3 | [] |
+ jwhois | [] |
+ kbd | |
+ keytouch | [] |
+ keytouch-editor | [] |
+ keytouch-keyboa... | [] |
+ klavaro | [] |
+ latrine | [] |
+ ld | |
+ leafpad | [] [] [] |
+ libc | [] |
+ libexif | |
+ libextractor | |
+ libgnutls | [] |
+ libgpewidget | [] [] |
+ libgpg-error | |
+ libgphoto2 | |
+ libgphoto2_port | |
+ libgsasl | |
+ libiconv | |
+ libidn | |
+ lifelines | |
+ liferea | |
+ lilypond | |
+ linkdr | |
+ lordsawar | |
+ lprng | |
+ lynx | |
+ m4 | |
+ mailfromd | |
+ mailutils | |
+ make | [] |
+ man-db | |
+ man-db-manpages | |
+ minicom | [] |
+ mkisofs | |
+ myserver | |
+ nano | [] [] |
+ opcodes | |
+ parted | |
+ pies | |
+ popt | [] [] [] |
+ psmisc | |
+ pspp | |
+ pwdutils | |
+ radius | |
+ recode | |
+ rosegarden | |
+ rpm | |
+ rush | |
+ sarg | |
+ screem | |
+ scrollkeeper | [] [] |
+ sed | |
+ sharutils | |
+ shishi | |
+ skencil | |
+ solfege | [] |
+ solfege-manual | |
+ soundtracker | |
+ sp | |
+ sysstat | [] |
+ tar | [] |
+ texinfo | [] |
+ tin | |
+ unicode-han-tra... | |
+ unicode-transla... | |
+ util-linux-ng | |
+ vice | |
+ vmm | |
+ vorbis-tools | |
+ wastesedge | |
+ wdiff | |
+ wget | [] |
+ wyslij-po | |
+ xchat | [] [] [] |
+ xdg-user-dirs | [] [] [] [] [] [] [] [] |
+ xkeyboard-config | [] [] [] |
+ +-----------------------------------------------+
+ ko ku ky lg lt lv mk ml mn mr ms mt nb nds ne
+ 20 5 10 1 12 48 4 2 2 4 24 10 19 3 1
+
+ nl nn or pa pl ps pt pt_BR ro ru rw sk sl sq sr
+ +---------------------------------------------------+
+ a2ps | [] [] [] [] [] [] [] [] |
+ aegis | [] [] [] |
+ ant-phone | [] [] |
+ anubis | [] [] [] |
+ aspell | [] [] [] [] [] |
+ bash | [] [] |
+ bfd | [] |
+ bibshelf | [] [] |
+ binutils | [] [] |
+ bison | [] [] [] |
+ bison-runtime | [] [] [] [] [] [] [] |
+ bluez-pin | [] [] [] [] [] [] [] [] |
+ bombono-dvd | [] () |
+ buzztard | [] [] |
+ cflow | [] |
+ clisp | [] [] |
+ coreutils | [] [] [] [] [] [] |
+ cpio | [] [] [] |
+ cppi | [] |
+ cpplib | [] |
+ cryptsetup | [] |
+ dfarc | [] |
+ dialog | [] [] [] [] |
+ dico | [] |
+ diffutils | [] [] [] [] [] [] |
+ dink | () |
+ doodle | [] [] |
+ e2fsprogs | [] [] |
+ enscript | [] [] [] [] [] |
+ exif | [] [] [] () [] |
+ fetchmail | [] [] [] [] |
+ findutils | [] [] [] [] [] |
+ flex | [] [] [] [] [] |
+ freedink | [] [] |
+ gas | |
+ gawk | [] [] [] [] |
+ gcal | |
+ gcc | [] |
+ gettext-examples | [] [] [] [] [] [] [] [] |
+ gettext-runtime | [] [] [] [] [] [] [] [] [] |
+ gettext-tools | [] [] [] [] [] [] |
+ gip | [] [] [] [] [] |
+ gjay | |
+ gliv | [] [] [] [] [] [] |
+ glunarclock | [] [] [] [] [] |
+ gnubiff | [] () |
+ gnucash | [] () () () |
+ gnuedu | [] |
+ gnulib | [] [] [] [] |
+ gnunet | |
+ gnunet-gtk | |
+ gnutls | [] [] |
+ gold | |
+ gpe-aerial | [] [] [] [] [] [] [] |
+ gpe-beam | [] [] [] [] [] [] [] |
+ gpe-bluetooth | [] [] |
+ gpe-calendar | [] [] [] [] |
+ gpe-clock | [] [] [] [] [] [] [] [] |
+ gpe-conf | [] [] [] [] [] [] [] |
+ gpe-contacts | [] [] [] [] [] |
+ gpe-edit | [] [] [] |
+ gpe-filemanager | [] [] [] |
+ gpe-go | [] [] [] [] [] [] [] [] |
+ gpe-login | [] [] |
+ gpe-ownerinfo | [] [] [] [] [] [] [] [] |
+ gpe-package | [] [] |
+ gpe-sketchbook | [] [] [] [] [] [] [] |
+ gpe-su | [] [] [] [] [] [] [] [] |
+ gpe-taskmanager | [] [] [] [] [] [] [] [] |
+ gpe-timesheet | [] [] [] [] [] [] [] [] |
+ gpe-today | [] [] [] [] [] [] [] [] |
+ gpe-todo | [] [] [] [] [] |
+ gphoto2 | [] [] [] [] [] [] [] [] |
+ gprof | [] [] [] |
+ gpsdrive | [] [] |
+ gramadoir | [] [] |
+ grep | [] [] [] [] |
+ grub | [] [] [] |
+ gsasl | [] [] [] [] |
+ gss | [] [] [] |
+ gst-plugins-bad | [] [] [] [] [] |
+ gst-plugins-base | [] [] [] [] [] |
+ gst-plugins-good | [] [] [] [] [] |
+ gst-plugins-ugly | [] [] [] [] [] [] |
+ gstreamer | [] [] [] [] [] |
+ gtick | [] [] [] |
+ gtkam | [] [] [] [] [] [] |
+ gtkorphan | [] |
+ gtkspell | [] [] [] [] [] [] [] [] [] [] |
+ gutenprint | [] [] |
+ hello | [] [] [] [] |
+ help2man | [] [] |
+ hylafax | [] |
+ idutils | [] [] [] [] [] |
+ indent | [] [] [] [] [] [] [] |
+ iso_15924 | [] [] [] [] |
+ iso_3166 | [] [] [] [] [] () [] [] [] [] [] [] [] [] |
+ iso_3166_2 | [] [] [] |
+ iso_4217 | [] [] [] [] [] [] [] [] |
+ iso_639 | [] [] [] [] [] [] [] [] [] |
+ iso_639_3 | [] [] |
+ jwhois | [] [] [] [] |
+ kbd | [] [] [] |
+ keytouch | [] [] [] |
+ keytouch-editor | [] [] [] |
+ keytouch-keyboa... | [] [] [] |
+ klavaro | [] [] |
+ latrine | [] [] |
+ ld | |
+ leafpad | [] [] [] [] [] [] [] [] [] |
+ libc | [] [] [] [] |
+ libexif | [] [] () [] |
+ libextractor | |
+ libgnutls | [] [] |
+ libgpewidget | [] [] [] |
+ libgpg-error | [] [] |
+ libgphoto2 | [] [] |
+ libgphoto2_port | [] [] [] [] |
+ libgsasl | [] [] [] [] [] |
+ libiconv | [] [] [] [] [] |
+ libidn | [] [] |
+ lifelines | [] [] |
+ liferea | [] [] [] [] [] () () [] |
+ lilypond | [] |
+ linkdr | [] [] [] |
+ lordsawar | |
+ lprng | [] |
+ lynx | [] [] [] |
+ m4 | [] [] [] [] [] |
+ mailfromd | [] |
+ mailutils | [] |
+ make | [] [] [] [] |
+ man-db | [] [] [] |
+ man-db-manpages | [] [] [] |
+ minicom | [] [] [] [] |
+ mkisofs | [] [] [] |
+ myserver | |
+ nano | [] [] [] [] |
+ opcodes | [] [] |
+ parted | [] [] [] [] |
+ pies | [] |
+ popt | [] [] [] [] |
+ psmisc | [] [] [] |
+ pspp | [] [] |
+ pwdutils | [] |
+ radius | [] [] [] |
+ recode | [] [] [] [] [] [] [] [] |
+ rosegarden | () () |
+ rpm | [] [] [] |
+ rush | [] [] |
+ sarg | |
+ screem | |
+ scrollkeeper | [] [] [] [] [] [] [] [] |
+ sed | [] [] [] [] [] [] [] [] [] |
+ sharutils | [] [] [] [] |
+ shishi | [] |
+ skencil | [] [] |
+ solfege | [] [] [] [] |
+ solfege-manual | [] [] [] |
+ soundtracker | [] |
+ sp | |
+ sysstat | [] [] [] [] |
+ tar | [] [] [] [] |
+ texinfo | [] [] [] [] |
+ tin | [] |
+ unicode-han-tra... | |
+ unicode-transla... | |
+ util-linux-ng | [] [] [] [] [] |
+ vice | [] |
+ vmm | [] |
+ vorbis-tools | [] [] |
+ wastesedge | [] |
+ wdiff | [] [] |
+ wget | [] [] [] [] [] [] [] |
+ wyslij-po | [] [] [] |
+ xchat | [] [] [] [] [] [] [] [] [] |
+ xdg-user-dirs | [] [] [] [] [] [] [] [] [] [] [] [] [] [] |
+ xkeyboard-config | [] [] [] [] [] |
+ +---------------------------------------------------+
+ nl nn or pa pl ps pt pt_BR ro ru rw sk sl sq sr
+ 135 10 4 7 105 1 29 61 47 91 3 55 47 8 37
+
+ sv sw ta te tg th tr uk vi wa zh_CN zh_HK zh_TW
+ +---------------------------------------------------+
+ a2ps | [] [] [] [] [] | 27
+ aegis | [] | 9
+ ant-phone | [] [] [] [] | 9
+ anubis | [] [] [] [] | 15
+ aspell | [] [] [] | 20
+ bash | [] [] | 11
+ bfd | [] | 6
+ bibshelf | [] [] [] | 16
+ binutils | [] [] | 8
+ bison | [] [] | 12
+ bison-runtime | [] [] [] [] [] [] | 29
+ bluez-pin | [] [] [] [] [] [] [] [] | 37
+ bombono-dvd | [] | 4
+ buzztard | [] | 7
+ cflow | [] [] [] | 9
+ clisp | | 10
+ coreutils | [] [] [] [] | 22
+ cpio | [] [] [] [] [] [] | 13
+ cppi | [] [] | 5
+ cpplib | [] [] [] [] [] [] | 13
+ cryptsetup | [] [] | 7
+ dfarc | [] | 9
+ dialog | [] [] [] [] [] [] [] | 30
+ dico | [] | 2
+ diffutils | [] [] [] [] [] [] | 30
+ dink | | 4
+ doodle | [] [] | 7
+ e2fsprogs | [] [] [] | 11
+ enscript | [] [] [] [] | 17
+ exif | [] [] [] | 16
+ fetchmail | [] [] [] | 17
+ findutils | [] [] [] [] [] | 20
+ flex | [] [] [] [] | 15
+ freedink | [] | 10
+ gas | [] | 4
+ gawk | [] [] [] [] | 18
+ gcal | [] [] | 5
+ gcc | [] [] [] | 7
+ gettext-examples | [] [] [] [] [] [] [] | 34
+ gettext-runtime | [] [] [] [] [] [] [] | 30
+ gettext-tools | [] [] [] [] [] [] | 22
+ gip | [] [] [] [] | 22
+ gjay | [] | 3
+ gliv | [] [] [] | 14
+ glunarclock | [] [] [] [] [] | 19
+ gnubiff | [] [] | 4
+ gnucash | () [] () () | 9
+ gnuedu | [] [] | 7
+ gnulib | [] [] [] [] | 16
+ gnunet | [] | 1
+ gnunet-gtk | [] [] [] | 5
+ gnutls | [] [] [] | 10
+ gold | [] | 4
+ gpe-aerial | [] [] [] | 18
+ gpe-beam | [] [] [] | 19
+ gpe-bluetooth | [] [] [] | 13
+ gpe-calendar | [] [] [] [] | 12
+ gpe-clock | [] [] [] [] [] | 28
+ gpe-conf | [] [] [] [] | 20
+ gpe-contacts | [] [] [] | 17
+ gpe-edit | [] [] [] | 12
+ gpe-filemanager | [] [] [] [] | 16
+ gpe-go | [] [] [] [] [] | 25
+ gpe-login | [] [] [] | 11
+ gpe-ownerinfo | [] [] [] [] [] | 25
+ gpe-package | [] [] [] | 13
+ gpe-sketchbook | [] [] [] | 20
+ gpe-su | [] [] [] [] [] | 30
+ gpe-taskmanager | [] [] [] [] [] | 29
+ gpe-timesheet | [] [] [] [] [] | 25
+ gpe-today | [] [] [] [] [] [] | 30
+ gpe-todo | [] [] [] [] | 17
+ gphoto2 | [] [] [] [] [] | 24
+ gprof | [] [] [] | 15
+ gpsdrive | [] [] [] | 11
+ gramadoir | [] [] [] | 11
+ grep | [] [] [] | 10
+ grub | [] [] [] | 14
+ gsasl | [] [] [] [] | 14
+ gss | [] [] [] | 11
+ gst-plugins-bad | [] [] [] [] | 22
+ gst-plugins-base | [] [] [] [] [] | 24
+ gst-plugins-good | [] [] [] [] [] | 25
+ gst-plugins-ugly | [] [] [] [] [] | 29
+ gstreamer | [] [] [] [] | 22
+ gtick | [] [] [] | 13
+ gtkam | [] [] [] | 20
+ gtkorphan | [] [] [] | 14
+ gtkspell | [] [] [] [] [] [] [] [] [] | 45
+ gutenprint | [] | 10
+ hello | [] [] [] [] [] [] | 21
+ help2man | [] [] | 7
+ hylafax | [] | 5
+ idutils | [] [] [] [] | 17
+ indent | [] [] [] [] [] [] | 30
+ iso_15924 | () [] () [] [] | 16
+ iso_3166 | [] [] () [] [] () [] [] [] () | 53
+ iso_3166_2 | () [] () [] | 9
+ iso_4217 | [] () [] [] () [] [] | 26
+ iso_639 | [] [] [] () [] () [] [] [] [] | 38
+ iso_639_3 | [] () | 8
+ jwhois | [] [] [] [] [] | 16
+ kbd | [] [] [] [] [] | 15
+ keytouch | [] [] [] | 16
+ keytouch-editor | [] [] [] | 14
+ keytouch-keyboa... | [] [] [] | 14
+ klavaro | [] | 11
+ latrine | [] [] [] | 10
+ ld | [] [] [] [] | 11
+ leafpad | [] [] [] [] [] [] | 33
+ libc | [] [] [] [] [] | 21
+ libexif | [] () | 6
+ libextractor | [] | 1
+ libgnutls | [] [] [] | 9
+ libgpewidget | [] [] [] | 14
+ libgpg-error | [] [] [] | 9
+ libgphoto2 | [] [] | 8
+ libgphoto2_port | [] [] [] [] | 13
+ libgsasl | [] [] [] | 13
+ libiconv | [] [] [] [] | 21
+ libidn | () [] [] | 11
+ lifelines | [] | 4
+ liferea | [] [] [] | 21
+ lilypond | [] | 7
+ linkdr | [] [] [] [] [] | 17
+ lordsawar | | 1
+ lprng | [] | 3
+ lynx | [] [] [] [] | 17
+ m4 | [] [] [] [] | 19
+ mailfromd | [] [] | 3
+ mailutils | [] | 5
+ make | [] [] [] [] | 21
+ man-db | [] [] [] | 8
+ man-db-manpages | | 4
+ minicom | [] [] | 16
+ mkisofs | [] [] | 9
+ myserver | | 0
+ nano | [] [] [] [] | 21
+ opcodes | [] [] [] | 11
+ parted | [] [] [] [] [] | 15
+ pies | [] [] | 3
+ popt | [] [] [] [] [] [] | 27
+ psmisc | [] [] | 11
+ pspp | | 4
+ pwdutils | [] [] | 6
+ radius | [] [] | 9
+ recode | [] [] [] [] | 28
+ rosegarden | () | 0
+ rpm | [] [] [] | 11
+ rush | [] [] | 4
+ sarg | | 1
+ screem | [] | 3
+ scrollkeeper | [] [] [] [] [] | 27
+ sed | [] [] [] [] [] | 30
+ sharutils | [] [] [] [] [] | 22
+ shishi | [] | 3
+ skencil | [] [] | 7
+ solfege | [] [] [] [] | 16
+ solfege-manual | [] | 8
+ soundtracker | [] [] [] | 9
+ sp | [] | 3
+ sysstat | [] [] | 15
+ tar | [] [] [] [] [] [] | 23
+ texinfo | [] [] [] [] | 16
+ tin | | 4
+ unicode-han-tra... | | 0
+ unicode-transla... | | 2
+ util-linux-ng | [] [] [] [] | 20
+ vice | () () | 1
+ vmm | [] | 4
+ vorbis-tools | [] | 6
+ wastesedge | | 2
+ wdiff | [] [] | 7
+ wget | [] [] [] [] [] | 26
+ wyslij-po | [] [] | 8
+ xchat | [] [] [] [] [] [] | 36
+ xdg-user-dirs | [] [] [] [] [] [] [] [] [] | 60
+ xkeyboard-config | [] [] [] [] | 25
+ +---------------------------------------------------+
+ 84 teams sv sw ta te tg th tr uk vi wa zh_CN zh_HK zh_TW
+ 178 domains 119 1 3 2 0 10 66 50 155 17 97 7 41 2610
+
+ Some counters in the preceding matrix are higher than the number of
+visible blocks let us expect. This is because a few extra PO files are
+used for implementing regional variants of languages, or language
+dialects.
+
+ For a PO file in the matrix above to be effective, the package to
+which it applies should also have been internationalized and
+distributed as such by its maintainer. There might be an observable
+lag between the mere existence a PO file and its wide availability in a
+distribution.
+
+ If May 2010 seems to be old, you may fetch a more recent copy of
+this `ABOUT-NLS' file on most GNU archive sites. The most up-to-date
+matrix with full percentage details can be found at
+`http://translationproject.org/extra/matrix.html'.
+
+1.6 Using `gettext' in new packages
+===================================
+
+If you are writing a freely available program and want to
+internationalize it you are welcome to use GNU `gettext' in your
+package. Of course you have to respect the GNU Library General Public
+License which covers the use of the GNU `gettext' library. This means
+in particular that even non-free programs can use `libintl' as a shared
+library, whereas only free software can use `libintl' as a static
+library or use modified versions of `libintl'.
+
+ Once the sources are changed appropriately and the setup can handle
+the use of `gettext' the only thing missing are the translations. The
+Free Translation Project is also available for packages which are not
+developed inside the GNU project. Therefore the information given above
+applies also for every other Free Software Project. Contact
+`coordinator@translationproject.org' to make the `.pot' files available
+to the translation teams.
+
diff --git a/Makefile.am b/Makefile.am
index 94c44199..14682d92 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,9 +1,21 @@
SUBDIRS = pixmaps\
icons\
- ${PLUGINS_DIRS}
+ ${PLUGINS_DIRS}\
+ po\
+ intl
bin_PROGRAMS = deadbeef
+INTLTOOL_FILES = \
+ intltool-extract.in \
+ intltool-merge.in \
+ intltool-update.in
+
+DISTCLEANFILES = \
+ intltool-extract \
+ intltool-merge \
+ intltool-update
+
deadbeef_SOURCES =\
main.c common.h deadbeef.h\
plugins.c plugins.h moduleconf.h\
@@ -19,7 +31,8 @@ deadbeef_SOURCES =\
vfs.c vfs.h vfs_stdio.c\
timeline.c timeline.h\
md5/md5.c md5/md5.h\
- metacache.c metacache.h
+ metacache.c metacache.h\
+ gettext.h
sdkdir = $(pkgincludedir)
sdk_HEADERS = deadbeef.h
@@ -36,4 +49,6 @@ docs_DATA = README COPYING.GPLv2 help.txt about.txt ChangeLog COPYING.LGPLv2.1
desktopdir = $(datadir)/applications
desktop_DATA = deadbeef.desktop
-EXTRA_DIST = $(docs_DATA) $(desktop_DATA)
+EXTRA_DIST = $(docs_DATA) $(desktop_DATA) $(INTLTOOL_FILES)
+
+ACLOCAL_AMFLAGS = -I m4
diff --git a/README.transifex b/README.transifex
new file mode 100644
index 00000000..db9acfdb
--- /dev/null
+++ b/README.transifex
@@ -0,0 +1,11 @@
+Transifex.net Token Verification
+=================================
+
+The list of tokens bellow guarantee the respective users to be able to enable
+submission on components using the following repository url:
+
+git+ssh://transifex@lxde.git.sourceforge.net/gitroot/lxde/deadbeef
+
+Tokens:
+
+GTmYuQVvkNdXE5xNfpGXLqytXLxKMT2y / PCMan
diff --git a/config.rpath b/config.rpath
new file mode 100755
index 00000000..17298f23
--- /dev/null
+++ b/config.rpath
@@ -0,0 +1,672 @@
+#! /bin/sh
+# Output a system dependent set of variables, describing how to set the
+# run time search path of shared libraries in an executable.
+#
+# Copyright 1996-2010 Free Software Foundation, Inc.
+# Taken from GNU libtool, 2001
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+#
+# The first argument passed to this file is the canonical host specification,
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld
+# should be set by the caller.
+#
+# The set of defined variables is at the end of this script.
+
+# Known limitations:
+# - On IRIX 6.5 with CC="cc", the run time search patch must not be longer
+# than 256 bytes, otherwise the compiler driver will dump core. The only
+# known workaround is to choose shorter directory names for the build
+# directory and/or the installation directory.
+
+# All known linkers require a `.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+shrext=.so
+
+host="$1"
+host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+# Code taken from libtool.m4's _LT_CC_BASENAME.
+
+for cc_temp in $CC""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'`
+
+# Code taken from libtool.m4's _LT_COMPILER_PIC.
+
+wl=
+if test "$GCC" = yes; then
+ wl='-Wl,'
+else
+ case "$host_os" in
+ aix*)
+ wl='-Wl,'
+ ;;
+ darwin*)
+ case $cc_basename in
+ xlc*)
+ wl='-Wl,'
+ ;;
+ esac
+ ;;
+ mingw* | cygwin* | pw32* | os2* | cegcc*)
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ wl='-Wl,'
+ ;;
+ irix5* | irix6* | nonstopux*)
+ wl='-Wl,'
+ ;;
+ newsos6)
+ ;;
+ linux* | k*bsd*-gnu)
+ case $cc_basename in
+ ecc*)
+ wl='-Wl,'
+ ;;
+ icc* | ifort*)
+ wl='-Wl,'
+ ;;
+ lf95*)
+ wl='-Wl,'
+ ;;
+ pgcc | pgf77 | pgf90)
+ wl='-Wl,'
+ ;;
+ ccc*)
+ wl='-Wl,'
+ ;;
+ como)
+ wl='-lopt='
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ C*)
+ wl='-Wl,'
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ osf3* | osf4* | osf5*)
+ wl='-Wl,'
+ ;;
+ rdos*)
+ ;;
+ solaris*)
+ wl='-Wl,'
+ ;;
+ sunos4*)
+ wl='-Qoption ld '
+ ;;
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ wl='-Wl,'
+ ;;
+ sysv4*MP*)
+ ;;
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ wl='-Wl,'
+ ;;
+ unicos*)
+ wl='-Wl,'
+ ;;
+ uts4*)
+ ;;
+ esac
+fi
+
+# Code taken from libtool.m4's _LT_LINKER_SHLIBS.
+
+hardcode_libdir_flag_spec=
+hardcode_libdir_separator=
+hardcode_direct=no
+hardcode_minus_L=no
+
+case "$host_os" in
+ cygwin* | mingw* | pw32* | cegcc*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+esac
+
+ld_shlibs=yes
+if test "$with_gnu_ld" = yes; then
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ # Unlike libtool, we use -rpath here, not --rpath, since the documented
+ # option of GNU ld is called -rpath, not --rpath.
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ case "$host_os" in
+ aix[3-9]*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ ld_shlibs=no
+ fi
+ ;;
+ amigaos*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+ # that the semantics of dynamic libraries on AmigaOS, at least up
+ # to version 4, is to share data among multiple programs linked
+ # with the same dynamic library. Since this doesn't match the
+ # behavior of shared libraries on other platforms, we cannot use
+ # them.
+ ld_shlibs=no
+ ;;
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ :
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ cygwin* | mingw* | pw32* | cegcc*)
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec='-L$libdir'
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ :
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ interix[3-9]*)
+ hardcode_direct=no
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ ;;
+ gnu* | linux* | k*bsd*-gnu)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ :
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ netbsd*)
+ ;;
+ solaris*)
+ if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+ ld_shlibs=no
+ elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ :
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+ ld_shlibs=no
+ ;;
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+ ;;
+ sunos4*)
+ hardcode_direct=yes
+ ;;
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ :
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+ if test "$ld_shlibs" = no; then
+ hardcode_libdir_flag_spec=
+ fi
+else
+ case "$host_os" in
+ aix3*)
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L=yes
+ if test "$GCC" = yes; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct=unsupported
+ fi
+ ;;
+ aix[4-9]*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ else
+ aix_use_runtimelinking=no
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ esac
+ fi
+ hardcode_direct=yes
+ hardcode_libdir_separator=':'
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ :
+ else
+ # We have old collect2
+ hardcode_direct=unsupported
+ hardcode_minus_L=yes
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_libdir_separator=
+ fi
+ ;;
+ esac
+ fi
+ # Begin _LT_AC_SYS_LIBPATH_AIX.
+ echo 'int main () { return 0; }' > conftest.c
+ ${CC} ${LDFLAGS} conftest.c -o conftest
+ aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+ if test -z "$aix_libpath"; then
+ aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+ fi
+ if test -z "$aix_libpath"; then
+ aix_libpath="/usr/lib:/lib"
+ fi
+ rm -f conftest.c conftest
+ # End _LT_AC_SYS_LIBPATH_AIX.
+ if test "$aix_use_runtimelinking" = yes; then
+ hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+ else
+ hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+ fi
+ fi
+ ;;
+ amigaos*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ # see comment about different semantics on the GNU ld section
+ ld_shlibs=no
+ ;;
+ bsdi[45]*)
+ ;;
+ cygwin* | mingw* | pw32* | cegcc*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec=' '
+ libext=lib
+ ;;
+ darwin* | rhapsody*)
+ hardcode_direct=no
+ if test "$GCC" = yes ; then
+ :
+ else
+ case $cc_basename in
+ xlc*)
+ ;;
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+ fi
+ ;;
+ dgux*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ ;;
+ freebsd1*)
+ ld_shlibs=no
+ ;;
+ freebsd2.2*)
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ ;;
+ freebsd2*)
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ ;;
+ freebsd* | dragonfly*)
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ ;;
+ hpux9*)
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ ;;
+ hpux10*)
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ fi
+ ;;
+ hpux11*)
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_direct=no
+ ;;
+ *)
+ hardcode_direct=yes
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ ;;
+ esac
+ fi
+ ;;
+ irix5* | irix6* | nonstopux*)
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+ netbsd*)
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ ;;
+ newsos6)
+ hardcode_direct=yes
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+ openbsd*)
+ if test -f /usr/libexec/ld.so; then
+ hardcode_direct=yes
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ else
+ case "$host_os" in
+ openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+ hardcode_libdir_flag_spec='-R$libdir'
+ ;;
+ *)
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ os2*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ ;;
+ osf3*)
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+ osf4* | osf5*)
+ if test "$GCC" = yes; then
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ else
+ # Both cc and cxx compiler support -rpath directly
+ hardcode_libdir_flag_spec='-rpath $libdir'
+ fi
+ hardcode_libdir_separator=:
+ ;;
+ solaris*)
+ hardcode_libdir_flag_spec='-R$libdir'
+ ;;
+ sunos4*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ ;;
+ sysv4)
+ case $host_vendor in
+ sni)
+ hardcode_direct=yes # is this really true???
+ ;;
+ siemens)
+ hardcode_direct=no
+ ;;
+ motorola)
+ hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ ;;
+ sysv4.3*)
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ ld_shlibs=yes
+ fi
+ ;;
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+ ;;
+ sysv5* | sco3.2v5* | sco5v6*)
+ hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ hardcode_libdir_separator=':'
+ ;;
+ uts4*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ ;;
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+fi
+
+# Check dynamic linker characteristics
+# Code taken from libtool.m4's _LT_SYS_DYNAMIC_LINKER.
+# Unlike libtool.m4, here we don't care about _all_ names of the library, but
+# only about the one the linker finds when passed -lNAME. This is the last
+# element of library_names_spec in libtool.m4, or possibly two of them if the
+# linker has special search rules.
+library_names_spec= # the last element of library_names_spec in libtool.m4
+libname_spec='lib$name'
+case "$host_os" in
+ aix3*)
+ library_names_spec='$libname.a'
+ ;;
+ aix[4-9]*)
+ library_names_spec='$libname$shrext'
+ ;;
+ amigaos*)
+ library_names_spec='$libname.a'
+ ;;
+ beos*)
+ library_names_spec='$libname$shrext'
+ ;;
+ bsdi[45]*)
+ library_names_spec='$libname$shrext'
+ ;;
+ cygwin* | mingw* | pw32* | cegcc*)
+ shrext=.dll
+ library_names_spec='$libname.dll.a $libname.lib'
+ ;;
+ darwin* | rhapsody*)
+ shrext=.dylib
+ library_names_spec='$libname$shrext'
+ ;;
+ dgux*)
+ library_names_spec='$libname$shrext'
+ ;;
+ freebsd1*)
+ ;;
+ freebsd* | dragonfly*)
+ case "$host_os" in
+ freebsd[123]*)
+ library_names_spec='$libname$shrext$versuffix' ;;
+ *)
+ library_names_spec='$libname$shrext' ;;
+ esac
+ ;;
+ gnu*)
+ library_names_spec='$libname$shrext'
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ case $host_cpu in
+ ia64*)
+ shrext=.so
+ ;;
+ hppa*64*)
+ shrext=.sl
+ ;;
+ *)
+ shrext=.sl
+ ;;
+ esac
+ library_names_spec='$libname$shrext'
+ ;;
+ interix[3-9]*)
+ library_names_spec='$libname$shrext'
+ ;;
+ irix5* | irix6* | nonstopux*)
+ library_names_spec='$libname$shrext'
+ case "$host_os" in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;;
+ *) libsuff= shlibsuff= ;;
+ esac
+ ;;
+ esac
+ ;;
+ linux*oldld* | linux*aout* | linux*coff*)
+ ;;
+ linux* | k*bsd*-gnu)
+ library_names_spec='$libname$shrext'
+ ;;
+ knetbsd*-gnu)
+ library_names_spec='$libname$shrext'
+ ;;
+ netbsd*)
+ library_names_spec='$libname$shrext'
+ ;;
+ newsos6)
+ library_names_spec='$libname$shrext'
+ ;;
+ nto-qnx*)
+ library_names_spec='$libname$shrext'
+ ;;
+ openbsd*)
+ library_names_spec='$libname$shrext$versuffix'
+ ;;
+ os2*)
+ libname_spec='$name'
+ shrext=.dll
+ library_names_spec='$libname.a'
+ ;;
+ osf3* | osf4* | osf5*)
+ library_names_spec='$libname$shrext'
+ ;;
+ rdos*)
+ ;;
+ solaris*)
+ library_names_spec='$libname$shrext'
+ ;;
+ sunos4*)
+ library_names_spec='$libname$shrext$versuffix'
+ ;;
+ sysv4 | sysv4.3*)
+ library_names_spec='$libname$shrext'
+ ;;
+ sysv4*MP*)
+ library_names_spec='$libname$shrext'
+ ;;
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ library_names_spec='$libname$shrext'
+ ;;
+ uts4*)
+ library_names_spec='$libname$shrext'
+ ;;
+esac
+
+sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
+escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"`
+shlibext=`echo "$shrext" | sed -e 's,^\.,,'`
+escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
+escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
+escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
+
+LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <<EOF
+
+# How to pass a linker flag through the compiler.
+wl="$escaped_wl"
+
+# Static library suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally "so").
+shlibext="$shlibext"
+
+# Format of library name prefix.
+libname_spec="$escaped_libname_spec"
+
+# Library names that the linker finds when passed -lNAME.
+library_names_spec="$escaped_library_names_spec"
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec="$escaped_hardcode_libdir_flag_spec"
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator="$hardcode_libdir_separator"
+
+# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct="$hardcode_direct"
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L="$hardcode_minus_L"
+
+EOF
diff --git a/configure.ac b/configure.ac
index b27dfd09..7e7eb778 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,6 +6,7 @@ AC_CONFIG_HEADER(config.h)
AM_INIT_AUTOMAKE([1.11 dist-bzip2])
AM_MAINTAINER_MODE()
+AC_USE_SYSTEM_EXTENSIONS
AC_PROG_CC
AC_PROG_CXX
AC_STDC_HEADERS
@@ -13,6 +14,15 @@ AC_PROG_INSTALL
AC_PROG_LIBTOOL
AC_CONFIG_MACRO_DIR([m4])
AC_C_BIGENDIAN
+AM_GNU_GETTEXT
+
+IT_PROG_INTLTOOL([0.41.0])
+GETTEXT_PACKAGE=deadbeef
+AC_SUBST(GETTEXT_PACKAGE)
+
+test "$prefix" = NONE && prefix=/usr/local
+AC_DEFINE_UNQUOTED(LOCALEDIR, "${prefix}/${DATADIRNAME}/locale", [Name of gettext locale directory])
+
if test "x$USE_MAINTAINER_MODE" = "xyes" ; then
AM_PROG_VALAC([0.7.0])
if test "x$VALAC" = "x" ; then
@@ -453,6 +463,8 @@ plugins/artwork/Makefile
plugins/supereq/Makefile
plugins/notify/Makefile
plugins/emidi/Makefile
+intl/Makefile
+po/Makefile.in
deadbeef.desktop
])
diff --git a/deadbeef.desktop.in b/deadbeef.desktop.in
index 5aa6ff2f..3150f570 100644
--- a/deadbeef.desktop.in
+++ b/deadbeef.desktop.in
@@ -1,10 +1,13 @@
[Desktop Entry]
+Encoding=UTF-8
Name=DeaDBeeF
GenericName=Audio Player
-Comment=Play music
+Comment=Listen to music
Exec=deadbeef %F
MimeType=application/ogg;audio/x-vorbis+ogg;application/x-ogg;audio/mp3;audio/prs.sid;audio/x-flac;audio/mpeg;audio/x-mpeg;audio/x-mod;audio/x-it;audio/x-s3m;audio/x-xm;
Categories=AudioVideo;Player;
Terminal=false
Type=Application
Icon=deadbeef
+GenericName[ru]=Аудио плеер
+Comment[ru]=Слушай музыку
diff --git a/gettext.h b/gettext.h
new file mode 100644
index 00000000..837a6e7e
--- /dev/null
+++ b/gettext.h
@@ -0,0 +1,15 @@
+#ifndef _GETTEXT_H
+#define _GETTEXT_H 1
+
+#if ENABLE_NLS
+
+# include <libintl.h>
+#define _(s) gettext(s)
+
+#else
+
+#define _(s) (s)
+
+#endif
+
+#endif
diff --git a/intl/ChangeLog b/intl/ChangeLog
new file mode 100644
index 00000000..66d3a174
--- /dev/null
+++ b/intl/ChangeLog
@@ -0,0 +1,4 @@
+2010-05-09 GNU <bug-gnu-gettext@gnu.org>
+
+ * Version 0.18 released.
+
diff --git a/intl/Makefile.in b/intl/Makefile.in
new file mode 100644
index 00000000..d547fe05
--- /dev/null
+++ b/intl/Makefile.in
@@ -0,0 +1,659 @@
+# Makefile for directory with message catalog handling library of GNU gettext
+# Copyright (C) 1995-1998, 2000-2007, 2009-2010 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Library General Public License as published
+# by the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+# USA.
+
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+
+SHELL = /bin/sh
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+top_builddir = ..
+
+# The VPATH variables allows builds with $builddir != $srcdir, assuming a
+# 'make' program that supports VPATH (such as GNU make). This line is removed
+# by autoconf automatically when "$(srcdir)" = ".".
+# In this directory, the VPATH handling is particular:
+# 1. If INTL_LIBTOOL_SUFFIX_PREFIX is 'l' (indicating a build with libtool),
+# the .c -> .lo rules carefully use $(srcdir), so that VPATH can be omitted.
+# 2. If PACKAGE = gettext-tools, VPATH _must_ be omitted, because otherwise
+# 'make' does the wrong thing if GNU gettext was configured with
+# "./configure --srcdir=`pwd`", namely it gets confused by the .lo and .la
+# files it finds in srcdir = ../../gettext-runtime/intl.
+VPATH = $(srcdir)
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+transform = @program_transform_name@
+libdir = @libdir@
+includedir = @includedir@
+datarootdir = @datarootdir@
+datadir = @datadir@
+localedir = $(datadir)/locale
+gettextsrcdir = $(datadir)/gettext/intl
+aliaspath = $(localedir)
+subdir = intl
+
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+
+# We use $(mkdir_p).
+# In automake <= 1.9.x, $(mkdir_p) is defined either as "mkdir -p --" or as
+# "$(mkinstalldirs)" or as "$(install_sh) -d". For these automake versions,
+# @install_sh@ does not start with $(SHELL), so we add it.
+# In automake >= 1.10, @mkdir_p@ is derived from ${MKDIR_P}, which is defined
+# either as "/path/to/mkdir -p" or ".../install-sh -c -d". For these automake
+# versions, $(mkinstalldirs) and $(install_sh) are unused.
+mkinstalldirs = $(SHELL) @install_sh@ -d
+install_sh = $(SHELL) @install_sh@
+MKDIR_P = @MKDIR_P@
+mkdir_p = @mkdir_p@
+
+l = @INTL_LIBTOOL_SUFFIX_PREFIX@
+
+AR = ar
+CC = @CC@
+LIBTOOL = @LIBTOOL@
+RANLIB = @RANLIB@
+YACC = @INTLBISON@ -y -d
+YFLAGS = --name-prefix=__gettext
+# Windows resource compiler (windres). Used when libtool is not used.
+WINDRES = @WINDRES@
+# Windows resource compiler (windres). Used via libtool.
+RC = @RC@
+
+# Support for silent-rules.
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_@INTL_DEFAULT_VERBOSITY@)
+am__v_at_0 = @
+AM_V_AR = $(am__v_AR_$(V))
+am__v_AR_ = $(am__v_AR_@INTL_DEFAULT_VERBOSITY@)
+am__v_AR_0 = @echo " AR " $@;
+AM_V_CC = $(am__v_CC_$(V))
+am__v_CC_ = $(am__v_CC_@INTL_DEFAULT_VERBOSITY@)
+am__v_CC_0 = @echo " CC " $@;
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_@INTL_DEFAULT_VERBOSITY@)
+am__v_GEN_0 = @echo " GEN " $@;
+AM_V_YACC = $(am__v_YACC_$(V))
+am__v_YACC_ = $(am__v_YACC_@INTL_DEFAULT_VERBOSITY@)
+am__v_YACC_0 = @echo " YACC " $@;
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_@INTL_DEFAULT_VERBOSITY@)
+am__v_lt_0 = --silent
+
+# -DBUILDING_LIBINTL: Change expansion of LIBINTL_DLL_EXPORTED macro.
+# -DBUILDING_DLL: Change expansion of RELOCATABLE_DLL_EXPORTED macro.
+DEFS = -DLOCALEDIR=\"$(localedir)\" -DLOCALE_ALIAS_PATH=\"$(aliaspath)\" \
+-DLIBDIR=\"$(libdir)\" -DBUILDING_LIBINTL -DBUILDING_DLL -DIN_LIBINTL \
+-DENABLE_RELOCATABLE=1 -DIN_LIBRARY -DINSTALLDIR=\"$(libdir)\" -DNO_XMALLOC \
+-Dset_relocation_prefix=libintl_set_relocation_prefix \
+-Drelocate=libintl_relocate \
+-DDEPENDS_ON_LIBICONV=1 @DEFS@
+CPPFLAGS = @CPPFLAGS@
+CFLAGS = @CFLAGS@ @CFLAG_VISIBILITY@
+LDFLAGS = @LDFLAGS@ $(LDFLAGS_@WOE32DLL@)
+LDFLAGS_yes = -Wl,--export-all-symbols
+LDFLAGS_no =
+LIBS = @LIBS@
+
+COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS)
+
+HEADERS = \
+ gmo.h \
+ gettextP.h \
+ hash-string.h \
+ loadinfo.h \
+ plural-exp.h \
+ eval-plural.h \
+ localcharset.h \
+ lock.h \
+ relocatable.h \
+ tsearch.h tsearch.c \
+ xsize.h \
+ printf-args.h printf-args.c \
+ printf-parse.h wprintf-parse.h printf-parse.c \
+ vasnprintf.h vasnwprintf.h vasnprintf.c \
+ os2compat.h \
+ libgnuintl.h.in
+SOURCES = \
+ bindtextdom.c \
+ dcgettext.c \
+ dgettext.c \
+ gettext.c \
+ finddomain.c \
+ hash-string.c \
+ loadmsgcat.c \
+ localealias.c \
+ textdomain.c \
+ l10nflist.c \
+ explodename.c \
+ dcigettext.c \
+ dcngettext.c \
+ dngettext.c \
+ ngettext.c \
+ plural.y \
+ plural-exp.c \
+ localcharset.c \
+ threadlib.c \
+ lock.c \
+ relocatable.c \
+ langprefs.c \
+ localename.c \
+ log.c \
+ printf.c \
+ setlocale.c \
+ version.c \
+ osdep.c \
+ os2compat.c \
+ intl-exports.c \
+ intl-compat.c
+OBJECTS = \
+ bindtextdom.$lo \
+ dcgettext.$lo \
+ dgettext.$lo \
+ gettext.$lo \
+ finddomain.$lo \
+ hash-string.$lo \
+ loadmsgcat.$lo \
+ localealias.$lo \
+ textdomain.$lo \
+ l10nflist.$lo \
+ explodename.$lo \
+ dcigettext.$lo \
+ dcngettext.$lo \
+ dngettext.$lo \
+ ngettext.$lo \
+ plural.$lo \
+ plural-exp.$lo \
+ localcharset.$lo \
+ threadlib.$lo \
+ lock.$lo \
+ relocatable.$lo \
+ langprefs.$lo \
+ localename.$lo \
+ log.$lo \
+ printf.$lo \
+ setlocale.$lo \
+ version.$lo \
+ osdep.$lo \
+ intl-compat.$lo
+OBJECTS_RES_yes = libintl.res.$lo
+OBJECTS_RES_no =
+DISTFILES.common = Makefile.in \
+config.charset locale.alias ref-add.sin ref-del.sin export.h libintl.rc \
+$(HEADERS) $(SOURCES)
+DISTFILES.generated = plural.c
+DISTFILES.normal = VERSION
+DISTFILES.gettext = COPYING.LIB-2.0 COPYING.LIB-2.1 libintl.glibc README.woe32
+DISTFILES.obsolete = xopen-msg.sed linux-msg.sed po2tbl.sed.in cat-compat.c \
+COPYING.LIB-2 gettext.h libgettext.h plural-eval.c libgnuintl.h \
+libgnuintl.h_vms Makefile.vms libgnuintl.h.msvc-static \
+libgnuintl.h.msvc-shared Makefile.msvc
+
+all: all-@USE_INCLUDED_LIBINTL@
+all-yes: libintl.$la libintl.h charset.alias ref-add.sed ref-del.sed
+all-no: all-no-@BUILD_INCLUDED_LIBINTL@
+all-no-yes: libgnuintl.$la
+all-no-no:
+
+libintl.a libgnuintl.a: $(OBJECTS)
+ $(AM_V_at)rm -f $@
+ $(AM_V_AR)$(AR) cru $@ $(OBJECTS)
+ $(AM_V_at)$(RANLIB) $@
+
+libintl.la libgnuintl.la: $(OBJECTS) $(OBJECTS_RES_@WOE32@)
+ $(AM_V_GEN)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=link \
+ $(CC) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS) $(LDFLAGS) -o $@ \
+ $(OBJECTS) @LTLIBICONV@ @INTL_MACOSX_LIBS@ $(LIBS) @LTLIBTHREAD@ @LTLIBC@ \
+ $(OBJECTS_RES_@WOE32@) \
+ -version-info $(LTV_CURRENT):$(LTV_REVISION):$(LTV_AGE) \
+ -rpath $(libdir) \
+ -no-undefined
+
+# Libtool's library version information for libintl.
+# Before making a gettext release, the gettext maintainer must change this
+# according to the libtool documentation, section "Library interface versions".
+# Maintainers of other packages that include the intl directory must *not*
+# change these values.
+LTV_CURRENT=9
+LTV_REVISION=0
+LTV_AGE=1
+
+.SUFFIXES:
+.SUFFIXES: .c .y .o .lo .sin .sed
+
+.c.o:
+ $(AM_V_CC)$(COMPILE) $<
+
+.y.c:
+ $(AM_V_YACC)$(YACC) $(YFLAGS) --output $@ $<
+ $(AM_V_at)rm -f $*.h
+
+bindtextdom.lo: $(srcdir)/bindtextdom.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/bindtextdom.c
+dcgettext.lo: $(srcdir)/dcgettext.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/dcgettext.c
+dgettext.lo: $(srcdir)/dgettext.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/dgettext.c
+gettext.lo: $(srcdir)/gettext.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/gettext.c
+finddomain.lo: $(srcdir)/finddomain.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/finddomain.c
+hash-string.lo: $(srcdir)/hash-string.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/hash-string.c
+loadmsgcat.lo: $(srcdir)/loadmsgcat.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/loadmsgcat.c
+localealias.lo: $(srcdir)/localealias.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/localealias.c
+textdomain.lo: $(srcdir)/textdomain.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/textdomain.c
+l10nflist.lo: $(srcdir)/l10nflist.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/l10nflist.c
+explodename.lo: $(srcdir)/explodename.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/explodename.c
+dcigettext.lo: $(srcdir)/dcigettext.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/dcigettext.c
+dcngettext.lo: $(srcdir)/dcngettext.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/dcngettext.c
+dngettext.lo: $(srcdir)/dngettext.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/dngettext.c
+ngettext.lo: $(srcdir)/ngettext.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/ngettext.c
+plural.lo: $(srcdir)/plural.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/plural.c
+plural-exp.lo: $(srcdir)/plural-exp.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/plural-exp.c
+localcharset.lo: $(srcdir)/localcharset.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/localcharset.c
+threadlib.lo: $(srcdir)/threadlib.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/threadlib.c
+lock.lo: $(srcdir)/lock.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/lock.c
+relocatable.lo: $(srcdir)/relocatable.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/relocatable.c
+langprefs.lo: $(srcdir)/langprefs.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/langprefs.c
+localename.lo: $(srcdir)/localename.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/localename.c
+log.lo: $(srcdir)/log.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/log.c
+printf.lo: $(srcdir)/printf.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/printf.c
+setlocale.lo: $(srcdir)/setlocale.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/setlocale.c
+version.lo: $(srcdir)/version.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/version.c
+osdep.lo: $(srcdir)/osdep.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/osdep.c
+intl-compat.lo: $(srcdir)/intl-compat.c
+ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(COMPILE) $(srcdir)/intl-compat.c
+
+# This rule is executed only on Woe32 systems.
+# The following sed expressions come from the windres-options script. They are
+# inlined here, so that they can be written in a Makefile without requiring a
+# temporary file. They must contain literal newlines rather than semicolons,
+# so that they work with the sed-3.02 that is shipped with MSYS.
+libintl.res.o: $(srcdir)/libintl.rc
+ nlinit=`echo 'nl="'; echo '"'`; eval "$$nlinit"; \
+ sed_extract_major='/^[0-9]/{'$${nl}'s/^\([0-9]*\).*/\1/p'$${nl}q$${nl}'}'$${nl}'c\'$${nl}0$${nl}q; \
+ sed_extract_minor='/^[0-9][0-9]*[.][0-9]/{'$${nl}'s/^[0-9]*[.]\([0-9]*\).*/\1/p'$${nl}q$${nl}'}'$${nl}'c\'$${nl}0$${nl}q; \
+ sed_extract_subminor='/^[0-9][0-9]*[.][0-9][0-9]*[.][0-9]/{'$${nl}'s/^[0-9]*[.][0-9]*[.]\([0-9]*\).*/\1/p'$${nl}q$${nl}'}'$${nl}'c\'$${nl}0$${nl}q; \
+ $(WINDRES) \
+ "-DPACKAGE_VERSION_STRING=\\\"$(VERSION)\\\"" \
+ "-DPACKAGE_VERSION_MAJOR="`echo '$(VERSION)' | sed -n -e "$$sed_extract_major"` \
+ "-DPACKAGE_VERSION_MINOR="`echo '$(VERSION)' | sed -n -e "$$sed_extract_minor"` \
+ "-DPACKAGE_VERSION_SUBMINOR="`echo '$(VERSION)' | sed -n -e "$$sed_extract_subminor"` \
+ -i $(srcdir)/libintl.rc -o libintl.res.o --output-format=coff
+libintl.res.lo: $(srcdir)/libintl.rc
+ nlinit=`echo 'nl="'; echo '"'`; eval "$$nlinit"; \
+ sed_extract_major='/^[0-9]/{'$${nl}'s/^\([0-9]*\).*/\1/p'$${nl}q$${nl}'}'$${nl}'c\'$${nl}0$${nl}q; \
+ sed_extract_minor='/^[0-9][0-9]*[.][0-9]/{'$${nl}'s/^[0-9]*[.]\([0-9]*\).*/\1/p'$${nl}q$${nl}'}'$${nl}'c\'$${nl}0$${nl}q; \
+ sed_extract_subminor='/^[0-9][0-9]*[.][0-9][0-9]*[.][0-9]/{'$${nl}'s/^[0-9]*[.][0-9]*[.]\([0-9]*\).*/\1/p'$${nl}q$${nl}'}'$${nl}'c\'$${nl}0$${nl}q; \
+ $(LIBTOOL) --mode=compile --tag=RC $(RC) \
+ "-DPACKAGE_VERSION_STRING=\\\"$(VERSION)\\\"" \
+ "-DPACKAGE_VERSION_MAJOR="`echo '$(VERSION)' | sed -n -e "$$sed_extract_major"` \
+ "-DPACKAGE_VERSION_MINOR="`echo '$(VERSION)' | sed -n -e "$$sed_extract_minor"` \
+ "-DPACKAGE_VERSION_SUBMINOR="`echo '$(VERSION)' | sed -n -e "$$sed_extract_subminor"` \
+ -i $(srcdir)/libintl.rc -o libintl.res.lo --output-format=coff
+
+ref-add.sed: $(srcdir)/ref-add.sin
+ sed -e '/^#/d' -e 's/@''PACKAGE''@/@PACKAGE@/g' $(srcdir)/ref-add.sin > t-ref-add.sed
+ mv t-ref-add.sed ref-add.sed
+ref-del.sed: $(srcdir)/ref-del.sin
+ sed -e '/^#/d' -e 's/@''PACKAGE''@/@PACKAGE@/g' $(srcdir)/ref-del.sin > t-ref-del.sed
+ mv t-ref-del.sed ref-del.sed
+
+INCLUDES = -I. -I$(srcdir) -I..
+
+libgnuintl.h: $(srcdir)/libgnuintl.h.in
+ sed -e '/IN_LIBGLOCALE/d' \
+ -e 's,@''HAVE_POSIX_PRINTF''@,@HAVE_POSIX_PRINTF@,g' \
+ -e 's,@''HAVE_ASPRINTF''@,@HAVE_ASPRINTF@,g' \
+ -e 's,@''HAVE_NEWLOCALE''@,@HAVE_NEWLOCALE@,g' \
+ -e 's,@''HAVE_SNPRINTF''@,@HAVE_SNPRINTF@,g' \
+ -e 's,@''HAVE_WPRINTF''@,@HAVE_WPRINTF@,g' \
+ < $(srcdir)/libgnuintl.h.in \
+ | if test '@WOE32DLL@' = yes; then \
+ sed -e 's/extern \([^()]*\);/extern __declspec (dllimport) \1;/'; \
+ else \
+ cat; \
+ fi \
+ | sed -e 's/extern \([^"]\)/extern LIBINTL_DLL_EXPORTED \1/' \
+ -e "/#define _LIBINTL_H/r $(srcdir)/export.h" \
+ | sed -e 's,@''HAVE_VISIBILITY''@,@HAVE_VISIBILITY@,g' \
+ > libgnuintl.h
+
+libintl.h: $(srcdir)/libgnuintl.h.in
+ sed -e '/IN_LIBGLOCALE/d' \
+ -e 's,@''HAVE_POSIX_PRINTF''@,@HAVE_POSIX_PRINTF@,g' \
+ -e 's,@''HAVE_ASPRINTF''@,@HAVE_ASPRINTF@,g' \
+ -e 's,@''HAVE_NEWLOCALE''@,@HAVE_NEWLOCALE@,g' \
+ -e 's,@''HAVE_SNPRINTF''@,@HAVE_SNPRINTF@,g' \
+ -e 's,@''HAVE_WPRINTF''@,@HAVE_WPRINTF@,g' \
+ < $(srcdir)/libgnuintl.h.in > libintl.h
+
+charset.alias: $(srcdir)/config.charset
+ $(SHELL) $(srcdir)/config.charset '@host@' > t-$@
+ mv t-$@ $@
+
+check: all
+
+# We must not install the libintl.h/libintl.a files if we are on a
+# system which has the GNU gettext() function in its C library or in a
+# separate library.
+# If you want to use the one which comes with this version of the
+# package, you have to use `configure --with-included-gettext'.
+install: install-exec install-data
+install-exec: all
+ if { test "$(PACKAGE)" = "gettext-runtime" || test "$(PACKAGE)" = "gettext-tools"; } \
+ && test '@USE_INCLUDED_LIBINTL@' = yes; then \
+ $(mkdir_p) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir); \
+ $(INSTALL_DATA) libintl.h $(DESTDIR)$(includedir)/libintl.h; \
+ $(LIBTOOL) --mode=install \
+ $(INSTALL_DATA) libintl.$la $(DESTDIR)$(libdir)/libintl.$la; \
+ if test "@RELOCATABLE@" = yes; then \
+ dependencies=`sed -n -e 's,^dependency_libs=\(.*\),\1,p' < $(DESTDIR)$(libdir)/libintl.la | sed -e "s,^',," -e "s,'\$$,,"`; \
+ if test -n "$$dependencies"; then \
+ rm -f $(DESTDIR)$(libdir)/libintl.la; \
+ fi; \
+ fi; \
+ else \
+ : ; \
+ fi
+ if test "$(PACKAGE)" = "gettext-tools" \
+ && test '@USE_INCLUDED_LIBINTL@' = no \
+ && test @GLIBC2@ != no; then \
+ $(mkdir_p) $(DESTDIR)$(libdir); \
+ $(LIBTOOL) --mode=install \
+ $(INSTALL_DATA) libgnuintl.$la $(DESTDIR)$(libdir)/libgnuintl.$la; \
+ rm -f $(DESTDIR)$(libdir)/preloadable_libintl.so; \
+ $(INSTALL_DATA) $(DESTDIR)$(libdir)/libgnuintl.so $(DESTDIR)$(libdir)/preloadable_libintl.so; \
+ $(LIBTOOL) --mode=uninstall \
+ rm -f $(DESTDIR)$(libdir)/libgnuintl.$la; \
+ else \
+ : ; \
+ fi
+ if test '@USE_INCLUDED_LIBINTL@' = yes; then \
+ if test @GLIBC21@ = no; then \
+ case '@host_os@' in \
+ darwin[56]*) \
+ need_charset_alias=true ;; \
+ darwin* | cygwin* | mingw* | pw32* | cegcc*) \
+ need_charset_alias=false ;; \
+ *) \
+ need_charset_alias=true ;; \
+ esac; \
+ else \
+ need_charset_alias=false; \
+ fi; \
+ if $$need_charset_alias; then \
+ $(mkdir_p) $(DESTDIR)$(libdir); \
+ fi; \
+ temp=$(DESTDIR)$(libdir)/t-charset.alias; \
+ dest=$(DESTDIR)$(libdir)/charset.alias; \
+ if test -f $(DESTDIR)$(libdir)/charset.alias; then \
+ orig=$(DESTDIR)$(libdir)/charset.alias; \
+ sed -f ref-add.sed $$orig > $$temp; \
+ $(INSTALL_DATA) $$temp $$dest; \
+ rm -f $$temp; \
+ else \
+ if $$need_charset_alias; then \
+ orig=charset.alias; \
+ sed -f ref-add.sed $$orig > $$temp; \
+ $(INSTALL_DATA) $$temp $$dest; \
+ rm -f $$temp; \
+ fi; \
+ fi; \
+ $(mkdir_p) $(DESTDIR)$(localedir); \
+ test -f $(DESTDIR)$(localedir)/locale.alias \
+ && orig=$(DESTDIR)$(localedir)/locale.alias \
+ || orig=$(srcdir)/locale.alias; \
+ temp=$(DESTDIR)$(localedir)/t-locale.alias; \
+ dest=$(DESTDIR)$(localedir)/locale.alias; \
+ sed -f ref-add.sed $$orig > $$temp; \
+ $(INSTALL_DATA) $$temp $$dest; \
+ rm -f $$temp; \
+ else \
+ : ; \
+ fi
+install-data: all
+ if test "$(PACKAGE)" = "gettext-tools"; then \
+ $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \
+ $(INSTALL_DATA) VERSION $(DESTDIR)$(gettextsrcdir)/VERSION; \
+ $(INSTALL_DATA) ChangeLog.inst $(DESTDIR)$(gettextsrcdir)/ChangeLog; \
+ dists="COPYING.LIB-2.0 COPYING.LIB-2.1 $(DISTFILES.common)"; \
+ for file in $$dists; do \
+ $(INSTALL_DATA) $(srcdir)/$$file \
+ $(DESTDIR)$(gettextsrcdir)/$$file; \
+ done; \
+ chmod a+x $(DESTDIR)$(gettextsrcdir)/config.charset; \
+ dists="$(DISTFILES.generated)"; \
+ for file in $$dists; do \
+ if test -f $$file; then dir=.; else dir=$(srcdir); fi; \
+ $(INSTALL_DATA) $$dir/$$file \
+ $(DESTDIR)$(gettextsrcdir)/$$file; \
+ done; \
+ dists="$(DISTFILES.obsolete)"; \
+ for file in $$dists; do \
+ rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \
+ done; \
+ else \
+ : ; \
+ fi
+
+install-strip: install
+
+install-dvi install-html install-info install-ps install-pdf:
+
+installdirs:
+ if { test "$(PACKAGE)" = "gettext-runtime" || test "$(PACKAGE)" = "gettext-tools"; } \
+ && test '@USE_INCLUDED_LIBINTL@' = yes; then \
+ $(mkdir_p) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir); \
+ else \
+ : ; \
+ fi
+ if test "$(PACKAGE)" = "gettext-tools" \
+ && test '@USE_INCLUDED_LIBINTL@' = no \
+ && test @GLIBC2@ != no; then \
+ $(mkdir_p) $(DESTDIR)$(libdir); \
+ else \
+ : ; \
+ fi
+ if test '@USE_INCLUDED_LIBINTL@' = yes; then \
+ if test @GLIBC21@ = no; then \
+ case '@host_os@' in \
+ darwin[56]*) \
+ need_charset_alias=true ;; \
+ darwin* | cygwin* | mingw* | pw32* | cegcc*) \
+ need_charset_alias=false ;; \
+ *) \
+ need_charset_alias=true ;; \
+ esac; \
+ else \
+ need_charset_alias=false; \
+ fi; \
+ if $$need_charset_alias; then \
+ $(mkdir_p) $(DESTDIR)$(libdir); \
+ fi; \
+ $(mkdir_p) $(DESTDIR)$(localedir); \
+ else \
+ : ; \
+ fi
+ if test "$(PACKAGE)" = "gettext-tools"; then \
+ $(mkdir_p) $(DESTDIR)$(gettextsrcdir); \
+ else \
+ : ; \
+ fi
+
+# Define this as empty until I found a useful application.
+installcheck:
+
+uninstall:
+ if { test "$(PACKAGE)" = "gettext-runtime" || test "$(PACKAGE)" = "gettext-tools"; } \
+ && test '@USE_INCLUDED_LIBINTL@' = yes; then \
+ rm -f $(DESTDIR)$(includedir)/libintl.h; \
+ $(LIBTOOL) --mode=uninstall \
+ rm -f $(DESTDIR)$(libdir)/libintl.$la; \
+ else \
+ : ; \
+ fi
+ if test "$(PACKAGE)" = "gettext-tools" \
+ && test '@USE_INCLUDED_LIBINTL@' = no \
+ && test @GLIBC2@ != no; then \
+ rm -f $(DESTDIR)$(libdir)/preloadable_libintl.so; \
+ else \
+ : ; \
+ fi
+ if test '@USE_INCLUDED_LIBINTL@' = yes; then \
+ if test -f $(DESTDIR)$(libdir)/charset.alias; then \
+ temp=$(DESTDIR)$(libdir)/t-charset.alias; \
+ dest=$(DESTDIR)$(libdir)/charset.alias; \
+ sed -f ref-del.sed $$dest > $$temp; \
+ if grep '^# Packages using this file: $$' $$temp > /dev/null; then \
+ rm -f $$dest; \
+ else \
+ $(INSTALL_DATA) $$temp $$dest; \
+ fi; \
+ rm -f $$temp; \
+ fi; \
+ if test -f $(DESTDIR)$(localedir)/locale.alias; then \
+ temp=$(DESTDIR)$(localedir)/t-locale.alias; \
+ dest=$(DESTDIR)$(localedir)/locale.alias; \
+ sed -f ref-del.sed $$dest > $$temp; \
+ if grep '^# Packages using this file: $$' $$temp > /dev/null; then \
+ rm -f $$dest; \
+ else \
+ $(INSTALL_DATA) $$temp $$dest; \
+ fi; \
+ rm -f $$temp; \
+ fi; \
+ else \
+ : ; \
+ fi
+ if test "$(PACKAGE)" = "gettext-tools"; then \
+ for file in VERSION ChangeLog COPYING.LIB-2.0 COPYING.LIB-2.1 $(DISTFILES.common) $(DISTFILES.generated); do \
+ rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \
+ done; \
+ else \
+ : ; \
+ fi
+
+info dvi ps pdf html:
+
+$(OBJECTS): ../config.h libgnuintl.h
+bindtextdom.$lo dcgettext.$lo dcigettext.$lo dcngettext.$lo dgettext.$lo dngettext.$lo finddomain.$lo gettext.$lo intl-compat.$lo loadmsgcat.$lo localealias.$lo ngettext.$lo setlocale.$lo textdomain.$lo: $(srcdir)/gettextP.h $(srcdir)/gmo.h $(srcdir)/loadinfo.h
+localename.$lo: $(srcdir)/gettextP.h
+hash-string.$lo dcigettext.$lo loadmsgcat.$lo: $(srcdir)/hash-string.h
+explodename.$lo l10nflist.$lo: $(srcdir)/loadinfo.h
+dcigettext.$lo loadmsgcat.$lo plural.$lo plural-exp.$lo: $(srcdir)/plural-exp.h
+dcigettext.$lo: $(srcdir)/eval-plural.h
+localcharset.$lo: $(srcdir)/localcharset.h
+bindtextdom.$lo dcigettext.$lo finddomain.$lo loadmsgcat.$lo localealias.$lo lock.$lo log.$lo: $(srcdir)/lock.h
+localealias.$lo localcharset.$lo relocatable.$lo: $(srcdir)/relocatable.h
+printf.$lo: $(srcdir)/printf-args.h $(srcdir)/printf-args.c $(srcdir)/printf-parse.h $(srcdir)/wprintf-parse.h $(srcdir)/xsize.h $(srcdir)/printf-parse.c $(srcdir)/vasnprintf.h $(srcdir)/vasnwprintf.h $(srcdir)/vasnprintf.c
+
+# A bison-2.1 generated plural.c includes <libintl.h> if ENABLE_NLS.
+PLURAL_DEPS_yes = libintl.h
+PLURAL_DEPS_no =
+plural.$lo: $(PLURAL_DEPS_@USE_INCLUDED_LIBINTL@)
+
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES)
+ here=`pwd`; cd $(srcdir) && etags -o $$here/TAGS $(HEADERS) $(SOURCES)
+
+ctags: CTAGS
+
+CTAGS: $(HEADERS) $(SOURCES)
+ here=`pwd`; cd $(srcdir) && ctags -o $$here/CTAGS $(HEADERS) $(SOURCES)
+
+id: ID
+
+ID: $(HEADERS) $(SOURCES)
+ here=`pwd`; cd $(srcdir) && mkid -f$$here/ID $(HEADERS) $(SOURCES)
+
+
+mostlyclean:
+ rm -f *.a *.la *.o *.obj *.lo core core.*
+ rm -f libgnuintl.h libintl.h charset.alias ref-add.sed ref-del.sed
+ rm -f -r .libs _libs
+
+clean: mostlyclean
+
+distclean: clean
+ rm -f Makefile ID TAGS
+ if test "$(PACKAGE)" = "gettext-runtime" || test "$(PACKAGE)" = "gettext-tools"; then \
+ rm -f ChangeLog.inst $(DISTFILES.normal); \
+ else \
+ : ; \
+ fi
+
+maintainer-clean: distclean
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+
+# GNU gettext needs not contain the file `VERSION' but contains some
+# other files which should not be distributed in other packages.
+distdir = ../$(PACKAGE)-$(VERSION)/$(subdir)
+dist distdir: Makefile
+ if test "$(PACKAGE)" = "gettext-tools"; then \
+ : ; \
+ else \
+ if test "$(PACKAGE)" = "gettext-runtime"; then \
+ additional="$(DISTFILES.gettext)"; \
+ else \
+ additional="$(DISTFILES.normal)"; \
+ fi; \
+ $(MAKE) $(DISTFILES.common) $(DISTFILES.generated) $$additional; \
+ for file in ChangeLog $(DISTFILES.common) $(DISTFILES.generated) $$additional; do \
+ if test -f $$file; then dir=.; else dir=$(srcdir); fi; \
+ cp -p $$dir/$$file $(distdir) || test $$file = Makefile.in || exit 1; \
+ done; \
+ fi
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) && $(SHELL) ./config.status
+# This would be more efficient, but doesn't work any more with autoconf-2.57,
+# when AC_CONFIG_FILES([intl/Makefile:somedir/Makefile.in]) is used.
+# cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+
+# Tell versions [3.59,3.63) of GNU make not to export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/intl/VERSION b/intl/VERSION
new file mode 100644
index 00000000..5cd7e1a0
--- /dev/null
+++ b/intl/VERSION
@@ -0,0 +1 @@
+GNU gettext library from gettext-0.18
diff --git a/intl/bindtextdom.c b/intl/bindtextdom.c
new file mode 100644
index 00000000..54ce061e
--- /dev/null
+++ b/intl/bindtextdom.c
@@ -0,0 +1,340 @@
+/* Implementation of the bindtextdomain(3) function
+ Copyright (C) 1995-1998, 2000-2003, 2005-2006, 2008 Free Software
+ Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "gettextP.h"
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+/* Handle multi-threaded applications. */
+#ifdef _LIBC
+# include <bits/libc-lock.h>
+# define gl_rwlock_define __libc_rwlock_define
+# define gl_rwlock_wrlock __libc_rwlock_wrlock
+# define gl_rwlock_unlock __libc_rwlock_unlock
+#else
+# include "lock.h"
+#endif
+
+/* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
+#ifndef offsetof
+# define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Lock variable to protect the global data in the gettext implementation. */
+gl_rwlock_define (extern, _nl_state_lock attribute_hidden)
+
+
+/* Names for the libintl functions are a problem. They must not clash
+ with existing names and they should follow ANSI C. But this source
+ code is also used in GNU C Library where the names have a __
+ prefix. So we have to make a difference here. */
+#ifdef _LIBC
+# define BINDTEXTDOMAIN __bindtextdomain
+# define BIND_TEXTDOMAIN_CODESET __bind_textdomain_codeset
+# ifndef strdup
+# define strdup(str) __strdup (str)
+# endif
+#else
+# define BINDTEXTDOMAIN libintl_bindtextdomain
+# define BIND_TEXTDOMAIN_CODESET libintl_bind_textdomain_codeset
+#endif
+
+/* Specifies the directory name *DIRNAMEP and the output codeset *CODESETP
+ to be used for the DOMAINNAME message catalog.
+ If *DIRNAMEP or *CODESETP is NULL, the corresponding attribute is not
+ modified, only the current value is returned.
+ If DIRNAMEP or CODESETP is NULL, the corresponding attribute is neither
+ modified nor returned. */
+static void
+set_binding_values (const char *domainname,
+ const char **dirnamep, const char **codesetp)
+{
+ struct binding *binding;
+ int modified;
+
+ /* Some sanity checks. */
+ if (domainname == NULL || domainname[0] == '\0')
+ {
+ if (dirnamep)
+ *dirnamep = NULL;
+ if (codesetp)
+ *codesetp = NULL;
+ return;
+ }
+
+ gl_rwlock_wrlock (_nl_state_lock);
+
+ modified = 0;
+
+ for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
+ {
+ int compare = strcmp (domainname, binding->domainname);
+ if (compare == 0)
+ /* We found it! */
+ break;
+ if (compare < 0)
+ {
+ /* It is not in the list. */
+ binding = NULL;
+ break;
+ }
+ }
+
+ if (binding != NULL)
+ {
+ if (dirnamep)
+ {
+ const char *dirname = *dirnamep;
+
+ if (dirname == NULL)
+ /* The current binding has be to returned. */
+ *dirnamep = binding->dirname;
+ else
+ {
+ /* The domain is already bound. If the new value and the old
+ one are equal we simply do nothing. Otherwise replace the
+ old binding. */
+ char *result = binding->dirname;
+ if (strcmp (dirname, result) != 0)
+ {
+ if (strcmp (dirname, _nl_default_dirname) == 0)
+ result = (char *) _nl_default_dirname;
+ else
+ {
+#if defined _LIBC || defined HAVE_STRDUP
+ result = strdup (dirname);
+#else
+ size_t len = strlen (dirname) + 1;
+ result = (char *) malloc (len);
+ if (__builtin_expect (result != NULL, 1))
+ memcpy (result, dirname, len);
+#endif
+ }
+
+ if (__builtin_expect (result != NULL, 1))
+ {
+ if (binding->dirname != _nl_default_dirname)
+ free (binding->dirname);
+
+ binding->dirname = result;
+ modified = 1;
+ }
+ }
+ *dirnamep = result;
+ }
+ }
+
+ if (codesetp)
+ {
+ const char *codeset = *codesetp;
+
+ if (codeset == NULL)
+ /* The current binding has be to returned. */
+ *codesetp = binding->codeset;
+ else
+ {
+ /* The domain is already bound. If the new value and the old
+ one are equal we simply do nothing. Otherwise replace the
+ old binding. */
+ char *result = binding->codeset;
+ if (result == NULL || strcmp (codeset, result) != 0)
+ {
+#if defined _LIBC || defined HAVE_STRDUP
+ result = strdup (codeset);
+#else
+ size_t len = strlen (codeset) + 1;
+ result = (char *) malloc (len);
+ if (__builtin_expect (result != NULL, 1))
+ memcpy (result, codeset, len);
+#endif
+
+ if (__builtin_expect (result != NULL, 1))
+ {
+ free (binding->codeset);
+
+ binding->codeset = result;
+ modified = 1;
+ }
+ }
+ *codesetp = result;
+ }
+ }
+ }
+ else if ((dirnamep == NULL || *dirnamep == NULL)
+ && (codesetp == NULL || *codesetp == NULL))
+ {
+ /* Simply return the default values. */
+ if (dirnamep)
+ *dirnamep = _nl_default_dirname;
+ if (codesetp)
+ *codesetp = NULL;
+ }
+ else
+ {
+ /* We have to create a new binding. */
+ size_t len = strlen (domainname) + 1;
+ struct binding *new_binding =
+ (struct binding *) malloc (offsetof (struct binding, domainname) + len);
+
+ if (__builtin_expect (new_binding == NULL, 0))
+ goto failed;
+
+ memcpy (new_binding->domainname, domainname, len);
+
+ if (dirnamep)
+ {
+ const char *dirname = *dirnamep;
+
+ if (dirname == NULL)
+ /* The default value. */
+ dirname = _nl_default_dirname;
+ else
+ {
+ if (strcmp (dirname, _nl_default_dirname) == 0)
+ dirname = _nl_default_dirname;
+ else
+ {
+ char *result;
+#if defined _LIBC || defined HAVE_STRDUP
+ result = strdup (dirname);
+ if (__builtin_expect (result == NULL, 0))
+ goto failed_dirname;
+#else
+ size_t len = strlen (dirname) + 1;
+ result = (char *) malloc (len);
+ if (__builtin_expect (result == NULL, 0))
+ goto failed_dirname;
+ memcpy (result, dirname, len);
+#endif
+ dirname = result;
+ }
+ }
+ *dirnamep = dirname;
+ new_binding->dirname = (char *) dirname;
+ }
+ else
+ /* The default value. */
+ new_binding->dirname = (char *) _nl_default_dirname;
+
+ if (codesetp)
+ {
+ const char *codeset = *codesetp;
+
+ if (codeset != NULL)
+ {
+ char *result;
+
+#if defined _LIBC || defined HAVE_STRDUP
+ result = strdup (codeset);
+ if (__builtin_expect (result == NULL, 0))
+ goto failed_codeset;
+#else
+ size_t len = strlen (codeset) + 1;
+ result = (char *) malloc (len);
+ if (__builtin_expect (result == NULL, 0))
+ goto failed_codeset;
+ memcpy (result, codeset, len);
+#endif
+ codeset = result;
+ }
+ *codesetp = codeset;
+ new_binding->codeset = (char *) codeset;
+ }
+ else
+ new_binding->codeset = NULL;
+
+ /* Now enqueue it. */
+ if (_nl_domain_bindings == NULL
+ || strcmp (domainname, _nl_domain_bindings->domainname) < 0)
+ {
+ new_binding->next = _nl_domain_bindings;
+ _nl_domain_bindings = new_binding;
+ }
+ else
+ {
+ binding = _nl_domain_bindings;
+ while (binding->next != NULL
+ && strcmp (domainname, binding->next->domainname) > 0)
+ binding = binding->next;
+
+ new_binding->next = binding->next;
+ binding->next = new_binding;
+ }
+
+ modified = 1;
+
+ /* Here we deal with memory allocation failures. */
+ if (0)
+ {
+ failed_codeset:
+ if (new_binding->dirname != _nl_default_dirname)
+ free (new_binding->dirname);
+ failed_dirname:
+ free (new_binding);
+ failed:
+ if (dirnamep)
+ *dirnamep = NULL;
+ if (codesetp)
+ *codesetp = NULL;
+ }
+ }
+
+ /* If we modified any binding, we flush the caches. */
+ if (modified)
+ ++_nl_msg_cat_cntr;
+
+ gl_rwlock_unlock (_nl_state_lock);
+}
+
+/* Specify that the DOMAINNAME message catalog will be found
+ in DIRNAME rather than in the system locale data base. */
+char *
+BINDTEXTDOMAIN (const char *domainname, const char *dirname)
+{
+ set_binding_values (domainname, &dirname, NULL);
+ return (char *) dirname;
+}
+
+/* Specify the character encoding in which the messages from the
+ DOMAINNAME message catalog will be returned. */
+char *
+BIND_TEXTDOMAIN_CODESET (const char *domainname, const char *codeset)
+{
+ set_binding_values (domainname, NULL, &codeset);
+ return (char *) codeset;
+}
+
+#ifdef _LIBC
+/* Aliases for function names in GNU C Library. */
+weak_alias (__bindtextdomain, bindtextdomain);
+weak_alias (__bind_textdomain_codeset, bind_textdomain_codeset);
+#endif
diff --git a/intl/config.charset b/intl/config.charset
new file mode 100755
index 00000000..b9dccbb9
--- /dev/null
+++ b/intl/config.charset
@@ -0,0 +1,684 @@
+#! /bin/sh
+# Output a system dependent table of character encoding aliases.
+#
+# Copyright (C) 2000-2004, 2006-2010 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Library General Public License as published
+# by the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+# USA.
+#
+# The table consists of lines of the form
+# ALIAS CANONICAL
+#
+# ALIAS is the (system dependent) result of "nl_langinfo (CODESET)".
+# ALIAS is compared in a case sensitive way.
+#
+# CANONICAL is the GNU canonical name for this character encoding.
+# It must be an encoding supported by libiconv. Support by GNU libc is
+# also desirable. CANONICAL is case insensitive. Usually an upper case
+# MIME charset name is preferred.
+# The current list of GNU canonical charset names is as follows.
+#
+# name MIME? used by which systems
+# ASCII, ANSI_X3.4-1968 glibc solaris freebsd netbsd darwin cygwin
+# ISO-8859-1 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin
+# ISO-8859-2 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin
+# ISO-8859-3 Y glibc solaris cygwin
+# ISO-8859-4 Y osf solaris freebsd netbsd openbsd darwin
+# ISO-8859-5 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin
+# ISO-8859-6 Y glibc aix hpux solaris cygwin
+# ISO-8859-7 Y glibc aix hpux irix osf solaris netbsd openbsd darwin cygwin
+# ISO-8859-8 Y glibc aix hpux osf solaris cygwin
+# ISO-8859-9 Y glibc aix hpux irix osf solaris darwin cygwin
+# ISO-8859-13 glibc netbsd openbsd darwin cygwin
+# ISO-8859-14 glibc cygwin
+# ISO-8859-15 glibc aix osf solaris freebsd netbsd openbsd darwin cygwin
+# KOI8-R Y glibc solaris freebsd netbsd openbsd darwin
+# KOI8-U Y glibc freebsd netbsd openbsd darwin cygwin
+# KOI8-T glibc
+# CP437 dos
+# CP775 dos
+# CP850 aix osf dos
+# CP852 dos
+# CP855 dos
+# CP856 aix
+# CP857 dos
+# CP861 dos
+# CP862 dos
+# CP864 dos
+# CP865 dos
+# CP866 freebsd netbsd openbsd darwin dos
+# CP869 dos
+# CP874 woe32 dos
+# CP922 aix
+# CP932 aix cygwin woe32 dos
+# CP943 aix
+# CP949 osf darwin woe32 dos
+# CP950 woe32 dos
+# CP1046 aix
+# CP1124 aix
+# CP1125 dos
+# CP1129 aix
+# CP1131 darwin
+# CP1250 woe32
+# CP1251 glibc solaris netbsd openbsd darwin cygwin woe32
+# CP1252 aix woe32
+# CP1253 woe32
+# CP1254 woe32
+# CP1255 glibc woe32
+# CP1256 woe32
+# CP1257 woe32
+# GB2312 Y glibc aix hpux irix solaris freebsd netbsd darwin
+# EUC-JP Y glibc aix hpux irix osf solaris freebsd netbsd darwin
+# EUC-KR Y glibc aix hpux irix osf solaris freebsd netbsd darwin cygwin
+# EUC-TW glibc aix hpux irix osf solaris netbsd
+# BIG5 Y glibc aix hpux osf solaris freebsd netbsd darwin cygwin
+# BIG5-HKSCS glibc solaris darwin
+# GBK glibc aix osf solaris darwin cygwin woe32 dos
+# GB18030 glibc solaris netbsd darwin
+# SHIFT_JIS Y hpux osf solaris freebsd netbsd darwin
+# JOHAB glibc solaris woe32
+# TIS-620 glibc aix hpux osf solaris cygwin
+# VISCII Y glibc
+# TCVN5712-1 glibc
+# ARMSCII-8 glibc darwin
+# GEORGIAN-PS glibc cygwin
+# PT154 glibc
+# HP-ROMAN8 hpux
+# HP-ARABIC8 hpux
+# HP-GREEK8 hpux
+# HP-HEBREW8 hpux
+# HP-TURKISH8 hpux
+# HP-KANA8 hpux
+# DEC-KANJI osf
+# DEC-HANYU osf
+# UTF-8 Y glibc aix hpux osf solaris netbsd darwin cygwin
+#
+# Note: Names which are not marked as being a MIME name should not be used in
+# Internet protocols for information interchange (mail, news, etc.).
+#
+# Note: ASCII and ANSI_X3.4-1968 are synonymous canonical names. Applications
+# must understand both names and treat them as equivalent.
+#
+# The first argument passed to this file is the canonical host specification,
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+
+host="$1"
+os=`echo "$host" | sed -e 's/^[^-]*-[^-]*-\(.*\)$/\1/'`
+echo "# This file contains a table of character encoding aliases,"
+echo "# suitable for operating system '${os}'."
+echo "# It was automatically generated from config.charset."
+# List of references, updated during installation:
+echo "# Packages using this file: "
+case "$os" in
+ linux-gnulibc1*)
+ # Linux libc5 doesn't have nl_langinfo(CODESET); therefore
+ # localcharset.c falls back to using the full locale name
+ # from the environment variables.
+ echo "C ASCII"
+ echo "POSIX ASCII"
+ for l in af af_ZA ca ca_ES da da_DK de de_AT de_BE de_CH de_DE de_LU \
+ en en_AU en_BW en_CA en_DK en_GB en_IE en_NZ en_US en_ZA \
+ en_ZW es es_AR es_BO es_CL es_CO es_DO es_EC es_ES es_GT \
+ es_HN es_MX es_PA es_PE es_PY es_SV es_US es_UY es_VE et \
+ et_EE eu eu_ES fi fi_FI fo fo_FO fr fr_BE fr_CA fr_CH fr_FR \
+ fr_LU ga ga_IE gl gl_ES id id_ID in in_ID is is_IS it it_CH \
+ it_IT kl kl_GL nl nl_BE nl_NL no no_NO pt pt_BR pt_PT sv \
+ sv_FI sv_SE; do
+ echo "$l ISO-8859-1"
+ echo "$l.iso-8859-1 ISO-8859-1"
+ echo "$l.iso-8859-15 ISO-8859-15"
+ echo "$l.iso-8859-15@euro ISO-8859-15"
+ echo "$l@euro ISO-8859-15"
+ echo "$l.cp-437 CP437"
+ echo "$l.cp-850 CP850"
+ echo "$l.cp-1252 CP1252"
+ echo "$l.cp-1252@euro CP1252"
+ #echo "$l.atari-st ATARI-ST" # not a commonly used encoding
+ echo "$l.utf-8 UTF-8"
+ echo "$l.utf-8@euro UTF-8"
+ done
+ for l in cs cs_CZ hr hr_HR hu hu_HU pl pl_PL ro ro_RO sk sk_SK sl \
+ sl_SI sr sr_CS sr_YU; do
+ echo "$l ISO-8859-2"
+ echo "$l.iso-8859-2 ISO-8859-2"
+ echo "$l.cp-852 CP852"
+ echo "$l.cp-1250 CP1250"
+ echo "$l.utf-8 UTF-8"
+ done
+ for l in mk mk_MK ru ru_RU; do
+ echo "$l ISO-8859-5"
+ echo "$l.iso-8859-5 ISO-8859-5"
+ echo "$l.koi8-r KOI8-R"
+ echo "$l.cp-866 CP866"
+ echo "$l.cp-1251 CP1251"
+ echo "$l.utf-8 UTF-8"
+ done
+ for l in ar ar_SA; do
+ echo "$l ISO-8859-6"
+ echo "$l.iso-8859-6 ISO-8859-6"
+ echo "$l.cp-864 CP864"
+ #echo "$l.cp-868 CP868" # not a commonly used encoding
+ echo "$l.cp-1256 CP1256"
+ echo "$l.utf-8 UTF-8"
+ done
+ for l in el el_GR gr gr_GR; do
+ echo "$l ISO-8859-7"
+ echo "$l.iso-8859-7 ISO-8859-7"
+ echo "$l.cp-869 CP869"
+ echo "$l.cp-1253 CP1253"
+ echo "$l.cp-1253@euro CP1253"
+ echo "$l.utf-8 UTF-8"
+ echo "$l.utf-8@euro UTF-8"
+ done
+ for l in he he_IL iw iw_IL; do
+ echo "$l ISO-8859-8"
+ echo "$l.iso-8859-8 ISO-8859-8"
+ echo "$l.cp-862 CP862"
+ echo "$l.cp-1255 CP1255"
+ echo "$l.utf-8 UTF-8"
+ done
+ for l in tr tr_TR; do
+ echo "$l ISO-8859-9"
+ echo "$l.iso-8859-9 ISO-8859-9"
+ echo "$l.cp-857 CP857"
+ echo "$l.cp-1254 CP1254"
+ echo "$l.utf-8 UTF-8"
+ done
+ for l in lt lt_LT lv lv_LV; do
+ #echo "$l BALTIC" # not a commonly used encoding, wrong encoding name
+ echo "$l ISO-8859-13"
+ done
+ for l in ru_UA uk uk_UA; do
+ echo "$l KOI8-U"
+ done
+ for l in zh zh_CN; do
+ #echo "$l GB_2312-80" # not a commonly used encoding, wrong encoding name
+ echo "$l GB2312"
+ done
+ for l in ja ja_JP ja_JP.EUC; do
+ echo "$l EUC-JP"
+ done
+ for l in ko ko_KR; do
+ echo "$l EUC-KR"
+ done
+ for l in th th_TH; do
+ echo "$l TIS-620"
+ done
+ for l in fa fa_IR; do
+ #echo "$l ISIRI-3342" # a broken encoding
+ echo "$l.utf-8 UTF-8"
+ done
+ ;;
+ linux* | *-gnu*)
+ # With glibc-2.1 or newer, we don't need any canonicalization,
+ # because glibc has iconv and both glibc and libiconv support all
+ # GNU canonical names directly. Therefore, the Makefile does not
+ # need to install the alias file at all.
+ # The following applies only to glibc-2.0.x and older libcs.
+ echo "ISO_646.IRV:1983 ASCII"
+ ;;
+ aix*)
+ echo "ISO8859-1 ISO-8859-1"
+ echo "ISO8859-2 ISO-8859-2"
+ echo "ISO8859-5 ISO-8859-5"
+ echo "ISO8859-6 ISO-8859-6"
+ echo "ISO8859-7 ISO-8859-7"
+ echo "ISO8859-8 ISO-8859-8"
+ echo "ISO8859-9 ISO-8859-9"
+ echo "ISO8859-15 ISO-8859-15"
+ echo "IBM-850 CP850"
+ echo "IBM-856 CP856"
+ echo "IBM-921 ISO-8859-13"
+ echo "IBM-922 CP922"
+ echo "IBM-932 CP932"
+ echo "IBM-943 CP943"
+ echo "IBM-1046 CP1046"
+ echo "IBM-1124 CP1124"
+ echo "IBM-1129 CP1129"
+ echo "IBM-1252 CP1252"
+ echo "IBM-eucCN GB2312"
+ echo "IBM-eucJP EUC-JP"
+ echo "IBM-eucKR EUC-KR"
+ echo "IBM-eucTW EUC-TW"
+ echo "big5 BIG5"
+ echo "GBK GBK"
+ echo "TIS-620 TIS-620"
+ echo "UTF-8 UTF-8"
+ ;;
+ hpux*)
+ echo "iso88591 ISO-8859-1"
+ echo "iso88592 ISO-8859-2"
+ echo "iso88595 ISO-8859-5"
+ echo "iso88596 ISO-8859-6"
+ echo "iso88597 ISO-8859-7"
+ echo "iso88598 ISO-8859-8"
+ echo "iso88599 ISO-8859-9"
+ echo "iso885915 ISO-8859-15"
+ echo "roman8 HP-ROMAN8"
+ echo "arabic8 HP-ARABIC8"
+ echo "greek8 HP-GREEK8"
+ echo "hebrew8 HP-HEBREW8"
+ echo "turkish8 HP-TURKISH8"
+ echo "kana8 HP-KANA8"
+ echo "tis620 TIS-620"
+ echo "big5 BIG5"
+ echo "eucJP EUC-JP"
+ echo "eucKR EUC-KR"
+ echo "eucTW EUC-TW"
+ echo "hp15CN GB2312"
+ #echo "ccdc ?" # what is this?
+ echo "SJIS SHIFT_JIS"
+ echo "utf8 UTF-8"
+ ;;
+ irix*)
+ echo "ISO8859-1 ISO-8859-1"
+ echo "ISO8859-2 ISO-8859-2"
+ echo "ISO8859-5 ISO-8859-5"
+ echo "ISO8859-7 ISO-8859-7"
+ echo "ISO8859-9 ISO-8859-9"
+ echo "eucCN GB2312"
+ echo "eucJP EUC-JP"
+ echo "eucKR EUC-KR"
+ echo "eucTW EUC-TW"
+ ;;
+ osf*)
+ echo "ISO8859-1 ISO-8859-1"
+ echo "ISO8859-2 ISO-8859-2"
+ echo "ISO8859-4 ISO-8859-4"
+ echo "ISO8859-5 ISO-8859-5"
+ echo "ISO8859-7 ISO-8859-7"
+ echo "ISO8859-8 ISO-8859-8"
+ echo "ISO8859-9 ISO-8859-9"
+ echo "ISO8859-15 ISO-8859-15"
+ echo "cp850 CP850"
+ echo "big5 BIG5"
+ echo "dechanyu DEC-HANYU"
+ echo "dechanzi GB2312"
+ echo "deckanji DEC-KANJI"
+ echo "deckorean EUC-KR"
+ echo "eucJP EUC-JP"
+ echo "eucKR EUC-KR"
+ echo "eucTW EUC-TW"
+ echo "GBK GBK"
+ echo "KSC5601 CP949"
+ echo "sdeckanji EUC-JP"
+ echo "SJIS SHIFT_JIS"
+ echo "TACTIS TIS-620"
+ echo "UTF-8 UTF-8"
+ ;;
+ solaris*)
+ echo "646 ASCII"
+ echo "ISO8859-1 ISO-8859-1"
+ echo "ISO8859-2 ISO-8859-2"
+ echo "ISO8859-3 ISO-8859-3"
+ echo "ISO8859-4 ISO-8859-4"
+ echo "ISO8859-5 ISO-8859-5"
+ echo "ISO8859-6 ISO-8859-6"
+ echo "ISO8859-7 ISO-8859-7"
+ echo "ISO8859-8 ISO-8859-8"
+ echo "ISO8859-9 ISO-8859-9"
+ echo "ISO8859-15 ISO-8859-15"
+ echo "koi8-r KOI8-R"
+ echo "ansi-1251 CP1251"
+ echo "BIG5 BIG5"
+ echo "Big5-HKSCS BIG5-HKSCS"
+ echo "gb2312 GB2312"
+ echo "GBK GBK"
+ echo "GB18030 GB18030"
+ echo "cns11643 EUC-TW"
+ echo "5601 EUC-KR"
+ echo "ko_KR.johap92 JOHAB"
+ echo "eucJP EUC-JP"
+ echo "PCK SHIFT_JIS"
+ echo "TIS620.2533 TIS-620"
+ #echo "sun_eu_greek ?" # what is this?
+ echo "UTF-8 UTF-8"
+ ;;
+ freebsd* | os2*)
+ # FreeBSD 4.2 doesn't have nl_langinfo(CODESET); therefore
+ # localcharset.c falls back to using the full locale name
+ # from the environment variables.
+ # Likewise for OS/2. OS/2 has XFree86 just like FreeBSD. Just
+ # reuse FreeBSD's locale data for OS/2.
+ echo "C ASCII"
+ echo "US-ASCII ASCII"
+ for l in la_LN lt_LN; do
+ echo "$l.ASCII ASCII"
+ done
+ for l in da_DK de_AT de_CH de_DE en_AU en_CA en_GB en_US es_ES \
+ fi_FI fr_BE fr_CA fr_CH fr_FR is_IS it_CH it_IT la_LN \
+ lt_LN nl_BE nl_NL no_NO pt_PT sv_SE; do
+ echo "$l.ISO_8859-1 ISO-8859-1"
+ echo "$l.DIS_8859-15 ISO-8859-15"
+ done
+ for l in cs_CZ hr_HR hu_HU la_LN lt_LN pl_PL sl_SI; do
+ echo "$l.ISO_8859-2 ISO-8859-2"
+ done
+ for l in la_LN lt_LT; do
+ echo "$l.ISO_8859-4 ISO-8859-4"
+ done
+ for l in ru_RU ru_SU; do
+ echo "$l.KOI8-R KOI8-R"
+ echo "$l.ISO_8859-5 ISO-8859-5"
+ echo "$l.CP866 CP866"
+ done
+ echo "uk_UA.KOI8-U KOI8-U"
+ echo "zh_TW.BIG5 BIG5"
+ echo "zh_TW.Big5 BIG5"
+ echo "zh_CN.EUC GB2312"
+ echo "ja_JP.EUC EUC-JP"
+ echo "ja_JP.SJIS SHIFT_JIS"
+ echo "ja_JP.Shift_JIS SHIFT_JIS"
+ echo "ko_KR.EUC EUC-KR"
+ ;;
+ netbsd*)
+ echo "646 ASCII"
+ echo "ISO8859-1 ISO-8859-1"
+ echo "ISO8859-2 ISO-8859-2"
+ echo "ISO8859-4 ISO-8859-4"
+ echo "ISO8859-5 ISO-8859-5"
+ echo "ISO8859-7 ISO-8859-7"
+ echo "ISO8859-13 ISO-8859-13"
+ echo "ISO8859-15 ISO-8859-15"
+ echo "eucCN GB2312"
+ echo "eucJP EUC-JP"
+ echo "eucKR EUC-KR"
+ echo "eucTW EUC-TW"
+ echo "BIG5 BIG5"
+ echo "SJIS SHIFT_JIS"
+ ;;
+ openbsd*)
+ echo "646 ASCII"
+ echo "ISO8859-1 ISO-8859-1"
+ echo "ISO8859-2 ISO-8859-2"
+ echo "ISO8859-4 ISO-8859-4"
+ echo "ISO8859-5 ISO-8859-5"
+ echo "ISO8859-7 ISO-8859-7"
+ echo "ISO8859-13 ISO-8859-13"
+ echo "ISO8859-15 ISO-8859-15"
+ ;;
+ darwin[56]*)
+ # Darwin 6.8 doesn't have nl_langinfo(CODESET); therefore
+ # localcharset.c falls back to using the full locale name
+ # from the environment variables.
+ echo "C ASCII"
+ for l in en_AU en_CA en_GB en_US la_LN; do
+ echo "$l.US-ASCII ASCII"
+ done
+ for l in da_DK de_AT de_CH de_DE en_AU en_CA en_GB en_US es_ES \
+ fi_FI fr_BE fr_CA fr_CH fr_FR is_IS it_CH it_IT nl_BE \
+ nl_NL no_NO pt_PT sv_SE; do
+ echo "$l ISO-8859-1"
+ echo "$l.ISO8859-1 ISO-8859-1"
+ echo "$l.ISO8859-15 ISO-8859-15"
+ done
+ for l in la_LN; do
+ echo "$l.ISO8859-1 ISO-8859-1"
+ echo "$l.ISO8859-15 ISO-8859-15"
+ done
+ for l in cs_CZ hr_HR hu_HU la_LN pl_PL sl_SI; do
+ echo "$l.ISO8859-2 ISO-8859-2"
+ done
+ for l in la_LN lt_LT; do
+ echo "$l.ISO8859-4 ISO-8859-4"
+ done
+ for l in ru_RU; do
+ echo "$l.KOI8-R KOI8-R"
+ echo "$l.ISO8859-5 ISO-8859-5"
+ echo "$l.CP866 CP866"
+ done
+ for l in bg_BG; do
+ echo "$l.CP1251 CP1251"
+ done
+ echo "uk_UA.KOI8-U KOI8-U"
+ echo "zh_TW.BIG5 BIG5"
+ echo "zh_TW.Big5 BIG5"
+ echo "zh_CN.EUC GB2312"
+ echo "ja_JP.EUC EUC-JP"
+ echo "ja_JP.SJIS SHIFT_JIS"
+ echo "ko_KR.EUC EUC-KR"
+ ;;
+ darwin*)
+ # Darwin 7.5 has nl_langinfo(CODESET), but sometimes its value is
+ # useless:
+ # - It returns the empty string when LANG is set to a locale of the
+ # form ll_CC, although ll_CC/LC_CTYPE is a symlink to an UTF-8
+ # LC_CTYPE file.
+ # - The environment variables LANG, LC_CTYPE, LC_ALL are not set by
+ # the system; nl_langinfo(CODESET) returns "US-ASCII" in this case.
+ # - The documentation says:
+ # "... all code that calls BSD system routines should ensure
+ # that the const *char parameters of these routines are in UTF-8
+ # encoding. All BSD system functions expect their string
+ # parameters to be in UTF-8 encoding and nothing else."
+ # It also says
+ # "An additional caveat is that string parameters for files,
+ # paths, and other file-system entities must be in canonical
+ # UTF-8. In a canonical UTF-8 Unicode string, all decomposable
+ # characters are decomposed ..."
+ # but this is not true: You can pass non-decomposed UTF-8 strings
+ # to file system functions, and it is the OS which will convert
+ # them to decomposed UTF-8 before accessing the file system.
+ # - The Apple Terminal application displays UTF-8 by default.
+ # - However, other applications are free to use different encodings:
+ # - xterm uses ISO-8859-1 by default.
+ # - TextEdit uses MacRoman by default.
+ # We prefer UTF-8 over decomposed UTF-8-MAC because one should
+ # minimize the use of decomposed Unicode. Unfortunately, through the
+ # Darwin file system, decomposed UTF-8 strings are leaked into user
+ # space nevertheless.
+ # Then there are also the locales with encodings other than US-ASCII
+ # and UTF-8. These locales can be occasionally useful to users (e.g.
+ # when grepping through ISO-8859-1 encoded text files), when all their
+ # file names are in US-ASCII.
+ echo "ISO8859-1 ISO-8859-1"
+ echo "ISO8859-2 ISO-8859-2"
+ echo "ISO8859-4 ISO-8859-4"
+ echo "ISO8859-5 ISO-8859-5"
+ echo "ISO8859-7 ISO-8859-7"
+ echo "ISO8859-9 ISO-8859-9"
+ echo "ISO8859-13 ISO-8859-13"
+ echo "ISO8859-15 ISO-8859-15"
+ echo "KOI8-R KOI8-R"
+ echo "KOI8-U KOI8-U"
+ echo "CP866 CP866"
+ echo "CP949 CP949"
+ echo "CP1131 CP1131"
+ echo "CP1251 CP1251"
+ echo "eucCN GB2312"
+ echo "GB2312 GB2312"
+ echo "eucJP EUC-JP"
+ echo "eucKR EUC-KR"
+ echo "Big5 BIG5"
+ echo "Big5HKSCS BIG5-HKSCS"
+ echo "GBK GBK"
+ echo "GB18030 GB18030"
+ echo "SJIS SHIFT_JIS"
+ echo "ARMSCII-8 ARMSCII-8"
+ echo "PT154 PT154"
+ #echo "ISCII-DEV ?"
+ echo "* UTF-8"
+ ;;
+ beos* | haiku*)
+ # BeOS and Haiku have a single locale, and it has UTF-8 encoding.
+ echo "* UTF-8"
+ ;;
+ msdosdjgpp*)
+ # DJGPP 2.03 doesn't have nl_langinfo(CODESET); therefore
+ # localcharset.c falls back to using the full locale name
+ # from the environment variables.
+ echo "#"
+ echo "# The encodings given here may not all be correct."
+ echo "# If you find that the encoding given for your language and"
+ echo "# country is not the one your DOS machine actually uses, just"
+ echo "# correct it in this file, and send a mail to"
+ echo "# Juan Manuel Guerrero <juan.guerrero@gmx.de>"
+ echo "# and Bruno Haible <bruno@clisp.org>."
+ echo "#"
+ echo "C ASCII"
+ # ISO-8859-1 languages
+ echo "ca CP850"
+ echo "ca_ES CP850"
+ echo "da CP865" # not CP850 ??
+ echo "da_DK CP865" # not CP850 ??
+ echo "de CP850"
+ echo "de_AT CP850"
+ echo "de_CH CP850"
+ echo "de_DE CP850"
+ echo "en CP850"
+ echo "en_AU CP850" # not CP437 ??
+ echo "en_CA CP850"
+ echo "en_GB CP850"
+ echo "en_NZ CP437"
+ echo "en_US CP437"
+ echo "en_ZA CP850" # not CP437 ??
+ echo "es CP850"
+ echo "es_AR CP850"
+ echo "es_BO CP850"
+ echo "es_CL CP850"
+ echo "es_CO CP850"
+ echo "es_CR CP850"
+ echo "es_CU CP850"
+ echo "es_DO CP850"
+ echo "es_EC CP850"
+ echo "es_ES CP850"
+ echo "es_GT CP850"
+ echo "es_HN CP850"
+ echo "es_MX CP850"
+ echo "es_NI CP850"
+ echo "es_PA CP850"
+ echo "es_PY CP850"
+ echo "es_PE CP850"
+ echo "es_SV CP850"
+ echo "es_UY CP850"
+ echo "es_VE CP850"
+ echo "et CP850"
+ echo "et_EE CP850"
+ echo "eu CP850"
+ echo "eu_ES CP850"
+ echo "fi CP850"
+ echo "fi_FI CP850"
+ echo "fr CP850"
+ echo "fr_BE CP850"
+ echo "fr_CA CP850"
+ echo "fr_CH CP850"
+ echo "fr_FR CP850"
+ echo "ga CP850"
+ echo "ga_IE CP850"
+ echo "gd CP850"
+ echo "gd_GB CP850"
+ echo "gl CP850"
+ echo "gl_ES CP850"
+ echo "id CP850" # not CP437 ??
+ echo "id_ID CP850" # not CP437 ??
+ echo "is CP861" # not CP850 ??
+ echo "is_IS CP861" # not CP850 ??
+ echo "it CP850"
+ echo "it_CH CP850"
+ echo "it_IT CP850"
+ echo "lt CP775"
+ echo "lt_LT CP775"
+ echo "lv CP775"
+ echo "lv_LV CP775"
+ echo "nb CP865" # not CP850 ??
+ echo "nb_NO CP865" # not CP850 ??
+ echo "nl CP850"
+ echo "nl_BE CP850"
+ echo "nl_NL CP850"
+ echo "nn CP865" # not CP850 ??
+ echo "nn_NO CP865" # not CP850 ??
+ echo "no CP865" # not CP850 ??
+ echo "no_NO CP865" # not CP850 ??
+ echo "pt CP850"
+ echo "pt_BR CP850"
+ echo "pt_PT CP850"
+ echo "sv CP850"
+ echo "sv_SE CP850"
+ # ISO-8859-2 languages
+ echo "cs CP852"
+ echo "cs_CZ CP852"
+ echo "hr CP852"
+ echo "hr_HR CP852"
+ echo "hu CP852"
+ echo "hu_HU CP852"
+ echo "pl CP852"
+ echo "pl_PL CP852"
+ echo "ro CP852"
+ echo "ro_RO CP852"
+ echo "sk CP852"
+ echo "sk_SK CP852"
+ echo "sl CP852"
+ echo "sl_SI CP852"
+ echo "sq CP852"
+ echo "sq_AL CP852"
+ echo "sr CP852" # CP852 or CP866 or CP855 ??
+ echo "sr_CS CP852" # CP852 or CP866 or CP855 ??
+ echo "sr_YU CP852" # CP852 or CP866 or CP855 ??
+ # ISO-8859-3 languages
+ echo "mt CP850"
+ echo "mt_MT CP850"
+ # ISO-8859-5 languages
+ echo "be CP866"
+ echo "be_BE CP866"
+ echo "bg CP866" # not CP855 ??
+ echo "bg_BG CP866" # not CP855 ??
+ echo "mk CP866" # not CP855 ??
+ echo "mk_MK CP866" # not CP855 ??
+ echo "ru CP866"
+ echo "ru_RU CP866"
+ echo "uk CP1125"
+ echo "uk_UA CP1125"
+ # ISO-8859-6 languages
+ echo "ar CP864"
+ echo "ar_AE CP864"
+ echo "ar_DZ CP864"
+ echo "ar_EG CP864"
+ echo "ar_IQ CP864"
+ echo "ar_IR CP864"
+ echo "ar_JO CP864"
+ echo "ar_KW CP864"
+ echo "ar_MA CP864"
+ echo "ar_OM CP864"
+ echo "ar_QA CP864"
+ echo "ar_SA CP864"
+ echo "ar_SY CP864"
+ # ISO-8859-7 languages
+ echo "el CP869"
+ echo "el_GR CP869"
+ # ISO-8859-8 languages
+ echo "he CP862"
+ echo "he_IL CP862"
+ # ISO-8859-9 languages
+ echo "tr CP857"
+ echo "tr_TR CP857"
+ # Japanese
+ echo "ja CP932"
+ echo "ja_JP CP932"
+ # Chinese
+ echo "zh_CN GBK"
+ echo "zh_TW CP950" # not CP938 ??
+ # Korean
+ echo "kr CP949" # not CP934 ??
+ echo "kr_KR CP949" # not CP934 ??
+ # Thai
+ echo "th CP874"
+ echo "th_TH CP874"
+ # Other
+ echo "eo CP850"
+ echo "eo_EO CP850"
+ ;;
+esac
diff --git a/intl/dcgettext.c b/intl/dcgettext.c
new file mode 100644
index 00000000..c2a63f08
--- /dev/null
+++ b/intl/dcgettext.c
@@ -0,0 +1,56 @@
+/* Implementation of the dcgettext(3) function.
+ Copyright (C) 1995-1999, 2000-2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "gettextP.h"
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Names for the libintl functions are a problem. They must not clash
+ with existing names and they should follow ANSI C. But this source
+ code is also used in GNU C Library where the names have a __
+ prefix. So we have to make a difference here. */
+#ifdef _LIBC
+# define DCGETTEXT __dcgettext
+# define DCIGETTEXT __dcigettext
+#else
+# define DCGETTEXT libintl_dcgettext
+# define DCIGETTEXT libintl_dcigettext
+#endif
+
+/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY
+ locale. */
+char *
+DCGETTEXT (const char *domainname, const char *msgid, int category)
+{
+ return DCIGETTEXT (domainname, msgid, NULL, 0, 0, category);
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library. */
+INTDEF(__dcgettext)
+weak_alias (__dcgettext, dcgettext);
+#endif
diff --git a/intl/dcigettext.c b/intl/dcigettext.c
new file mode 100644
index 00000000..b2add5db
--- /dev/null
+++ b/intl/dcigettext.c
@@ -0,0 +1,1705 @@
+/* Implementation of the internal dcigettext function.
+ Copyright (C) 1995-1999, 2000-2009 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+/* Tell glibc's <string.h> to provide a prototype for mempcpy().
+ This must come before <config.h> because <config.h> may include
+ <features.h>, and once <features.h> has been included, it's too late. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+# define HAVE_ALLOCA 1
+#else
+# ifdef _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+# else
+# if defined HAVE_ALLOCA_H || defined _LIBC
+# include <alloca.h>
+# else
+# ifdef _AIX
+ #pragma alloca
+# else
+# ifndef alloca
+char *alloca ();
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
+#ifndef __set_errno
+# define __set_errno(val) errno = (val)
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined HAVE_UNISTD_H || defined _LIBC
+# include <unistd.h>
+#endif
+
+#include <locale.h>
+
+#ifdef _LIBC
+ /* Guess whether integer division by zero raises signal SIGFPE.
+ Set to 1 only if you know for sure. In case of doubt, set to 0. */
+# if defined __alpha__ || defined __arm__ || defined __i386__ \
+ || defined __m68k__ || defined __s390__
+# define INTDIV0_RAISES_SIGFPE 1
+# else
+# define INTDIV0_RAISES_SIGFPE 0
+# endif
+#endif
+#if !INTDIV0_RAISES_SIGFPE
+# include <signal.h>
+#endif
+
+#if defined HAVE_SYS_PARAM_H || defined _LIBC
+# include <sys/param.h>
+#endif
+
+#if !defined _LIBC
+# include "localcharset.h"
+#endif
+
+#include "gettextP.h"
+#include "plural-exp.h"
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# ifdef IN_LIBGLOCALE
+# include <libintl.h>
+# endif
+# include "libgnuintl.h"
+#endif
+#include "hash-string.h"
+
+/* Handle multi-threaded applications. */
+#ifdef _LIBC
+# include <bits/libc-lock.h>
+# define gl_rwlock_define_initialized __libc_rwlock_define_initialized
+# define gl_rwlock_rdlock __libc_rwlock_rdlock
+# define gl_rwlock_wrlock __libc_rwlock_wrlock
+# define gl_rwlock_unlock __libc_rwlock_unlock
+#else
+# include "lock.h"
+#endif
+
+/* Alignment of types. */
+#if defined __GNUC__ && __GNUC__ >= 2
+# define alignof(TYPE) __alignof__ (TYPE)
+#else
+# define alignof(TYPE) \
+ ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2)
+#endif
+
+/* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
+#ifndef offsetof
+# define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
+#endif
+
+/* @@ end of prolog @@ */
+
+#ifdef _LIBC
+/* Rename the non ANSI C functions. This is required by the standard
+ because some ANSI C functions will require linking with this object
+ file and the name space must not be polluted. */
+# define getcwd __getcwd
+# ifndef stpcpy
+# define stpcpy __stpcpy
+# endif
+# define tfind __tfind
+#else
+# if !defined HAVE_GETCWD
+char *getwd ();
+# define getcwd(buf, max) getwd (buf)
+# else
+# if VMS
+# define getcwd(buf, max) (getcwd) (buf, max, 0)
+# else
+char *getcwd ();
+# endif
+# endif
+# ifndef HAVE_STPCPY
+static char *stpcpy (char *dest, const char *src);
+# endif
+# ifndef HAVE_MEMPCPY
+static void *mempcpy (void *dest, const void *src, size_t n);
+# endif
+#endif
+
+/* Use a replacement if the system does not provide the `tsearch' function
+ family. */
+#if HAVE_TSEARCH || defined _LIBC
+# include <search.h>
+#else
+# define tsearch libintl_tsearch
+# define tfind libintl_tfind
+# define tdelete libintl_tdelete
+# define twalk libintl_twalk
+# include "tsearch.h"
+#endif
+
+#ifdef _LIBC
+# define tsearch __tsearch
+#endif
+
+/* Amount to increase buffer size by in each try. */
+#define PATH_INCR 32
+
+/* The following is from pathmax.h. */
+/* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define
+ PATH_MAX but might cause redefinition warnings when sys/param.h is
+ later included (as on MORE/BSD 4.3). */
+#if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__)
+# include <limits.h>
+#endif
+
+#ifndef _POSIX_PATH_MAX
+# define _POSIX_PATH_MAX 255
+#endif
+
+#if !defined PATH_MAX && defined _PC_PATH_MAX
+# define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX))
+#endif
+
+/* Don't include sys/param.h if it already has been. */
+#if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
+# include <sys/param.h>
+#endif
+
+#if !defined PATH_MAX && defined MAXPATHLEN
+# define PATH_MAX MAXPATHLEN
+#endif
+
+#ifndef PATH_MAX
+# define PATH_MAX _POSIX_PATH_MAX
+#endif
+
+/* Pathname support.
+ ISSLASH(C) tests whether C is a directory separator character.
+ IS_ABSOLUTE_PATH(P) tests whether P is an absolute path. If it is not,
+ it may be concatenated to a directory pathname.
+ IS_PATH_WITH_DIR(P) tests whether P contains a directory specification.
+ */
+#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
+ /* Win32, Cygwin, OS/2, DOS */
+# define ISSLASH(C) ((C) == '/' || (C) == '\\')
+# define HAS_DEVICE(P) \
+ ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
+ && (P)[1] == ':')
+# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P))
+# define IS_PATH_WITH_DIR(P) \
+ (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
+#else
+ /* Unix */
+# define ISSLASH(C) ((C) == '/')
+# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0])
+# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
+#endif
+
+/* Whether to support different locales in different threads. */
+#if defined _LIBC || HAVE_USELOCALE || defined IN_LIBGLOCALE
+# define HAVE_PER_THREAD_LOCALE
+#endif
+
+/* This is the type used for the search tree where known translations
+ are stored. */
+struct known_translation_t
+{
+ /* Domain in which to search. */
+ const char *domainname;
+
+ /* The category. */
+ int category;
+
+#ifdef HAVE_PER_THREAD_LOCALE
+ /* Name of the relevant locale category, or "" for the global locale. */
+ const char *localename;
+#endif
+
+#ifdef IN_LIBGLOCALE
+ /* The character encoding. */
+ const char *encoding;
+#endif
+
+ /* State of the catalog counter at the point the string was found. */
+ int counter;
+
+ /* Catalog where the string was found. */
+ struct loaded_l10nfile *domain;
+
+ /* And finally the translation. */
+ const char *translation;
+ size_t translation_length;
+
+ /* Pointer to the string in question. */
+ union
+ {
+ char appended[ZERO]; /* used if domain != NULL */
+ const char *ptr; /* used if domain == NULL */
+ }
+ msgid;
+};
+
+gl_rwlock_define_initialized (static, tree_lock)
+
+/* Root of the search tree with known translations. */
+static void *root;
+
+/* Function to compare two entries in the table of known translations. */
+static int
+transcmp (const void *p1, const void *p2)
+{
+ const struct known_translation_t *s1;
+ const struct known_translation_t *s2;
+ int result;
+
+ s1 = (const struct known_translation_t *) p1;
+ s2 = (const struct known_translation_t *) p2;
+
+ result = strcmp (s1->domain != NULL ? s1->msgid.appended : s1->msgid.ptr,
+ s2->domain != NULL ? s2->msgid.appended : s2->msgid.ptr);
+ if (result == 0)
+ {
+ result = strcmp (s1->domainname, s2->domainname);
+ if (result == 0)
+ {
+#ifdef HAVE_PER_THREAD_LOCALE
+ result = strcmp (s1->localename, s2->localename);
+ if (result == 0)
+#endif
+ {
+#ifdef IN_LIBGLOCALE
+ result = strcmp (s1->encoding, s2->encoding);
+ if (result == 0)
+#endif
+ /* We compare the category last (though this is the cheapest
+ operation) since it is hopefully always the same (namely
+ LC_MESSAGES). */
+ result = s1->category - s2->category;
+ }
+ }
+ }
+
+ return result;
+}
+
+/* Name of the default domain used for gettext(3) prior any call to
+ textdomain(3). The default value for this is "messages". */
+const char _nl_default_default_domain[] attribute_hidden = "messages";
+
+#ifndef IN_LIBGLOCALE
+/* Value used as the default domain for gettext(3). */
+const char *_nl_current_default_domain attribute_hidden
+ = _nl_default_default_domain;
+#endif
+
+/* Contains the default location of the message catalogs. */
+#if defined __EMX__
+extern const char _nl_default_dirname[];
+#else
+# ifdef _LIBC
+extern const char _nl_default_dirname[];
+libc_hidden_proto (_nl_default_dirname)
+# endif
+const char _nl_default_dirname[] = LOCALEDIR;
+# ifdef _LIBC
+libc_hidden_data_def (_nl_default_dirname)
+# endif
+#endif
+
+#ifndef IN_LIBGLOCALE
+/* List with bindings of specific domains created by bindtextdomain()
+ calls. */
+struct binding *_nl_domain_bindings;
+#endif
+
+/* Prototypes for local functions. */
+static char *plural_lookup (struct loaded_l10nfile *domain,
+ unsigned long int n,
+ const char *translation, size_t translation_len)
+ internal_function;
+
+#ifdef IN_LIBGLOCALE
+static const char *guess_category_value (int category,
+ const char *categoryname,
+ const char *localename)
+ internal_function;
+#else
+static const char *guess_category_value (int category,
+ const char *categoryname)
+ internal_function;
+#endif
+
+#ifdef _LIBC
+# include "../locale/localeinfo.h"
+# define category_to_name(category) \
+ _nl_category_names.str + _nl_category_name_idxs[category]
+#else
+static const char *category_to_name (int category) internal_function;
+#endif
+#if (defined _LIBC || HAVE_ICONV) && !defined IN_LIBGLOCALE
+static const char *get_output_charset (struct binding *domainbinding)
+ internal_function;
+#endif
+
+
+/* For those loosing systems which don't have `alloca' we have to add
+ some additional code emulating it. */
+#ifdef HAVE_ALLOCA
+/* Nothing has to be done. */
+# define freea(p) /* nothing */
+# define ADD_BLOCK(list, address) /* nothing */
+# define FREE_BLOCKS(list) /* nothing */
+#else
+struct block_list
+{
+ void *address;
+ struct block_list *next;
+};
+# define ADD_BLOCK(list, addr) \
+ do { \
+ struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \
+ /* If we cannot get a free block we cannot add the new element to \
+ the list. */ \
+ if (newp != NULL) { \
+ newp->address = (addr); \
+ newp->next = (list); \
+ (list) = newp; \
+ } \
+ } while (0)
+# define FREE_BLOCKS(list) \
+ do { \
+ while (list != NULL) { \
+ struct block_list *old = list; \
+ list = list->next; \
+ free (old->address); \
+ free (old); \
+ } \
+ } while (0)
+# undef alloca
+# define alloca(size) (malloc (size))
+# define freea(p) free (p)
+#endif /* have alloca */
+
+
+#ifdef _LIBC
+/* List of blocks allocated for translations. */
+typedef struct transmem_list
+{
+ struct transmem_list *next;
+ char data[ZERO];
+} transmem_block_t;
+static struct transmem_list *transmem_list;
+#else
+typedef unsigned char transmem_block_t;
+#endif
+
+
+/* Names for the libintl functions are a problem. They must not clash
+ with existing names and they should follow ANSI C. But this source
+ code is also used in GNU C Library where the names have a __
+ prefix. So we have to make a difference here. */
+#ifdef _LIBC
+# define DCIGETTEXT __dcigettext
+#else
+# define DCIGETTEXT libintl_dcigettext
+#endif
+
+/* Lock variable to protect the global data in the gettext implementation. */
+gl_rwlock_define_initialized (, _nl_state_lock attribute_hidden)
+
+/* Checking whether the binaries runs SUID must be done and glibc provides
+ easier methods therefore we make a difference here. */
+#ifdef _LIBC
+# define ENABLE_SECURE __libc_enable_secure
+# define DETERMINE_SECURE
+#else
+# ifndef HAVE_GETUID
+# define getuid() 0
+# endif
+# ifndef HAVE_GETGID
+# define getgid() 0
+# endif
+# ifndef HAVE_GETEUID
+# define geteuid() getuid()
+# endif
+# ifndef HAVE_GETEGID
+# define getegid() getgid()
+# endif
+static int enable_secure;
+# define ENABLE_SECURE (enable_secure == 1)
+# define DETERMINE_SECURE \
+ if (enable_secure == 0) \
+ { \
+ if (getuid () != geteuid () || getgid () != getegid ()) \
+ enable_secure = 1; \
+ else \
+ enable_secure = -1; \
+ }
+#endif
+
+/* Get the function to evaluate the plural expression. */
+#include "eval-plural.h"
+
+/* Look up MSGID in the DOMAINNAME message catalog for the current
+ CATEGORY locale and, if PLURAL is nonzero, search over string
+ depending on the plural form determined by N. */
+#ifdef IN_LIBGLOCALE
+char *
+gl_dcigettext (const char *domainname,
+ const char *msgid1, const char *msgid2,
+ int plural, unsigned long int n,
+ int category,
+ const char *localename, const char *encoding)
+#else
+char *
+DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
+ int plural, unsigned long int n, int category)
+#endif
+{
+#ifndef HAVE_ALLOCA
+ struct block_list *block_list = NULL;
+#endif
+ struct loaded_l10nfile *domain;
+ struct binding *binding;
+ const char *categoryname;
+ const char *categoryvalue;
+ const char *dirname;
+ char *xdomainname;
+ char *single_locale;
+ char *retval;
+ size_t retlen;
+ int saved_errno;
+ struct known_translation_t search;
+ struct known_translation_t **foundp = NULL;
+#if defined HAVE_PER_THREAD_LOCALE && !defined IN_LIBGLOCALE
+ const char *localename;
+#endif
+ size_t domainname_len;
+
+ /* If no real MSGID is given return NULL. */
+ if (msgid1 == NULL)
+ return NULL;
+
+#ifdef _LIBC
+ if (category < 0 || category >= __LC_LAST || category == LC_ALL)
+ /* Bogus. */
+ return (plural == 0
+ ? (char *) msgid1
+ /* Use the Germanic plural rule. */
+ : n == 1 ? (char *) msgid1 : (char *) msgid2);
+#endif
+
+ /* Preserve the `errno' value. */
+ saved_errno = errno;
+
+#ifdef _LIBC
+ __libc_rwlock_define (extern, __libc_setlocale_lock attribute_hidden)
+ __libc_rwlock_rdlock (__libc_setlocale_lock);
+#endif
+
+ gl_rwlock_rdlock (_nl_state_lock);
+
+ /* If DOMAINNAME is NULL, we are interested in the default domain. If
+ CATEGORY is not LC_MESSAGES this might not make much sense but the
+ definition left this undefined. */
+ if (domainname == NULL)
+ domainname = _nl_current_default_domain;
+
+ /* OS/2 specific: backward compatibility with older libintl versions */
+#ifdef LC_MESSAGES_COMPAT
+ if (category == LC_MESSAGES_COMPAT)
+ category = LC_MESSAGES;
+#endif
+
+ /* Try to find the translation among those which we found at
+ some time. */
+ search.domain = NULL;
+ search.msgid.ptr = msgid1;
+ search.domainname = domainname;
+ search.category = category;
+#ifdef HAVE_PER_THREAD_LOCALE
+# ifndef IN_LIBGLOCALE
+# ifdef _LIBC
+ localename = _strdupa (_current_locale_name (category));
+# else
+ categoryname = category_to_name (category);
+# define CATEGORYNAME_INITIALIZED
+ localename = _nl_locale_name_thread_unsafe (category, categoryname);
+ if (localename == NULL)
+ localename = "";
+# endif
+# endif
+ search.localename = localename;
+# ifdef IN_LIBGLOCALE
+ search.encoding = encoding;
+# endif
+
+ /* Since tfind/tsearch manage a balanced tree, concurrent tfind and
+ tsearch calls can be fatal. */
+ gl_rwlock_rdlock (tree_lock);
+
+ foundp = (struct known_translation_t **) tfind (&search, &root, transcmp);
+
+ gl_rwlock_unlock (tree_lock);
+
+ if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
+ {
+ /* Now deal with plural. */
+ if (plural)
+ retval = plural_lookup ((*foundp)->domain, n, (*foundp)->translation,
+ (*foundp)->translation_length);
+ else
+ retval = (char *) (*foundp)->translation;
+
+ gl_rwlock_unlock (_nl_state_lock);
+# ifdef _LIBC
+ __libc_rwlock_unlock (__libc_setlocale_lock);
+# endif
+ __set_errno (saved_errno);
+ return retval;
+ }
+#endif
+
+ /* See whether this is a SUID binary or not. */
+ DETERMINE_SECURE;
+
+ /* First find matching binding. */
+#ifdef IN_LIBGLOCALE
+ /* We can use a trivial binding, since _nl_find_msg will ignore it anyway,
+ and _nl_load_domain and _nl_find_domain just pass it through. */
+ binding = NULL;
+ dirname = bindtextdomain (domainname, NULL);
+#else
+ for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
+ {
+ int compare = strcmp (domainname, binding->domainname);
+ if (compare == 0)
+ /* We found it! */
+ break;
+ if (compare < 0)
+ {
+ /* It is not in the list. */
+ binding = NULL;
+ break;
+ }
+ }
+
+ if (binding == NULL)
+ dirname = _nl_default_dirname;
+ else
+ {
+ dirname = binding->dirname;
+#endif
+ if (!IS_ABSOLUTE_PATH (dirname))
+ {
+ /* We have a relative path. Make it absolute now. */
+ size_t dirname_len = strlen (dirname) + 1;
+ size_t path_max;
+ char *resolved_dirname;
+ char *ret;
+
+ path_max = (unsigned int) PATH_MAX;
+ path_max += 2; /* The getcwd docs say to do this. */
+
+ for (;;)
+ {
+ resolved_dirname = (char *) alloca (path_max + dirname_len);
+ ADD_BLOCK (block_list, tmp_dirname);
+
+ __set_errno (0);
+ ret = getcwd (resolved_dirname, path_max);
+ if (ret != NULL || errno != ERANGE)
+ break;
+
+ path_max += path_max / 2;
+ path_max += PATH_INCR;
+ }
+
+ if (ret == NULL)
+ /* We cannot get the current working directory. Don't signal an
+ error but simply return the default string. */
+ goto return_untranslated;
+
+ stpcpy (stpcpy (strchr (resolved_dirname, '\0'), "/"), dirname);
+ dirname = resolved_dirname;
+ }
+#ifndef IN_LIBGLOCALE
+ }
+#endif
+
+ /* Now determine the symbolic name of CATEGORY and its value. */
+#ifndef CATEGORYNAME_INITIALIZED
+ categoryname = category_to_name (category);
+#endif
+#ifdef IN_LIBGLOCALE
+ categoryvalue = guess_category_value (category, categoryname, localename);
+#else
+ categoryvalue = guess_category_value (category, categoryname);
+#endif
+
+ domainname_len = strlen (domainname);
+ xdomainname = (char *) alloca (strlen (categoryname)
+ + domainname_len + 5);
+ ADD_BLOCK (block_list, xdomainname);
+
+ stpcpy ((char *) mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
+ domainname, domainname_len),
+ ".mo");
+
+ /* Creating working area. */
+ single_locale = (char *) alloca (strlen (categoryvalue) + 1);
+ ADD_BLOCK (block_list, single_locale);
+
+
+ /* Search for the given string. This is a loop because we perhaps
+ got an ordered list of languages to consider for the translation. */
+ while (1)
+ {
+ /* Make CATEGORYVALUE point to the next element of the list. */
+ while (categoryvalue[0] != '\0' && categoryvalue[0] == ':')
+ ++categoryvalue;
+ if (categoryvalue[0] == '\0')
+ {
+ /* The whole contents of CATEGORYVALUE has been searched but
+ no valid entry has been found. We solve this situation
+ by implicitly appending a "C" entry, i.e. no translation
+ will take place. */
+ single_locale[0] = 'C';
+ single_locale[1] = '\0';
+ }
+ else
+ {
+ char *cp = single_locale;
+ while (categoryvalue[0] != '\0' && categoryvalue[0] != ':')
+ *cp++ = *categoryvalue++;
+ *cp = '\0';
+
+ /* When this is a SUID binary we must not allow accessing files
+ outside the dedicated directories. */
+ if (ENABLE_SECURE && IS_PATH_WITH_DIR (single_locale))
+ /* Ingore this entry. */
+ continue;
+ }
+
+ /* If the current locale value is C (or POSIX) we don't load a
+ domain. Return the MSGID. */
+ if (strcmp (single_locale, "C") == 0
+ || strcmp (single_locale, "POSIX") == 0)
+ break;
+
+ /* Find structure describing the message catalog matching the
+ DOMAINNAME and CATEGORY. */
+ domain = _nl_find_domain (dirname, single_locale, xdomainname, binding);
+
+ if (domain != NULL)
+ {
+#if defined IN_LIBGLOCALE
+ retval = _nl_find_msg (domain, binding, encoding, msgid1, &retlen);
+#else
+ retval = _nl_find_msg (domain, binding, msgid1, 1, &retlen);
+#endif
+
+ if (retval == NULL)
+ {
+ int cnt;
+
+ for (cnt = 0; domain->successor[cnt] != NULL; ++cnt)
+ {
+#if defined IN_LIBGLOCALE
+ retval = _nl_find_msg (domain->successor[cnt], binding,
+ encoding, msgid1, &retlen);
+#else
+ retval = _nl_find_msg (domain->successor[cnt], binding,
+ msgid1, 1, &retlen);
+#endif
+
+ if (retval != NULL)
+ {
+ domain = domain->successor[cnt];
+ break;
+ }
+ }
+ }
+
+ /* Returning -1 means that some resource problem exists
+ (likely memory) and that the strings could not be
+ converted. Return the original strings. */
+ if (__builtin_expect (retval == (char *) -1, 0))
+ break;
+
+ if (retval != NULL)
+ {
+ /* Found the translation of MSGID1 in domain DOMAIN:
+ starting at RETVAL, RETLEN bytes. */
+ FREE_BLOCKS (block_list);
+ if (foundp == NULL)
+ {
+ /* Create a new entry and add it to the search tree. */
+ size_t msgid_len;
+ size_t size;
+ struct known_translation_t *newp;
+
+ msgid_len = strlen (msgid1) + 1;
+ size = offsetof (struct known_translation_t, msgid)
+ + msgid_len + domainname_len + 1;
+#ifdef HAVE_PER_THREAD_LOCALE
+ size += strlen (localename) + 1;
+#endif
+ newp = (struct known_translation_t *) malloc (size);
+ if (newp != NULL)
+ {
+ char *new_domainname;
+#ifdef HAVE_PER_THREAD_LOCALE
+ char *new_localename;
+#endif
+
+ new_domainname =
+ (char *) mempcpy (newp->msgid.appended, msgid1,
+ msgid_len);
+ memcpy (new_domainname, domainname, domainname_len + 1);
+#ifdef HAVE_PER_THREAD_LOCALE
+ new_localename = new_domainname + domainname_len + 1;
+ strcpy (new_localename, localename);
+#endif
+ newp->domainname = new_domainname;
+ newp->category = category;
+#ifdef HAVE_PER_THREAD_LOCALE
+ newp->localename = new_localename;
+#endif
+#ifdef IN_LIBGLOCALE
+ newp->encoding = encoding;
+#endif
+ newp->counter = _nl_msg_cat_cntr;
+ newp->domain = domain;
+ newp->translation = retval;
+ newp->translation_length = retlen;
+
+ gl_rwlock_wrlock (tree_lock);
+
+ /* Insert the entry in the search tree. */
+ foundp = (struct known_translation_t **)
+ tsearch (newp, &root, transcmp);
+
+ gl_rwlock_unlock (tree_lock);
+
+ if (foundp == NULL
+ || __builtin_expect (*foundp != newp, 0))
+ /* The insert failed. */
+ free (newp);
+ }
+ }
+ else
+ {
+ /* We can update the existing entry. */
+ (*foundp)->counter = _nl_msg_cat_cntr;
+ (*foundp)->domain = domain;
+ (*foundp)->translation = retval;
+ (*foundp)->translation_length = retlen;
+ }
+
+ __set_errno (saved_errno);
+
+ /* Now deal with plural. */
+ if (plural)
+ retval = plural_lookup (domain, n, retval, retlen);
+
+ gl_rwlock_unlock (_nl_state_lock);
+#ifdef _LIBC
+ __libc_rwlock_unlock (__libc_setlocale_lock);
+#endif
+ return retval;
+ }
+ }
+ }
+
+ return_untranslated:
+ /* Return the untranslated MSGID. */
+ FREE_BLOCKS (block_list);
+ gl_rwlock_unlock (_nl_state_lock);
+#ifdef _LIBC
+ __libc_rwlock_unlock (__libc_setlocale_lock);
+#endif
+#ifndef _LIBC
+ if (!ENABLE_SECURE)
+ {
+ extern void _nl_log_untranslated (const char *logfilename,
+ const char *domainname,
+ const char *msgid1, const char *msgid2,
+ int plural);
+ const char *logfilename = getenv ("GETTEXT_LOG_UNTRANSLATED");
+
+ if (logfilename != NULL && logfilename[0] != '\0')
+ _nl_log_untranslated (logfilename, domainname, msgid1, msgid2, plural);
+ }
+#endif
+ __set_errno (saved_errno);
+ return (plural == 0
+ ? (char *) msgid1
+ /* Use the Germanic plural rule. */
+ : n == 1 ? (char *) msgid1 : (char *) msgid2);
+}
+
+
+/* Look up the translation of msgid within DOMAIN_FILE and DOMAINBINDING.
+ Return it if found. Return NULL if not found or in case of a conversion
+ failure (problem in the particular message catalog). Return (char *) -1
+ in case of a memory allocation failure during conversion (only if
+ ENCODING != NULL resp. CONVERT == true). */
+char *
+internal_function
+#ifdef IN_LIBGLOCALE
+_nl_find_msg (struct loaded_l10nfile *domain_file,
+ struct binding *domainbinding, const char *encoding,
+ const char *msgid,
+ size_t *lengthp)
+#else
+_nl_find_msg (struct loaded_l10nfile *domain_file,
+ struct binding *domainbinding,
+ const char *msgid, int convert,
+ size_t *lengthp)
+#endif
+{
+ struct loaded_domain *domain;
+ nls_uint32 nstrings;
+ size_t act;
+ char *result;
+ size_t resultlen;
+
+ if (domain_file->decided <= 0)
+ _nl_load_domain (domain_file, domainbinding);
+
+ if (domain_file->data == NULL)
+ return NULL;
+
+ domain = (struct loaded_domain *) domain_file->data;
+
+ nstrings = domain->nstrings;
+
+ /* Locate the MSGID and its translation. */
+ if (domain->hash_tab != NULL)
+ {
+ /* Use the hashing table. */
+ nls_uint32 len = strlen (msgid);
+ nls_uint32 hash_val = __hash_string (msgid);
+ nls_uint32 idx = hash_val % domain->hash_size;
+ nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
+
+ while (1)
+ {
+ nls_uint32 nstr =
+ W (domain->must_swap_hash_tab, domain->hash_tab[idx]);
+
+ if (nstr == 0)
+ /* Hash table entry is empty. */
+ return NULL;
+
+ nstr--;
+
+ /* Compare msgid with the original string at index nstr.
+ We compare the lengths with >=, not ==, because plural entries
+ are represented by strings with an embedded NUL. */
+ if (nstr < nstrings
+ ? W (domain->must_swap, domain->orig_tab[nstr].length) >= len
+ && (strcmp (msgid,
+ domain->data + W (domain->must_swap,
+ domain->orig_tab[nstr].offset))
+ == 0)
+ : domain->orig_sysdep_tab[nstr - nstrings].length > len
+ && (strcmp (msgid,
+ domain->orig_sysdep_tab[nstr - nstrings].pointer)
+ == 0))
+ {
+ act = nstr;
+ goto found;
+ }
+
+ if (idx >= domain->hash_size - incr)
+ idx -= domain->hash_size - incr;
+ else
+ idx += incr;
+ }
+ /* NOTREACHED */
+ }
+ else
+ {
+ /* Try the default method: binary search in the sorted array of
+ messages. */
+ size_t top, bottom;
+
+ bottom = 0;
+ top = nstrings;
+ while (bottom < top)
+ {
+ int cmp_val;
+
+ act = (bottom + top) / 2;
+ cmp_val = strcmp (msgid, (domain->data
+ + W (domain->must_swap,
+ domain->orig_tab[act].offset)));
+ if (cmp_val < 0)
+ top = act;
+ else if (cmp_val > 0)
+ bottom = act + 1;
+ else
+ goto found;
+ }
+ /* No translation was found. */
+ return NULL;
+ }
+
+ found:
+ /* The translation was found at index ACT. If we have to convert the
+ string to use a different character set, this is the time. */
+ if (act < nstrings)
+ {
+ result = (char *)
+ (domain->data + W (domain->must_swap, domain->trans_tab[act].offset));
+ resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1;
+ }
+ else
+ {
+ result = (char *) domain->trans_sysdep_tab[act - nstrings].pointer;
+ resultlen = domain->trans_sysdep_tab[act - nstrings].length;
+ }
+
+#if defined _LIBC || HAVE_ICONV
+# ifdef IN_LIBGLOCALE
+ if (encoding != NULL)
+# else
+ if (convert)
+# endif
+ {
+ /* We are supposed to do a conversion. */
+# ifndef IN_LIBGLOCALE
+ const char *encoding = get_output_charset (domainbinding);
+# endif
+ size_t nconversions;
+ struct converted_domain *convd;
+ size_t i;
+
+ /* Protect against reallocation of the table. */
+ gl_rwlock_rdlock (domain->conversions_lock);
+
+ /* Search whether a table with converted translations for this
+ encoding has already been allocated. */
+ nconversions = domain->nconversions;
+ convd = NULL;
+
+ for (i = nconversions; i > 0; )
+ {
+ i--;
+ if (strcmp (domain->conversions[i].encoding, encoding) == 0)
+ {
+ convd = &domain->conversions[i];
+ break;
+ }
+ }
+
+ gl_rwlock_unlock (domain->conversions_lock);
+
+ if (convd == NULL)
+ {
+ /* We have to allocate a new conversions table. */
+ gl_rwlock_wrlock (domain->conversions_lock);
+ nconversions = domain->nconversions;
+
+ /* Maybe in the meantime somebody added the translation.
+ Recheck. */
+ for (i = nconversions; i > 0; )
+ {
+ i--;
+ if (strcmp (domain->conversions[i].encoding, encoding) == 0)
+ {
+ convd = &domain->conversions[i];
+ goto found_convd;
+ }
+ }
+
+ {
+ /* Allocate a table for the converted translations for this
+ encoding. */
+ struct converted_domain *new_conversions =
+ (struct converted_domain *)
+ (domain->conversions != NULL
+ ? realloc (domain->conversions,
+ (nconversions + 1) * sizeof (struct converted_domain))
+ : malloc ((nconversions + 1) * sizeof (struct converted_domain)));
+
+ if (__builtin_expect (new_conversions == NULL, 0))
+ {
+ /* Nothing we can do, no more memory. We cannot use the
+ translation because it might be encoded incorrectly. */
+ unlock_fail:
+ gl_rwlock_unlock (domain->conversions_lock);
+ return (char *) -1;
+ }
+
+ domain->conversions = new_conversions;
+
+ /* Copy the 'encoding' string to permanent storage. */
+ encoding = strdup (encoding);
+ if (__builtin_expect (encoding == NULL, 0))
+ /* Nothing we can do, no more memory. We cannot use the
+ translation because it might be encoded incorrectly. */
+ goto unlock_fail;
+
+ convd = &new_conversions[nconversions];
+ convd->encoding = encoding;
+
+ /* Find out about the character set the file is encoded with.
+ This can be found (in textual form) in the entry "". If this
+ entry does not exist or if this does not contain the 'charset='
+ information, we will assume the charset matches the one the
+ current locale and we don't have to perform any conversion. */
+# ifdef _LIBC
+ convd->conv = (__gconv_t) -1;
+# else
+# if HAVE_ICONV
+ convd->conv = (iconv_t) -1;
+# endif
+# endif
+ {
+ char *nullentry;
+ size_t nullentrylen;
+
+ /* Get the header entry. This is a recursion, but it doesn't
+ reallocate domain->conversions because we pass
+ encoding = NULL or convert = 0, respectively. */
+ nullentry =
+# ifdef IN_LIBGLOCALE
+ _nl_find_msg (domain_file, domainbinding, NULL, "",
+ &nullentrylen);
+# else
+ _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
+# endif
+
+ if (nullentry != NULL)
+ {
+ const char *charsetstr;
+
+ charsetstr = strstr (nullentry, "charset=");
+ if (charsetstr != NULL)
+ {
+ size_t len;
+ char *charset;
+ const char *outcharset;
+
+ charsetstr += strlen ("charset=");
+ len = strcspn (charsetstr, " \t\n");
+
+ charset = (char *) alloca (len + 1);
+# if defined _LIBC || HAVE_MEMPCPY
+ *((char *) mempcpy (charset, charsetstr, len)) = '\0';
+# else
+ memcpy (charset, charsetstr, len);
+ charset[len] = '\0';
+# endif
+
+ outcharset = encoding;
+
+# ifdef _LIBC
+ /* We always want to use transliteration. */
+ outcharset = norm_add_slashes (outcharset, "TRANSLIT");
+ charset = norm_add_slashes (charset, "");
+ int r = __gconv_open (outcharset, charset, &convd->conv,
+ GCONV_AVOID_NOCONV);
+ if (__builtin_expect (r != __GCONV_OK, 0))
+ {
+ /* If the output encoding is the same there is
+ nothing to do. Otherwise do not use the
+ translation at all. */
+ if (__builtin_expect (r != __GCONV_NULCONV, 1))
+ {
+ gl_rwlock_unlock (domain->conversions_lock);
+ free ((char *) encoding);
+ return NULL;
+ }
+
+ convd->conv = (__gconv_t) -1;
+ }
+# else
+# if HAVE_ICONV
+ /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
+ we want to use transliteration. */
+# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
+ || _LIBICONV_VERSION >= 0x0105
+ if (strchr (outcharset, '/') == NULL)
+ {
+ char *tmp;
+
+ len = strlen (outcharset);
+ tmp = (char *) alloca (len + 10 + 1);
+ memcpy (tmp, outcharset, len);
+ memcpy (tmp + len, "//TRANSLIT", 10 + 1);
+ outcharset = tmp;
+
+ convd->conv = iconv_open (outcharset, charset);
+
+ freea (outcharset);
+ }
+ else
+# endif
+ convd->conv = iconv_open (outcharset, charset);
+# endif
+# endif
+
+ freea (charset);
+ }
+ }
+ }
+ convd->conv_tab = NULL;
+ /* Here domain->conversions is still == new_conversions. */
+ domain->nconversions++;
+ }
+
+ found_convd:
+ gl_rwlock_unlock (domain->conversions_lock);
+ }
+
+ if (
+# ifdef _LIBC
+ convd->conv != (__gconv_t) -1
+# else
+# if HAVE_ICONV
+ convd->conv != (iconv_t) -1
+# endif
+# endif
+ )
+ {
+ /* We are supposed to do a conversion. First allocate an
+ appropriate table with the same structure as the table
+ of translations in the file, where we can put the pointers
+ to the converted strings in.
+ There is a slight complication with plural entries. They
+ are represented by consecutive NUL terminated strings. We
+ handle this case by converting RESULTLEN bytes, including
+ NULs. */
+
+ /* This lock primarily protects the memory management variables
+ freemem, freemem_size. It also protects write accesses to
+ convd->conv_tab. It's not worth using a separate lock (such
+ as domain->conversions_lock) for this purpose, because when
+ modifying convd->conv_tab, we also need to lock freemem,
+ freemem_size for most of the time. */
+ __libc_lock_define_initialized (static, lock)
+
+ if (__builtin_expect (convd->conv_tab == NULL, 0))
+ {
+ __libc_lock_lock (lock);
+ if (convd->conv_tab == NULL)
+ {
+ convd->conv_tab =
+ (char **) calloc (nstrings + domain->n_sysdep_strings,
+ sizeof (char *));
+ if (convd->conv_tab != NULL)
+ goto not_translated_yet;
+ /* Mark that we didn't succeed allocating a table. */
+ convd->conv_tab = (char **) -1;
+ }
+ __libc_lock_unlock (lock);
+ }
+
+ if (__builtin_expect (convd->conv_tab == (char **) -1, 0))
+ /* Nothing we can do, no more memory. We cannot use the
+ translation because it might be encoded incorrectly. */
+ return (char *) -1;
+
+ if (convd->conv_tab[act] == NULL)
+ {
+ /* We haven't used this string so far, so it is not
+ translated yet. Do this now. */
+ /* We use a bit more efficient memory handling.
+ We allocate always larger blocks which get used over
+ time. This is faster than many small allocations. */
+# define INITIAL_BLOCK_SIZE 4080
+ static unsigned char *freemem;
+ static size_t freemem_size;
+
+ const unsigned char *inbuf;
+ unsigned char *outbuf;
+ int malloc_count;
+# ifndef _LIBC
+ transmem_block_t *transmem_list;
+# endif
+
+ __libc_lock_lock (lock);
+ not_translated_yet:
+
+ inbuf = (const unsigned char *) result;
+ outbuf = freemem + sizeof (size_t);
+# ifndef _LIBC
+ transmem_list = NULL;
+# endif
+
+ malloc_count = 0;
+ while (1)
+ {
+ transmem_block_t *newmem;
+# ifdef _LIBC
+ size_t non_reversible;
+ int res;
+
+ if (freemem_size < sizeof (size_t))
+ goto resize_freemem;
+
+ res = __gconv (convd->conv,
+ &inbuf, inbuf + resultlen,
+ &outbuf,
+ outbuf + freemem_size - sizeof (size_t),
+ &non_reversible);
+
+ if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
+ break;
+
+ if (res != __GCONV_FULL_OUTPUT)
+ {
+ /* We should not use the translation at all, it
+ is incorrectly encoded. */
+ __libc_lock_unlock (lock);
+ return NULL;
+ }
+
+ inbuf = (const unsigned char *) result;
+# else
+# if HAVE_ICONV
+ const char *inptr = (const char *) inbuf;
+ size_t inleft = resultlen;
+ char *outptr = (char *) outbuf;
+ size_t outleft;
+
+ if (freemem_size < sizeof (size_t))
+ goto resize_freemem;
+
+ outleft = freemem_size - sizeof (size_t);
+ if (iconv (convd->conv,
+ (ICONV_CONST char **) &inptr, &inleft,
+ &outptr, &outleft)
+ != (size_t) (-1))
+ {
+ outbuf = (unsigned char *) outptr;
+ break;
+ }
+ if (errno != E2BIG)
+ {
+ __libc_lock_unlock (lock);
+ return NULL;
+ }
+# endif
+# endif
+
+ resize_freemem:
+ /* We must allocate a new buffer or resize the old one. */
+ if (malloc_count > 0)
+ {
+ ++malloc_count;
+ freemem_size = malloc_count * INITIAL_BLOCK_SIZE;
+ newmem = (transmem_block_t *) realloc (transmem_list,
+ freemem_size);
+# ifdef _LIBC
+ if (newmem != NULL)
+ transmem_list = transmem_list->next;
+ else
+ {
+ struct transmem_list *old = transmem_list;
+
+ transmem_list = transmem_list->next;
+ free (old);
+ }
+# endif
+ }
+ else
+ {
+ malloc_count = 1;
+ freemem_size = INITIAL_BLOCK_SIZE;
+ newmem = (transmem_block_t *) malloc (freemem_size);
+ }
+ if (__builtin_expect (newmem == NULL, 0))
+ {
+ freemem = NULL;
+ freemem_size = 0;
+ __libc_lock_unlock (lock);
+ return (char *) -1;
+ }
+
+# ifdef _LIBC
+ /* Add the block to the list of blocks we have to free
+ at some point. */
+ newmem->next = transmem_list;
+ transmem_list = newmem;
+
+ freemem = (unsigned char *) newmem->data;
+ freemem_size -= offsetof (struct transmem_list, data);
+# else
+ transmem_list = newmem;
+ freemem = newmem;
+# endif
+
+ outbuf = freemem + sizeof (size_t);
+ }
+
+ /* We have now in our buffer a converted string. Put this
+ into the table of conversions. */
+ *(size_t *) freemem = outbuf - freemem - sizeof (size_t);
+ convd->conv_tab[act] = (char *) freemem;
+ /* Shrink freemem, but keep it aligned. */
+ freemem_size -= outbuf - freemem;
+ freemem = outbuf;
+ freemem += freemem_size & (alignof (size_t) - 1);
+ freemem_size = freemem_size & ~ (alignof (size_t) - 1);
+
+ __libc_lock_unlock (lock);
+ }
+
+ /* Now convd->conv_tab[act] contains the translation of all
+ the plural variants. */
+ result = convd->conv_tab[act] + sizeof (size_t);
+ resultlen = *(size_t *) convd->conv_tab[act];
+ }
+ }
+
+ /* The result string is converted. */
+
+#endif /* _LIBC || HAVE_ICONV */
+
+ *lengthp = resultlen;
+ return result;
+}
+
+
+/* Look up a plural variant. */
+static char *
+internal_function
+plural_lookup (struct loaded_l10nfile *domain, unsigned long int n,
+ const char *translation, size_t translation_len)
+{
+ struct loaded_domain *domaindata = (struct loaded_domain *) domain->data;
+ unsigned long int index;
+ const char *p;
+
+ index = plural_eval (domaindata->plural, n);
+ if (index >= domaindata->nplurals)
+ /* This should never happen. It means the plural expression and the
+ given maximum value do not match. */
+ index = 0;
+
+ /* Skip INDEX strings at TRANSLATION. */
+ p = translation;
+ while (index-- > 0)
+ {
+#ifdef _LIBC
+ p = __rawmemchr (p, '\0');
+#else
+ p = strchr (p, '\0');
+#endif
+ /* And skip over the NUL byte. */
+ p++;
+
+ if (p >= translation + translation_len)
+ /* This should never happen. It means the plural expression
+ evaluated to a value larger than the number of variants
+ available for MSGID1. */
+ return (char *) translation;
+ }
+ return (char *) p;
+}
+
+#ifndef _LIBC
+/* Return string representation of locale CATEGORY. */
+static const char *
+internal_function
+category_to_name (int category)
+{
+ const char *retval;
+
+ switch (category)
+ {
+#ifdef LC_COLLATE
+ case LC_COLLATE:
+ retval = "LC_COLLATE";
+ break;
+#endif
+#ifdef LC_CTYPE
+ case LC_CTYPE:
+ retval = "LC_CTYPE";
+ break;
+#endif
+#ifdef LC_MONETARY
+ case LC_MONETARY:
+ retval = "LC_MONETARY";
+ break;
+#endif
+#ifdef LC_NUMERIC
+ case LC_NUMERIC:
+ retval = "LC_NUMERIC";
+ break;
+#endif
+#ifdef LC_TIME
+ case LC_TIME:
+ retval = "LC_TIME";
+ break;
+#endif
+#ifdef LC_MESSAGES
+ case LC_MESSAGES:
+ retval = "LC_MESSAGES";
+ break;
+#endif
+#ifdef LC_RESPONSE
+ case LC_RESPONSE:
+ retval = "LC_RESPONSE";
+ break;
+#endif
+#ifdef LC_ALL
+ case LC_ALL:
+ /* This might not make sense but is perhaps better than any other
+ value. */
+ retval = "LC_ALL";
+ break;
+#endif
+ default:
+ /* If you have a better idea for a default value let me know. */
+ retval = "LC_XXX";
+ }
+
+ return retval;
+}
+#endif
+
+/* Guess value of current locale from value of the environment variables
+ or system-dependent defaults. */
+static const char *
+internal_function
+#ifdef IN_LIBGLOCALE
+guess_category_value (int category, const char *categoryname,
+ const char *locale)
+
+#else
+guess_category_value (int category, const char *categoryname)
+#endif
+{
+ const char *language;
+#ifndef IN_LIBGLOCALE
+ const char *locale;
+# ifndef _LIBC
+ const char *language_default;
+ int locale_defaulted;
+# endif
+#endif
+
+ /* We use the settings in the following order:
+ 1. The value of the environment variable 'LANGUAGE'. This is a GNU
+ extension. Its value can be a colon-separated list of locale names.
+ 2. The value of the environment variable 'LC_ALL', 'LC_xxx', or 'LANG'.
+ More precisely, the first among these that is set to a non-empty value.
+ This is how POSIX specifies it. The value is a single locale name.
+ 3. A system-dependent preference list of languages. Its value can be a
+ colon-separated list of locale names.
+ 4. A system-dependent default locale name.
+ This way:
+ - System-dependent settings can be overridden by environment variables.
+ - If the system provides both a list of languages and a default locale,
+ the former is used. */
+
+#ifndef IN_LIBGLOCALE
+ /* Fetch the locale name, through the POSIX method of looking to `LC_ALL',
+ `LC_xxx', and `LANG'. On some systems this can be done by the
+ `setlocale' function itself. */
+# ifdef _LIBC
+ locale = __current_locale_name (category);
+# else
+ locale_defaulted = 0;
+# if HAVE_USELOCALE
+ locale = _nl_locale_name_thread_unsafe (category, categoryname);
+ if (locale == NULL)
+# endif
+ {
+ locale = _nl_locale_name_posix (category, categoryname);
+ if (locale == NULL)
+ {
+ locale = _nl_locale_name_default ();
+ locale_defaulted = 1;
+ }
+ }
+# endif
+#endif
+
+ /* Ignore LANGUAGE and its system-dependent analogon if the locale is set
+ to "C" because
+ 1. "C" locale usually uses the ASCII encoding, and most international
+ messages use non-ASCII characters. These characters get displayed
+ as question marks (if using glibc's iconv()) or as invalid 8-bit
+ characters (because other iconv()s refuse to convert most non-ASCII
+ characters to ASCII). In any case, the output is ugly.
+ 2. The precise output of some programs in the "C" locale is specified
+ by POSIX and should not depend on environment variables like
+ "LANGUAGE" or system-dependent information. We allow such programs
+ to use gettext(). */
+ if (strcmp (locale, "C") == 0)
+ return locale;
+
+ /* The highest priority value is the value of the 'LANGUAGE' environment
+ variable. */
+ language = getenv ("LANGUAGE");
+ if (language != NULL && language[0] != '\0')
+ return language;
+#if !defined IN_LIBGLOCALE && !defined _LIBC
+ /* The next priority value is the locale name, if not defaulted. */
+ if (locale_defaulted)
+ {
+ /* The next priority value is the default language preferences list. */
+ language_default = _nl_language_preferences_default ();
+ if (language_default != NULL)
+ return language_default;
+ }
+ /* The least priority value is the locale name, if defaulted. */
+#endif
+ return locale;
+}
+
+#if (defined _LIBC || HAVE_ICONV) && !defined IN_LIBGLOCALE
+/* Returns the output charset. */
+static const char *
+internal_function
+get_output_charset (struct binding *domainbinding)
+{
+ /* The output charset should normally be determined by the locale. But
+ sometimes the locale is not used or not correctly set up, so we provide
+ a possibility for the user to override this: the OUTPUT_CHARSET
+ environment variable. Moreover, the value specified through
+ bind_textdomain_codeset overrides both. */
+ if (domainbinding != NULL && domainbinding->codeset != NULL)
+ return domainbinding->codeset;
+ else
+ {
+ /* For speed reasons, we look at the value of OUTPUT_CHARSET only
+ once. This is a user variable that is not supposed to change
+ during a program run. */
+ static char *output_charset_cache;
+ static int output_charset_cached;
+
+ if (!output_charset_cached)
+ {
+ const char *value = getenv ("OUTPUT_CHARSET");
+
+ if (value != NULL && value[0] != '\0')
+ {
+ size_t len = strlen (value) + 1;
+ char *value_copy = (char *) malloc (len);
+
+ if (value_copy != NULL)
+ memcpy (value_copy, value, len);
+ output_charset_cache = value_copy;
+ }
+ output_charset_cached = 1;
+ }
+
+ if (output_charset_cache != NULL)
+ return output_charset_cache;
+ else
+ {
+# ifdef _LIBC
+ return _NL_CURRENT (LC_CTYPE, CODESET);
+# else
+# if HAVE_ICONV
+ return locale_charset ();
+# endif
+# endif
+ }
+ }
+}
+#endif
+
+/* @@ begin of epilog @@ */
+
+/* We don't want libintl.a to depend on any other library. So we
+ avoid the non-standard function stpcpy. In GNU C Library this
+ function is available, though. Also allow the symbol HAVE_STPCPY
+ to be defined. */
+#if !_LIBC && !HAVE_STPCPY
+static char *
+stpcpy (char *dest, const char *src)
+{
+ while ((*dest++ = *src++) != '\0')
+ /* Do nothing. */ ;
+ return dest - 1;
+}
+#endif
+
+#if !_LIBC && !HAVE_MEMPCPY
+static void *
+mempcpy (void *dest, const void *src, size_t n)
+{
+ return (void *) ((char *) memcpy (dest, src, n) + n);
+}
+#endif
+
+#if !_LIBC && !HAVE_TSEARCH
+# include "tsearch.c"
+#endif
+
+
+#ifdef _LIBC
+/* If we want to free all resources we have to do some work at
+ program's end. */
+libc_freeres_fn (free_mem)
+{
+ void *old;
+
+ while (_nl_domain_bindings != NULL)
+ {
+ struct binding *oldp = _nl_domain_bindings;
+ _nl_domain_bindings = _nl_domain_bindings->next;
+ if (oldp->dirname != _nl_default_dirname)
+ /* Yes, this is a pointer comparison. */
+ free (oldp->dirname);
+ free (oldp->codeset);
+ free (oldp);
+ }
+
+ if (_nl_current_default_domain != _nl_default_default_domain)
+ /* Yes, again a pointer comparison. */
+ free ((char *) _nl_current_default_domain);
+
+ /* Remove the search tree with the known translations. */
+ __tdestroy (root, free);
+ root = NULL;
+
+ while (transmem_list != NULL)
+ {
+ old = transmem_list;
+ transmem_list = transmem_list->next;
+ free (old);
+ }
+}
+#endif
diff --git a/intl/dcngettext.c b/intl/dcngettext.c
new file mode 100644
index 00000000..eb368336
--- /dev/null
+++ b/intl/dcngettext.c
@@ -0,0 +1,57 @@
+/* Implementation of the dcngettext(3) function.
+ Copyright (C) 1995-1999, 2000-2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "gettextP.h"
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Names for the libintl functions are a problem. They must not clash
+ with existing names and they should follow ANSI C. But this source
+ code is also used in GNU C Library where the names have a __
+ prefix. So we have to make a difference here. */
+#ifdef _LIBC
+# define DCNGETTEXT __dcngettext
+# define DCIGETTEXT __dcigettext
+#else
+# define DCNGETTEXT libintl_dcngettext
+# define DCIGETTEXT libintl_dcigettext
+#endif
+
+/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY
+ locale. */
+char *
+DCNGETTEXT (const char *domainname,
+ const char *msgid1, const char *msgid2, unsigned long int n,
+ int category)
+{
+ return DCIGETTEXT (domainname, msgid1, msgid2, 1, n, category);
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library. */
+weak_alias (__dcngettext, dcngettext);
+#endif
diff --git a/intl/dgettext.c b/intl/dgettext.c
new file mode 100644
index 00000000..9b0d0de6
--- /dev/null
+++ b/intl/dgettext.c
@@ -0,0 +1,58 @@
+/* Implementation of the dgettext(3) function.
+ Copyright (C) 1995-1997, 2000-2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "gettextP.h"
+
+#include <locale.h>
+
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Names for the libintl functions are a problem. They must not clash
+ with existing names and they should follow ANSI C. But this source
+ code is also used in GNU C Library where the names have a __
+ prefix. So we have to make a difference here. */
+#ifdef _LIBC
+# define DGETTEXT __dgettext
+# define DCGETTEXT INTUSE(__dcgettext)
+#else
+# define DGETTEXT libintl_dgettext
+# define DCGETTEXT libintl_dcgettext
+#endif
+
+/* Look up MSGID in the DOMAINNAME message catalog of the current
+ LC_MESSAGES locale. */
+char *
+DGETTEXT (const char *domainname, const char *msgid)
+{
+ return DCGETTEXT (domainname, msgid, LC_MESSAGES);
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library. */
+weak_alias (__dgettext, dgettext);
+#endif
diff --git a/intl/dngettext.c b/intl/dngettext.c
new file mode 100644
index 00000000..3278438f
--- /dev/null
+++ b/intl/dngettext.c
@@ -0,0 +1,59 @@
+/* Implementation of the dngettext(3) function.
+ Copyright (C) 1995-1997, 2000-2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "gettextP.h"
+
+#include <locale.h>
+
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Names for the libintl functions are a problem. They must not clash
+ with existing names and they should follow ANSI C. But this source
+ code is also used in GNU C Library where the names have a __
+ prefix. So we have to make a difference here. */
+#ifdef _LIBC
+# define DNGETTEXT __dngettext
+# define DCNGETTEXT __dcngettext
+#else
+# define DNGETTEXT libintl_dngettext
+# define DCNGETTEXT libintl_dcngettext
+#endif
+
+/* Look up MSGID in the DOMAINNAME message catalog of the current
+ LC_MESSAGES locale and skip message according to the plural form. */
+char *
+DNGETTEXT (const char *domainname,
+ const char *msgid1, const char *msgid2, unsigned long int n)
+{
+ return DCNGETTEXT (domainname, msgid1, msgid2, n, LC_MESSAGES);
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library. */
+weak_alias (__dngettext, dngettext);
+#endif
diff --git a/intl/eval-plural.h b/intl/eval-plural.h
new file mode 100644
index 00000000..21eecb3a
--- /dev/null
+++ b/intl/eval-plural.h
@@ -0,0 +1,108 @@
+/* Plural expression evaluation.
+ Copyright (C) 2000-2003, 2007 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifndef STATIC
+#define STATIC static
+#endif
+
+/* Evaluate the plural expression and return an index value. */
+STATIC
+unsigned long int
+internal_function
+plural_eval (const struct expression *pexp, unsigned long int n)
+{
+ switch (pexp->nargs)
+ {
+ case 0:
+ switch (pexp->operation)
+ {
+ case var:
+ return n;
+ case num:
+ return pexp->val.num;
+ default:
+ break;
+ }
+ /* NOTREACHED */
+ break;
+ case 1:
+ {
+ /* pexp->operation must be lnot. */
+ unsigned long int arg = plural_eval (pexp->val.args[0], n);
+ return ! arg;
+ }
+ case 2:
+ {
+ unsigned long int leftarg = plural_eval (pexp->val.args[0], n);
+ if (pexp->operation == lor)
+ return leftarg || plural_eval (pexp->val.args[1], n);
+ else if (pexp->operation == land)
+ return leftarg && plural_eval (pexp->val.args[1], n);
+ else
+ {
+ unsigned long int rightarg = plural_eval (pexp->val.args[1], n);
+
+ switch (pexp->operation)
+ {
+ case mult:
+ return leftarg * rightarg;
+ case divide:
+#if !INTDIV0_RAISES_SIGFPE
+ if (rightarg == 0)
+ raise (SIGFPE);
+#endif
+ return leftarg / rightarg;
+ case module:
+#if !INTDIV0_RAISES_SIGFPE
+ if (rightarg == 0)
+ raise (SIGFPE);
+#endif
+ return leftarg % rightarg;
+ case plus:
+ return leftarg + rightarg;
+ case minus:
+ return leftarg - rightarg;
+ case less_than:
+ return leftarg < rightarg;
+ case greater_than:
+ return leftarg > rightarg;
+ case less_or_equal:
+ return leftarg <= rightarg;
+ case greater_or_equal:
+ return leftarg >= rightarg;
+ case equal:
+ return leftarg == rightarg;
+ case not_equal:
+ return leftarg != rightarg;
+ default:
+ break;
+ }
+ }
+ /* NOTREACHED */
+ break;
+ }
+ case 3:
+ {
+ /* pexp->operation must be qmop. */
+ unsigned long int boolarg = plural_eval (pexp->val.args[0], n);
+ return plural_eval (pexp->val.args[boolarg ? 1 : 2], n);
+ }
+ }
+ /* NOTREACHED */
+ return 0;
+}
diff --git a/intl/explodename.c b/intl/explodename.c
new file mode 100644
index 00000000..eb5dd755
--- /dev/null
+++ b/intl/explodename.c
@@ -0,0 +1,135 @@
+/* Copyright (C) 1995-1998, 2000-2001, 2003, 2005, 2007 Free Software Foundation, Inc.
+ Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "loadinfo.h"
+
+/* On some strange systems still no definition of NULL is found. Sigh! */
+#ifndef NULL
+# if defined __STDC__ && __STDC__
+# define NULL ((void *) 0)
+# else
+# define NULL 0
+# endif
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Split a locale name NAME into a leading language part and all the
+ rest. Return a pointer to the first character after the language,
+ i.e. to the first byte of the rest. */
+static char *_nl_find_language (const char *name);
+
+static char *
+_nl_find_language (const char *name)
+{
+ while (name[0] != '\0' && name[0] != '_' && name[0] != '@' && name[0] != '.')
+ ++name;
+
+ return (char *) name;
+}
+
+
+int
+_nl_explode_name (char *name,
+ const char **language, const char **modifier,
+ const char **territory, const char **codeset,
+ const char **normalized_codeset)
+{
+ char *cp;
+ int mask;
+
+ *modifier = NULL;
+ *territory = NULL;
+ *codeset = NULL;
+ *normalized_codeset = NULL;
+
+ /* Now we determine the single parts of the locale name. First
+ look for the language. Termination symbols are `_', '.', and `@'. */
+ mask = 0;
+ *language = cp = name;
+ cp = _nl_find_language (*language);
+
+ if (*language == cp)
+ /* This does not make sense: language has to be specified. Use
+ this entry as it is without exploding. Perhaps it is an alias. */
+ cp = strchr (*language, '\0');
+ else
+ {
+ if (cp[0] == '_')
+ {
+ /* Next is the territory. */
+ cp[0] = '\0';
+ *territory = ++cp;
+
+ while (cp[0] != '\0' && cp[0] != '.' && cp[0] != '@')
+ ++cp;
+
+ mask |= XPG_TERRITORY;
+ }
+
+ if (cp[0] == '.')
+ {
+ /* Next is the codeset. */
+ cp[0] = '\0';
+ *codeset = ++cp;
+
+ while (cp[0] != '\0' && cp[0] != '@')
+ ++cp;
+
+ mask |= XPG_CODESET;
+
+ if (*codeset != cp && (*codeset)[0] != '\0')
+ {
+ *normalized_codeset = _nl_normalize_codeset (*codeset,
+ cp - *codeset);
+ if (*normalized_codeset == NULL)
+ return -1;
+ else if (strcmp (*codeset, *normalized_codeset) == 0)
+ free ((char *) *normalized_codeset);
+ else
+ mask |= XPG_NORM_CODESET;
+ }
+ }
+ }
+
+ if (cp[0] == '@')
+ {
+ /* Next is the modifier. */
+ cp[0] = '\0';
+ *modifier = ++cp;
+
+ if (cp[0] != '\0')
+ mask |= XPG_MODIFIER;
+ }
+
+ if (*territory != NULL && (*territory)[0] == '\0')
+ mask &= ~XPG_TERRITORY;
+
+ if (*codeset != NULL && (*codeset)[0] == '\0')
+ mask &= ~XPG_CODESET;
+
+ return mask;
+}
diff --git a/intl/export.h b/intl/export.h
new file mode 100644
index 00000000..b5c47ad5
--- /dev/null
+++ b/intl/export.h
@@ -0,0 +1,6 @@
+
+#if @HAVE_VISIBILITY@ && BUILDING_LIBINTL
+#define LIBINTL_DLL_EXPORTED __attribute__((__visibility__("default")))
+#else
+#define LIBINTL_DLL_EXPORTED
+#endif
diff --git a/intl/finddomain.c b/intl/finddomain.c
new file mode 100644
index 00000000..cab2c999
--- /dev/null
+++ b/intl/finddomain.c
@@ -0,0 +1,212 @@
+/* Handle list of needed message catalogs
+ Copyright (C) 1995-1999, 2000-2001, 2003-2007 Free Software Foundation, Inc.
+ Written by Ulrich Drepper <drepper@gnu.org>, 1995.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined HAVE_UNISTD_H || defined _LIBC
+# include <unistd.h>
+#endif
+
+#include "gettextP.h"
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+/* Handle multi-threaded applications. */
+#ifdef _LIBC
+# include <bits/libc-lock.h>
+# define gl_rwlock_define_initialized __libc_rwlock_define_initialized
+# define gl_rwlock_rdlock __libc_rwlock_rdlock
+# define gl_rwlock_wrlock __libc_rwlock_wrlock
+# define gl_rwlock_unlock __libc_rwlock_unlock
+#else
+# include "lock.h"
+#endif
+
+/* @@ end of prolog @@ */
+/* List of already loaded domains. */
+static struct loaded_l10nfile *_nl_loaded_domains;
+
+
+/* Return a data structure describing the message catalog described by
+ the DOMAINNAME and CATEGORY parameters with respect to the currently
+ established bindings. */
+struct loaded_l10nfile *
+internal_function
+_nl_find_domain (const char *dirname, char *locale,
+ const char *domainname, struct binding *domainbinding)
+{
+ struct loaded_l10nfile *retval;
+ const char *language;
+ const char *modifier;
+ const char *territory;
+ const char *codeset;
+ const char *normalized_codeset;
+ const char *alias_value;
+ int mask;
+
+ /* LOCALE can consist of up to four recognized parts for the XPG syntax:
+
+ language[_territory][.codeset][@modifier]
+
+ Beside the first part all of them are allowed to be missing. If
+ the full specified locale is not found, the less specific one are
+ looked for. The various parts will be stripped off according to
+ the following order:
+ (1) codeset
+ (2) normalized codeset
+ (3) territory
+ (4) modifier
+ */
+
+ /* We need to protect modifying the _NL_LOADED_DOMAINS data. */
+ gl_rwlock_define_initialized (static, lock);
+ gl_rwlock_rdlock (lock);
+
+ /* If we have already tested for this locale entry there has to
+ be one data set in the list of loaded domains. */
+ retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
+ strlen (dirname) + 1, 0, locale, NULL, NULL,
+ NULL, NULL, domainname, 0);
+
+ gl_rwlock_unlock (lock);
+
+ if (retval != NULL)
+ {
+ /* We know something about this locale. */
+ int cnt;
+
+ if (retval->decided <= 0)
+ _nl_load_domain (retval, domainbinding);
+
+ if (retval->data != NULL)
+ return retval;
+
+ for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
+ {
+ if (retval->successor[cnt]->decided <= 0)
+ _nl_load_domain (retval->successor[cnt], domainbinding);
+
+ if (retval->successor[cnt]->data != NULL)
+ break;
+ }
+
+ return retval;
+ /* NOTREACHED */
+ }
+
+ /* See whether the locale value is an alias. If yes its value
+ *overwrites* the alias name. No test for the original value is
+ done. */
+ alias_value = _nl_expand_alias (locale);
+ if (alias_value != NULL)
+ {
+#if defined _LIBC || defined HAVE_STRDUP
+ locale = strdup (alias_value);
+ if (locale == NULL)
+ return NULL;
+#else
+ size_t len = strlen (alias_value) + 1;
+ locale = (char *) malloc (len);
+ if (locale == NULL)
+ return NULL;
+
+ memcpy (locale, alias_value, len);
+#endif
+ }
+
+ /* Now we determine the single parts of the locale name. First
+ look for the language. Termination symbols are `_', '.', and `@'. */
+ mask = _nl_explode_name (locale, &language, &modifier, &territory,
+ &codeset, &normalized_codeset);
+ if (mask == -1)
+ /* This means we are out of core. */
+ return NULL;
+
+ /* We need to protect modifying the _NL_LOADED_DOMAINS data. */
+ gl_rwlock_wrlock (lock);
+
+ /* Create all possible locale entries which might be interested in
+ generalization. */
+ retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
+ strlen (dirname) + 1, mask, language, territory,
+ codeset, normalized_codeset, modifier,
+ domainname, 1);
+
+ gl_rwlock_unlock (lock);
+
+ if (retval == NULL)
+ /* This means we are out of core. */
+ goto out;
+
+ if (retval->decided <= 0)
+ _nl_load_domain (retval, domainbinding);
+ if (retval->data == NULL)
+ {
+ int cnt;
+ for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
+ {
+ if (retval->successor[cnt]->decided <= 0)
+ _nl_load_domain (retval->successor[cnt], domainbinding);
+ if (retval->successor[cnt]->data != NULL)
+ break;
+ }
+ }
+
+ /* The room for an alias was dynamically allocated. Free it now. */
+ if (alias_value != NULL)
+ free (locale);
+
+out:
+ /* The space for normalized_codeset is dynamically allocated. Free it. */
+ if (mask & XPG_NORM_CODESET)
+ free ((void *) normalized_codeset);
+
+ return retval;
+}
+
+
+#ifdef _LIBC
+/* This is called from iconv/gconv_db.c's free_mem, as locales must
+ be freed before freeing gconv steps arrays. */
+void __libc_freeres_fn_section
+_nl_finddomain_subfreeres ()
+{
+ struct loaded_l10nfile *runp = _nl_loaded_domains;
+
+ while (runp != NULL)
+ {
+ struct loaded_l10nfile *here = runp;
+ if (runp->data != NULL)
+ _nl_unload_domain ((struct loaded_domain *) runp->data);
+ runp = runp->next;
+ free ((char *) here->filename);
+ free (here);
+ }
+}
+#endif
diff --git a/intl/gettext.c b/intl/gettext.c
new file mode 100644
index 00000000..d82d439c
--- /dev/null
+++ b/intl/gettext.c
@@ -0,0 +1,63 @@
+/* Implementation of gettext(3) function.
+ Copyright (C) 1995, 1997, 2000-2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef _LIBC
+# define __need_NULL
+# include <stddef.h>
+#else
+# include <stdlib.h> /* Just for NULL. */
+#endif
+
+#include "gettextP.h"
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+/* @@ end of prolog @@ */
+
+/* Names for the libintl functions are a problem. They must not clash
+ with existing names and they should follow ANSI C. But this source
+ code is also used in GNU C Library where the names have a __
+ prefix. So we have to make a difference here. */
+#ifdef _LIBC
+# define GETTEXT __gettext
+# define DCGETTEXT INTUSE(__dcgettext)
+#else
+# define GETTEXT libintl_gettext
+# define DCGETTEXT libintl_dcgettext
+#endif
+
+/* Look up MSGID in the current default message catalog for the current
+ LC_MESSAGES locale. If not found, returns MSGID itself (the default
+ text). */
+char *
+GETTEXT (const char *msgid)
+{
+ return DCGETTEXT (NULL, msgid, LC_MESSAGES);
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library. */
+weak_alias (__gettext, gettext);
+#endif
diff --git a/intl/gettextP.h b/intl/gettextP.h
new file mode 100644
index 00000000..33e68779
--- /dev/null
+++ b/intl/gettextP.h
@@ -0,0 +1,307 @@
+/* Header describing internals of libintl library.
+ Copyright (C) 1995-1999, 2000-2007, 2009 Free Software Foundation, Inc.
+ Written by Ulrich Drepper <drepper@cygnus.com>, 1995.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifndef _GETTEXTP_H
+#define _GETTEXTP_H
+
+#include <stddef.h> /* Get size_t. */
+
+#ifdef _LIBC
+# include "../iconv/gconv_int.h"
+#else
+# if HAVE_ICONV
+# include <iconv.h>
+# endif
+#endif
+
+/* Handle multi-threaded applications. */
+#ifdef _LIBC
+# include <bits/libc-lock.h>
+# define gl_rwlock_define __libc_rwlock_define
+#else
+# include "lock.h"
+#endif
+
+#ifdef _LIBC
+extern char *__gettext (const char *__msgid);
+extern char *__dgettext (const char *__domainname, const char *__msgid);
+extern char *__dcgettext (const char *__domainname, const char *__msgid,
+ int __category);
+extern char *__ngettext (const char *__msgid1, const char *__msgid2,
+ unsigned long int __n);
+extern char *__dngettext (const char *__domainname,
+ const char *__msgid1, const char *__msgid2,
+ unsigned long int n);
+extern char *__dcngettext (const char *__domainname,
+ const char *__msgid1, const char *__msgid2,
+ unsigned long int __n, int __category);
+extern char *__dcigettext (const char *__domainname,
+ const char *__msgid1, const char *__msgid2,
+ int __plural, unsigned long int __n,
+ int __category);
+extern char *__textdomain (const char *__domainname);
+extern char *__bindtextdomain (const char *__domainname,
+ const char *__dirname);
+extern char *__bind_textdomain_codeset (const char *__domainname,
+ const char *__codeset);
+extern void _nl_finddomain_subfreeres (void) attribute_hidden;
+extern void _nl_unload_domain (struct loaded_domain *__domain)
+ internal_function attribute_hidden;
+#else
+/* Declare the exported libintl_* functions, in a way that allows us to
+ call them under their real name. */
+# undef _INTL_REDIRECT_INLINE
+# undef _INTL_REDIRECT_MACROS
+# define _INTL_REDIRECT_MACROS
+# include "libgnuintl.h"
+# ifdef IN_LIBGLOCALE
+extern char *gl_dcigettext (const char *__domainname,
+ const char *__msgid1, const char *__msgid2,
+ int __plural, unsigned long int __n,
+ int __category,
+ const char *__localename, const char *__encoding);
+# else
+extern char *libintl_dcigettext (const char *__domainname,
+ const char *__msgid1, const char *__msgid2,
+ int __plural, unsigned long int __n,
+ int __category);
+# endif
+#endif
+
+#include "loadinfo.h"
+
+#include "gmo.h" /* Get nls_uint32. */
+
+/* @@ end of prolog @@ */
+
+#ifndef internal_function
+# define internal_function
+#endif
+
+#ifndef attribute_hidden
+# define attribute_hidden
+#endif
+
+/* Tell the compiler when a conditional or integer expression is
+ almost always true or almost always false. */
+#ifndef HAVE_BUILTIN_EXPECT
+# define __builtin_expect(expr, val) (expr)
+#endif
+
+#ifndef W
+# define W(flag, data) ((flag) ? SWAP (data) : (data))
+#endif
+
+
+#ifdef _LIBC
+# include <byteswap.h>
+# define SWAP(i) bswap_32 (i)
+#else
+static inline nls_uint32
+# ifdef __cplusplus
+SWAP (nls_uint32 i)
+# else
+SWAP (i)
+ nls_uint32 i;
+# endif
+{
+ return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24);
+}
+#endif
+
+
+/* In-memory representation of system dependent string. */
+struct sysdep_string_desc
+{
+ /* Length of addressed string, including the trailing NUL. */
+ size_t length;
+ /* Pointer to addressed string. */
+ const char *pointer;
+};
+
+/* Cache of translated strings after charset conversion.
+ Note: The strings are converted to the target encoding only on an as-needed
+ basis. */
+struct converted_domain
+{
+ /* The target encoding name. */
+ const char *encoding;
+ /* The descriptor for conversion from the message catalog's encoding to
+ this target encoding. */
+#ifdef _LIBC
+ __gconv_t conv;
+#else
+# if HAVE_ICONV
+ iconv_t conv;
+# endif
+#endif
+ /* The table of translated strings after charset conversion. */
+ char **conv_tab;
+};
+
+/* The representation of an opened message catalog. */
+struct loaded_domain
+{
+ /* Pointer to memory containing the .mo file. */
+ const char *data;
+ /* 1 if the memory is mmap()ed, 0 if the memory is malloc()ed. */
+ int use_mmap;
+ /* Size of mmap()ed memory. */
+ size_t mmap_size;
+ /* 1 if the .mo file uses a different endianness than this machine. */
+ int must_swap;
+ /* Pointer to additional malloc()ed memory. */
+ void *malloced;
+
+ /* Number of static strings pairs. */
+ nls_uint32 nstrings;
+ /* Pointer to descriptors of original strings in the file. */
+ const struct string_desc *orig_tab;
+ /* Pointer to descriptors of translated strings in the file. */
+ const struct string_desc *trans_tab;
+
+ /* Number of system dependent strings pairs. */
+ nls_uint32 n_sysdep_strings;
+ /* Pointer to descriptors of original sysdep strings. */
+ const struct sysdep_string_desc *orig_sysdep_tab;
+ /* Pointer to descriptors of translated sysdep strings. */
+ const struct sysdep_string_desc *trans_sysdep_tab;
+
+ /* Size of hash table. */
+ nls_uint32 hash_size;
+ /* Pointer to hash table. */
+ const nls_uint32 *hash_tab;
+ /* 1 if the hash table uses a different endianness than this machine. */
+ int must_swap_hash_tab;
+
+ /* Cache of charset conversions of the translated strings. */
+ struct converted_domain *conversions;
+ size_t nconversions;
+ gl_rwlock_define (, conversions_lock)
+
+ const struct expression *plural;
+ unsigned long int nplurals;
+};
+
+/* We want to allocate a string at the end of the struct. But ISO C
+ doesn't allow zero sized arrays. */
+#ifdef __GNUC__
+# define ZERO 0
+#else
+# define ZERO 1
+#endif
+
+/* A set of settings bound to a message domain. Used to store settings
+ from bindtextdomain() and bind_textdomain_codeset(). */
+struct binding
+{
+ struct binding *next;
+ char *dirname;
+ char *codeset;
+ char domainname[ZERO];
+};
+
+/* A counter which is incremented each time some previous translations
+ become invalid.
+ This variable is part of the external ABI of the GNU libintl. */
+#ifdef IN_LIBGLOCALE
+# include <glocale/config.h>
+extern LIBGLOCALE_DLL_EXPORTED int _nl_msg_cat_cntr;
+#else
+extern LIBINTL_DLL_EXPORTED int _nl_msg_cat_cntr;
+#endif
+
+#ifndef _LIBC
+extern const char *_nl_language_preferences_default (void);
+# define gl_locale_name_canonicalize _nl_locale_name_canonicalize
+extern void _nl_locale_name_canonicalize (char *name);
+# define gl_locale_name_from_win32_LANGID _nl_locale_name_from_win32_LANGID
+/* extern const char *_nl_locale_name_from_win32_LANGID (LANGID langid); */
+# define gl_locale_name_from_win32_LCID _nl_locale_name_from_win32_LCID
+/* extern const char *_nl_locale_name_from_win32_LCID (LCID lcid); */
+# define gl_locale_name_thread_unsafe _nl_locale_name_thread_unsafe
+extern const char *_nl_locale_name_thread_unsafe (int category,
+ const char *categoryname);
+# define gl_locale_name_posix _nl_locale_name_posix
+extern const char *_nl_locale_name_posix (int category,
+ const char *categoryname);
+# define gl_locale_name_environ _nl_locale_name_environ
+extern const char *_nl_locale_name_environ (int category,
+ const char *categoryname);
+# define gl_locale_name_default _nl_locale_name_default
+extern const char *_nl_locale_name_default (void);
+# define gl_locale_name _nl_locale_name
+extern const char *_nl_locale_name (int category, const char *categoryname);
+#endif
+
+struct loaded_l10nfile *_nl_find_domain (const char *__dirname, char *__locale,
+ const char *__domainname,
+ struct binding *__domainbinding)
+ internal_function;
+void _nl_load_domain (struct loaded_l10nfile *__domain,
+ struct binding *__domainbinding)
+ internal_function;
+
+#ifdef IN_LIBGLOCALE
+char *_nl_find_msg (struct loaded_l10nfile *domain_file,
+ struct binding *domainbinding, const char *encoding,
+ const char *msgid,
+ size_t *lengthp)
+ internal_function;
+#else
+char *_nl_find_msg (struct loaded_l10nfile *domain_file,
+ struct binding *domainbinding, const char *msgid,
+ int convert, size_t *lengthp)
+ internal_function;
+#endif
+
+/* The internal variables in the standalone libintl.a must have different
+ names than the internal variables in GNU libc, otherwise programs
+ using libintl.a cannot be linked statically. */
+#if !defined _LIBC
+# define _nl_default_dirname libintl_nl_default_dirname
+# define _nl_domain_bindings libintl_nl_domain_bindings
+#endif
+
+/* Contains the default location of the message catalogs. */
+extern const char _nl_default_dirname[];
+#ifdef _LIBC
+libc_hidden_proto (_nl_default_dirname)
+#endif
+
+/* List with bindings of specific domains. */
+extern struct binding *_nl_domain_bindings;
+
+/* The internal variables in the standalone libintl.a must have different
+ names than the internal variables in GNU libc, otherwise programs
+ using libintl.a cannot be linked statically. */
+#if !defined _LIBC
+# define _nl_default_default_domain libintl_nl_default_default_domain
+# define _nl_current_default_domain libintl_nl_current_default_domain
+#endif
+
+/* Name of the default text domain. */
+extern const char _nl_default_default_domain[] attribute_hidden;
+
+/* Default text domain in which entries for gettext(3) are to be found. */
+extern const char *_nl_current_default_domain attribute_hidden;
+
+/* @@ begin of epilog @@ */
+
+#endif /* gettextP.h */
diff --git a/intl/gmo.h b/intl/gmo.h
new file mode 100644
index 00000000..da9dbaa9
--- /dev/null
+++ b/intl/gmo.h
@@ -0,0 +1,152 @@
+/* Description of GNU message catalog format: general file layout.
+ Copyright (C) 1995, 1997, 2000-2002, 2004, 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifndef _GETTEXT_H
+#define _GETTEXT_H 1
+
+#include <limits.h>
+
+/* @@ end of prolog @@ */
+
+/* The magic number of the GNU message catalog format. */
+#define _MAGIC 0x950412de
+#define _MAGIC_SWAPPED 0xde120495
+
+/* Revision number of the currently used .mo (binary) file format. */
+#define MO_REVISION_NUMBER 0
+#define MO_REVISION_NUMBER_WITH_SYSDEP_I 1
+
+/* The following contortions are an attempt to use the C preprocessor
+ to determine an unsigned integral type that is 32 bits wide. An
+ alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but
+ as of version autoconf-2.13, the AC_CHECK_SIZEOF macro doesn't work
+ when cross-compiling. */
+
+#if __STDC__
+# define UINT_MAX_32_BITS 4294967295U
+#else
+# define UINT_MAX_32_BITS 0xFFFFFFFF
+#endif
+
+/* If UINT_MAX isn't defined, assume it's a 32-bit type.
+ This should be valid for all systems GNU cares about because
+ that doesn't include 16-bit systems, and only modern systems
+ (that certainly have <limits.h>) have 64+-bit integral types. */
+
+#ifndef UINT_MAX
+# define UINT_MAX UINT_MAX_32_BITS
+#endif
+
+#if UINT_MAX == UINT_MAX_32_BITS
+typedef unsigned nls_uint32;
+#else
+# if USHRT_MAX == UINT_MAX_32_BITS
+typedef unsigned short nls_uint32;
+# else
+# if ULONG_MAX == UINT_MAX_32_BITS
+typedef unsigned long nls_uint32;
+# else
+ /* The following line is intended to throw an error. Using #error is
+ not portable enough. */
+ "Cannot determine unsigned 32-bit data type."
+# endif
+# endif
+#endif
+
+
+/* Header for binary .mo file format. */
+struct mo_file_header
+{
+ /* The magic number. */
+ nls_uint32 magic;
+ /* The revision number of the file format. */
+ nls_uint32 revision;
+
+ /* The following are only used in .mo files with major revision 0 or 1. */
+
+ /* The number of strings pairs. */
+ nls_uint32 nstrings;
+ /* Offset of table with start offsets of original strings. */
+ nls_uint32 orig_tab_offset;
+ /* Offset of table with start offsets of translated strings. */
+ nls_uint32 trans_tab_offset;
+ /* Size of hash table. */
+ nls_uint32 hash_tab_size;
+ /* Offset of first hash table entry. */
+ nls_uint32 hash_tab_offset;
+
+ /* The following are only used in .mo files with minor revision >= 1. */
+
+ /* The number of system dependent segments. */
+ nls_uint32 n_sysdep_segments;
+ /* Offset of table describing system dependent segments. */
+ nls_uint32 sysdep_segments_offset;
+ /* The number of system dependent strings pairs. */
+ nls_uint32 n_sysdep_strings;
+ /* Offset of table with start offsets of original sysdep strings. */
+ nls_uint32 orig_sysdep_tab_offset;
+ /* Offset of table with start offsets of translated sysdep strings. */
+ nls_uint32 trans_sysdep_tab_offset;
+};
+
+/* Descriptor for static string contained in the binary .mo file. */
+struct string_desc
+{
+ /* Length of addressed string, not including the trailing NUL. */
+ nls_uint32 length;
+ /* Offset of string in file. */
+ nls_uint32 offset;
+};
+
+/* The following are only used in .mo files with minor revision >= 1. */
+
+/* Descriptor for system dependent string segment. */
+struct sysdep_segment
+{
+ /* Length of addressed string, including the trailing NUL. */
+ nls_uint32 length;
+ /* Offset of string in file. */
+ nls_uint32 offset;
+};
+
+/* Pair of a static and a system dependent segment, in struct sysdep_string. */
+struct segment_pair
+{
+ /* Size of static segment. */
+ nls_uint32 segsize;
+ /* Reference to system dependent string segment, or ~0 at the end. */
+ nls_uint32 sysdepref;
+};
+
+/* Descriptor for system dependent string. */
+struct sysdep_string
+{
+ /* Offset of static string segments in file. */
+ nls_uint32 offset;
+ /* Alternating sequence of static and system dependent segments.
+ The last segment is a static segment, including the trailing NUL. */
+ struct segment_pair segments[1];
+};
+
+/* Marker for the end of the segments[] array. This has the value 0xFFFFFFFF,
+ regardless whether 'int' is 16 bit, 32 bit, or 64 bit. */
+#define SEGMENTS_END ((nls_uint32) ~0)
+
+/* @@ begin of epilog @@ */
+
+#endif /* gettext.h */
diff --git a/intl/hash-string.c b/intl/hash-string.c
new file mode 100644
index 00000000..3c513f09
--- /dev/null
+++ b/intl/hash-string.c
@@ -0,0 +1,51 @@
+/* Implements a string hashing function.
+ Copyright (C) 1995, 1997, 1998, 2000, 2003 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Specification. */
+#include "hash-string.h"
+
+
+/* Defines the so called `hashpjw' function by P.J. Weinberger
+ [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
+ 1986, 1987 Bell Telephone Laboratories, Inc.] */
+unsigned long int
+__hash_string (const char *str_param)
+{
+ unsigned long int hval, g;
+ const char *str = str_param;
+
+ /* Compute the hash value for the given string. */
+ hval = 0;
+ while (*str != '\0')
+ {
+ hval <<= 4;
+ hval += (unsigned char) *str++;
+ g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4));
+ if (g != 0)
+ {
+ hval ^= g >> (HASHWORDBITS - 8);
+ hval ^= g;
+ }
+ }
+ return hval;
+}
diff --git a/intl/hash-string.h b/intl/hash-string.h
new file mode 100644
index 00000000..98c07e4a
--- /dev/null
+++ b/intl/hash-string.h
@@ -0,0 +1,36 @@
+/* Description of GNU message catalog format: string hashing function.
+ Copyright (C) 1995, 1997-1998, 2000-2003, 2005 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+/* @@ end of prolog @@ */
+
+/* We assume to have `unsigned long int' value with at least 32 bits. */
+#define HASHWORDBITS 32
+
+
+#ifndef _LIBC
+# ifdef IN_LIBINTL
+# define __hash_string libintl_hash_string
+# else
+# define __hash_string hash_string
+# endif
+#endif
+
+/* Defines the so called `hashpjw' function by P.J. Weinberger
+ [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
+ 1986, 1987 Bell Telephone Laboratories, Inc.] */
+extern unsigned long int __hash_string (const char *str_param);
diff --git a/intl/intl-compat.c b/intl/intl-compat.c
new file mode 100644
index 00000000..43d45174
--- /dev/null
+++ b/intl/intl-compat.c
@@ -0,0 +1,133 @@
+/* intl-compat.c - Stub functions to call gettext functions from GNU gettext
+ Library.
+ Copyright (C) 1995, 2000-2003, 2005 Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "gettextP.h"
+
+/* @@ end of prolog @@ */
+
+/* This file redirects the gettext functions (without prefix) to those
+ defined in the included GNU libintl library (with "libintl_" prefix).
+ It is compiled into libintl in order to make the AM_GNU_GETTEXT test
+ of gettext <= 0.11.2 work with the libintl library >= 0.11.3 which
+ has the redirections primarily in the <libintl.h> include file.
+ It is also compiled into libgnuintl so that libgnuintl.so can be used
+ as LD_PRELOADable library on glibc systems, to provide the extra
+ features that the functions in the libc don't have (namely, logging). */
+
+
+#undef gettext
+#undef dgettext
+#undef dcgettext
+#undef ngettext
+#undef dngettext
+#undef dcngettext
+#undef textdomain
+#undef bindtextdomain
+#undef bind_textdomain_codeset
+
+
+/* When building a DLL, we must export some functions. Note that because
+ the functions are only defined for binary backward compatibility, we
+ don't need to use __declspec(dllimport) in any case. */
+#if HAVE_VISIBILITY && BUILDING_DLL
+# define DLL_EXPORTED __attribute__((__visibility__("default")))
+#elif defined _MSC_VER && BUILDING_DLL
+# define DLL_EXPORTED __declspec(dllexport)
+#else
+# define DLL_EXPORTED
+#endif
+
+
+DLL_EXPORTED
+char *
+gettext (const char *msgid)
+{
+ return libintl_gettext (msgid);
+}
+
+
+DLL_EXPORTED
+char *
+dgettext (const char *domainname, const char *msgid)
+{
+ return libintl_dgettext (domainname, msgid);
+}
+
+
+DLL_EXPORTED
+char *
+dcgettext (const char *domainname, const char *msgid, int category)
+{
+ return libintl_dcgettext (domainname, msgid, category);
+}
+
+
+DLL_EXPORTED
+char *
+ngettext (const char *msgid1, const char *msgid2, unsigned long int n)
+{
+ return libintl_ngettext (msgid1, msgid2, n);
+}
+
+
+DLL_EXPORTED
+char *
+dngettext (const char *domainname,
+ const char *msgid1, const char *msgid2, unsigned long int n)
+{
+ return libintl_dngettext (domainname, msgid1, msgid2, n);
+}
+
+
+DLL_EXPORTED
+char *
+dcngettext (const char *domainname,
+ const char *msgid1, const char *msgid2, unsigned long int n,
+ int category)
+{
+ return libintl_dcngettext (domainname, msgid1, msgid2, n, category);
+}
+
+
+DLL_EXPORTED
+char *
+textdomain (const char *domainname)
+{
+ return libintl_textdomain (domainname);
+}
+
+
+DLL_EXPORTED
+char *
+bindtextdomain (const char *domainname, const char *dirname)
+{
+ return libintl_bindtextdomain (domainname, dirname);
+}
+
+
+DLL_EXPORTED
+char *
+bind_textdomain_codeset (const char *domainname, const char *codeset)
+{
+ return libintl_bind_textdomain_codeset (domainname, codeset);
+}
diff --git a/intl/intl-exports.c b/intl/intl-exports.c
new file mode 100644
index 00000000..9e0a13e8
--- /dev/null
+++ b/intl/intl-exports.c
@@ -0,0 +1,36 @@
+/* List of exported symbols of libintl on Cygwin.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2006.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+ /* IMP(x) is a symbol that contains the address of x. */
+#define IMP(x) _imp__##x
+
+ /* Ensure that the variable x is exported from the library, and that a
+ pseudo-variable IMP(x) is available. */
+#define VARIABLE(x) \
+ /* Export x without redefining x. This code was found by compiling a \
+ snippet: \
+ extern __declspec(dllexport) int x; int x = 42; */ \
+ asm (".section .drectve\n"); \
+ asm (".ascii \" -export:" #x ",data\"\n"); \
+ asm (".data\n"); \
+ /* Allocate a pseudo-variable IMP(x). */ \
+ extern int x; \
+ void * IMP(x) = &x;
+
+VARIABLE(libintl_version)
diff --git a/intl/l10nflist.c b/intl/l10nflist.c
new file mode 100644
index 00000000..7252d54e
--- /dev/null
+++ b/intl/l10nflist.c
@@ -0,0 +1,400 @@
+/* Copyright (C) 1995-1999, 2000-2007 Free Software Foundation, Inc.
+ Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+/* Tell glibc's <string.h> to provide a prototype for stpcpy().
+ This must come before <config.h> because <config.h> may include
+ <features.h>, and once <features.h> has been included, it's too late. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#if defined _LIBC || defined HAVE_ARGZ_H
+# include <argz.h>
+#endif
+#include <ctype.h>
+#include <sys/types.h>
+#include <stdlib.h>
+
+#include "loadinfo.h"
+
+/* On some strange systems still no definition of NULL is found. Sigh! */
+#ifndef NULL
+# if defined __STDC__ && __STDC__
+# define NULL ((void *) 0)
+# else
+# define NULL 0
+# endif
+#endif
+
+/* @@ end of prolog @@ */
+
+#ifdef _LIBC
+/* Rename the non ANSI C functions. This is required by the standard
+ because some ANSI C functions will require linking with this object
+ file and the name space must not be polluted. */
+# ifndef stpcpy
+# define stpcpy(dest, src) __stpcpy(dest, src)
+# endif
+#else
+# ifndef HAVE_STPCPY
+static char *stpcpy (char *dest, const char *src);
+# endif
+#endif
+
+/* Pathname support.
+ ISSLASH(C) tests whether C is a directory separator character.
+ IS_ABSOLUTE_PATH(P) tests whether P is an absolute path. If it is not,
+ it may be concatenated to a directory pathname.
+ */
+#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
+ /* Win32, Cygwin, OS/2, DOS */
+# define ISSLASH(C) ((C) == '/' || (C) == '\\')
+# define HAS_DEVICE(P) \
+ ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
+ && (P)[1] == ':')
+# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P))
+#else
+ /* Unix */
+# define ISSLASH(C) ((C) == '/')
+# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0])
+#endif
+
+/* Define function which are usually not available. */
+
+#ifdef _LIBC
+# define __argz_count(argz, len) INTUSE(__argz_count) (argz, len)
+#elif defined HAVE_ARGZ_COUNT
+# undef __argz_count
+# define __argz_count argz_count
+#else
+/* Returns the number of strings in ARGZ. */
+static size_t
+argz_count__ (const char *argz, size_t len)
+{
+ size_t count = 0;
+ while (len > 0)
+ {
+ size_t part_len = strlen (argz);
+ argz += part_len + 1;
+ len -= part_len + 1;
+ count++;
+ }
+ return count;
+}
+# undef __argz_count
+# define __argz_count(argz, len) argz_count__ (argz, len)
+#endif /* !_LIBC && !HAVE_ARGZ_COUNT */
+
+#ifdef _LIBC
+# define __argz_stringify(argz, len, sep) \
+ INTUSE(__argz_stringify) (argz, len, sep)
+#elif defined HAVE_ARGZ_STRINGIFY
+# undef __argz_stringify
+# define __argz_stringify argz_stringify
+#else
+/* Make '\0' separated arg vector ARGZ printable by converting all the '\0's
+ except the last into the character SEP. */
+static void
+argz_stringify__ (char *argz, size_t len, int sep)
+{
+ while (len > 0)
+ {
+ size_t part_len = strlen (argz);
+ argz += part_len;
+ len -= part_len + 1;
+ if (len > 0)
+ *argz++ = sep;
+ }
+}
+# undef __argz_stringify
+# define __argz_stringify(argz, len, sep) argz_stringify__ (argz, len, sep)
+#endif /* !_LIBC && !HAVE_ARGZ_STRINGIFY */
+
+#ifdef _LIBC
+#elif defined HAVE_ARGZ_NEXT
+# undef __argz_next
+# define __argz_next argz_next
+#else
+static char *
+argz_next__ (char *argz, size_t argz_len, const char *entry)
+{
+ if (entry)
+ {
+ if (entry < argz + argz_len)
+ entry = strchr (entry, '\0') + 1;
+
+ return entry >= argz + argz_len ? NULL : (char *) entry;
+ }
+ else
+ if (argz_len > 0)
+ return argz;
+ else
+ return 0;
+}
+# undef __argz_next
+# define __argz_next(argz, len, entry) argz_next__ (argz, len, entry)
+#endif /* !_LIBC && !HAVE_ARGZ_NEXT */
+
+
+/* Return number of bits set in X. */
+static inline int
+pop (int x)
+{
+ /* We assume that no more than 16 bits are used. */
+ x = ((x & ~0x5555) >> 1) + (x & 0x5555);
+ x = ((x & ~0x3333) >> 2) + (x & 0x3333);
+ x = ((x >> 4) + x) & 0x0f0f;
+ x = ((x >> 8) + x) & 0xff;
+
+ return x;
+}
+
+
+struct loaded_l10nfile *
+_nl_make_l10nflist (struct loaded_l10nfile **l10nfile_list,
+ const char *dirlist, size_t dirlist_len,
+ int mask, const char *language, const char *territory,
+ const char *codeset, const char *normalized_codeset,
+ const char *modifier,
+ const char *filename, int do_allocate)
+{
+ char *abs_filename;
+ struct loaded_l10nfile **lastp;
+ struct loaded_l10nfile *retval;
+ char *cp;
+ size_t dirlist_count;
+ size_t entries;
+ int cnt;
+
+ /* If LANGUAGE contains an absolute directory specification, we ignore
+ DIRLIST. */
+ if (IS_ABSOLUTE_PATH (language))
+ dirlist_len = 0;
+
+ /* Allocate room for the full file name. */
+ abs_filename = (char *) malloc (dirlist_len
+ + strlen (language)
+ + ((mask & XPG_TERRITORY) != 0
+ ? strlen (territory) + 1 : 0)
+ + ((mask & XPG_CODESET) != 0
+ ? strlen (codeset) + 1 : 0)
+ + ((mask & XPG_NORM_CODESET) != 0
+ ? strlen (normalized_codeset) + 1 : 0)
+ + ((mask & XPG_MODIFIER) != 0
+ ? strlen (modifier) + 1 : 0)
+ + 1 + strlen (filename) + 1);
+
+ if (abs_filename == NULL)
+ return NULL;
+
+ /* Construct file name. */
+ cp = abs_filename;
+ if (dirlist_len > 0)
+ {
+ memcpy (cp, dirlist, dirlist_len);
+ __argz_stringify (cp, dirlist_len, PATH_SEPARATOR);
+ cp += dirlist_len;
+ cp[-1] = '/';
+ }
+
+ cp = stpcpy (cp, language);
+
+ if ((mask & XPG_TERRITORY) != 0)
+ {
+ *cp++ = '_';
+ cp = stpcpy (cp, territory);
+ }
+ if ((mask & XPG_CODESET) != 0)
+ {
+ *cp++ = '.';
+ cp = stpcpy (cp, codeset);
+ }
+ if ((mask & XPG_NORM_CODESET) != 0)
+ {
+ *cp++ = '.';
+ cp = stpcpy (cp, normalized_codeset);
+ }
+ if ((mask & XPG_MODIFIER) != 0)
+ {
+ *cp++ = '@';
+ cp = stpcpy (cp, modifier);
+ }
+
+ *cp++ = '/';
+ stpcpy (cp, filename);
+
+ /* Look in list of already loaded domains whether it is already
+ available. */
+ lastp = l10nfile_list;
+ for (retval = *l10nfile_list; retval != NULL; retval = retval->next)
+ if (retval->filename != NULL)
+ {
+ int compare = strcmp (retval->filename, abs_filename);
+ if (compare == 0)
+ /* We found it! */
+ break;
+ if (compare < 0)
+ {
+ /* It's not in the list. */
+ retval = NULL;
+ break;
+ }
+
+ lastp = &retval->next;
+ }
+
+ if (retval != NULL || do_allocate == 0)
+ {
+ free (abs_filename);
+ return retval;
+ }
+
+ dirlist_count = (dirlist_len > 0 ? __argz_count (dirlist, dirlist_len) : 1);
+
+ /* Allocate a new loaded_l10nfile. */
+ retval =
+ (struct loaded_l10nfile *)
+ malloc (sizeof (*retval)
+ + (((dirlist_count << pop (mask)) + (dirlist_count > 1 ? 1 : 0))
+ * sizeof (struct loaded_l10nfile *)));
+ if (retval == NULL)
+ {
+ free (abs_filename);
+ return NULL;
+ }
+
+ retval->filename = abs_filename;
+
+ /* We set retval->data to NULL here; it is filled in later.
+ Setting retval->decided to 1 here means that retval does not
+ correspond to a real file (dirlist_count > 1) or is not worth
+ looking up (if an unnormalized codeset was specified). */
+ retval->decided = (dirlist_count > 1
+ || ((mask & XPG_CODESET) != 0
+ && (mask & XPG_NORM_CODESET) != 0));
+ retval->data = NULL;
+
+ retval->next = *lastp;
+ *lastp = retval;
+
+ entries = 0;
+ /* Recurse to fill the inheritance list of RETVAL.
+ If the DIRLIST is a real list (i.e. DIRLIST_COUNT > 1), the RETVAL
+ entry does not correspond to a real file; retval->filename contains
+ colons. In this case we loop across all elements of DIRLIST and
+ across all bit patterns dominated by MASK.
+ If the DIRLIST is a single directory or entirely redundant (i.e.
+ DIRLIST_COUNT == 1), we loop across all bit patterns dominated by
+ MASK, excluding MASK itself.
+ In either case, we loop down from MASK to 0. This has the effect
+ that the extra bits in the locale name are dropped in this order:
+ first the modifier, then the territory, then the codeset, then the
+ normalized_codeset. */
+ for (cnt = dirlist_count > 1 ? mask : mask - 1; cnt >= 0; --cnt)
+ if ((cnt & ~mask) == 0
+ && !((cnt & XPG_CODESET) != 0 && (cnt & XPG_NORM_CODESET) != 0))
+ {
+ if (dirlist_count > 1)
+ {
+ /* Iterate over all elements of the DIRLIST. */
+ char *dir = NULL;
+
+ while ((dir = __argz_next ((char *) dirlist, dirlist_len, dir))
+ != NULL)
+ retval->successor[entries++]
+ = _nl_make_l10nflist (l10nfile_list, dir, strlen (dir) + 1,
+ cnt, language, territory, codeset,
+ normalized_codeset, modifier, filename,
+ 1);
+ }
+ else
+ retval->successor[entries++]
+ = _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len,
+ cnt, language, territory, codeset,
+ normalized_codeset, modifier, filename, 1);
+ }
+ retval->successor[entries] = NULL;
+
+ return retval;
+}
+
+/* Normalize codeset name. There is no standard for the codeset
+ names. Normalization allows the user to use any of the common
+ names. The return value is dynamically allocated and has to be
+ freed by the caller. */
+const char *
+_nl_normalize_codeset (const char *codeset, size_t name_len)
+{
+ size_t len = 0;
+ int only_digit = 1;
+ char *retval;
+ char *wp;
+ size_t cnt;
+
+ for (cnt = 0; cnt < name_len; ++cnt)
+ if (isalnum ((unsigned char) codeset[cnt]))
+ {
+ ++len;
+
+ if (isalpha ((unsigned char) codeset[cnt]))
+ only_digit = 0;
+ }
+
+ retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1);
+
+ if (retval != NULL)
+ {
+ if (only_digit)
+ wp = stpcpy (retval, "iso");
+ else
+ wp = retval;
+
+ for (cnt = 0; cnt < name_len; ++cnt)
+ if (isalpha ((unsigned char) codeset[cnt]))
+ *wp++ = tolower ((unsigned char) codeset[cnt]);
+ else if (isdigit ((unsigned char) codeset[cnt]))
+ *wp++ = codeset[cnt];
+
+ *wp = '\0';
+ }
+
+ return (const char *) retval;
+}
+
+
+/* @@ begin of epilog @@ */
+
+/* We don't want libintl.a to depend on any other library. So we
+ avoid the non-standard function stpcpy. In GNU C Library this
+ function is available, though. Also allow the symbol HAVE_STPCPY
+ to be defined. */
+#if !_LIBC && !HAVE_STPCPY
+static char *
+stpcpy (char *dest, const char *src)
+{
+ while ((*dest++ = *src++) != '\0')
+ /* Do nothing. */ ;
+ return dest - 1;
+}
+#endif
diff --git a/intl/langprefs.c b/intl/langprefs.c
new file mode 100644
index 00000000..de66ad8c
--- /dev/null
+++ b/intl/langprefs.c
@@ -0,0 +1,355 @@
+/* Determine the user's language preferences.
+ Copyright (C) 2004-2007 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+/* Written by Bruno Haible <bruno@clisp.org>.
+ Win32 code originally by Michele Cicciotti <hackbunny@reactos.com>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#if HAVE_CFPREFERENCESCOPYAPPVALUE
+# include <string.h>
+# include <CoreFoundation/CFPreferences.h>
+# include <CoreFoundation/CFPropertyList.h>
+# include <CoreFoundation/CFArray.h>
+# include <CoreFoundation/CFString.h>
+extern void _nl_locale_name_canonicalize (char *name);
+#endif
+
+#if defined _WIN32 || defined __WIN32__
+# define WIN32_NATIVE
+#endif
+
+#ifdef WIN32_NATIVE
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+
+# ifndef MUI_LANGUAGE_NAME
+# define MUI_LANGUAGE_NAME 8
+# endif
+# ifndef STATUS_BUFFER_OVERFLOW
+# define STATUS_BUFFER_OVERFLOW 0x80000005
+# endif
+
+extern void _nl_locale_name_canonicalize (char *name);
+extern const char *_nl_locale_name_from_win32_LANGID (LANGID langid);
+extern const char *_nl_locale_name_from_win32_LCID (LCID lcid);
+
+/* Get the preferences list through the MUI APIs. This works on Windows Vista
+ and newer. */
+static const char *
+_nl_language_preferences_win32_mui (HMODULE kernel32)
+{
+ /* DWORD GetUserPreferredUILanguages (ULONG dwFlags,
+ PULONG pulNumLanguages,
+ PWSTR pwszLanguagesBuffer,
+ PULONG pcchLanguagesBuffer); */
+ typedef DWORD (WINAPI *GetUserPreferredUILanguages_func) (ULONG, PULONG, PWSTR, PULONG);
+ GetUserPreferredUILanguages_func p_GetUserPreferredUILanguages;
+
+ p_GetUserPreferredUILanguages =
+ (GetUserPreferredUILanguages_func)
+ GetProcAddress (kernel32, "GetUserPreferredUILanguages");
+ if (p_GetUserPreferredUILanguages != NULL)
+ {
+ ULONG num_languages;
+ ULONG bufsize;
+ DWORD ret;
+
+ bufsize = 0;
+ ret = p_GetUserPreferredUILanguages (MUI_LANGUAGE_NAME,
+ &num_languages,
+ NULL, &bufsize);
+ if (ret == 0
+ && GetLastError () == STATUS_BUFFER_OVERFLOW
+ && bufsize > 0)
+ {
+ WCHAR *buffer = (WCHAR *) malloc (bufsize * sizeof (WCHAR));
+ if (buffer != NULL)
+ {
+ ret = p_GetUserPreferredUILanguages (MUI_LANGUAGE_NAME,
+ &num_languages,
+ buffer, &bufsize);
+ if (ret)
+ {
+ /* Convert the list from NUL-delimited WCHAR[] Win32 locale
+ names to colon-delimited char[] Unix locale names.
+ We assume that all these locale names are in ASCII,
+ nonempty and contain no colons. */
+ char *languages =
+ (char *) malloc (bufsize + num_languages * 10 + 1);
+ if (languages != NULL)
+ {
+ const WCHAR *p = buffer;
+ char *q = languages;
+ ULONG i;
+ for (i = 0; i < num_languages; i++)
+ {
+ char *q1;
+ char *q2;
+
+ q1 = q;
+ if (i > 0)
+ *q++ = ':';
+ q2 = q;
+ for (; *p != (WCHAR)'\0'; p++)
+ {
+ if ((unsigned char) *p != *p || *p == ':')
+ {
+ /* A non-ASCII character or a colon inside
+ the Win32 locale name! Punt. */
+ q = q1;
+ break;
+ }
+ *q++ = (unsigned char) *p;
+ }
+ if (q == q1)
+ /* An unexpected Win32 locale name occurred. */
+ break;
+ *q = '\0';
+ _nl_locale_name_canonicalize (q2);
+ q = q2 + strlen (q2);
+ p++;
+ }
+ *q = '\0';
+ if (q > languages)
+ {
+ free (buffer);
+ return languages;
+ }
+ free (languages);
+ }
+ }
+ free (buffer);
+ }
+ }
+ }
+ return NULL;
+}
+
+/* Get a preference. This works on Windows ME and newer. */
+static const char *
+_nl_language_preferences_win32_ME (HMODULE kernel32)
+{
+ /* LANGID GetUserDefaultUILanguage (void); */
+ typedef LANGID (WINAPI *GetUserDefaultUILanguage_func) (void);
+ GetUserDefaultUILanguage_func p_GetUserDefaultUILanguage;
+
+ p_GetUserDefaultUILanguage =
+ (GetUserDefaultUILanguage_func)
+ GetProcAddress (kernel32, "GetUserDefaultUILanguage");
+ if (p_GetUserDefaultUILanguage != NULL)
+ return _nl_locale_name_from_win32_LANGID (p_GetUserDefaultUILanguage ());
+ return NULL;
+}
+
+/* Get a preference. This works on Windows 95 and newer. */
+static const char *
+_nl_language_preferences_win32_95 ()
+{
+ HKEY desktop_resource_locale_key;
+
+ if (RegOpenKeyExA (HKEY_CURRENT_USER,
+ "Control Panel\\Desktop\\ResourceLocale",
+ 0, KEY_QUERY_VALUE, &desktop_resource_locale_key)
+ == NO_ERROR)
+ {
+ DWORD type;
+ char data[8 + 1];
+ DWORD data_size = sizeof (data);
+ DWORD ret;
+
+ ret = RegQueryValueExA (desktop_resource_locale_key, NULL, NULL,
+ &type, data, &data_size);
+ RegCloseKey (desktop_resource_locale_key);
+
+ if (ret == NO_ERROR)
+ {
+ /* We expect a string, at most 8 bytes long, that parses as a
+ hexadecimal number. */
+ if (type == REG_SZ
+ && data_size <= sizeof (data)
+ && (data_size < sizeof (data)
+ || data[sizeof (data) - 1] == '\0'))
+ {
+ LCID lcid;
+ char *endp;
+ /* Ensure it's NUL terminated. */
+ if (data_size < sizeof (data))
+ data[data_size] = '\0';
+ /* Parse it as a hexadecimal number. */
+ lcid = strtoul (data, &endp, 16);
+ if (endp > data && *endp == '\0')
+ return _nl_locale_name_from_win32_LCID (lcid);
+ }
+ }
+ }
+ return NULL;
+}
+
+/* Get the system's preference. This can be used as a fallback. */
+static BOOL CALLBACK
+ret_first_language (HMODULE h, LPCSTR type, LPCSTR name, WORD lang, LONG_PTR param)
+{
+ *(const char **)param = _nl_locale_name_from_win32_LANGID (lang);
+ return FALSE;
+}
+static const char *
+_nl_language_preferences_win32_system (HMODULE kernel32)
+{
+ const char *languages = NULL;
+ /* Ignore the warning on mingw here. mingw has a wrong definition of the last
+ parameter type of ENUMRESLANGPROC. */
+ EnumResourceLanguages (kernel32, RT_VERSION, MAKEINTRESOURCE (1),
+ ret_first_language, (LONG_PTR)&languages);
+ return languages;
+}
+
+#endif
+
+/* Determine the user's language preferences, as a colon separated list of
+ locale names in XPG syntax
+ language[_territory][.codeset][@modifier]
+ The result must not be freed; it is statically allocated.
+ The LANGUAGE environment variable does not need to be considered; it is
+ already taken into account by the caller. */
+
+const char *
+_nl_language_preferences_default (void)
+{
+#if HAVE_CFPREFERENCESCOPYAPPVALUE /* MacOS X 10.2 or newer */
+ {
+ /* Cache the preferences list, since CoreFoundation calls are expensive. */
+ static const char *cached_languages;
+ static int cache_initialized;
+
+ if (!cache_initialized)
+ {
+ CFTypeRef preferences =
+ CFPreferencesCopyAppValue (CFSTR ("AppleLanguages"),
+ kCFPreferencesCurrentApplication);
+ if (preferences != NULL
+ && CFGetTypeID (preferences) == CFArrayGetTypeID ())
+ {
+ CFArrayRef prefArray = (CFArrayRef)preferences;
+ int n = CFArrayGetCount (prefArray);
+ char buf[256];
+ size_t size = 0;
+ int i;
+
+ for (i = 0; i < n; i++)
+ {
+ CFTypeRef element = CFArrayGetValueAtIndex (prefArray, i);
+ if (element != NULL
+ && CFGetTypeID (element) == CFStringGetTypeID ()
+ && CFStringGetCString ((CFStringRef)element,
+ buf, sizeof (buf),
+ kCFStringEncodingASCII))
+ {
+ _nl_locale_name_canonicalize (buf);
+ size += strlen (buf) + 1;
+ /* Most GNU programs use msgids in English and don't ship
+ an en.mo message catalog. Therefore when we see "en"
+ in the preferences list, arrange for gettext() to
+ return the msgid, and ignore all further elements of
+ the preferences list. */
+ if (strcmp (buf, "en") == 0)
+ break;
+ }
+ else
+ break;
+ }
+ if (size > 0)
+ {
+ char *languages = (char *) malloc (size);
+
+ if (languages != NULL)
+ {
+ char *p = languages;
+
+ for (i = 0; i < n; i++)
+ {
+ CFTypeRef element =
+ CFArrayGetValueAtIndex (prefArray, i);
+ if (element != NULL
+ && CFGetTypeID (element) == CFStringGetTypeID ()
+ && CFStringGetCString ((CFStringRef)element,
+ buf, sizeof (buf),
+ kCFStringEncodingASCII))
+ {
+ _nl_locale_name_canonicalize (buf);
+ strcpy (p, buf);
+ p += strlen (buf);
+ *p++ = ':';
+ if (strcmp (buf, "en") == 0)
+ break;
+ }
+ else
+ break;
+ }
+ *--p = '\0';
+
+ cached_languages = languages;
+ }
+ }
+ }
+ cache_initialized = 1;
+ }
+ if (cached_languages != NULL)
+ return cached_languages;
+ }
+#endif
+
+#ifdef WIN32_NATIVE
+ {
+ /* Cache the preferences list, since computing it is expensive. */
+ static const char *cached_languages;
+ static int cache_initialized;
+
+ /* Activate the new code only when the GETTEXT_MUI environment variable is
+ set, for the time being, since the new code is not well tested. */
+ if (!cache_initialized && getenv ("GETTEXT_MUI") != NULL)
+ {
+ const char *languages = NULL;
+ HMODULE kernel32 = GetModuleHandle ("kernel32");
+
+ if (kernel32 != NULL)
+ languages = _nl_language_preferences_win32_mui (kernel32);
+
+ if (languages == NULL && kernel32 != NULL)
+ languages = _nl_language_preferences_win32_ME (kernel32);
+
+ if (languages == NULL)
+ languages = _nl_language_preferences_win32_95 ();
+
+ if (languages == NULL && kernel32 != NULL)
+ languages = _nl_language_preferences_win32_system (kernel32);
+
+ cached_languages = languages;
+ cache_initialized = 1;
+ }
+ if (cached_languages != NULL)
+ return cached_languages;
+ }
+#endif
+
+ return NULL;
+}
diff --git a/intl/libgnuintl.h.in b/intl/libgnuintl.h.in
new file mode 100644
index 00000000..c991bf05
--- /dev/null
+++ b/intl/libgnuintl.h.in
@@ -0,0 +1,460 @@
+/* Message catalogs for internationalization.
+ Copyright (C) 1995-1997, 2000-2010 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifndef _LIBINTL_H
+#define _LIBINTL_H 1
+
+#include <locale.h>
+#if (defined __APPLE__ && defined __MACH__) && @HAVE_NEWLOCALE@
+# include <xlocale.h>
+#endif
+
+/* The LC_MESSAGES locale category is the category used by the functions
+ gettext() and dgettext(). It is specified in POSIX, but not in ANSI C.
+ On systems that don't define it, use an arbitrary value instead.
+ On Solaris, <locale.h> defines __LOCALE_H (or _LOCALE_H in Solaris 2.5)
+ then includes <libintl.h> (i.e. this file!) and then only defines
+ LC_MESSAGES. To avoid a redefinition warning, don't define LC_MESSAGES
+ in this case. */
+#if !defined LC_MESSAGES && !(defined __LOCALE_H || (defined _LOCALE_H && defined __sun))
+# define LC_MESSAGES 1729
+#endif
+
+/* We define an additional symbol to signal that we use the GNU
+ implementation of gettext. */
+#define __USE_GNU_GETTEXT 1
+
+/* Provide information about the supported file formats. Returns the
+ maximum minor revision number supported for a given major revision. */
+#define __GNU_GETTEXT_SUPPORTED_REVISION(major) \
+ ((major) == 0 || (major) == 1 ? 1 : -1)
+
+/* Resolve a platform specific conflict on DJGPP. GNU gettext takes
+ precedence over _conio_gettext. */
+#ifdef __DJGPP__
+# undef gettext
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Version number: (major<<16) + (minor<<8) + subminor */
+#define LIBINTL_VERSION 0x001200
+extern int libintl_version;
+
+
+/* We redirect the functions to those prefixed with "libintl_". This is
+ necessary, because some systems define gettext/textdomain/... in the C
+ library (namely, Solaris 2.4 and newer, and GNU libc 2.0 and newer).
+ If we used the unprefixed names, there would be cases where the
+ definition in the C library would override the one in the libintl.so
+ shared library. Recall that on ELF systems, the symbols are looked
+ up in the following order:
+ 1. in the executable,
+ 2. in the shared libraries specified on the link command line, in order,
+ 3. in the dependencies of the shared libraries specified on the link
+ command line,
+ 4. in the dlopen()ed shared libraries, in the order in which they were
+ dlopen()ed.
+ The definition in the C library would override the one in libintl.so if
+ either
+ * -lc is given on the link command line and -lintl isn't, or
+ * -lc is given on the link command line before -lintl, or
+ * libintl.so is a dependency of a dlopen()ed shared library but not
+ linked to the executable at link time.
+ Since Solaris gettext() behaves differently than GNU gettext(), this
+ would be unacceptable.
+
+ The redirection happens by default through macros in C, so that &gettext
+ is independent of the compilation unit, but through inline functions in
+ C++, in order not to interfere with the name mangling of class fields or
+ class methods called 'gettext'. */
+
+/* The user can define _INTL_REDIRECT_INLINE or _INTL_REDIRECT_MACROS.
+ If he doesn't, we choose the method. A third possible method is
+ _INTL_REDIRECT_ASM, supported only by GCC. */
+#if !(defined _INTL_REDIRECT_INLINE || defined _INTL_REDIRECT_MACROS)
+# if defined __GNUC__ && __GNUC__ >= 2 && !(defined __APPLE_CC__ && __APPLE_CC__ > 1) && !defined __MINGW32__ && !(__GNUC__ == 2 && defined _AIX) && (defined __STDC__ || defined __cplusplus)
+# define _INTL_REDIRECT_ASM
+# else
+# ifdef __cplusplus
+# define _INTL_REDIRECT_INLINE
+# else
+# define _INTL_REDIRECT_MACROS
+# endif
+# endif
+#endif
+/* Auxiliary macros. */
+#ifdef _INTL_REDIRECT_ASM
+# define _INTL_ASM(cname) __asm__ (_INTL_ASMNAME (__USER_LABEL_PREFIX__, #cname))
+# define _INTL_ASMNAME(prefix,cnamestring) _INTL_STRINGIFY (prefix) cnamestring
+# define _INTL_STRINGIFY(prefix) #prefix
+#else
+# define _INTL_ASM(cname)
+#endif
+
+/* _INTL_MAY_RETURN_STRING_ARG(n) declares that the given function may return
+ its n-th argument literally. This enables GCC to warn for example about
+ printf (gettext ("foo %y")). */
+#if defined __GNUC__ && __GNUC__ >= 3 && !(defined __APPLE_CC__ && __APPLE_CC__ > 1 && defined __cplusplus)
+# define _INTL_MAY_RETURN_STRING_ARG(n) __attribute__ ((__format_arg__ (n)))
+#else
+# define _INTL_MAY_RETURN_STRING_ARG(n)
+#endif
+
+/* Look up MSGID in the current default message catalog for the current
+ LC_MESSAGES locale. If not found, returns MSGID itself (the default
+ text). */
+#ifdef _INTL_REDIRECT_INLINE
+extern char *libintl_gettext (const char *__msgid)
+ _INTL_MAY_RETURN_STRING_ARG (1);
+static inline char *gettext (const char *__msgid)
+{
+ return libintl_gettext (__msgid);
+}
+#else
+#ifdef _INTL_REDIRECT_MACROS
+# define gettext libintl_gettext
+#endif
+extern char *gettext (const char *__msgid)
+ _INTL_ASM (libintl_gettext)
+ _INTL_MAY_RETURN_STRING_ARG (1);
+#endif
+
+/* Look up MSGID in the DOMAINNAME message catalog for the current
+ LC_MESSAGES locale. */
+#ifdef _INTL_REDIRECT_INLINE
+extern char *libintl_dgettext (const char *__domainname, const char *__msgid)
+ _INTL_MAY_RETURN_STRING_ARG (2);
+static inline char *dgettext (const char *__domainname, const char *__msgid)
+{
+ return libintl_dgettext (__domainname, __msgid);
+}
+#else
+#ifdef _INTL_REDIRECT_MACROS
+# define dgettext libintl_dgettext
+#endif
+extern char *dgettext (const char *__domainname, const char *__msgid)
+ _INTL_ASM (libintl_dgettext)
+ _INTL_MAY_RETURN_STRING_ARG (2);
+#endif
+
+/* Look up MSGID in the DOMAINNAME message catalog for the current CATEGORY
+ locale. */
+#ifdef _INTL_REDIRECT_INLINE
+extern char *libintl_dcgettext (const char *__domainname, const char *__msgid,
+ int __category)
+ _INTL_MAY_RETURN_STRING_ARG (2);
+static inline char *dcgettext (const char *__domainname, const char *__msgid,
+ int __category)
+{
+ return libintl_dcgettext (__domainname, __msgid, __category);
+}
+#else
+#ifdef _INTL_REDIRECT_MACROS
+# define dcgettext libintl_dcgettext
+#endif
+extern char *dcgettext (const char *__domainname, const char *__msgid,
+ int __category)
+ _INTL_ASM (libintl_dcgettext)
+ _INTL_MAY_RETURN_STRING_ARG (2);
+#endif
+
+
+/* Similar to `gettext' but select the plural form corresponding to the
+ number N. */
+#ifdef _INTL_REDIRECT_INLINE
+extern char *libintl_ngettext (const char *__msgid1, const char *__msgid2,
+ unsigned long int __n)
+ _INTL_MAY_RETURN_STRING_ARG (1) _INTL_MAY_RETURN_STRING_ARG (2);
+static inline char *ngettext (const char *__msgid1, const char *__msgid2,
+ unsigned long int __n)
+{
+ return libintl_ngettext (__msgid1, __msgid2, __n);
+}
+#else
+#ifdef _INTL_REDIRECT_MACROS
+# define ngettext libintl_ngettext
+#endif
+extern char *ngettext (const char *__msgid1, const char *__msgid2,
+ unsigned long int __n)
+ _INTL_ASM (libintl_ngettext)
+ _INTL_MAY_RETURN_STRING_ARG (1) _INTL_MAY_RETURN_STRING_ARG (2);
+#endif
+
+/* Similar to `dgettext' but select the plural form corresponding to the
+ number N. */
+#ifdef _INTL_REDIRECT_INLINE
+extern char *libintl_dngettext (const char *__domainname, const char *__msgid1,
+ const char *__msgid2, unsigned long int __n)
+ _INTL_MAY_RETURN_STRING_ARG (2) _INTL_MAY_RETURN_STRING_ARG (3);
+static inline char *dngettext (const char *__domainname, const char *__msgid1,
+ const char *__msgid2, unsigned long int __n)
+{
+ return libintl_dngettext (__domainname, __msgid1, __msgid2, __n);
+}
+#else
+#ifdef _INTL_REDIRECT_MACROS
+# define dngettext libintl_dngettext
+#endif
+extern char *dngettext (const char *__domainname,
+ const char *__msgid1, const char *__msgid2,
+ unsigned long int __n)
+ _INTL_ASM (libintl_dngettext)
+ _INTL_MAY_RETURN_STRING_ARG (2) _INTL_MAY_RETURN_STRING_ARG (3);
+#endif
+
+/* Similar to `dcgettext' but select the plural form corresponding to the
+ number N. */
+#ifdef _INTL_REDIRECT_INLINE
+extern char *libintl_dcngettext (const char *__domainname,
+ const char *__msgid1, const char *__msgid2,
+ unsigned long int __n, int __category)
+ _INTL_MAY_RETURN_STRING_ARG (2) _INTL_MAY_RETURN_STRING_ARG (3);
+static inline char *dcngettext (const char *__domainname,
+ const char *__msgid1, const char *__msgid2,
+ unsigned long int __n, int __category)
+{
+ return libintl_dcngettext (__domainname, __msgid1, __msgid2, __n, __category);
+}
+#else
+#ifdef _INTL_REDIRECT_MACROS
+# define dcngettext libintl_dcngettext
+#endif
+extern char *dcngettext (const char *__domainname,
+ const char *__msgid1, const char *__msgid2,
+ unsigned long int __n, int __category)
+ _INTL_ASM (libintl_dcngettext)
+ _INTL_MAY_RETURN_STRING_ARG (2) _INTL_MAY_RETURN_STRING_ARG (3);
+#endif
+
+
+#ifndef IN_LIBGLOCALE
+
+/* Set the current default message catalog to DOMAINNAME.
+ If DOMAINNAME is null, return the current default.
+ If DOMAINNAME is "", reset to the default of "messages". */
+#ifdef _INTL_REDIRECT_INLINE
+extern char *libintl_textdomain (const char *__domainname);
+static inline char *textdomain (const char *__domainname)
+{
+ return libintl_textdomain (__domainname);
+}
+#else
+#ifdef _INTL_REDIRECT_MACROS
+# define textdomain libintl_textdomain
+#endif
+extern char *textdomain (const char *__domainname)
+ _INTL_ASM (libintl_textdomain);
+#endif
+
+/* Specify that the DOMAINNAME message catalog will be found
+ in DIRNAME rather than in the system locale data base. */
+#ifdef _INTL_REDIRECT_INLINE
+extern char *libintl_bindtextdomain (const char *__domainname,
+ const char *__dirname);
+static inline char *bindtextdomain (const char *__domainname,
+ const char *__dirname)
+{
+ return libintl_bindtextdomain (__domainname, __dirname);
+}
+#else
+#ifdef _INTL_REDIRECT_MACROS
+# define bindtextdomain libintl_bindtextdomain
+#endif
+extern char *bindtextdomain (const char *__domainname, const char *__dirname)
+ _INTL_ASM (libintl_bindtextdomain);
+#endif
+
+/* Specify the character encoding in which the messages from the
+ DOMAINNAME message catalog will be returned. */
+#ifdef _INTL_REDIRECT_INLINE
+extern char *libintl_bind_textdomain_codeset (const char *__domainname,
+ const char *__codeset);
+static inline char *bind_textdomain_codeset (const char *__domainname,
+ const char *__codeset)
+{
+ return libintl_bind_textdomain_codeset (__domainname, __codeset);
+}
+#else
+#ifdef _INTL_REDIRECT_MACROS
+# define bind_textdomain_codeset libintl_bind_textdomain_codeset
+#endif
+extern char *bind_textdomain_codeset (const char *__domainname,
+ const char *__codeset)
+ _INTL_ASM (libintl_bind_textdomain_codeset);
+#endif
+
+#endif /* IN_LIBGLOCALE */
+
+
+/* Support for format strings with positions in *printf(), following the
+ POSIX/XSI specification.
+ Note: These replacements for the *printf() functions are visible only
+ in source files that #include <libintl.h> or #include "gettext.h".
+ Packages that use *printf() in source files that don't refer to _()
+ or gettext() but for which the format string could be the return value
+ of _() or gettext() need to add this #include. Oh well. */
+
+#if !@HAVE_POSIX_PRINTF@
+
+#include <stdio.h>
+#include <stddef.h>
+
+/* Get va_list. */
+#if (defined __STDC__ && __STDC__) || defined __cplusplus || defined _MSC_VER
+# include <stdarg.h>
+#else
+# include <varargs.h>
+#endif
+
+#if !(defined fprintf && defined _GL_STDIO_H) /* don't override gnulib */
+#undef fprintf
+#define fprintf libintl_fprintf
+extern int fprintf (FILE *, const char *, ...);
+#endif
+#if !(defined vfprintf && defined _GL_STDIO_H) /* don't override gnulib */
+#undef vfprintf
+#define vfprintf libintl_vfprintf
+extern int vfprintf (FILE *, const char *, va_list);
+#endif
+
+#if !(defined printf && defined _GL_STDIO_H) /* don't override gnulib */
+#undef printf
+#if defined __NetBSD__ || defined __BEOS__ || defined __CYGWIN__ || defined __MINGW32__
+/* Don't break __attribute__((format(printf,M,N))).
+ This redefinition is only possible because the libc in NetBSD, Cygwin,
+ mingw does not have a function __printf__. */
+# define libintl_printf __printf__
+#endif
+#define printf libintl_printf
+extern int printf (const char *, ...);
+#endif
+#if !(defined vprintf && defined _GL_STDIO_H) /* don't override gnulib */
+#undef vprintf
+#define vprintf libintl_vprintf
+extern int vprintf (const char *, va_list);
+#endif
+
+#if !(defined sprintf && defined _GL_STDIO_H) /* don't override gnulib */
+#undef sprintf
+#define sprintf libintl_sprintf
+extern int sprintf (char *, const char *, ...);
+#endif
+#if !(defined vsprintf && defined _GL_STDIO_H) /* don't override gnulib */
+#undef vsprintf
+#define vsprintf libintl_vsprintf
+extern int vsprintf (char *, const char *, va_list);
+#endif
+
+#if @HAVE_SNPRINTF@
+
+#if !(defined snprintf && defined _GL_STDIO_H) /* don't override gnulib */
+#undef snprintf
+#define snprintf libintl_snprintf
+extern int snprintf (char *, size_t, const char *, ...);
+#endif
+#if !(defined vsnprintf && defined _GL_STDIO_H) /* don't override gnulib */
+#undef vsnprintf
+#define vsnprintf libintl_vsnprintf
+extern int vsnprintf (char *, size_t, const char *, va_list);
+#endif
+
+#endif
+
+#if @HAVE_ASPRINTF@
+
+#if !(defined asprintf && defined _GL_STDIO_H) /* don't override gnulib */
+#undef asprintf
+#define asprintf libintl_asprintf
+extern int asprintf (char **, const char *, ...);
+#endif
+#if !(defined vasprintf && defined _GL_STDIO_H) /* don't override gnulib */
+#undef vasprintf
+#define vasprintf libintl_vasprintf
+extern int vasprintf (char **, const char *, va_list);
+#endif
+
+#endif
+
+#if @HAVE_WPRINTF@
+
+#undef fwprintf
+#define fwprintf libintl_fwprintf
+extern int fwprintf (FILE *, const wchar_t *, ...);
+#undef vfwprintf
+#define vfwprintf libintl_vfwprintf
+extern int vfwprintf (FILE *, const wchar_t *, va_list);
+
+#undef wprintf
+#define wprintf libintl_wprintf
+extern int wprintf (const wchar_t *, ...);
+#undef vwprintf
+#define vwprintf libintl_vwprintf
+extern int vwprintf (const wchar_t *, va_list);
+
+#undef swprintf
+#define swprintf libintl_swprintf
+extern int swprintf (wchar_t *, size_t, const wchar_t *, ...);
+#undef vswprintf
+#define vswprintf libintl_vswprintf
+extern int vswprintf (wchar_t *, size_t, const wchar_t *, va_list);
+
+#endif
+
+#endif
+
+
+/* Support for the locale chosen by the user. */
+#if (defined __APPLE__ && defined __MACH__) || defined _WIN32 || defined __WIN32__ || defined __CYGWIN__
+
+#undef setlocale
+#define setlocale libintl_setlocale
+extern char *setlocale (int, const char *);
+
+#if @HAVE_NEWLOCALE@
+
+#undef newlocale
+#define newlocale libintl_newlocale
+extern locale_t newlocale (int, const char *, locale_t);
+
+#endif
+
+#endif
+
+
+/* Support for relocatable packages. */
+
+/* Sets the original and the current installation prefix of the package.
+ Relocation simply replaces a pathname starting with the original prefix
+ by the corresponding pathname with the current prefix instead. Both
+ prefixes should be directory names without trailing slash (i.e. use ""
+ instead of "/"). */
+#define libintl_set_relocation_prefix libintl_set_relocation_prefix
+extern void
+ libintl_set_relocation_prefix (const char *orig_prefix,
+ const char *curr_prefix);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* libintl.h */
diff --git a/intl/libintl.rc b/intl/libintl.rc
new file mode 100644
index 00000000..b58fffbd
--- /dev/null
+++ b/intl/libintl.rc
@@ -0,0 +1,38 @@
+/* Resources for intl.dll */
+
+#include <winver.h>
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION PACKAGE_VERSION_MAJOR,PACKAGE_VERSION_MINOR,PACKAGE_VERSION_SUBMINOR,0
+ PRODUCTVERSION PACKAGE_VERSION_MAJOR,PACKAGE_VERSION_MINOR,PACKAGE_VERSION_SUBMINOR,0
+ FILEFLAGSMASK 0x3fL /* VS_FFI_FILEFLAGSMASK */
+#ifdef _DEBUG
+ FILEFLAGS 0x1L /* VS_FF_DEBUG */
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x10004L /* VOS_DOS_WINDOWS32 */
+ FILETYPE 0x2L /* VFT_DLL */
+ FILESUBTYPE 0x0L /* VFT2_UNKNOWN */
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "04090000" /* Lang = US English, Charset = ASCII */
+ BEGIN
+ VALUE "Comments", "This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\0"
+ VALUE "CompanyName", "Free Software Foundation\0"
+ VALUE "FileDescription", "LGPLed libintl for Windows NT/2000/XP/Vista/7 and Windows 95/98/ME\0"
+ VALUE "FileVersion", PACKAGE_VERSION_STRING "\0"
+ VALUE "InternalName", "intl.dll\0"
+ VALUE "LegalCopyright", "Copyright (C) 1995-2010\0"
+ VALUE "LegalTrademarks", "\0"
+ VALUE "OriginalFilename", "intl.dll\0"
+ VALUE "ProductName", "libintl: accessing NLS message catalogs\0"
+ VALUE "ProductVersion", PACKAGE_VERSION_STRING "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0409, 0 /* US English, ASCII */
+ END
+END
diff --git a/intl/loadinfo.h b/intl/loadinfo.h
new file mode 100644
index 00000000..a7a19703
--- /dev/null
+++ b/intl/loadinfo.h
@@ -0,0 +1,132 @@
+/* Copyright (C) 1996-1999, 2000-2003, 2005-2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifndef _LOADINFO_H
+#define _LOADINFO_H 1
+
+/* Declarations of locale dependent catalog lookup functions.
+ Implemented in
+
+ localealias.c Possibly replace a locale name by another.
+ explodename.c Split a locale name into its various fields.
+ l10nflist.c Generate a list of filenames of possible message catalogs.
+ finddomain.c Find and open the relevant message catalogs.
+
+ The main function _nl_find_domain() in finddomain.c is declared
+ in gettextP.h.
+ */
+
+#ifndef internal_function
+# define internal_function
+#endif
+
+#ifndef LIBINTL_DLL_EXPORTED
+# define LIBINTL_DLL_EXPORTED
+#endif
+
+/* Tell the compiler when a conditional or integer expression is
+ almost always true or almost always false. */
+#ifndef HAVE_BUILTIN_EXPECT
+# define __builtin_expect(expr, val) (expr)
+#endif
+
+/* Separator in PATH like lists of pathnames. */
+#if ((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) || defined __EMX__ || defined __DJGPP__
+ /* Win32, OS/2, DOS */
+# define PATH_SEPARATOR ';'
+#else
+ /* Unix */
+# define PATH_SEPARATOR ':'
+#endif
+
+/* Encoding of locale name parts. */
+#define XPG_NORM_CODESET 1
+#define XPG_CODESET 2
+#define XPG_TERRITORY 4
+#define XPG_MODIFIER 8
+
+
+struct loaded_l10nfile
+{
+ const char *filename;
+ int decided;
+
+ const void *data;
+
+ struct loaded_l10nfile *next;
+ struct loaded_l10nfile *successor[1];
+};
+
+
+/* Normalize codeset name. There is no standard for the codeset
+ names. Normalization allows the user to use any of the common
+ names. The return value is dynamically allocated and has to be
+ freed by the caller. */
+extern const char *_nl_normalize_codeset (const char *codeset,
+ size_t name_len);
+
+/* Lookup a locale dependent file.
+ *L10NFILE_LIST denotes a pool of lookup results of locale dependent
+ files of the same kind, sorted in decreasing order of ->filename.
+ DIRLIST and DIRLIST_LEN are an argz list of directories in which to
+ look, containing at least one directory (i.e. DIRLIST_LEN > 0).
+ MASK, LANGUAGE, TERRITORY, CODESET, NORMALIZED_CODESET, MODIFIER
+ are the pieces of the locale name, as produced by _nl_explode_name().
+ FILENAME is the filename suffix.
+ The return value is the lookup result, either found in *L10NFILE_LIST,
+ or - if DO_ALLOCATE is nonzero - freshly allocated, or possibly NULL.
+ If the return value is non-NULL, it is added to *L10NFILE_LIST, and
+ its ->next field denotes the chaining inside *L10NFILE_LIST, and
+ furthermore its ->successor[] field contains a list of other lookup
+ results from which this lookup result inherits. */
+extern struct loaded_l10nfile *
+_nl_make_l10nflist (struct loaded_l10nfile **l10nfile_list,
+ const char *dirlist, size_t dirlist_len, int mask,
+ const char *language, const char *territory,
+ const char *codeset, const char *normalized_codeset,
+ const char *modifier,
+ const char *filename, int do_allocate);
+
+/* Lookup the real locale name for a locale alias NAME, or NULL if
+ NAME is not a locale alias (but possibly a real locale name).
+ The return value is statically allocated and must not be freed. */
+/* Part of the libintl ABI only for the sake of the gettext.m4 macro. */
+extern LIBINTL_DLL_EXPORTED const char *_nl_expand_alias (const char *name);
+
+/* Split a locale name NAME into its pieces: language, modifier,
+ territory, codeset.
+ NAME gets destructively modified: NUL bytes are inserted here and
+ there. *LANGUAGE gets assigned NAME. Each of *MODIFIER, *TERRITORY,
+ *CODESET gets assigned either a pointer into the old NAME string, or
+ NULL. *NORMALIZED_CODESET gets assigned the expanded *CODESET, if it
+ is different from *CODESET; this one is dynamically allocated and has
+ to be freed by the caller.
+ The return value is a bitmask, where each bit corresponds to one
+ filled-in value:
+ XPG_MODIFIER for *MODIFIER,
+ XPG_TERRITORY for *TERRITORY,
+ XPG_CODESET for *CODESET,
+ XPG_NORM_CODESET for *NORMALIZED_CODESET.
+ */
+extern int _nl_explode_name (char *name, const char **language,
+ const char **modifier, const char **territory,
+ const char **codeset,
+ const char **normalized_codeset);
+
+#endif /* loadinfo.h */
diff --git a/intl/loadmsgcat.c b/intl/loadmsgcat.c
new file mode 100644
index 00000000..bf883a37
--- /dev/null
+++ b/intl/loadmsgcat.c
@@ -0,0 +1,1333 @@
+/* Load needed message catalogs.
+ Copyright (C) 1995-1999, 2000-2008 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+/* Tell glibc's <string.h> to provide a prototype for mempcpy().
+ This must come before <config.h> because <config.h> may include
+ <features.h>, and once <features.h> has been included, it's too late. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef __GNUC__
+# undef alloca
+# define alloca __builtin_alloca
+# define HAVE_ALLOCA 1
+#else
+# ifdef _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+# else
+# if defined HAVE_ALLOCA_H || defined _LIBC
+# include <alloca.h>
+# else
+# ifdef _AIX
+ #pragma alloca
+# else
+# ifndef alloca
+char *alloca ();
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#if defined HAVE_UNISTD_H || defined _LIBC
+# include <unistd.h>
+#endif
+
+#ifdef _LIBC
+# include <langinfo.h>
+# include <locale.h>
+#endif
+
+#if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
+ || (defined _LIBC && defined _POSIX_MAPPED_FILES)
+# include <sys/mman.h>
+# undef HAVE_MMAP
+# define HAVE_MMAP 1
+#else
+# undef HAVE_MMAP
+#endif
+
+#if defined HAVE_STDINT_H_WITH_UINTMAX || defined _LIBC
+# include <stdint.h>
+#endif
+#if defined HAVE_INTTYPES_H || defined _LIBC
+# include <inttypes.h>
+#endif
+
+#include "gmo.h"
+#include "gettextP.h"
+#include "hash-string.h"
+#include "plural-exp.h"
+
+#ifdef _LIBC
+# include "../locale/localeinfo.h"
+# include <not-cancel.h>
+#endif
+
+/* Handle multi-threaded applications. */
+#ifdef _LIBC
+# include <bits/libc-lock.h>
+#else
+# include "lock.h"
+#endif
+
+/* Provide fallback values for macros that ought to be defined in <inttypes.h>.
+ Note that our fallback values need not be literal strings, because we don't
+ use them with preprocessor string concatenation. */
+#if !defined PRId8 || PRI_MACROS_BROKEN
+# undef PRId8
+# define PRId8 "d"
+#endif
+#if !defined PRIi8 || PRI_MACROS_BROKEN
+# undef PRIi8
+# define PRIi8 "i"
+#endif
+#if !defined PRIo8 || PRI_MACROS_BROKEN
+# undef PRIo8
+# define PRIo8 "o"
+#endif
+#if !defined PRIu8 || PRI_MACROS_BROKEN
+# undef PRIu8
+# define PRIu8 "u"
+#endif
+#if !defined PRIx8 || PRI_MACROS_BROKEN
+# undef PRIx8
+# define PRIx8 "x"
+#endif
+#if !defined PRIX8 || PRI_MACROS_BROKEN
+# undef PRIX8
+# define PRIX8 "X"
+#endif
+#if !defined PRId16 || PRI_MACROS_BROKEN
+# undef PRId16
+# define PRId16 "d"
+#endif
+#if !defined PRIi16 || PRI_MACROS_BROKEN
+# undef PRIi16
+# define PRIi16 "i"
+#endif
+#if !defined PRIo16 || PRI_MACROS_BROKEN
+# undef PRIo16
+# define PRIo16 "o"
+#endif
+#if !defined PRIu16 || PRI_MACROS_BROKEN
+# undef PRIu16
+# define PRIu16 "u"
+#endif
+#if !defined PRIx16 || PRI_MACROS_BROKEN
+# undef PRIx16
+# define PRIx16 "x"
+#endif
+#if !defined PRIX16 || PRI_MACROS_BROKEN
+# undef PRIX16
+# define PRIX16 "X"
+#endif
+#if !defined PRId32 || PRI_MACROS_BROKEN
+# undef PRId32
+# define PRId32 "d"
+#endif
+#if !defined PRIi32 || PRI_MACROS_BROKEN
+# undef PRIi32
+# define PRIi32 "i"
+#endif
+#if !defined PRIo32 || PRI_MACROS_BROKEN
+# undef PRIo32
+# define PRIo32 "o"
+#endif
+#if !defined PRIu32 || PRI_MACROS_BROKEN
+# undef PRIu32
+# define PRIu32 "u"
+#endif
+#if !defined PRIx32 || PRI_MACROS_BROKEN
+# undef PRIx32
+# define PRIx32 "x"
+#endif
+#if !defined PRIX32 || PRI_MACROS_BROKEN
+# undef PRIX32
+# define PRIX32 "X"
+#endif
+#if !defined PRId64 || PRI_MACROS_BROKEN
+# undef PRId64
+# define PRId64 (sizeof (long) == 8 ? "ld" : "lld")
+#endif
+#if !defined PRIi64 || PRI_MACROS_BROKEN
+# undef PRIi64
+# define PRIi64 (sizeof (long) == 8 ? "li" : "lli")
+#endif
+#if !defined PRIo64 || PRI_MACROS_BROKEN
+# undef PRIo64
+# define PRIo64 (sizeof (long) == 8 ? "lo" : "llo")
+#endif
+#if !defined PRIu64 || PRI_MACROS_BROKEN
+# undef PRIu64
+# define PRIu64 (sizeof (long) == 8 ? "lu" : "llu")
+#endif
+#if !defined PRIx64 || PRI_MACROS_BROKEN
+# undef PRIx64
+# define PRIx64 (sizeof (long) == 8 ? "lx" : "llx")
+#endif
+#if !defined PRIX64 || PRI_MACROS_BROKEN
+# undef PRIX64
+# define PRIX64 (sizeof (long) == 8 ? "lX" : "llX")
+#endif
+#if !defined PRIdLEAST8 || PRI_MACROS_BROKEN
+# undef PRIdLEAST8
+# define PRIdLEAST8 "d"
+#endif
+#if !defined PRIiLEAST8 || PRI_MACROS_BROKEN
+# undef PRIiLEAST8
+# define PRIiLEAST8 "i"
+#endif
+#if !defined PRIoLEAST8 || PRI_MACROS_BROKEN
+# undef PRIoLEAST8
+# define PRIoLEAST8 "o"
+#endif
+#if !defined PRIuLEAST8 || PRI_MACROS_BROKEN
+# undef PRIuLEAST8
+# define PRIuLEAST8 "u"
+#endif
+#if !defined PRIxLEAST8 || PRI_MACROS_BROKEN
+# undef PRIxLEAST8
+# define PRIxLEAST8 "x"
+#endif
+#if !defined PRIXLEAST8 || PRI_MACROS_BROKEN
+# undef PRIXLEAST8
+# define PRIXLEAST8 "X"
+#endif
+#if !defined PRIdLEAST16 || PRI_MACROS_BROKEN
+# undef PRIdLEAST16
+# define PRIdLEAST16 "d"
+#endif
+#if !defined PRIiLEAST16 || PRI_MACROS_BROKEN
+# undef PRIiLEAST16
+# define PRIiLEAST16 "i"
+#endif
+#if !defined PRIoLEAST16 || PRI_MACROS_BROKEN
+# undef PRIoLEAST16
+# define PRIoLEAST16 "o"
+#endif
+#if !defined PRIuLEAST16 || PRI_MACROS_BROKEN
+# undef PRIuLEAST16
+# define PRIuLEAST16 "u"
+#endif
+#if !defined PRIxLEAST16 || PRI_MACROS_BROKEN
+# undef PRIxLEAST16
+# define PRIxLEAST16 "x"
+#endif
+#if !defined PRIXLEAST16 || PRI_MACROS_BROKEN
+# undef PRIXLEAST16
+# define PRIXLEAST16 "X"
+#endif
+#if !defined PRIdLEAST32 || PRI_MACROS_BROKEN
+# undef PRIdLEAST32
+# define PRIdLEAST32 "d"
+#endif
+#if !defined PRIiLEAST32 || PRI_MACROS_BROKEN
+# undef PRIiLEAST32
+# define PRIiLEAST32 "i"
+#endif
+#if !defined PRIoLEAST32 || PRI_MACROS_BROKEN
+# undef PRIoLEAST32
+# define PRIoLEAST32 "o"
+#endif
+#if !defined PRIuLEAST32 || PRI_MACROS_BROKEN
+# undef PRIuLEAST32
+# define PRIuLEAST32 "u"
+#endif
+#if !defined PRIxLEAST32 || PRI_MACROS_BROKEN
+# undef PRIxLEAST32
+# define PRIxLEAST32 "x"
+#endif
+#if !defined PRIXLEAST32 || PRI_MACROS_BROKEN
+# undef PRIXLEAST32
+# define PRIXLEAST32 "X"
+#endif
+#if !defined PRIdLEAST64 || PRI_MACROS_BROKEN
+# undef PRIdLEAST64
+# define PRIdLEAST64 PRId64
+#endif
+#if !defined PRIiLEAST64 || PRI_MACROS_BROKEN
+# undef PRIiLEAST64
+# define PRIiLEAST64 PRIi64
+#endif
+#if !defined PRIoLEAST64 || PRI_MACROS_BROKEN
+# undef PRIoLEAST64
+# define PRIoLEAST64 PRIo64
+#endif
+#if !defined PRIuLEAST64 || PRI_MACROS_BROKEN
+# undef PRIuLEAST64
+# define PRIuLEAST64 PRIu64
+#endif
+#if !defined PRIxLEAST64 || PRI_MACROS_BROKEN
+# undef PRIxLEAST64
+# define PRIxLEAST64 PRIx64
+#endif
+#if !defined PRIXLEAST64 || PRI_MACROS_BROKEN
+# undef PRIXLEAST64
+# define PRIXLEAST64 PRIX64
+#endif
+#if !defined PRIdFAST8 || PRI_MACROS_BROKEN
+# undef PRIdFAST8
+# define PRIdFAST8 "d"
+#endif
+#if !defined PRIiFAST8 || PRI_MACROS_BROKEN
+# undef PRIiFAST8
+# define PRIiFAST8 "i"
+#endif
+#if !defined PRIoFAST8 || PRI_MACROS_BROKEN
+# undef PRIoFAST8
+# define PRIoFAST8 "o"
+#endif
+#if !defined PRIuFAST8 || PRI_MACROS_BROKEN
+# undef PRIuFAST8
+# define PRIuFAST8 "u"
+#endif
+#if !defined PRIxFAST8 || PRI_MACROS_BROKEN
+# undef PRIxFAST8
+# define PRIxFAST8 "x"
+#endif
+#if !defined PRIXFAST8 || PRI_MACROS_BROKEN
+# undef PRIXFAST8
+# define PRIXFAST8 "X"
+#endif
+#if !defined PRIdFAST16 || PRI_MACROS_BROKEN
+# undef PRIdFAST16
+# define PRIdFAST16 "d"
+#endif
+#if !defined PRIiFAST16 || PRI_MACROS_BROKEN
+# undef PRIiFAST16
+# define PRIiFAST16 "i"
+#endif
+#if !defined PRIoFAST16 || PRI_MACROS_BROKEN
+# undef PRIoFAST16
+# define PRIoFAST16 "o"
+#endif
+#if !defined PRIuFAST16 || PRI_MACROS_BROKEN
+# undef PRIuFAST16
+# define PRIuFAST16 "u"
+#endif
+#if !defined PRIxFAST16 || PRI_MACROS_BROKEN
+# undef PRIxFAST16
+# define PRIxFAST16 "x"
+#endif
+#if !defined PRIXFAST16 || PRI_MACROS_BROKEN
+# undef PRIXFAST16
+# define PRIXFAST16 "X"
+#endif
+#if !defined PRIdFAST32 || PRI_MACROS_BROKEN
+# undef PRIdFAST32
+# define PRIdFAST32 "d"
+#endif
+#if !defined PRIiFAST32 || PRI_MACROS_BROKEN
+# undef PRIiFAST32
+# define PRIiFAST32 "i"
+#endif
+#if !defined PRIoFAST32 || PRI_MACROS_BROKEN
+# undef PRIoFAST32
+# define PRIoFAST32 "o"
+#endif
+#if !defined PRIuFAST32 || PRI_MACROS_BROKEN
+# undef PRIuFAST32
+# define PRIuFAST32 "u"
+#endif
+#if !defined PRIxFAST32 || PRI_MACROS_BROKEN
+# undef PRIxFAST32
+# define PRIxFAST32 "x"
+#endif
+#if !defined PRIXFAST32 || PRI_MACROS_BROKEN
+# undef PRIXFAST32
+# define PRIXFAST32 "X"
+#endif
+#if !defined PRIdFAST64 || PRI_MACROS_BROKEN
+# undef PRIdFAST64
+# define PRIdFAST64 PRId64
+#endif
+#if !defined PRIiFAST64 || PRI_MACROS_BROKEN
+# undef PRIiFAST64
+# define PRIiFAST64 PRIi64
+#endif
+#if !defined PRIoFAST64 || PRI_MACROS_BROKEN
+# undef PRIoFAST64
+# define PRIoFAST64 PRIo64
+#endif
+#if !defined PRIuFAST64 || PRI_MACROS_BROKEN
+# undef PRIuFAST64
+# define PRIuFAST64 PRIu64
+#endif
+#if !defined PRIxFAST64 || PRI_MACROS_BROKEN
+# undef PRIxFAST64
+# define PRIxFAST64 PRIx64
+#endif
+#if !defined PRIXFAST64 || PRI_MACROS_BROKEN
+# undef PRIXFAST64
+# define PRIXFAST64 PRIX64
+#endif
+#if !defined PRIdMAX || PRI_MACROS_BROKEN
+# undef PRIdMAX
+# define PRIdMAX (sizeof (uintmax_t) == sizeof (long) ? "ld" : "lld")
+#endif
+#if !defined PRIiMAX || PRI_MACROS_BROKEN
+# undef PRIiMAX
+# define PRIiMAX (sizeof (uintmax_t) == sizeof (long) ? "li" : "lli")
+#endif
+#if !defined PRIoMAX || PRI_MACROS_BROKEN
+# undef PRIoMAX
+# define PRIoMAX (sizeof (uintmax_t) == sizeof (long) ? "lo" : "llo")
+#endif
+#if !defined PRIuMAX || PRI_MACROS_BROKEN
+# undef PRIuMAX
+# define PRIuMAX (sizeof (uintmax_t) == sizeof (long) ? "lu" : "llu")
+#endif
+#if !defined PRIxMAX || PRI_MACROS_BROKEN
+# undef PRIxMAX
+# define PRIxMAX (sizeof (uintmax_t) == sizeof (long) ? "lx" : "llx")
+#endif
+#if !defined PRIXMAX || PRI_MACROS_BROKEN
+# undef PRIXMAX
+# define PRIXMAX (sizeof (uintmax_t) == sizeof (long) ? "lX" : "llX")
+#endif
+#if !defined PRIdPTR || PRI_MACROS_BROKEN
+# undef PRIdPTR
+# define PRIdPTR \
+ (sizeof (void *) == sizeof (long) ? "ld" : \
+ sizeof (void *) == sizeof (int) ? "d" : \
+ "lld")
+#endif
+#if !defined PRIiPTR || PRI_MACROS_BROKEN
+# undef PRIiPTR
+# define PRIiPTR \
+ (sizeof (void *) == sizeof (long) ? "li" : \
+ sizeof (void *) == sizeof (int) ? "i" : \
+ "lli")
+#endif
+#if !defined PRIoPTR || PRI_MACROS_BROKEN
+# undef PRIoPTR
+# define PRIoPTR \
+ (sizeof (void *) == sizeof (long) ? "lo" : \
+ sizeof (void *) == sizeof (int) ? "o" : \
+ "llo")
+#endif
+#if !defined PRIuPTR || PRI_MACROS_BROKEN
+# undef PRIuPTR
+# define PRIuPTR \
+ (sizeof (void *) == sizeof (long) ? "lu" : \
+ sizeof (void *) == sizeof (int) ? "u" : \
+ "llu")
+#endif
+#if !defined PRIxPTR || PRI_MACROS_BROKEN
+# undef PRIxPTR
+# define PRIxPTR \
+ (sizeof (void *) == sizeof (long) ? "lx" : \
+ sizeof (void *) == sizeof (int) ? "x" : \
+ "llx")
+#endif
+#if !defined PRIXPTR || PRI_MACROS_BROKEN
+# undef PRIXPTR
+# define PRIXPTR \
+ (sizeof (void *) == sizeof (long) ? "lX" : \
+ sizeof (void *) == sizeof (int) ? "X" : \
+ "llX")
+#endif
+
+/* @@ end of prolog @@ */
+
+#ifdef _LIBC
+/* Rename the non ISO C functions. This is required by the standard
+ because some ISO C functions will require linking with this object
+ file and the name space must not be polluted. */
+# define open(name, flags) open_not_cancel_2 (name, flags)
+# define close(fd) close_not_cancel_no_status (fd)
+# define read(fd, buf, n) read_not_cancel (fd, buf, n)
+# define mmap(addr, len, prot, flags, fd, offset) \
+ __mmap (addr, len, prot, flags, fd, offset)
+# define munmap(addr, len) __munmap (addr, len)
+#endif
+
+/* For those losing systems which don't have `alloca' we have to add
+ some additional code emulating it. */
+#ifdef HAVE_ALLOCA
+# define freea(p) /* nothing */
+#else
+# define alloca(n) malloc (n)
+# define freea(p) free (p)
+#endif
+
+/* For systems that distinguish between text and binary I/O.
+ O_BINARY is usually declared in <fcntl.h>. */
+#if !defined O_BINARY && defined _O_BINARY
+ /* For MSC-compatible compilers. */
+# define O_BINARY _O_BINARY
+# define O_TEXT _O_TEXT
+#endif
+#ifdef __BEOS__
+ /* BeOS 5 has O_BINARY and O_TEXT, but they have no effect. */
+# undef O_BINARY
+# undef O_TEXT
+#endif
+/* On reasonable systems, binary I/O is the default. */
+#ifndef O_BINARY
+# define O_BINARY 0
+#endif
+
+
+/* We need a sign, whether a new catalog was loaded, which can be associated
+ with all translations. This is important if the translations are
+ cached by one of GCC's features. */
+int _nl_msg_cat_cntr;
+
+
+/* Expand a system dependent string segment. Return NULL if unsupported. */
+static const char *
+get_sysdep_segment_value (const char *name)
+{
+ /* Test for an ISO C 99 section 7.8.1 format string directive.
+ Syntax:
+ P R I { d | i | o | u | x | X }
+ { { | LEAST | FAST } { 8 | 16 | 32 | 64 } | MAX | PTR } */
+ /* We don't use a table of 14 times 6 'const char *' strings here, because
+ data relocations cost startup time. */
+ if (name[0] == 'P' && name[1] == 'R' && name[2] == 'I')
+ {
+ if (name[3] == 'd' || name[3] == 'i' || name[3] == 'o' || name[3] == 'u'
+ || name[3] == 'x' || name[3] == 'X')
+ {
+ if (name[4] == '8' && name[5] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRId8;
+ if (name[3] == 'i')
+ return PRIi8;
+ if (name[3] == 'o')
+ return PRIo8;
+ if (name[3] == 'u')
+ return PRIu8;
+ if (name[3] == 'x')
+ return PRIx8;
+ if (name[3] == 'X')
+ return PRIX8;
+ abort ();
+ }
+ if (name[4] == '1' && name[5] == '6' && name[6] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRId16;
+ if (name[3] == 'i')
+ return PRIi16;
+ if (name[3] == 'o')
+ return PRIo16;
+ if (name[3] == 'u')
+ return PRIu16;
+ if (name[3] == 'x')
+ return PRIx16;
+ if (name[3] == 'X')
+ return PRIX16;
+ abort ();
+ }
+ if (name[4] == '3' && name[5] == '2' && name[6] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRId32;
+ if (name[3] == 'i')
+ return PRIi32;
+ if (name[3] == 'o')
+ return PRIo32;
+ if (name[3] == 'u')
+ return PRIu32;
+ if (name[3] == 'x')
+ return PRIx32;
+ if (name[3] == 'X')
+ return PRIX32;
+ abort ();
+ }
+ if (name[4] == '6' && name[5] == '4' && name[6] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRId64;
+ if (name[3] == 'i')
+ return PRIi64;
+ if (name[3] == 'o')
+ return PRIo64;
+ if (name[3] == 'u')
+ return PRIu64;
+ if (name[3] == 'x')
+ return PRIx64;
+ if (name[3] == 'X')
+ return PRIX64;
+ abort ();
+ }
+ if (name[4] == 'L' && name[5] == 'E' && name[6] == 'A'
+ && name[7] == 'S' && name[8] == 'T')
+ {
+ if (name[9] == '8' && name[10] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRIdLEAST8;
+ if (name[3] == 'i')
+ return PRIiLEAST8;
+ if (name[3] == 'o')
+ return PRIoLEAST8;
+ if (name[3] == 'u')
+ return PRIuLEAST8;
+ if (name[3] == 'x')
+ return PRIxLEAST8;
+ if (name[3] == 'X')
+ return PRIXLEAST8;
+ abort ();
+ }
+ if (name[9] == '1' && name[10] == '6' && name[11] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRIdLEAST16;
+ if (name[3] == 'i')
+ return PRIiLEAST16;
+ if (name[3] == 'o')
+ return PRIoLEAST16;
+ if (name[3] == 'u')
+ return PRIuLEAST16;
+ if (name[3] == 'x')
+ return PRIxLEAST16;
+ if (name[3] == 'X')
+ return PRIXLEAST16;
+ abort ();
+ }
+ if (name[9] == '3' && name[10] == '2' && name[11] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRIdLEAST32;
+ if (name[3] == 'i')
+ return PRIiLEAST32;
+ if (name[3] == 'o')
+ return PRIoLEAST32;
+ if (name[3] == 'u')
+ return PRIuLEAST32;
+ if (name[3] == 'x')
+ return PRIxLEAST32;
+ if (name[3] == 'X')
+ return PRIXLEAST32;
+ abort ();
+ }
+ if (name[9] == '6' && name[10] == '4' && name[11] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRIdLEAST64;
+ if (name[3] == 'i')
+ return PRIiLEAST64;
+ if (name[3] == 'o')
+ return PRIoLEAST64;
+ if (name[3] == 'u')
+ return PRIuLEAST64;
+ if (name[3] == 'x')
+ return PRIxLEAST64;
+ if (name[3] == 'X')
+ return PRIXLEAST64;
+ abort ();
+ }
+ }
+ if (name[4] == 'F' && name[5] == 'A' && name[6] == 'S'
+ && name[7] == 'T')
+ {
+ if (name[8] == '8' && name[9] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRIdFAST8;
+ if (name[3] == 'i')
+ return PRIiFAST8;
+ if (name[3] == 'o')
+ return PRIoFAST8;
+ if (name[3] == 'u')
+ return PRIuFAST8;
+ if (name[3] == 'x')
+ return PRIxFAST8;
+ if (name[3] == 'X')
+ return PRIXFAST8;
+ abort ();
+ }
+ if (name[8] == '1' && name[9] == '6' && name[10] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRIdFAST16;
+ if (name[3] == 'i')
+ return PRIiFAST16;
+ if (name[3] == 'o')
+ return PRIoFAST16;
+ if (name[3] == 'u')
+ return PRIuFAST16;
+ if (name[3] == 'x')
+ return PRIxFAST16;
+ if (name[3] == 'X')
+ return PRIXFAST16;
+ abort ();
+ }
+ if (name[8] == '3' && name[9] == '2' && name[10] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRIdFAST32;
+ if (name[3] == 'i')
+ return PRIiFAST32;
+ if (name[3] == 'o')
+ return PRIoFAST32;
+ if (name[3] == 'u')
+ return PRIuFAST32;
+ if (name[3] == 'x')
+ return PRIxFAST32;
+ if (name[3] == 'X')
+ return PRIXFAST32;
+ abort ();
+ }
+ if (name[8] == '6' && name[9] == '4' && name[10] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRIdFAST64;
+ if (name[3] == 'i')
+ return PRIiFAST64;
+ if (name[3] == 'o')
+ return PRIoFAST64;
+ if (name[3] == 'u')
+ return PRIuFAST64;
+ if (name[3] == 'x')
+ return PRIxFAST64;
+ if (name[3] == 'X')
+ return PRIXFAST64;
+ abort ();
+ }
+ }
+ if (name[4] == 'M' && name[5] == 'A' && name[6] == 'X'
+ && name[7] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRIdMAX;
+ if (name[3] == 'i')
+ return PRIiMAX;
+ if (name[3] == 'o')
+ return PRIoMAX;
+ if (name[3] == 'u')
+ return PRIuMAX;
+ if (name[3] == 'x')
+ return PRIxMAX;
+ if (name[3] == 'X')
+ return PRIXMAX;
+ abort ();
+ }
+ if (name[4] == 'P' && name[5] == 'T' && name[6] == 'R'
+ && name[7] == '\0')
+ {
+ if (name[3] == 'd')
+ return PRIdPTR;
+ if (name[3] == 'i')
+ return PRIiPTR;
+ if (name[3] == 'o')
+ return PRIoPTR;
+ if (name[3] == 'u')
+ return PRIuPTR;
+ if (name[3] == 'x')
+ return PRIxPTR;
+ if (name[3] == 'X')
+ return PRIXPTR;
+ abort ();
+ }
+ }
+ }
+ /* Test for a glibc specific printf() format directive flag. */
+ if (name[0] == 'I' && name[1] == '\0')
+ {
+#if defined _LIBC || __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)
+ /* The 'I' flag, in numeric format directives, replaces ASCII digits
+ with the 'outdigits' defined in the LC_CTYPE locale facet. This is
+ used for Farsi (Persian) and maybe Arabic. */
+ return "I";
+#else
+ return "";
+#endif
+ }
+ /* Other system dependent strings are not valid. */
+ return NULL;
+}
+
+/* Load the message catalogs specified by FILENAME. If it is no valid
+ message catalog do nothing. */
+void
+internal_function
+_nl_load_domain (struct loaded_l10nfile *domain_file,
+ struct binding *domainbinding)
+{
+ __libc_lock_define_initialized_recursive (static, lock)
+ int fd = -1;
+ size_t size;
+#ifdef _LIBC
+ struct stat64 st;
+#else
+ struct stat st;
+#endif
+ struct mo_file_header *data = (struct mo_file_header *) -1;
+ int use_mmap = 0;
+ struct loaded_domain *domain;
+ int revision;
+ const char *nullentry;
+ size_t nullentrylen;
+
+ __libc_lock_lock_recursive (lock);
+ if (domain_file->decided != 0)
+ {
+ /* There are two possibilities:
+
+ + this is the same thread calling again during this initialization
+ via _nl_find_msg. We have initialized everything this call needs.
+
+ + this is another thread which tried to initialize this object.
+ Not necessary anymore since if the lock is available this
+ is finished.
+ */
+ goto done;
+ }
+
+ domain_file->decided = -1;
+ domain_file->data = NULL;
+
+ /* Note that it would be useless to store domainbinding in domain_file
+ because domainbinding might be == NULL now but != NULL later (after
+ a call to bind_textdomain_codeset). */
+
+ /* If the record does not represent a valid locale the FILENAME
+ might be NULL. This can happen when according to the given
+ specification the locale file name is different for XPG and CEN
+ syntax. */
+ if (domain_file->filename == NULL)
+ goto out;
+
+ /* Try to open the addressed file. */
+ fd = open (domain_file->filename, O_RDONLY | O_BINARY);
+ if (fd == -1)
+ goto out;
+
+ /* We must know about the size of the file. */
+ if (
+#ifdef _LIBC
+ __builtin_expect (fstat64 (fd, &st) != 0, 0)
+#else
+ __builtin_expect (fstat (fd, &st) != 0, 0)
+#endif
+ || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
+ || __builtin_expect (size < sizeof (struct mo_file_header), 0))
+ /* Something went wrong. */
+ goto out;
+
+#ifdef HAVE_MMAP
+ /* Now we are ready to load the file. If mmap() is available we try
+ this first. If not available or it failed we try to load it. */
+ data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
+ MAP_PRIVATE, fd, 0);
+
+ if (__builtin_expect (data != (struct mo_file_header *) -1, 1))
+ {
+ /* mmap() call was successful. */
+ close (fd);
+ fd = -1;
+ use_mmap = 1;
+ }
+#endif
+
+ /* If the data is not yet available (i.e. mmap'ed) we try to load
+ it manually. */
+ if (data == (struct mo_file_header *) -1)
+ {
+ size_t to_read;
+ char *read_ptr;
+
+ data = (struct mo_file_header *) malloc (size);
+ if (data == NULL)
+ goto out;
+
+ to_read = size;
+ read_ptr = (char *) data;
+ do
+ {
+ long int nb = (long int) read (fd, read_ptr, to_read);
+ if (nb <= 0)
+ {
+#ifdef EINTR
+ if (nb == -1 && errno == EINTR)
+ continue;
+#endif
+ goto out;
+ }
+ read_ptr += nb;
+ to_read -= nb;
+ }
+ while (to_read > 0);
+
+ close (fd);
+ fd = -1;
+ }
+
+ /* Using the magic number we can test whether it really is a message
+ catalog file. */
+ if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED,
+ 0))
+ {
+ /* The magic number is wrong: not a message catalog file. */
+#ifdef HAVE_MMAP
+ if (use_mmap)
+ munmap ((caddr_t) data, size);
+ else
+#endif
+ free (data);
+ goto out;
+ }
+
+ domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
+ if (domain == NULL)
+ goto out;
+ domain_file->data = domain;
+
+ domain->data = (char *) data;
+ domain->use_mmap = use_mmap;
+ domain->mmap_size = size;
+ domain->must_swap = data->magic != _MAGIC;
+ domain->malloced = NULL;
+
+ /* Fill in the information about the available tables. */
+ revision = W (domain->must_swap, data->revision);
+ /* We support only the major revisions 0 and 1. */
+ switch (revision >> 16)
+ {
+ case 0:
+ case 1:
+ domain->nstrings = W (domain->must_swap, data->nstrings);
+ domain->orig_tab = (const struct string_desc *)
+ ((char *) data + W (domain->must_swap, data->orig_tab_offset));
+ domain->trans_tab = (const struct string_desc *)
+ ((char *) data + W (domain->must_swap, data->trans_tab_offset));
+ domain->hash_size = W (domain->must_swap, data->hash_tab_size);
+ domain->hash_tab =
+ (domain->hash_size > 2
+ ? (const nls_uint32 *)
+ ((char *) data + W (domain->must_swap, data->hash_tab_offset))
+ : NULL);
+ domain->must_swap_hash_tab = domain->must_swap;
+
+ /* Now dispatch on the minor revision. */
+ switch (revision & 0xffff)
+ {
+ case 0:
+ domain->n_sysdep_strings = 0;
+ domain->orig_sysdep_tab = NULL;
+ domain->trans_sysdep_tab = NULL;
+ break;
+ case 1:
+ default:
+ {
+ nls_uint32 n_sysdep_strings;
+
+ if (domain->hash_tab == NULL)
+ /* This is invalid. These minor revisions need a hash table. */
+ goto invalid;
+
+ n_sysdep_strings =
+ W (domain->must_swap, data->n_sysdep_strings);
+ if (n_sysdep_strings > 0)
+ {
+ nls_uint32 n_sysdep_segments;
+ const struct sysdep_segment *sysdep_segments;
+ const char **sysdep_segment_values;
+ const nls_uint32 *orig_sysdep_tab;
+ const nls_uint32 *trans_sysdep_tab;
+ nls_uint32 n_inmem_sysdep_strings;
+ size_t memneed;
+ char *mem;
+ struct sysdep_string_desc *inmem_orig_sysdep_tab;
+ struct sysdep_string_desc *inmem_trans_sysdep_tab;
+ nls_uint32 *inmem_hash_tab;
+ unsigned int i, j;
+
+ /* Get the values of the system dependent segments. */
+ n_sysdep_segments =
+ W (domain->must_swap, data->n_sysdep_segments);
+ sysdep_segments = (const struct sysdep_segment *)
+ ((char *) data
+ + W (domain->must_swap, data->sysdep_segments_offset));
+ sysdep_segment_values =
+ (const char **)
+ alloca (n_sysdep_segments * sizeof (const char *));
+ for (i = 0; i < n_sysdep_segments; i++)
+ {
+ const char *name =
+ (char *) data
+ + W (domain->must_swap, sysdep_segments[i].offset);
+ nls_uint32 namelen =
+ W (domain->must_swap, sysdep_segments[i].length);
+
+ if (!(namelen > 0 && name[namelen - 1] == '\0'))
+ {
+ freea (sysdep_segment_values);
+ goto invalid;
+ }
+
+ sysdep_segment_values[i] = get_sysdep_segment_value (name);
+ }
+
+ orig_sysdep_tab = (const nls_uint32 *)
+ ((char *) data
+ + W (domain->must_swap, data->orig_sysdep_tab_offset));
+ trans_sysdep_tab = (const nls_uint32 *)
+ ((char *) data
+ + W (domain->must_swap, data->trans_sysdep_tab_offset));
+
+ /* Compute the amount of additional memory needed for the
+ system dependent strings and the augmented hash table.
+ At the same time, also drop string pairs which refer to
+ an undefined system dependent segment. */
+ n_inmem_sysdep_strings = 0;
+ memneed = domain->hash_size * sizeof (nls_uint32);
+ for (i = 0; i < n_sysdep_strings; i++)
+ {
+ int valid = 1;
+ size_t needs[2];
+
+ for (j = 0; j < 2; j++)
+ {
+ const struct sysdep_string *sysdep_string =
+ (const struct sysdep_string *)
+ ((char *) data
+ + W (domain->must_swap,
+ j == 0
+ ? orig_sysdep_tab[i]
+ : trans_sysdep_tab[i]));
+ size_t need = 0;
+ const struct segment_pair *p = sysdep_string->segments;
+
+ if (W (domain->must_swap, p->sysdepref) != SEGMENTS_END)
+ for (p = sysdep_string->segments;; p++)
+ {
+ nls_uint32 sysdepref;
+
+ need += W (domain->must_swap, p->segsize);
+
+ sysdepref = W (domain->must_swap, p->sysdepref);
+ if (sysdepref == SEGMENTS_END)
+ break;
+
+ if (sysdepref >= n_sysdep_segments)
+ {
+ /* Invalid. */
+ freea (sysdep_segment_values);
+ goto invalid;
+ }
+
+ if (sysdep_segment_values[sysdepref] == NULL)
+ {
+ /* This particular string pair is invalid. */
+ valid = 0;
+ break;
+ }
+
+ need += strlen (sysdep_segment_values[sysdepref]);
+ }
+
+ needs[j] = need;
+ if (!valid)
+ break;
+ }
+
+ if (valid)
+ {
+ n_inmem_sysdep_strings++;
+ memneed += needs[0] + needs[1];
+ }
+ }
+ memneed += 2 * n_inmem_sysdep_strings
+ * sizeof (struct sysdep_string_desc);
+
+ if (n_inmem_sysdep_strings > 0)
+ {
+ unsigned int k;
+
+ /* Allocate additional memory. */
+ mem = (char *) malloc (memneed);
+ if (mem == NULL)
+ goto invalid;
+
+ domain->malloced = mem;
+ inmem_orig_sysdep_tab = (struct sysdep_string_desc *) mem;
+ mem += n_inmem_sysdep_strings
+ * sizeof (struct sysdep_string_desc);
+ inmem_trans_sysdep_tab = (struct sysdep_string_desc *) mem;
+ mem += n_inmem_sysdep_strings
+ * sizeof (struct sysdep_string_desc);
+ inmem_hash_tab = (nls_uint32 *) mem;
+ mem += domain->hash_size * sizeof (nls_uint32);
+
+ /* Compute the system dependent strings. */
+ k = 0;
+ for (i = 0; i < n_sysdep_strings; i++)
+ {
+ int valid = 1;
+
+ for (j = 0; j < 2; j++)
+ {
+ const struct sysdep_string *sysdep_string =
+ (const struct sysdep_string *)
+ ((char *) data
+ + W (domain->must_swap,
+ j == 0
+ ? orig_sysdep_tab[i]
+ : trans_sysdep_tab[i]));
+ const struct segment_pair *p =
+ sysdep_string->segments;
+
+ if (W (domain->must_swap, p->sysdepref)
+ != SEGMENTS_END)
+ for (p = sysdep_string->segments;; p++)
+ {
+ nls_uint32 sysdepref;
+
+ sysdepref =
+ W (domain->must_swap, p->sysdepref);
+ if (sysdepref == SEGMENTS_END)
+ break;
+
+ if (sysdep_segment_values[sysdepref] == NULL)
+ {
+ /* This particular string pair is
+ invalid. */
+ valid = 0;
+ break;
+ }
+ }
+
+ if (!valid)
+ break;
+ }
+
+ if (valid)
+ {
+ for (j = 0; j < 2; j++)
+ {
+ const struct sysdep_string *sysdep_string =
+ (const struct sysdep_string *)
+ ((char *) data
+ + W (domain->must_swap,
+ j == 0
+ ? orig_sysdep_tab[i]
+ : trans_sysdep_tab[i]));
+ const char *static_segments =
+ (char *) data
+ + W (domain->must_swap, sysdep_string->offset);
+ const struct segment_pair *p =
+ sysdep_string->segments;
+
+ /* Concatenate the segments, and fill
+ inmem_orig_sysdep_tab[k] (for j == 0) and
+ inmem_trans_sysdep_tab[k] (for j == 1). */
+
+ struct sysdep_string_desc *inmem_tab_entry =
+ (j == 0
+ ? inmem_orig_sysdep_tab
+ : inmem_trans_sysdep_tab)
+ + k;
+
+ if (W (domain->must_swap, p->sysdepref)
+ == SEGMENTS_END)
+ {
+ /* Only one static segment. */
+ inmem_tab_entry->length =
+ W (domain->must_swap, p->segsize);
+ inmem_tab_entry->pointer = static_segments;
+ }
+ else
+ {
+ inmem_tab_entry->pointer = mem;
+
+ for (p = sysdep_string->segments;; p++)
+ {
+ nls_uint32 segsize =
+ W (domain->must_swap, p->segsize);
+ nls_uint32 sysdepref =
+ W (domain->must_swap, p->sysdepref);
+ size_t n;
+
+ if (segsize > 0)
+ {
+ memcpy (mem, static_segments, segsize);
+ mem += segsize;
+ static_segments += segsize;
+ }
+
+ if (sysdepref == SEGMENTS_END)
+ break;
+
+ n = strlen (sysdep_segment_values[sysdepref]);
+ memcpy (mem, sysdep_segment_values[sysdepref], n);
+ mem += n;
+ }
+
+ inmem_tab_entry->length =
+ mem - inmem_tab_entry->pointer;
+ }
+ }
+
+ k++;
+ }
+ }
+ if (k != n_inmem_sysdep_strings)
+ abort ();
+
+ /* Compute the augmented hash table. */
+ for (i = 0; i < domain->hash_size; i++)
+ inmem_hash_tab[i] =
+ W (domain->must_swap_hash_tab, domain->hash_tab[i]);
+ for (i = 0; i < n_inmem_sysdep_strings; i++)
+ {
+ const char *msgid = inmem_orig_sysdep_tab[i].pointer;
+ nls_uint32 hash_val = __hash_string (msgid);
+ nls_uint32 idx = hash_val % domain->hash_size;
+ nls_uint32 incr =
+ 1 + (hash_val % (domain->hash_size - 2));
+
+ for (;;)
+ {
+ if (inmem_hash_tab[idx] == 0)
+ {
+ /* Hash table entry is empty. Use it. */
+ inmem_hash_tab[idx] = 1 + domain->nstrings + i;
+ break;
+ }
+
+ if (idx >= domain->hash_size - incr)
+ idx -= domain->hash_size - incr;
+ else
+ idx += incr;
+ }
+ }
+
+ domain->n_sysdep_strings = n_inmem_sysdep_strings;
+ domain->orig_sysdep_tab = inmem_orig_sysdep_tab;
+ domain->trans_sysdep_tab = inmem_trans_sysdep_tab;
+
+ domain->hash_tab = inmem_hash_tab;
+ domain->must_swap_hash_tab = 0;
+ }
+ else
+ {
+ domain->n_sysdep_strings = 0;
+ domain->orig_sysdep_tab = NULL;
+ domain->trans_sysdep_tab = NULL;
+ }
+
+ freea (sysdep_segment_values);
+ }
+ else
+ {
+ domain->n_sysdep_strings = 0;
+ domain->orig_sysdep_tab = NULL;
+ domain->trans_sysdep_tab = NULL;
+ }
+ }
+ break;
+ }
+ break;
+ default:
+ /* This is an invalid revision. */
+ invalid:
+ /* This is an invalid .mo file. */
+ free (domain->malloced);
+#ifdef HAVE_MMAP
+ if (use_mmap)
+ munmap ((caddr_t) data, size);
+ else
+#endif
+ free (data);
+ free (domain);
+ domain_file->data = NULL;
+ goto out;
+ }
+
+ /* No caches of converted translations so far. */
+ domain->conversions = NULL;
+ domain->nconversions = 0;
+ gl_rwlock_init (domain->conversions_lock);
+
+ /* Get the header entry and look for a plural specification. */
+#ifdef IN_LIBGLOCALE
+ nullentry =
+ _nl_find_msg (domain_file, domainbinding, NULL, "", &nullentrylen);
+#else
+ nullentry = _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
+#endif
+ EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals);
+
+ out:
+ if (fd != -1)
+ close (fd);
+
+ domain_file->decided = 1;
+
+ done:
+ __libc_lock_unlock_recursive (lock);
+}
+
+
+#ifdef _LIBC
+void
+internal_function __libc_freeres_fn_section
+_nl_unload_domain (struct loaded_domain *domain)
+{
+ size_t i;
+
+ if (domain->plural != &__gettext_germanic_plural)
+ __gettext_free_exp ((struct expression *) domain->plural);
+
+ for (i = 0; i < domain->nconversions; i++)
+ {
+ struct converted_domain *convd = &domain->conversions[i];
+
+ free (convd->encoding);
+ if (convd->conv_tab != NULL && convd->conv_tab != (char **) -1)
+ free (convd->conv_tab);
+ if (convd->conv != (__gconv_t) -1)
+ __gconv_close (convd->conv);
+ }
+ free (domain->conversions);
+ __libc_rwlock_fini (domain->conversions_lock);
+
+ free (domain->malloced);
+
+# ifdef _POSIX_MAPPED_FILES
+ if (domain->use_mmap)
+ munmap ((caddr_t) domain->data, domain->mmap_size);
+ else
+# endif /* _POSIX_MAPPED_FILES */
+ free ((void *) domain->data);
+
+ free (domain);
+}
+#endif
diff --git a/intl/localcharset.c b/intl/localcharset.c
new file mode 100644
index 00000000..cbcdaceb
--- /dev/null
+++ b/intl/localcharset.c
@@ -0,0 +1,549 @@
+/* Determine a canonical name for the current locale's character encoding.
+
+ Copyright (C) 2000-2006, 2008-2010 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+/* Written by Bruno Haible <bruno@clisp.org>. */
+
+#include <config.h>
+
+/* Specification. */
+#include "localcharset.h"
+
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#if defined __APPLE__ && defined __MACH__ && HAVE_LANGINFO_CODESET
+# define DARWIN7 /* Darwin 7 or newer, i.e. MacOS X 10.3 or newer */
+#endif
+
+#if defined _WIN32 || defined __WIN32__
+# define WIN32_NATIVE
+#endif
+
+#if defined __EMX__
+/* Assume EMX program runs on OS/2, even if compiled under DOS. */
+# ifndef OS2
+# define OS2
+# endif
+#endif
+
+#if !defined WIN32_NATIVE
+# include <unistd.h>
+# if HAVE_LANGINFO_CODESET
+# include <langinfo.h>
+# else
+# if 0 /* see comment below */
+# include <locale.h>
+# endif
+# endif
+# ifdef __CYGWIN__
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+# endif
+#elif defined WIN32_NATIVE
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif
+#if defined OS2
+# define INCL_DOS
+# include <os2.h>
+#endif
+
+#if ENABLE_RELOCATABLE
+# include "relocatable.h"
+#else
+# define relocate(pathname) (pathname)
+#endif
+
+/* Get LIBDIR. */
+#ifndef LIBDIR
+# include "configmake.h"
+#endif
+
+/* Define O_NOFOLLOW to 0 on platforms where it does not exist. */
+#ifndef O_NOFOLLOW
+# define O_NOFOLLOW 0
+#endif
+
+#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
+ /* Win32, Cygwin, OS/2, DOS */
+# define ISSLASH(C) ((C) == '/' || (C) == '\\')
+#endif
+
+#ifndef DIRECTORY_SEPARATOR
+# define DIRECTORY_SEPARATOR '/'
+#endif
+
+#ifndef ISSLASH
+# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR)
+#endif
+
+#if HAVE_DECL_GETC_UNLOCKED
+# undef getc
+# define getc getc_unlocked
+#endif
+
+/* The following static variable is declared 'volatile' to avoid a
+ possible multithread problem in the function get_charset_aliases. If we
+ are running in a threaded environment, and if two threads initialize
+ 'charset_aliases' simultaneously, both will produce the same value,
+ and everything will be ok if the two assignments to 'charset_aliases'
+ are atomic. But I don't know what will happen if the two assignments mix. */
+#if __STDC__ != 1
+# define volatile /* empty */
+#endif
+/* Pointer to the contents of the charset.alias file, if it has already been
+ read, else NULL. Its format is:
+ ALIAS_1 '\0' CANONICAL_1 '\0' ... ALIAS_n '\0' CANONICAL_n '\0' '\0' */
+static const char * volatile charset_aliases;
+
+/* Return a pointer to the contents of the charset.alias file. */
+static const char *
+get_charset_aliases (void)
+{
+ const char *cp;
+
+ cp = charset_aliases;
+ if (cp == NULL)
+ {
+#if !(defined DARWIN7 || defined VMS || defined WIN32_NATIVE || defined __CYGWIN__)
+ const char *dir;
+ const char *base = "charset.alias";
+ char *file_name;
+
+ /* Make it possible to override the charset.alias location. This is
+ necessary for running the testsuite before "make install". */
+ dir = getenv ("CHARSETALIASDIR");
+ if (dir == NULL || dir[0] == '\0')
+ dir = relocate (LIBDIR);
+
+ /* Concatenate dir and base into freshly allocated file_name. */
+ {
+ size_t dir_len = strlen (dir);
+ size_t base_len = strlen (base);
+ int add_slash = (dir_len > 0 && !ISSLASH (dir[dir_len - 1]));
+ file_name = (char *) malloc (dir_len + add_slash + base_len + 1);
+ if (file_name != NULL)
+ {
+ memcpy (file_name, dir, dir_len);
+ if (add_slash)
+ file_name[dir_len] = DIRECTORY_SEPARATOR;
+ memcpy (file_name + dir_len + add_slash, base, base_len + 1);
+ }
+ }
+
+ if (file_name == NULL)
+ /* Out of memory. Treat the file as empty. */
+ cp = "";
+ else
+ {
+ int fd;
+
+ /* Open the file. Reject symbolic links on platforms that support
+ O_NOFOLLOW. This is a security feature. Without it, an attacker
+ could retrieve parts of the contents (namely, the tail of the
+ first line that starts with "* ") of an arbitrary file by placing
+ a symbolic link to that file under the name "charset.alias" in
+ some writable directory and defining the environment variable
+ CHARSETALIASDIR to point to that directory. */
+ fd = open (file_name,
+ O_RDONLY | (HAVE_WORKING_O_NOFOLLOW ? O_NOFOLLOW : 0));
+ if (fd < 0)
+ /* File not found. Treat it as empty. */
+ cp = "";
+ else
+ {
+ FILE *fp;
+
+ fp = fdopen (fd, "r");
+ if (fp == NULL)
+ {
+ /* Out of memory. Treat the file as empty. */
+ close (fd);
+ cp = "";
+ }
+ else
+ {
+ /* Parse the file's contents. */
+ char *res_ptr = NULL;
+ size_t res_size = 0;
+
+ for (;;)
+ {
+ int c;
+ char buf1[50+1];
+ char buf2[50+1];
+ size_t l1, l2;
+ char *old_res_ptr;
+
+ c = getc (fp);
+ if (c == EOF)
+ break;
+ if (c == '\n' || c == ' ' || c == '\t')
+ continue;
+ if (c == '#')
+ {
+ /* Skip comment, to end of line. */
+ do
+ c = getc (fp);
+ while (!(c == EOF || c == '\n'));
+ if (c == EOF)
+ break;
+ continue;
+ }
+ ungetc (c, fp);
+ if (fscanf (fp, "%50s %50s", buf1, buf2) < 2)
+ break;
+ l1 = strlen (buf1);
+ l2 = strlen (buf2);
+ old_res_ptr = res_ptr;
+ if (res_size == 0)
+ {
+ res_size = l1 + 1 + l2 + 1;
+ res_ptr = (char *) malloc (res_size + 1);
+ }
+ else
+ {
+ res_size += l1 + 1 + l2 + 1;
+ res_ptr = (char *) realloc (res_ptr, res_size + 1);
+ }
+ if (res_ptr == NULL)
+ {
+ /* Out of memory. */
+ res_size = 0;
+ if (old_res_ptr != NULL)
+ free (old_res_ptr);
+ break;
+ }
+ strcpy (res_ptr + res_size - (l2 + 1) - (l1 + 1), buf1);
+ strcpy (res_ptr + res_size - (l2 + 1), buf2);
+ }
+ fclose (fp);
+ if (res_size == 0)
+ cp = "";
+ else
+ {
+ *(res_ptr + res_size) = '\0';
+ cp = res_ptr;
+ }
+ }
+ }
+
+ free (file_name);
+ }
+
+#else
+
+# if defined DARWIN7
+ /* To avoid the trouble of installing a file that is shared by many
+ GNU packages -- many packaging systems have problems with this --,
+ simply inline the aliases here. */
+ cp = "ISO8859-1" "\0" "ISO-8859-1" "\0"
+ "ISO8859-2" "\0" "ISO-8859-2" "\0"
+ "ISO8859-4" "\0" "ISO-8859-4" "\0"
+ "ISO8859-5" "\0" "ISO-8859-5" "\0"
+ "ISO8859-7" "\0" "ISO-8859-7" "\0"
+ "ISO8859-9" "\0" "ISO-8859-9" "\0"
+ "ISO8859-13" "\0" "ISO-8859-13" "\0"
+ "ISO8859-15" "\0" "ISO-8859-15" "\0"
+ "KOI8-R" "\0" "KOI8-R" "\0"
+ "KOI8-U" "\0" "KOI8-U" "\0"
+ "CP866" "\0" "CP866" "\0"
+ "CP949" "\0" "CP949" "\0"
+ "CP1131" "\0" "CP1131" "\0"
+ "CP1251" "\0" "CP1251" "\0"
+ "eucCN" "\0" "GB2312" "\0"
+ "GB2312" "\0" "GB2312" "\0"
+ "eucJP" "\0" "EUC-JP" "\0"
+ "eucKR" "\0" "EUC-KR" "\0"
+ "Big5" "\0" "BIG5" "\0"
+ "Big5HKSCS" "\0" "BIG5-HKSCS" "\0"
+ "GBK" "\0" "GBK" "\0"
+ "GB18030" "\0" "GB18030" "\0"
+ "SJIS" "\0" "SHIFT_JIS" "\0"
+ "ARMSCII-8" "\0" "ARMSCII-8" "\0"
+ "PT154" "\0" "PT154" "\0"
+ /*"ISCII-DEV" "\0" "?" "\0"*/
+ "*" "\0" "UTF-8" "\0";
+# endif
+
+# if defined VMS
+ /* To avoid the troubles of an extra file charset.alias_vms in the
+ sources of many GNU packages, simply inline the aliases here. */
+ /* The list of encodings is taken from the OpenVMS 7.3-1 documentation
+ "Compaq C Run-Time Library Reference Manual for OpenVMS systems"
+ section 10.7 "Handling Different Character Sets". */
+ cp = "ISO8859-1" "\0" "ISO-8859-1" "\0"
+ "ISO8859-2" "\0" "ISO-8859-2" "\0"
+ "ISO8859-5" "\0" "ISO-8859-5" "\0"
+ "ISO8859-7" "\0" "ISO-8859-7" "\0"
+ "ISO8859-8" "\0" "ISO-8859-8" "\0"
+ "ISO8859-9" "\0" "ISO-8859-9" "\0"
+ /* Japanese */
+ "eucJP" "\0" "EUC-JP" "\0"
+ "SJIS" "\0" "SHIFT_JIS" "\0"
+ "DECKANJI" "\0" "DEC-KANJI" "\0"
+ "SDECKANJI" "\0" "EUC-JP" "\0"
+ /* Chinese */
+ "eucTW" "\0" "EUC-TW" "\0"
+ "DECHANYU" "\0" "DEC-HANYU" "\0"
+ "DECHANZI" "\0" "GB2312" "\0"
+ /* Korean */
+ "DECKOREAN" "\0" "EUC-KR" "\0";
+# endif
+
+# if defined WIN32_NATIVE || defined __CYGWIN__
+ /* To avoid the troubles of installing a separate file in the same
+ directory as the DLL and of retrieving the DLL's directory at
+ runtime, simply inline the aliases here. */
+
+ cp = "CP936" "\0" "GBK" "\0"
+ "CP1361" "\0" "JOHAB" "\0"
+ "CP20127" "\0" "ASCII" "\0"
+ "CP20866" "\0" "KOI8-R" "\0"
+ "CP20936" "\0" "GB2312" "\0"
+ "CP21866" "\0" "KOI8-RU" "\0"
+ "CP28591" "\0" "ISO-8859-1" "\0"
+ "CP28592" "\0" "ISO-8859-2" "\0"
+ "CP28593" "\0" "ISO-8859-3" "\0"
+ "CP28594" "\0" "ISO-8859-4" "\0"
+ "CP28595" "\0" "ISO-8859-5" "\0"
+ "CP28596" "\0" "ISO-8859-6" "\0"
+ "CP28597" "\0" "ISO-8859-7" "\0"
+ "CP28598" "\0" "ISO-8859-8" "\0"
+ "CP28599" "\0" "ISO-8859-9" "\0"
+ "CP28605" "\0" "ISO-8859-15" "\0"
+ "CP38598" "\0" "ISO-8859-8" "\0"
+ "CP51932" "\0" "EUC-JP" "\0"
+ "CP51936" "\0" "GB2312" "\0"
+ "CP51949" "\0" "EUC-KR" "\0"
+ "CP51950" "\0" "EUC-TW" "\0"
+ "CP54936" "\0" "GB18030" "\0"
+ "CP65001" "\0" "UTF-8" "\0";
+# endif
+#endif
+
+ charset_aliases = cp;
+ }
+
+ return cp;
+}
+
+/* Determine the current locale's character encoding, and canonicalize it
+ into one of the canonical names listed in config.charset.
+ The result must not be freed; it is statically allocated.
+ If the canonical name cannot be determined, the result is a non-canonical
+ name. */
+
+#ifdef STATIC
+STATIC
+#endif
+const char *
+locale_charset (void)
+{
+ const char *codeset;
+ const char *aliases;
+
+#if !(defined WIN32_NATIVE || defined OS2)
+
+# if HAVE_LANGINFO_CODESET
+
+ /* Most systems support nl_langinfo (CODESET) nowadays. */
+ codeset = nl_langinfo (CODESET);
+
+# ifdef __CYGWIN__
+ /* Cygwin < 1.7 does not have locales. nl_langinfo (CODESET) always
+ returns "US-ASCII". Return the suffix of the locale name from the
+ environment variables (if present) or the codepage as a number. */
+ if (codeset != NULL && strcmp (codeset, "US-ASCII") == 0)
+ {
+ const char *locale;
+ static char buf[2 + 10 + 1];
+
+ locale = getenv ("LC_ALL");
+ if (locale == NULL || locale[0] == '\0')
+ {
+ locale = getenv ("LC_CTYPE");
+ if (locale == NULL || locale[0] == '\0')
+ locale = getenv ("LANG");
+ }
+ if (locale != NULL && locale[0] != '\0')
+ {
+ /* If the locale name contains an encoding after the dot, return
+ it. */
+ const char *dot = strchr (locale, '.');
+
+ if (dot != NULL)
+ {
+ const char *modifier;
+
+ dot++;
+ /* Look for the possible @... trailer and remove it, if any. */
+ modifier = strchr (dot, '@');
+ if (modifier == NULL)
+ return dot;
+ if (modifier - dot < sizeof (buf))
+ {
+ memcpy (buf, dot, modifier - dot);
+ buf [modifier - dot] = '\0';
+ return buf;
+ }
+ }
+ }
+
+ /* Woe32 has a function returning the locale's codepage as a number:
+ GetACP(). This encoding is used by Cygwin, unless the user has set
+ the environment variable CYGWIN=codepage:oem (which very few people
+ do).
+ Output directed to console windows needs to be converted (to
+ GetOEMCP() if the console is using a raster font, or to
+ GetConsoleOutputCP() if it is using a TrueType font). Cygwin does
+ this conversion transparently (see winsup/cygwin/fhandler_console.cc),
+ converting to GetConsoleOutputCP(). This leads to correct results,
+ except when SetConsoleOutputCP has been called and a raster font is
+ in use. */
+ sprintf (buf, "CP%u", GetACP ());
+ codeset = buf;
+ }
+# endif
+
+# else
+
+ /* On old systems which lack it, use setlocale or getenv. */
+ const char *locale = NULL;
+
+ /* But most old systems don't have a complete set of locales. Some
+ (like SunOS 4 or DJGPP) have only the C locale. Therefore we don't
+ use setlocale here; it would return "C" when it doesn't support the
+ locale name the user has set. */
+# if 0
+ locale = setlocale (LC_CTYPE, NULL);
+# endif
+ if (locale == NULL || locale[0] == '\0')
+ {
+ locale = getenv ("LC_ALL");
+ if (locale == NULL || locale[0] == '\0')
+ {
+ locale = getenv ("LC_CTYPE");
+ if (locale == NULL || locale[0] == '\0')
+ locale = getenv ("LANG");
+ }
+ }
+
+ /* On some old systems, one used to set locale = "iso8859_1". On others,
+ you set it to "language_COUNTRY.charset". In any case, we resolve it
+ through the charset.alias file. */
+ codeset = locale;
+
+# endif
+
+#elif defined WIN32_NATIVE
+
+ static char buf[2 + 10 + 1];
+
+ /* Woe32 has a function returning the locale's codepage as a number:
+ GetACP().
+ When the output goes to a console window, it needs to be provided in
+ GetOEMCP() encoding if the console is using a raster font, or in
+ GetConsoleOutputCP() encoding if it is using a TrueType font.
+ But in GUI programs and for output sent to files and pipes, GetACP()
+ encoding is the best bet. */
+ sprintf (buf, "CP%u", GetACP ());
+ codeset = buf;
+
+#elif defined OS2
+
+ const char *locale;
+ static char buf[2 + 10 + 1];
+ ULONG cp[3];
+ ULONG cplen;
+
+ /* Allow user to override the codeset, as set in the operating system,
+ with standard language environment variables. */
+ locale = getenv ("LC_ALL");
+ if (locale == NULL || locale[0] == '\0')
+ {
+ locale = getenv ("LC_CTYPE");
+ if (locale == NULL || locale[0] == '\0')
+ locale = getenv ("LANG");
+ }
+ if (locale != NULL && locale[0] != '\0')
+ {
+ /* If the locale name contains an encoding after the dot, return it. */
+ const char *dot = strchr (locale, '.');
+
+ if (dot != NULL)
+ {
+ const char *modifier;
+
+ dot++;
+ /* Look for the possible @... trailer and remove it, if any. */
+ modifier = strchr (dot, '@');
+ if (modifier == NULL)
+ return dot;
+ if (modifier - dot < sizeof (buf))
+ {
+ memcpy (buf, dot, modifier - dot);
+ buf [modifier - dot] = '\0';
+ return buf;
+ }
+ }
+
+ /* Resolve through the charset.alias file. */
+ codeset = locale;
+ }
+ else
+ {
+ /* OS/2 has a function returning the locale's codepage as a number. */
+ if (DosQueryCp (sizeof (cp), cp, &cplen))
+ codeset = "";
+ else
+ {
+ sprintf (buf, "CP%u", cp[0]);
+ codeset = buf;
+ }
+ }
+
+#endif
+
+ if (codeset == NULL)
+ /* The canonical name cannot be determined. */
+ codeset = "";
+
+ /* Resolve alias. */
+ for (aliases = get_charset_aliases ();
+ *aliases != '\0';
+ aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1)
+ if (strcmp (codeset, aliases) == 0
+ || (aliases[0] == '*' && aliases[1] == '\0'))
+ {
+ codeset = aliases + strlen (aliases) + 1;
+ break;
+ }
+
+ /* Don't return an empty string. GNU libc and GNU libiconv interpret
+ the empty string as denoting "the locale's character encoding",
+ thus GNU libiconv would call this function a second time. */
+ if (codeset[0] == '\0')
+ codeset = "ASCII";
+
+ return codeset;
+}
diff --git a/intl/localcharset.h b/intl/localcharset.h
new file mode 100644
index 00000000..129e4a4a
--- /dev/null
+++ b/intl/localcharset.h
@@ -0,0 +1,42 @@
+/* Determine a canonical name for the current locale's character encoding.
+ Copyright (C) 2000-2003 Free Software Foundation, Inc.
+ This file is part of the GNU CHARSET Library.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifndef _LOCALCHARSET_H
+#define _LOCALCHARSET_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* Determine the current locale's character encoding, and canonicalize it
+ into one of the canonical names listed in config.charset.
+ The result must not be freed; it is statically allocated.
+ If the canonical name cannot be determined, the result is a non-canonical
+ name. */
+extern const char * locale_charset (void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _LOCALCHARSET_H */
diff --git a/intl/locale.alias b/intl/locale.alias
new file mode 100644
index 00000000..1044a40c
--- /dev/null
+++ b/intl/locale.alias
@@ -0,0 +1,77 @@
+# Locale name alias data base.
+# Copyright (C) 1996-2001,2003,2007 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Library General Public License as published
+# by the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+# USA.
+
+# The format of this file is the same as for the corresponding file of
+# the X Window System, which normally can be found in
+# /usr/lib/X11/locale/locale.alias
+# A single line contains two fields: an alias and a substitution value.
+# All entries are case independent.
+
+# Note: This file is obsolete and is kept around for the time being for
+# backward compatibility. Nobody should rely on the names defined here.
+# Locales should always be specified by their full name.
+
+# Packages using this file:
+
+bokmal nb_NO.ISO-8859-1
+bokml nb_NO.ISO-8859-1
+catalan ca_ES.ISO-8859-1
+croatian hr_HR.ISO-8859-2
+czech cs_CZ.ISO-8859-2
+danish da_DK.ISO-8859-1
+dansk da_DK.ISO-8859-1
+deutsch de_DE.ISO-8859-1
+dutch nl_NL.ISO-8859-1
+eesti et_EE.ISO-8859-1
+estonian et_EE.ISO-8859-1
+finnish fi_FI.ISO-8859-1
+franais fr_FR.ISO-8859-1
+french fr_FR.ISO-8859-1
+galego gl_ES.ISO-8859-1
+galician gl_ES.ISO-8859-1
+german de_DE.ISO-8859-1
+greek el_GR.ISO-8859-7
+hebrew he_IL.ISO-8859-8
+hrvatski hr_HR.ISO-8859-2
+hungarian hu_HU.ISO-8859-2
+icelandic is_IS.ISO-8859-1
+italian it_IT.ISO-8859-1
+japanese ja_JP.eucJP
+japanese.euc ja_JP.eucJP
+ja_JP ja_JP.eucJP
+ja_JP.ujis ja_JP.eucJP
+japanese.sjis ja_JP.SJIS
+korean ko_KR.eucKR
+korean.euc ko_KR.eucKR
+ko_KR ko_KR.eucKR
+lithuanian lt_LT.ISO-8859-13
+no_NO nb_NO.ISO-8859-1
+no_NO.ISO-8859-1 nb_NO.ISO-8859-1
+norwegian nb_NO.ISO-8859-1
+nynorsk nn_NO.ISO-8859-1
+polish pl_PL.ISO-8859-2
+portuguese pt_PT.ISO-8859-1
+romanian ro_RO.ISO-8859-2
+russian ru_RU.ISO-8859-5
+slovak sk_SK.ISO-8859-2
+slovene sl_SI.ISO-8859-2
+slovenian sl_SI.ISO-8859-2
+spanish es_ES.ISO-8859-1
+swedish sv_SE.ISO-8859-1
+thai th_TH.TIS-620
+turkish tr_TR.ISO-8859-9
diff --git a/intl/localealias.c b/intl/localealias.c
new file mode 100644
index 00000000..910db530
--- /dev/null
+++ b/intl/localealias.c
@@ -0,0 +1,439 @@
+/* Handle aliases for locale names.
+ Copyright (C) 1995-1999, 2000-2001, 2003, 2005-2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+/* Tell glibc's <string.h> to provide a prototype for mempcpy().
+ This must come before <config.h> because <config.h> may include
+ <features.h>, and once <features.h> has been included, it's too late. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#if defined _LIBC || defined HAVE___FSETLOCKING
+# include <stdio_ext.h>
+#endif
+#include <sys/types.h>
+
+#ifdef __GNUC__
+# undef alloca
+# define alloca __builtin_alloca
+# define HAVE_ALLOCA 1
+#else
+# ifdef _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+# else
+# if defined HAVE_ALLOCA_H || defined _LIBC
+# include <alloca.h>
+# else
+# ifdef _AIX
+ #pragma alloca
+# else
+# ifndef alloca
+char *alloca ();
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "gettextP.h"
+
+#if ENABLE_RELOCATABLE
+# include "relocatable.h"
+#else
+# define relocate(pathname) (pathname)
+#endif
+
+/* @@ end of prolog @@ */
+
+#ifdef _LIBC
+/* Rename the non ANSI C functions. This is required by the standard
+ because some ANSI C functions will require linking with this object
+ file and the name space must not be polluted. */
+# define strcasecmp __strcasecmp
+
+# ifndef mempcpy
+# define mempcpy __mempcpy
+# endif
+# define HAVE_MEMPCPY 1
+# define HAVE___FSETLOCKING 1
+#endif
+
+/* Handle multi-threaded applications. */
+#ifdef _LIBC
+# include <bits/libc-lock.h>
+#else
+# include "lock.h"
+#endif
+
+#ifndef internal_function
+# define internal_function
+#endif
+
+/* Some optimizations for glibc. */
+#ifdef _LIBC
+# define FEOF(fp) feof_unlocked (fp)
+# define FGETS(buf, n, fp) fgets_unlocked (buf, n, fp)
+#else
+# define FEOF(fp) feof (fp)
+# define FGETS(buf, n, fp) fgets (buf, n, fp)
+#endif
+
+/* For those losing systems which don't have `alloca' we have to add
+ some additional code emulating it. */
+#ifdef HAVE_ALLOCA
+# define freea(p) /* nothing */
+#else
+# define alloca(n) malloc (n)
+# define freea(p) free (p)
+#endif
+
+#if defined _LIBC_REENTRANT || HAVE_DECL_FGETS_UNLOCKED
+# undef fgets
+# define fgets(buf, len, s) fgets_unlocked (buf, len, s)
+#endif
+#if defined _LIBC_REENTRANT || HAVE_DECL_FEOF_UNLOCKED
+# undef feof
+# define feof(s) feof_unlocked (s)
+#endif
+
+
+__libc_lock_define_initialized (static, lock)
+
+
+struct alias_map
+{
+ const char *alias;
+ const char *value;
+};
+
+
+#ifndef _LIBC
+# define libc_freeres_ptr(decl) decl
+#endif
+
+libc_freeres_ptr (static char *string_space);
+static size_t string_space_act;
+static size_t string_space_max;
+libc_freeres_ptr (static struct alias_map *map);
+static size_t nmap;
+static size_t maxmap;
+
+
+/* Prototypes for local functions. */
+static size_t read_alias_file (const char *fname, int fname_len)
+ internal_function;
+static int extend_alias_table (void);
+static int alias_compare (const struct alias_map *map1,
+ const struct alias_map *map2);
+
+
+const char *
+_nl_expand_alias (const char *name)
+{
+ static const char *locale_alias_path;
+ struct alias_map *retval;
+ const char *result = NULL;
+ size_t added;
+
+ __libc_lock_lock (lock);
+
+ if (locale_alias_path == NULL)
+ locale_alias_path = LOCALE_ALIAS_PATH;
+
+ do
+ {
+ struct alias_map item;
+
+ item.alias = name;
+
+ if (nmap > 0)
+ retval = (struct alias_map *) bsearch (&item, map, nmap,
+ sizeof (struct alias_map),
+ (int (*) (const void *,
+ const void *)
+ ) alias_compare);
+ else
+ retval = NULL;
+
+ /* We really found an alias. Return the value. */
+ if (retval != NULL)
+ {
+ result = retval->value;
+ break;
+ }
+
+ /* Perhaps we can find another alias file. */
+ added = 0;
+ while (added == 0 && locale_alias_path[0] != '\0')
+ {
+ const char *start;
+
+ while (locale_alias_path[0] == PATH_SEPARATOR)
+ ++locale_alias_path;
+ start = locale_alias_path;
+
+ while (locale_alias_path[0] != '\0'
+ && locale_alias_path[0] != PATH_SEPARATOR)
+ ++locale_alias_path;
+
+ if (start < locale_alias_path)
+ added = read_alias_file (start, locale_alias_path - start);
+ }
+ }
+ while (added != 0);
+
+ __libc_lock_unlock (lock);
+
+ return result;
+}
+
+
+static size_t
+internal_function
+read_alias_file (const char *fname, int fname_len)
+{
+ FILE *fp;
+ char *full_fname;
+ size_t added;
+ static const char aliasfile[] = "/locale.alias";
+
+ full_fname = (char *) alloca (fname_len + sizeof aliasfile);
+#ifdef HAVE_MEMPCPY
+ mempcpy (mempcpy (full_fname, fname, fname_len),
+ aliasfile, sizeof aliasfile);
+#else
+ memcpy (full_fname, fname, fname_len);
+ memcpy (&full_fname[fname_len], aliasfile, sizeof aliasfile);
+#endif
+
+#ifdef _LIBC
+ /* Note the file is opened with cancellation in the I/O functions
+ disabled. */
+ fp = fopen (relocate (full_fname), "rc");
+#else
+ fp = fopen (relocate (full_fname), "r");
+#endif
+ freea (full_fname);
+ if (fp == NULL)
+ return 0;
+
+#ifdef HAVE___FSETLOCKING
+ /* No threads present. */
+ __fsetlocking (fp, FSETLOCKING_BYCALLER);
+#endif
+
+ added = 0;
+ while (!FEOF (fp))
+ {
+ /* It is a reasonable approach to use a fix buffer here because
+ a) we are only interested in the first two fields
+ b) these fields must be usable as file names and so must not
+ be that long
+ We avoid a multi-kilobyte buffer here since this would use up
+ stack space which we might not have if the program ran out of
+ memory. */
+ char buf[400];
+ char *alias;
+ char *value;
+ char *cp;
+ int complete_line;
+
+ if (FGETS (buf, sizeof buf, fp) == NULL)
+ /* EOF reached. */
+ break;
+
+ /* Determine whether the line is complete. */
+ complete_line = strchr (buf, '\n') != NULL;
+
+ cp = buf;
+ /* Ignore leading white space. */
+ while (isspace ((unsigned char) cp[0]))
+ ++cp;
+
+ /* A leading '#' signals a comment line. */
+ if (cp[0] != '\0' && cp[0] != '#')
+ {
+ alias = cp++;
+ while (cp[0] != '\0' && !isspace ((unsigned char) cp[0]))
+ ++cp;
+ /* Terminate alias name. */
+ if (cp[0] != '\0')
+ *cp++ = '\0';
+
+ /* Now look for the beginning of the value. */
+ while (isspace ((unsigned char) cp[0]))
+ ++cp;
+
+ if (cp[0] != '\0')
+ {
+ value = cp++;
+ while (cp[0] != '\0' && !isspace ((unsigned char) cp[0]))
+ ++cp;
+ /* Terminate value. */
+ if (cp[0] == '\n')
+ {
+ /* This has to be done to make the following test
+ for the end of line possible. We are looking for
+ the terminating '\n' which do not overwrite here. */
+ *cp++ = '\0';
+ *cp = '\n';
+ }
+ else if (cp[0] != '\0')
+ *cp++ = '\0';
+
+#ifdef IN_LIBGLOCALE
+ /* glibc's locale.alias contains entries for ja_JP and ko_KR
+ that make it impossible to use a Japanese or Korean UTF-8
+ locale under the name "ja_JP" or "ko_KR". Ignore these
+ entries. */
+ if (strchr (alias, '_') == NULL)
+#endif
+ {
+ size_t alias_len;
+ size_t value_len;
+
+ if (nmap >= maxmap)
+ if (__builtin_expect (extend_alias_table (), 0))
+ goto out;
+
+ alias_len = strlen (alias) + 1;
+ value_len = strlen (value) + 1;
+
+ if (string_space_act + alias_len + value_len > string_space_max)
+ {
+ /* Increase size of memory pool. */
+ size_t new_size = (string_space_max
+ + (alias_len + value_len > 1024
+ ? alias_len + value_len : 1024));
+ char *new_pool = (char *) realloc (string_space, new_size);
+ if (new_pool == NULL)
+ goto out;
+
+ if (__builtin_expect (string_space != new_pool, 0))
+ {
+ size_t i;
+
+ for (i = 0; i < nmap; i++)
+ {
+ map[i].alias += new_pool - string_space;
+ map[i].value += new_pool - string_space;
+ }
+ }
+
+ string_space = new_pool;
+ string_space_max = new_size;
+ }
+
+ map[nmap].alias =
+ (const char *) memcpy (&string_space[string_space_act],
+ alias, alias_len);
+ string_space_act += alias_len;
+
+ map[nmap].value =
+ (const char *) memcpy (&string_space[string_space_act],
+ value, value_len);
+ string_space_act += value_len;
+
+ ++nmap;
+ ++added;
+ }
+ }
+ }
+
+ /* Possibly not the whole line fits into the buffer. Ignore
+ the rest of the line. */
+ if (! complete_line)
+ do
+ if (FGETS (buf, sizeof buf, fp) == NULL)
+ /* Make sure the inner loop will be left. The outer loop
+ will exit at the `feof' test. */
+ break;
+ while (strchr (buf, '\n') == NULL);
+ }
+
+ out:
+ /* Should we test for ferror()? I think we have to silently ignore
+ errors. --drepper */
+ fclose (fp);
+
+ if (added > 0)
+ qsort (map, nmap, sizeof (struct alias_map),
+ (int (*) (const void *, const void *)) alias_compare);
+
+ return added;
+}
+
+
+static int
+extend_alias_table ()
+{
+ size_t new_size;
+ struct alias_map *new_map;
+
+ new_size = maxmap == 0 ? 100 : 2 * maxmap;
+ new_map = (struct alias_map *) realloc (map, (new_size
+ * sizeof (struct alias_map)));
+ if (new_map == NULL)
+ /* Simply don't extend: we don't have any more core. */
+ return -1;
+
+ map = new_map;
+ maxmap = new_size;
+ return 0;
+}
+
+
+static int
+alias_compare (const struct alias_map *map1, const struct alias_map *map2)
+{
+#if defined _LIBC || defined HAVE_STRCASECMP
+ return strcasecmp (map1->alias, map2->alias);
+#else
+ const unsigned char *p1 = (const unsigned char *) map1->alias;
+ const unsigned char *p2 = (const unsigned char *) map2->alias;
+ unsigned char c1, c2;
+
+ if (p1 == p2)
+ return 0;
+
+ do
+ {
+ /* I know this seems to be odd but the tolower() function in
+ some systems libc cannot handle nonalpha characters. */
+ c1 = isupper (*p1) ? tolower (*p1) : *p1;
+ c2 = isupper (*p2) ? tolower (*p2) : *p2;
+ if (c1 == '\0')
+ break;
+ ++p1;
+ ++p2;
+ }
+ while (c1 == c2);
+
+ return c1 - c2;
+#endif
+}
diff --git a/intl/localename.c b/intl/localename.c
new file mode 100644
index 00000000..89a9692b
--- /dev/null
+++ b/intl/localename.c
@@ -0,0 +1,2959 @@
+/* Determine name of the currently selected locale.
+ Copyright (C) 1995-1999, 2000-2010 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+/* Written by Ulrich Drepper <drepper@gnu.org>, 1995. */
+/* Win32 code written by Tor Lillqvist <tml@iki.fi>. */
+/* MacOS X code written by Bruno Haible <bruno@clisp.org>. */
+
+#include <config.h>
+
+/* Specification. */
+#ifdef IN_LIBINTL
+# include "gettextP.h"
+#else
+# include "localename.h"
+#endif
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <locale.h>
+#include <string.h>
+
+#if HAVE_USELOCALE
+/* MacOS X 10.5 defines the locale_t type in <xlocale.h>. */
+# if defined __APPLE__ && defined __MACH__
+# include <xlocale.h>
+# endif
+# include <langinfo.h>
+# if !defined IN_LIBINTL
+# include "glthread/lock.h"
+# endif
+#endif
+
+#if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE
+# include <CoreFoundation/CFString.h>
+# if HAVE_CFLOCALECOPYCURRENT
+# include <CoreFoundation/CFLocale.h>
+# elif HAVE_CFPREFERENCESCOPYAPPVALUE
+# include <CoreFoundation/CFPreferences.h>
+# endif
+#endif
+
+#if defined _WIN32 || defined __WIN32__
+# define WIN32_NATIVE
+#endif
+
+#if defined WIN32_NATIVE || defined __CYGWIN__ /* WIN32 or Cygwin */
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+/* List of language codes, sorted by value:
+ 0x01 LANG_ARABIC
+ 0x02 LANG_BULGARIAN
+ 0x03 LANG_CATALAN
+ 0x04 LANG_CHINESE
+ 0x05 LANG_CZECH
+ 0x06 LANG_DANISH
+ 0x07 LANG_GERMAN
+ 0x08 LANG_GREEK
+ 0x09 LANG_ENGLISH
+ 0x0a LANG_SPANISH
+ 0x0b LANG_FINNISH
+ 0x0c LANG_FRENCH
+ 0x0d LANG_HEBREW
+ 0x0e LANG_HUNGARIAN
+ 0x0f LANG_ICELANDIC
+ 0x10 LANG_ITALIAN
+ 0x11 LANG_JAPANESE
+ 0x12 LANG_KOREAN
+ 0x13 LANG_DUTCH
+ 0x14 LANG_NORWEGIAN
+ 0x15 LANG_POLISH
+ 0x16 LANG_PORTUGUESE
+ 0x17 LANG_ROMANSH
+ 0x18 LANG_ROMANIAN
+ 0x19 LANG_RUSSIAN
+ 0x1a LANG_CROATIAN == LANG_SERBIAN
+ 0x1b LANG_SLOVAK
+ 0x1c LANG_ALBANIAN
+ 0x1d LANG_SWEDISH
+ 0x1e LANG_THAI
+ 0x1f LANG_TURKISH
+ 0x20 LANG_URDU
+ 0x21 LANG_INDONESIAN
+ 0x22 LANG_UKRAINIAN
+ 0x23 LANG_BELARUSIAN
+ 0x24 LANG_SLOVENIAN
+ 0x25 LANG_ESTONIAN
+ 0x26 LANG_LATVIAN
+ 0x27 LANG_LITHUANIAN
+ 0x28 LANG_TAJIK
+ 0x29 LANG_FARSI
+ 0x2a LANG_VIETNAMESE
+ 0x2b LANG_ARMENIAN
+ 0x2c LANG_AZERI
+ 0x2d LANG_BASQUE
+ 0x2e LANG_SORBIAN
+ 0x2f LANG_MACEDONIAN
+ 0x30 LANG_SUTU
+ 0x31 LANG_TSONGA
+ 0x32 LANG_TSWANA
+ 0x33 LANG_VENDA
+ 0x34 LANG_XHOSA
+ 0x35 LANG_ZULU
+ 0x36 LANG_AFRIKAANS
+ 0x37 LANG_GEORGIAN
+ 0x38 LANG_FAEROESE
+ 0x39 LANG_HINDI
+ 0x3a LANG_MALTESE
+ 0x3b LANG_SAMI
+ 0x3c LANG_GAELIC
+ 0x3d LANG_YIDDISH
+ 0x3e LANG_MALAY
+ 0x3f LANG_KAZAK
+ 0x40 LANG_KYRGYZ
+ 0x41 LANG_SWAHILI
+ 0x42 LANG_TURKMEN
+ 0x43 LANG_UZBEK
+ 0x44 LANG_TATAR
+ 0x45 LANG_BENGALI
+ 0x46 LANG_PUNJABI
+ 0x47 LANG_GUJARATI
+ 0x48 LANG_ORIYA
+ 0x49 LANG_TAMIL
+ 0x4a LANG_TELUGU
+ 0x4b LANG_KANNADA
+ 0x4c LANG_MALAYALAM
+ 0x4d LANG_ASSAMESE
+ 0x4e LANG_MARATHI
+ 0x4f LANG_SANSKRIT
+ 0x50 LANG_MONGOLIAN
+ 0x51 LANG_TIBETAN
+ 0x52 LANG_WELSH
+ 0x53 LANG_CAMBODIAN
+ 0x54 LANG_LAO
+ 0x55 LANG_BURMESE
+ 0x56 LANG_GALICIAN
+ 0x57 LANG_KONKANI
+ 0x58 LANG_MANIPURI
+ 0x59 LANG_SINDHI
+ 0x5a LANG_SYRIAC
+ 0x5b LANG_SINHALESE
+ 0x5c LANG_CHEROKEE
+ 0x5d LANG_INUKTITUT
+ 0x5e LANG_AMHARIC
+ 0x5f LANG_TAMAZIGHT
+ 0x60 LANG_KASHMIRI
+ 0x61 LANG_NEPALI
+ 0x62 LANG_FRISIAN
+ 0x63 LANG_PASHTO
+ 0x64 LANG_TAGALOG
+ 0x65 LANG_DIVEHI
+ 0x66 LANG_EDO
+ 0x67 LANG_FULFULDE
+ 0x68 LANG_HAUSA
+ 0x69 LANG_IBIBIO
+ 0x6a LANG_YORUBA
+ 0x6d LANG_BASHKIR
+ 0x6e LANG_LUXEMBOURGISH
+ 0x6f LANG_GREENLANDIC
+ 0x70 LANG_IGBO
+ 0x71 LANG_KANURI
+ 0x72 LANG_OROMO
+ 0x73 LANG_TIGRINYA
+ 0x74 LANG_GUARANI
+ 0x75 LANG_HAWAIIAN
+ 0x76 LANG_LATIN
+ 0x77 LANG_SOMALI
+ 0x78 LANG_YI
+ 0x79 LANG_PAPIAMENTU
+ 0x7a LANG_MAPUDUNGUN
+ 0x7c LANG_MOHAWK
+ 0x7e LANG_BRETON
+ 0x82 LANG_OCCITAN
+ 0x83 LANG_CORSICAN
+ 0x84 LANG_ALSATIAN
+ 0x85 LANG_YAKUT
+ 0x86 LANG_KICHE
+ 0x87 LANG_KINYARWANDA
+ 0x88 LANG_WOLOF
+ 0x8c LANG_DARI
+ 0x91 LANG_SCOTTISH_GAELIC
+*/
+/* Mingw headers don't have latest language and sublanguage codes. */
+# ifndef LANG_AFRIKAANS
+# define LANG_AFRIKAANS 0x36
+# endif
+# ifndef LANG_ALBANIAN
+# define LANG_ALBANIAN 0x1c
+# endif
+# ifndef LANG_ALSATIAN
+# define LANG_ALSATIAN 0x84
+# endif
+# ifndef LANG_AMHARIC
+# define LANG_AMHARIC 0x5e
+# endif
+# ifndef LANG_ARABIC
+# define LANG_ARABIC 0x01
+# endif
+# ifndef LANG_ARMENIAN
+# define LANG_ARMENIAN 0x2b
+# endif
+# ifndef LANG_ASSAMESE
+# define LANG_ASSAMESE 0x4d
+# endif
+# ifndef LANG_AZERI
+# define LANG_AZERI 0x2c
+# endif
+# ifndef LANG_BASHKIR
+# define LANG_BASHKIR 0x6d
+# endif
+# ifndef LANG_BASQUE
+# define LANG_BASQUE 0x2d
+# endif
+# ifndef LANG_BELARUSIAN
+# define LANG_BELARUSIAN 0x23
+# endif
+# ifndef LANG_BENGALI
+# define LANG_BENGALI 0x45
+# endif
+# ifndef LANG_BRETON
+# define LANG_BRETON 0x7e
+# endif
+# ifndef LANG_BURMESE
+# define LANG_BURMESE 0x55
+# endif
+# ifndef LANG_CAMBODIAN
+# define LANG_CAMBODIAN 0x53
+# endif
+# ifndef LANG_CATALAN
+# define LANG_CATALAN 0x03
+# endif
+# ifndef LANG_CHEROKEE
+# define LANG_CHEROKEE 0x5c
+# endif
+# ifndef LANG_CORSICAN
+# define LANG_CORSICAN 0x83
+# endif
+# ifndef LANG_DARI
+# define LANG_DARI 0x8c
+# endif
+# ifndef LANG_DIVEHI
+# define LANG_DIVEHI 0x65
+# endif
+# ifndef LANG_EDO
+# define LANG_EDO 0x66
+# endif
+# ifndef LANG_ESTONIAN
+# define LANG_ESTONIAN 0x25
+# endif
+# ifndef LANG_FAEROESE
+# define LANG_FAEROESE 0x38
+# endif
+# ifndef LANG_FARSI
+# define LANG_FARSI 0x29
+# endif
+# ifndef LANG_FRISIAN
+# define LANG_FRISIAN 0x62
+# endif
+# ifndef LANG_FULFULDE
+# define LANG_FULFULDE 0x67
+# endif
+# ifndef LANG_GAELIC
+# define LANG_GAELIC 0x3c
+# endif
+# ifndef LANG_GALICIAN
+# define LANG_GALICIAN 0x56
+# endif
+# ifndef LANG_GEORGIAN
+# define LANG_GEORGIAN 0x37
+# endif
+# ifndef LANG_GREENLANDIC
+# define LANG_GREENLANDIC 0x6f
+# endif
+# ifndef LANG_GUARANI
+# define LANG_GUARANI 0x74
+# endif
+# ifndef LANG_GUJARATI
+# define LANG_GUJARATI 0x47
+# endif
+# ifndef LANG_HAUSA
+# define LANG_HAUSA 0x68
+# endif
+# ifndef LANG_HAWAIIAN
+# define LANG_HAWAIIAN 0x75
+# endif
+# ifndef LANG_HEBREW
+# define LANG_HEBREW 0x0d
+# endif
+# ifndef LANG_HINDI
+# define LANG_HINDI 0x39
+# endif
+# ifndef LANG_IBIBIO
+# define LANG_IBIBIO 0x69
+# endif
+# ifndef LANG_IGBO
+# define LANG_IGBO 0x70
+# endif
+# ifndef LANG_INDONESIAN
+# define LANG_INDONESIAN 0x21
+# endif
+# ifndef LANG_INUKTITUT
+# define LANG_INUKTITUT 0x5d
+# endif
+# ifndef LANG_KANNADA
+# define LANG_KANNADA 0x4b
+# endif
+# ifndef LANG_KANURI
+# define LANG_KANURI 0x71
+# endif
+# ifndef LANG_KASHMIRI
+# define LANG_KASHMIRI 0x60
+# endif
+# ifndef LANG_KAZAK
+# define LANG_KAZAK 0x3f
+# endif
+# ifndef LANG_KICHE
+# define LANG_KICHE 0x86
+# endif
+# ifndef LANG_KINYARWANDA
+# define LANG_KINYARWANDA 0x87
+# endif
+# ifndef LANG_KONKANI
+# define LANG_KONKANI 0x57
+# endif
+# ifndef LANG_KYRGYZ
+# define LANG_KYRGYZ 0x40
+# endif
+# ifndef LANG_LAO
+# define LANG_LAO 0x54
+# endif
+# ifndef LANG_LATIN
+# define LANG_LATIN 0x76
+# endif
+# ifndef LANG_LATVIAN
+# define LANG_LATVIAN 0x26
+# endif
+# ifndef LANG_LITHUANIAN
+# define LANG_LITHUANIAN 0x27
+# endif
+# ifndef LANG_LUXEMBOURGISH
+# define LANG_LUXEMBOURGISH 0x6e
+# endif
+# ifndef LANG_MACEDONIAN
+# define LANG_MACEDONIAN 0x2f
+# endif
+# ifndef LANG_MALAY
+# define LANG_MALAY 0x3e
+# endif
+# ifndef LANG_MALAYALAM
+# define LANG_MALAYALAM 0x4c
+# endif
+# ifndef LANG_MALTESE
+# define LANG_MALTESE 0x3a
+# endif
+# ifndef LANG_MANIPURI
+# define LANG_MANIPURI 0x58
+# endif
+# ifndef LANG_MAORI
+# define LANG_MAORI 0x81
+# endif
+# ifndef LANG_MAPUDUNGUN
+# define LANG_MAPUDUNGUN 0x7a
+# endif
+# ifndef LANG_MARATHI
+# define LANG_MARATHI 0x4e
+# endif
+# ifndef LANG_MOHAWK
+# define LANG_MOHAWK 0x7c
+# endif
+# ifndef LANG_MONGOLIAN
+# define LANG_MONGOLIAN 0x50
+# endif
+# ifndef LANG_NEPALI
+# define LANG_NEPALI 0x61
+# endif
+# ifndef LANG_OCCITAN
+# define LANG_OCCITAN 0x82
+# endif
+# ifndef LANG_ORIYA
+# define LANG_ORIYA 0x48
+# endif
+# ifndef LANG_OROMO
+# define LANG_OROMO 0x72
+# endif
+# ifndef LANG_PAPIAMENTU
+# define LANG_PAPIAMENTU 0x79
+# endif
+# ifndef LANG_PASHTO
+# define LANG_PASHTO 0x63
+# endif
+# ifndef LANG_PUNJABI
+# define LANG_PUNJABI 0x46
+# endif
+# ifndef LANG_QUECHUA
+# define LANG_QUECHUA 0x6b
+# endif
+# ifndef LANG_ROMANSH
+# define LANG_ROMANSH 0x17
+# endif
+# ifndef LANG_SAMI
+# define LANG_SAMI 0x3b
+# endif
+# ifndef LANG_SANSKRIT
+# define LANG_SANSKRIT 0x4f
+# endif
+# ifndef LANG_SCOTTISH_GAELIC
+# define LANG_SCOTTISH_GAELIC 0x91
+# endif
+# ifndef LANG_SERBIAN
+# define LANG_SERBIAN 0x1a
+# endif
+# ifndef LANG_SINDHI
+# define LANG_SINDHI 0x59
+# endif
+# ifndef LANG_SINHALESE
+# define LANG_SINHALESE 0x5b
+# endif
+# ifndef LANG_SLOVAK
+# define LANG_SLOVAK 0x1b
+# endif
+# ifndef LANG_SOMALI
+# define LANG_SOMALI 0x77
+# endif
+# ifndef LANG_SORBIAN
+# define LANG_SORBIAN 0x2e
+# endif
+# ifndef LANG_SOTHO
+# define LANG_SOTHO 0x6c
+# endif
+# ifndef LANG_SUTU
+# define LANG_SUTU 0x30
+# endif
+# ifndef LANG_SWAHILI
+# define LANG_SWAHILI 0x41
+# endif
+# ifndef LANG_SYRIAC
+# define LANG_SYRIAC 0x5a
+# endif
+# ifndef LANG_TAGALOG
+# define LANG_TAGALOG 0x64
+# endif
+# ifndef LANG_TAJIK
+# define LANG_TAJIK 0x28
+# endif
+# ifndef LANG_TAMAZIGHT
+# define LANG_TAMAZIGHT 0x5f
+# endif
+# ifndef LANG_TAMIL
+# define LANG_TAMIL 0x49
+# endif
+# ifndef LANG_TATAR
+# define LANG_TATAR 0x44
+# endif
+# ifndef LANG_TELUGU
+# define LANG_TELUGU 0x4a
+# endif
+# ifndef LANG_THAI
+# define LANG_THAI 0x1e
+# endif
+# ifndef LANG_TIBETAN
+# define LANG_TIBETAN 0x51
+# endif
+# ifndef LANG_TIGRINYA
+# define LANG_TIGRINYA 0x73
+# endif
+# ifndef LANG_TSONGA
+# define LANG_TSONGA 0x31
+# endif
+# ifndef LANG_TSWANA
+# define LANG_TSWANA 0x32
+# endif
+# ifndef LANG_TURKMEN
+# define LANG_TURKMEN 0x42
+# endif
+# ifndef LANG_UIGHUR
+# define LANG_UIGHUR 0x80
+# endif
+# ifndef LANG_UKRAINIAN
+# define LANG_UKRAINIAN 0x22
+# endif
+# ifndef LANG_URDU
+# define LANG_URDU 0x20
+# endif
+# ifndef LANG_UZBEK
+# define LANG_UZBEK 0x43
+# endif
+# ifndef LANG_VENDA
+# define LANG_VENDA 0x33
+# endif
+# ifndef LANG_VIETNAMESE
+# define LANG_VIETNAMESE 0x2a
+# endif
+# ifndef LANG_WELSH
+# define LANG_WELSH 0x52
+# endif
+# ifndef LANG_WOLOF
+# define LANG_WOLOF 0x88
+# endif
+# ifndef LANG_XHOSA
+# define LANG_XHOSA 0x34
+# endif
+# ifndef LANG_YAKUT
+# define LANG_YAKUT 0x85
+# endif
+# ifndef LANG_YI
+# define LANG_YI 0x78
+# endif
+# ifndef LANG_YIDDISH
+# define LANG_YIDDISH 0x3d
+# endif
+# ifndef LANG_YORUBA
+# define LANG_YORUBA 0x6a
+# endif
+# ifndef LANG_ZULU
+# define LANG_ZULU 0x35
+# endif
+# ifndef SUBLANG_AFRIKAANS_SOUTH_AFRICA
+# define SUBLANG_AFRIKAANS_SOUTH_AFRICA 0x01
+# endif
+# ifndef SUBLANG_ALBANIAN_ALBANIA
+# define SUBLANG_ALBANIAN_ALBANIA 0x01
+# endif
+# ifndef SUBLANG_ALSATIAN_FRANCE
+# define SUBLANG_ALSATIAN_FRANCE 0x01
+# endif
+# ifndef SUBLANG_AMHARIC_ETHIOPIA
+# define SUBLANG_AMHARIC_ETHIOPIA 0x01
+# endif
+# ifndef SUBLANG_ARABIC_SAUDI_ARABIA
+# define SUBLANG_ARABIC_SAUDI_ARABIA 0x01
+# endif
+# ifndef SUBLANG_ARABIC_IRAQ
+# define SUBLANG_ARABIC_IRAQ 0x02
+# endif
+# ifndef SUBLANG_ARABIC_EGYPT
+# define SUBLANG_ARABIC_EGYPT 0x03
+# endif
+# ifndef SUBLANG_ARABIC_LIBYA
+# define SUBLANG_ARABIC_LIBYA 0x04
+# endif
+# ifndef SUBLANG_ARABIC_ALGERIA
+# define SUBLANG_ARABIC_ALGERIA 0x05
+# endif
+# ifndef SUBLANG_ARABIC_MOROCCO
+# define SUBLANG_ARABIC_MOROCCO 0x06
+# endif
+# ifndef SUBLANG_ARABIC_TUNISIA
+# define SUBLANG_ARABIC_TUNISIA 0x07
+# endif
+# ifndef SUBLANG_ARABIC_OMAN
+# define SUBLANG_ARABIC_OMAN 0x08
+# endif
+# ifndef SUBLANG_ARABIC_YEMEN
+# define SUBLANG_ARABIC_YEMEN 0x09
+# endif
+# ifndef SUBLANG_ARABIC_SYRIA
+# define SUBLANG_ARABIC_SYRIA 0x0a
+# endif
+# ifndef SUBLANG_ARABIC_JORDAN
+# define SUBLANG_ARABIC_JORDAN 0x0b
+# endif
+# ifndef SUBLANG_ARABIC_LEBANON
+# define SUBLANG_ARABIC_LEBANON 0x0c
+# endif
+# ifndef SUBLANG_ARABIC_KUWAIT
+# define SUBLANG_ARABIC_KUWAIT 0x0d
+# endif
+# ifndef SUBLANG_ARABIC_UAE
+# define SUBLANG_ARABIC_UAE 0x0e
+# endif
+# ifndef SUBLANG_ARABIC_BAHRAIN
+# define SUBLANG_ARABIC_BAHRAIN 0x0f
+# endif
+# ifndef SUBLANG_ARABIC_QATAR
+# define SUBLANG_ARABIC_QATAR 0x10
+# endif
+# ifndef SUBLANG_ARMENIAN_ARMENIA
+# define SUBLANG_ARMENIAN_ARMENIA 0x01
+# endif
+# ifndef SUBLANG_ASSAMESE_INDIA
+# define SUBLANG_ASSAMESE_INDIA 0x01
+# endif
+# ifndef SUBLANG_AZERI_LATIN
+# define SUBLANG_AZERI_LATIN 0x01
+# endif
+# ifndef SUBLANG_AZERI_CYRILLIC
+# define SUBLANG_AZERI_CYRILLIC 0x02
+# endif
+# ifndef SUBLANG_BASHKIR_RUSSIA
+# define SUBLANG_BASHKIR_RUSSIA 0x01
+# endif
+# ifndef SUBLANG_BASQUE_BASQUE
+# define SUBLANG_BASQUE_BASQUE 0x01
+# endif
+# ifndef SUBLANG_BELARUSIAN_BELARUS
+# define SUBLANG_BELARUSIAN_BELARUS 0x01
+# endif
+# ifndef SUBLANG_BENGALI_INDIA
+# define SUBLANG_BENGALI_INDIA 0x01
+# endif
+# ifndef SUBLANG_BENGALI_BANGLADESH
+# define SUBLANG_BENGALI_BANGLADESH 0x02
+# endif
+# ifndef SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN
+# define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN 0x05
+# endif
+# ifndef SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC
+# define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC 0x08
+# endif
+# ifndef SUBLANG_BRETON_FRANCE
+# define SUBLANG_BRETON_FRANCE 0x01
+# endif
+# ifndef SUBLANG_BULGARIAN_BULGARIA
+# define SUBLANG_BULGARIAN_BULGARIA 0x01
+# endif
+# ifndef SUBLANG_CAMBODIAN_CAMBODIA
+# define SUBLANG_CAMBODIAN_CAMBODIA 0x01
+# endif
+# ifndef SUBLANG_CATALAN_SPAIN
+# define SUBLANG_CATALAN_SPAIN 0x01
+# endif
+# ifndef SUBLANG_CORSICAN_FRANCE
+# define SUBLANG_CORSICAN_FRANCE 0x01
+# endif
+# ifndef SUBLANG_CROATIAN_CROATIA
+# define SUBLANG_CROATIAN_CROATIA 0x01
+# endif
+# ifndef SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN
+# define SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN 0x04
+# endif
+# ifndef SUBLANG_CHINESE_MACAU
+# define SUBLANG_CHINESE_MACAU 0x05
+# endif
+# ifndef SUBLANG_CZECH_CZECH_REPUBLIC
+# define SUBLANG_CZECH_CZECH_REPUBLIC 0x01
+# endif
+# ifndef SUBLANG_DANISH_DENMARK
+# define SUBLANG_DANISH_DENMARK 0x01
+# endif
+# ifndef SUBLANG_DARI_AFGHANISTAN
+# define SUBLANG_DARI_AFGHANISTAN 0x01
+# endif
+# ifndef SUBLANG_DIVEHI_MALDIVES
+# define SUBLANG_DIVEHI_MALDIVES 0x01
+# endif
+# ifndef SUBLANG_DUTCH_SURINAM
+# define SUBLANG_DUTCH_SURINAM 0x03
+# endif
+# ifndef SUBLANG_ENGLISH_SOUTH_AFRICA
+# define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07
+# endif
+# ifndef SUBLANG_ENGLISH_JAMAICA
+# define SUBLANG_ENGLISH_JAMAICA 0x08
+# endif
+# ifndef SUBLANG_ENGLISH_CARIBBEAN
+# define SUBLANG_ENGLISH_CARIBBEAN 0x09
+# endif
+# ifndef SUBLANG_ENGLISH_BELIZE
+# define SUBLANG_ENGLISH_BELIZE 0x0a
+# endif
+# ifndef SUBLANG_ENGLISH_TRINIDAD
+# define SUBLANG_ENGLISH_TRINIDAD 0x0b
+# endif
+# ifndef SUBLANG_ENGLISH_ZIMBABWE
+# define SUBLANG_ENGLISH_ZIMBABWE 0x0c
+# endif
+# ifndef SUBLANG_ENGLISH_PHILIPPINES
+# define SUBLANG_ENGLISH_PHILIPPINES 0x0d
+# endif
+# ifndef SUBLANG_ENGLISH_INDONESIA
+# define SUBLANG_ENGLISH_INDONESIA 0x0e
+# endif
+# ifndef SUBLANG_ENGLISH_HONGKONG
+# define SUBLANG_ENGLISH_HONGKONG 0x0f
+# endif
+# ifndef SUBLANG_ENGLISH_INDIA
+# define SUBLANG_ENGLISH_INDIA 0x10
+# endif
+# ifndef SUBLANG_ENGLISH_MALAYSIA
+# define SUBLANG_ENGLISH_MALAYSIA 0x11
+# endif
+# ifndef SUBLANG_ENGLISH_SINGAPORE
+# define SUBLANG_ENGLISH_SINGAPORE 0x12
+# endif
+# ifndef SUBLANG_ESTONIAN_ESTONIA
+# define SUBLANG_ESTONIAN_ESTONIA 0x01
+# endif
+# ifndef SUBLANG_FAEROESE_FAROE_ISLANDS
+# define SUBLANG_FAEROESE_FAROE_ISLANDS 0x01
+# endif
+# ifndef SUBLANG_FARSI_IRAN
+# define SUBLANG_FARSI_IRAN 0x01
+# endif
+# ifndef SUBLANG_FINNISH_FINLAND
+# define SUBLANG_FINNISH_FINLAND 0x01
+# endif
+# ifndef SUBLANG_FRENCH_LUXEMBOURG
+# define SUBLANG_FRENCH_LUXEMBOURG 0x05
+# endif
+# ifndef SUBLANG_FRENCH_MONACO
+# define SUBLANG_FRENCH_MONACO 0x06
+# endif
+# ifndef SUBLANG_FRENCH_WESTINDIES
+# define SUBLANG_FRENCH_WESTINDIES 0x07
+# endif
+# ifndef SUBLANG_FRENCH_REUNION
+# define SUBLANG_FRENCH_REUNION 0x08
+# endif
+# ifndef SUBLANG_FRENCH_CONGO
+# define SUBLANG_FRENCH_CONGO 0x09
+# endif
+# ifndef SUBLANG_FRENCH_SENEGAL
+# define SUBLANG_FRENCH_SENEGAL 0x0a
+# endif
+# ifndef SUBLANG_FRENCH_CAMEROON
+# define SUBLANG_FRENCH_CAMEROON 0x0b
+# endif
+# ifndef SUBLANG_FRENCH_COTEDIVOIRE
+# define SUBLANG_FRENCH_COTEDIVOIRE 0x0c
+# endif
+# ifndef SUBLANG_FRENCH_MALI
+# define SUBLANG_FRENCH_MALI 0x0d
+# endif
+# ifndef SUBLANG_FRENCH_MOROCCO
+# define SUBLANG_FRENCH_MOROCCO 0x0e
+# endif
+# ifndef SUBLANG_FRENCH_HAITI
+# define SUBLANG_FRENCH_HAITI 0x0f
+# endif
+# ifndef SUBLANG_FRISIAN_NETHERLANDS
+# define SUBLANG_FRISIAN_NETHERLANDS 0x01
+# endif
+# ifndef SUBLANG_GALICIAN_SPAIN
+# define SUBLANG_GALICIAN_SPAIN 0x01
+# endif
+# ifndef SUBLANG_GEORGIAN_GEORGIA
+# define SUBLANG_GEORGIAN_GEORGIA 0x01
+# endif
+# ifndef SUBLANG_GERMAN_LUXEMBOURG
+# define SUBLANG_GERMAN_LUXEMBOURG 0x04
+# endif
+# ifndef SUBLANG_GERMAN_LIECHTENSTEIN
+# define SUBLANG_GERMAN_LIECHTENSTEIN 0x05
+# endif
+# ifndef SUBLANG_GREEK_GREECE
+# define SUBLANG_GREEK_GREECE 0x01
+# endif
+# ifndef SUBLANG_GREENLANDIC_GREENLAND
+# define SUBLANG_GREENLANDIC_GREENLAND 0x01
+# endif
+# ifndef SUBLANG_GUJARATI_INDIA
+# define SUBLANG_GUJARATI_INDIA 0x01
+# endif
+# ifndef SUBLANG_HAUSA_NIGERIA_LATIN
+# define SUBLANG_HAUSA_NIGERIA_LATIN 0x01
+# endif
+# ifndef SUBLANG_HEBREW_ISRAEL
+# define SUBLANG_HEBREW_ISRAEL 0x01
+# endif
+# ifndef SUBLANG_HINDI_INDIA
+# define SUBLANG_HINDI_INDIA 0x01
+# endif
+# ifndef SUBLANG_HUNGARIAN_HUNGARY
+# define SUBLANG_HUNGARIAN_HUNGARY 0x01
+# endif
+# ifndef SUBLANG_ICELANDIC_ICELAND
+# define SUBLANG_ICELANDIC_ICELAND 0x01
+# endif
+# ifndef SUBLANG_IGBO_NIGERIA
+# define SUBLANG_IGBO_NIGERIA 0x01
+# endif
+# ifndef SUBLANG_INDONESIAN_INDONESIA
+# define SUBLANG_INDONESIAN_INDONESIA 0x01
+# endif
+# ifndef SUBLANG_INUKTITUT_CANADA
+# define SUBLANG_INUKTITUT_CANADA 0x01
+# endif
+# undef SUBLANG_INUKTITUT_CANADA_LATIN
+# define SUBLANG_INUKTITUT_CANADA_LATIN 0x02
+# undef SUBLANG_IRISH_IRELAND
+# define SUBLANG_IRISH_IRELAND 0x02
+# ifndef SUBLANG_JAPANESE_JAPAN
+# define SUBLANG_JAPANESE_JAPAN 0x01
+# endif
+# ifndef SUBLANG_KANNADA_INDIA
+# define SUBLANG_KANNADA_INDIA 0x01
+# endif
+# ifndef SUBLANG_KASHMIRI_INDIA
+# define SUBLANG_KASHMIRI_INDIA 0x02
+# endif
+# ifndef SUBLANG_KAZAK_KAZAKHSTAN
+# define SUBLANG_KAZAK_KAZAKHSTAN 0x01
+# endif
+# ifndef SUBLANG_KICHE_GUATEMALA
+# define SUBLANG_KICHE_GUATEMALA 0x01
+# endif
+# ifndef SUBLANG_KINYARWANDA_RWANDA
+# define SUBLANG_KINYARWANDA_RWANDA 0x01
+# endif
+# ifndef SUBLANG_KONKANI_INDIA
+# define SUBLANG_KONKANI_INDIA 0x01
+# endif
+# ifndef SUBLANG_KYRGYZ_KYRGYZSTAN
+# define SUBLANG_KYRGYZ_KYRGYZSTAN 0x01
+# endif
+# ifndef SUBLANG_LAO_LAOS
+# define SUBLANG_LAO_LAOS 0x01
+# endif
+# ifndef SUBLANG_LATVIAN_LATVIA
+# define SUBLANG_LATVIAN_LATVIA 0x01
+# endif
+# ifndef SUBLANG_LITHUANIAN_LITHUANIA
+# define SUBLANG_LITHUANIAN_LITHUANIA 0x01
+# endif
+# undef SUBLANG_LOWER_SORBIAN_GERMANY
+# define SUBLANG_LOWER_SORBIAN_GERMANY 0x02
+# ifndef SUBLANG_LUXEMBOURGISH_LUXEMBOURG
+# define SUBLANG_LUXEMBOURGISH_LUXEMBOURG 0x01
+# endif
+# ifndef SUBLANG_MACEDONIAN_MACEDONIA
+# define SUBLANG_MACEDONIAN_MACEDONIA 0x01
+# endif
+# ifndef SUBLANG_MALAY_MALAYSIA
+# define SUBLANG_MALAY_MALAYSIA 0x01
+# endif
+# ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM
+# define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02
+# endif
+# ifndef SUBLANG_MALAYALAM_INDIA
+# define SUBLANG_MALAYALAM_INDIA 0x01
+# endif
+# ifndef SUBLANG_MALTESE_MALTA
+# define SUBLANG_MALTESE_MALTA 0x01
+# endif
+# ifndef SUBLANG_MAORI_NEW_ZEALAND
+# define SUBLANG_MAORI_NEW_ZEALAND 0x01
+# endif
+# ifndef SUBLANG_MAPUDUNGUN_CHILE
+# define SUBLANG_MAPUDUNGUN_CHILE 0x01
+# endif
+# ifndef SUBLANG_MARATHI_INDIA
+# define SUBLANG_MARATHI_INDIA 0x01
+# endif
+# ifndef SUBLANG_MOHAWK_CANADA
+# define SUBLANG_MOHAWK_CANADA 0x01
+# endif
+# ifndef SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA
+# define SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA 0x01
+# endif
+# ifndef SUBLANG_MONGOLIAN_PRC
+# define SUBLANG_MONGOLIAN_PRC 0x02
+# endif
+# ifndef SUBLANG_NEPALI_NEPAL
+# define SUBLANG_NEPALI_NEPAL 0x01
+# endif
+# ifndef SUBLANG_NEPALI_INDIA
+# define SUBLANG_NEPALI_INDIA 0x02
+# endif
+# ifndef SUBLANG_OCCITAN_FRANCE
+# define SUBLANG_OCCITAN_FRANCE 0x01
+# endif
+# ifndef SUBLANG_ORIYA_INDIA
+# define SUBLANG_ORIYA_INDIA 0x01
+# endif
+# ifndef SUBLANG_PASHTO_AFGHANISTAN
+# define SUBLANG_PASHTO_AFGHANISTAN 0x01
+# endif
+# ifndef SUBLANG_POLISH_POLAND
+# define SUBLANG_POLISH_POLAND 0x01
+# endif
+# ifndef SUBLANG_PUNJABI_INDIA
+# define SUBLANG_PUNJABI_INDIA 0x01
+# endif
+# ifndef SUBLANG_PUNJABI_PAKISTAN
+# define SUBLANG_PUNJABI_PAKISTAN 0x02
+# endif
+# ifndef SUBLANG_QUECHUA_BOLIVIA
+# define SUBLANG_QUECHUA_BOLIVIA 0x01
+# endif
+# ifndef SUBLANG_QUECHUA_ECUADOR
+# define SUBLANG_QUECHUA_ECUADOR 0x02
+# endif
+# ifndef SUBLANG_QUECHUA_PERU
+# define SUBLANG_QUECHUA_PERU 0x03
+# endif
+# ifndef SUBLANG_ROMANIAN_ROMANIA
+# define SUBLANG_ROMANIAN_ROMANIA 0x01
+# endif
+# ifndef SUBLANG_ROMANIAN_MOLDOVA
+# define SUBLANG_ROMANIAN_MOLDOVA 0x02
+# endif
+# ifndef SUBLANG_ROMANSH_SWITZERLAND
+# define SUBLANG_ROMANSH_SWITZERLAND 0x01
+# endif
+# ifndef SUBLANG_RUSSIAN_RUSSIA
+# define SUBLANG_RUSSIAN_RUSSIA 0x01
+# endif
+# ifndef SUBLANG_RUSSIAN_MOLDAVIA
+# define SUBLANG_RUSSIAN_MOLDAVIA 0x02
+# endif
+# ifndef SUBLANG_SAMI_NORTHERN_NORWAY
+# define SUBLANG_SAMI_NORTHERN_NORWAY 0x01
+# endif
+# ifndef SUBLANG_SAMI_NORTHERN_SWEDEN
+# define SUBLANG_SAMI_NORTHERN_SWEDEN 0x02
+# endif
+# ifndef SUBLANG_SAMI_NORTHERN_FINLAND
+# define SUBLANG_SAMI_NORTHERN_FINLAND 0x03
+# endif
+# ifndef SUBLANG_SAMI_LULE_NORWAY
+# define SUBLANG_SAMI_LULE_NORWAY 0x04
+# endif
+# ifndef SUBLANG_SAMI_LULE_SWEDEN
+# define SUBLANG_SAMI_LULE_SWEDEN 0x05
+# endif
+# ifndef SUBLANG_SAMI_SOUTHERN_NORWAY
+# define SUBLANG_SAMI_SOUTHERN_NORWAY 0x06
+# endif
+# ifndef SUBLANG_SAMI_SOUTHERN_SWEDEN
+# define SUBLANG_SAMI_SOUTHERN_SWEDEN 0x07
+# endif
+# undef SUBLANG_SAMI_SKOLT_FINLAND
+# define SUBLANG_SAMI_SKOLT_FINLAND 0x08
+# undef SUBLANG_SAMI_INARI_FINLAND
+# define SUBLANG_SAMI_INARI_FINLAND 0x09
+# ifndef SUBLANG_SANSKRIT_INDIA
+# define SUBLANG_SANSKRIT_INDIA 0x01
+# endif
+# ifndef SUBLANG_SERBIAN_LATIN
+# define SUBLANG_SERBIAN_LATIN 0x02
+# endif
+# ifndef SUBLANG_SERBIAN_CYRILLIC
+# define SUBLANG_SERBIAN_CYRILLIC 0x03
+# endif
+# ifndef SUBLANG_SINDHI_INDIA
+# define SUBLANG_SINDHI_INDIA 0x01
+# endif
+# undef SUBLANG_SINDHI_PAKISTAN
+# define SUBLANG_SINDHI_PAKISTAN 0x02
+# ifndef SUBLANG_SINDHI_AFGHANISTAN
+# define SUBLANG_SINDHI_AFGHANISTAN 0x02
+# endif
+# ifndef SUBLANG_SINHALESE_SRI_LANKA
+# define SUBLANG_SINHALESE_SRI_LANKA 0x01
+# endif
+# ifndef SUBLANG_SLOVAK_SLOVAKIA
+# define SUBLANG_SLOVAK_SLOVAKIA 0x01
+# endif
+# ifndef SUBLANG_SLOVENIAN_SLOVENIA
+# define SUBLANG_SLOVENIAN_SLOVENIA 0x01
+# endif
+# ifndef SUBLANG_SOTHO_SOUTH_AFRICA
+# define SUBLANG_SOTHO_SOUTH_AFRICA 0x01
+# endif
+# ifndef SUBLANG_SPANISH_GUATEMALA
+# define SUBLANG_SPANISH_GUATEMALA 0x04
+# endif
+# ifndef SUBLANG_SPANISH_COSTA_RICA
+# define SUBLANG_SPANISH_COSTA_RICA 0x05
+# endif
+# ifndef SUBLANG_SPANISH_PANAMA
+# define SUBLANG_SPANISH_PANAMA 0x06
+# endif
+# ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC
+# define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07
+# endif
+# ifndef SUBLANG_SPANISH_VENEZUELA
+# define SUBLANG_SPANISH_VENEZUELA 0x08
+# endif
+# ifndef SUBLANG_SPANISH_COLOMBIA
+# define SUBLANG_SPANISH_COLOMBIA 0x09
+# endif
+# ifndef SUBLANG_SPANISH_PERU
+# define SUBLANG_SPANISH_PERU 0x0a
+# endif
+# ifndef SUBLANG_SPANISH_ARGENTINA
+# define SUBLANG_SPANISH_ARGENTINA 0x0b
+# endif
+# ifndef SUBLANG_SPANISH_ECUADOR
+# define SUBLANG_SPANISH_ECUADOR 0x0c
+# endif
+# ifndef SUBLANG_SPANISH_CHILE
+# define SUBLANG_SPANISH_CHILE 0x0d
+# endif
+# ifndef SUBLANG_SPANISH_URUGUAY
+# define SUBLANG_SPANISH_URUGUAY 0x0e
+# endif
+# ifndef SUBLANG_SPANISH_PARAGUAY
+# define SUBLANG_SPANISH_PARAGUAY 0x0f
+# endif
+# ifndef SUBLANG_SPANISH_BOLIVIA
+# define SUBLANG_SPANISH_BOLIVIA 0x10
+# endif
+# ifndef SUBLANG_SPANISH_EL_SALVADOR
+# define SUBLANG_SPANISH_EL_SALVADOR 0x11
+# endif
+# ifndef SUBLANG_SPANISH_HONDURAS
+# define SUBLANG_SPANISH_HONDURAS 0x12
+# endif
+# ifndef SUBLANG_SPANISH_NICARAGUA
+# define SUBLANG_SPANISH_NICARAGUA 0x13
+# endif
+# ifndef SUBLANG_SPANISH_PUERTO_RICO
+# define SUBLANG_SPANISH_PUERTO_RICO 0x14
+# endif
+# ifndef SUBLANG_SPANISH_US
+# define SUBLANG_SPANISH_US 0x15
+# endif
+# ifndef SUBLANG_SWAHILI_KENYA
+# define SUBLANG_SWAHILI_KENYA 0x01
+# endif
+# ifndef SUBLANG_SWEDISH_SWEDEN
+# define SUBLANG_SWEDISH_SWEDEN 0x01
+# endif
+# ifndef SUBLANG_SWEDISH_FINLAND
+# define SUBLANG_SWEDISH_FINLAND 0x02
+# endif
+# ifndef SUBLANG_SYRIAC_SYRIA
+# define SUBLANG_SYRIAC_SYRIA 0x01
+# endif
+# ifndef SUBLANG_TAGALOG_PHILIPPINES
+# define SUBLANG_TAGALOG_PHILIPPINES 0x01
+# endif
+# ifndef SUBLANG_TAJIK_TAJIKISTAN
+# define SUBLANG_TAJIK_TAJIKISTAN 0x01
+# endif
+# ifndef SUBLANG_TAMAZIGHT_ARABIC
+# define SUBLANG_TAMAZIGHT_ARABIC 0x01
+# endif
+# ifndef SUBLANG_TAMAZIGHT_ALGERIA_LATIN
+# define SUBLANG_TAMAZIGHT_ALGERIA_LATIN 0x02
+# endif
+# ifndef SUBLANG_TAMIL_INDIA
+# define SUBLANG_TAMIL_INDIA 0x01
+# endif
+# ifndef SUBLANG_TATAR_RUSSIA
+# define SUBLANG_TATAR_RUSSIA 0x01
+# endif
+# ifndef SUBLANG_TELUGU_INDIA
+# define SUBLANG_TELUGU_INDIA 0x01
+# endif
+# ifndef SUBLANG_THAI_THAILAND
+# define SUBLANG_THAI_THAILAND 0x01
+# endif
+# ifndef SUBLANG_TIBETAN_PRC
+# define SUBLANG_TIBETAN_PRC 0x01
+# endif
+# undef SUBLANG_TIBETAN_BHUTAN
+# define SUBLANG_TIBETAN_BHUTAN 0x02
+# ifndef SUBLANG_TIGRINYA_ETHIOPIA
+# define SUBLANG_TIGRINYA_ETHIOPIA 0x01
+# endif
+# ifndef SUBLANG_TIGRINYA_ERITREA
+# define SUBLANG_TIGRINYA_ERITREA 0x02
+# endif
+# ifndef SUBLANG_TSWANA_SOUTH_AFRICA
+# define SUBLANG_TSWANA_SOUTH_AFRICA 0x01
+# endif
+# ifndef SUBLANG_TURKISH_TURKEY
+# define SUBLANG_TURKISH_TURKEY 0x01
+# endif
+# ifndef SUBLANG_TURKMEN_TURKMENISTAN
+# define SUBLANG_TURKMEN_TURKMENISTAN 0x01
+# endif
+# ifndef SUBLANG_UIGHUR_PRC
+# define SUBLANG_UIGHUR_PRC 0x01
+# endif
+# ifndef SUBLANG_UKRAINIAN_UKRAINE
+# define SUBLANG_UKRAINIAN_UKRAINE 0x01
+# endif
+# ifndef SUBLANG_UPPER_SORBIAN_GERMANY
+# define SUBLANG_UPPER_SORBIAN_GERMANY 0x01
+# endif
+# ifndef SUBLANG_URDU_PAKISTAN
+# define SUBLANG_URDU_PAKISTAN 0x01
+# endif
+# ifndef SUBLANG_URDU_INDIA
+# define SUBLANG_URDU_INDIA 0x02
+# endif
+# ifndef SUBLANG_UZBEK_LATIN
+# define SUBLANG_UZBEK_LATIN 0x01
+# endif
+# ifndef SUBLANG_UZBEK_CYRILLIC
+# define SUBLANG_UZBEK_CYRILLIC 0x02
+# endif
+# ifndef SUBLANG_VIETNAMESE_VIETNAM
+# define SUBLANG_VIETNAMESE_VIETNAM 0x01
+# endif
+# ifndef SUBLANG_WELSH_UNITED_KINGDOM
+# define SUBLANG_WELSH_UNITED_KINGDOM 0x01
+# endif
+# ifndef SUBLANG_WOLOF_SENEGAL
+# define SUBLANG_WOLOF_SENEGAL 0x01
+# endif
+# ifndef SUBLANG_XHOSA_SOUTH_AFRICA
+# define SUBLANG_XHOSA_SOUTH_AFRICA 0x01
+# endif
+# ifndef SUBLANG_YAKUT_RUSSIA
+# define SUBLANG_YAKUT_RUSSIA 0x01
+# endif
+# ifndef SUBLANG_YI_PRC
+# define SUBLANG_YI_PRC 0x01
+# endif
+# ifndef SUBLANG_YORUBA_NIGERIA
+# define SUBLANG_YORUBA_NIGERIA 0x01
+# endif
+# ifndef SUBLANG_ZULU_SOUTH_AFRICA
+# define SUBLANG_ZULU_SOUTH_AFRICA 0x01
+# endif
+/* GetLocaleInfoA operations. */
+# ifndef LOCALE_SNAME
+# define LOCALE_SNAME 0x5c
+# endif
+#endif
+
+
+#if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE
+/* MacOS X 10.2 or newer */
+
+/* Canonicalize a MacOS X locale name to a Unix locale name.
+ NAME is a sufficiently large buffer.
+ On input, it contains the MacOS X locale name.
+ On output, it contains the Unix locale name. */
+# if !defined IN_LIBINTL
+static
+# endif
+void
+gl_locale_name_canonicalize (char *name)
+{
+ /* This conversion is based on a posting by
+ Deborah GoldSmith <goldsmit@apple.com> on 2005-03-08,
+ http://lists.apple.com/archives/carbon-dev/2005/Mar/msg00293.html */
+
+ /* Convert legacy (NeXTstep inherited) English names to Unix (ISO 639 and
+ ISO 3166) names. Prior to MacOS X 10.3, there is no API for doing this.
+ Therefore we do it ourselves, using a table based on the results of the
+ MacOS X 10.3.8 function
+ CFLocaleCreateCanonicalLocaleIdentifierFromString(). */
+ typedef struct { const char legacy[21+1]; const char unixy[5+1]; }
+ legacy_entry;
+ static const legacy_entry legacy_table[] = {
+ { "Afrikaans", "af" },
+ { "Albanian", "sq" },
+ { "Amharic", "am" },
+ { "Arabic", "ar" },
+ { "Armenian", "hy" },
+ { "Assamese", "as" },
+ { "Aymara", "ay" },
+ { "Azerbaijani", "az" },
+ { "Basque", "eu" },
+ { "Belarusian", "be" },
+ { "Belorussian", "be" },
+ { "Bengali", "bn" },
+ { "Brazilian Portugese", "pt_BR" },
+ { "Brazilian Portuguese", "pt_BR" },
+ { "Breton", "br" },
+ { "Bulgarian", "bg" },
+ { "Burmese", "my" },
+ { "Byelorussian", "be" },
+ { "Catalan", "ca" },
+ { "Chewa", "ny" },
+ { "Chichewa", "ny" },
+ { "Chinese", "zh" },
+ { "Chinese, Simplified", "zh_CN" },
+ { "Chinese, Traditional", "zh_TW" },
+ { "Chinese, Tradtional", "zh_TW" },
+ { "Croatian", "hr" },
+ { "Czech", "cs" },
+ { "Danish", "da" },
+ { "Dutch", "nl" },
+ { "Dzongkha", "dz" },
+ { "English", "en" },
+ { "Esperanto", "eo" },
+ { "Estonian", "et" },
+ { "Faroese", "fo" },
+ { "Farsi", "fa" },
+ { "Finnish", "fi" },
+ { "Flemish", "nl_BE" },
+ { "French", "fr" },
+ { "Galician", "gl" },
+ { "Gallegan", "gl" },
+ { "Georgian", "ka" },
+ { "German", "de" },
+ { "Greek", "el" },
+ { "Greenlandic", "kl" },
+ { "Guarani", "gn" },
+ { "Gujarati", "gu" },
+ { "Hawaiian", "haw" }, /* Yes, "haw", not "cpe". */
+ { "Hebrew", "he" },
+ { "Hindi", "hi" },
+ { "Hungarian", "hu" },
+ { "Icelandic", "is" },
+ { "Indonesian", "id" },
+ { "Inuktitut", "iu" },
+ { "Irish", "ga" },
+ { "Italian", "it" },
+ { "Japanese", "ja" },
+ { "Javanese", "jv" },
+ { "Kalaallisut", "kl" },
+ { "Kannada", "kn" },
+ { "Kashmiri", "ks" },
+ { "Kazakh", "kk" },
+ { "Khmer", "km" },
+ { "Kinyarwanda", "rw" },
+ { "Kirghiz", "ky" },
+ { "Korean", "ko" },
+ { "Kurdish", "ku" },
+ { "Latin", "la" },
+ { "Latvian", "lv" },
+ { "Lithuanian", "lt" },
+ { "Macedonian", "mk" },
+ { "Malagasy", "mg" },
+ { "Malay", "ms" },
+ { "Malayalam", "ml" },
+ { "Maltese", "mt" },
+ { "Manx", "gv" },
+ { "Marathi", "mr" },
+ { "Moldavian", "mo" },
+ { "Mongolian", "mn" },
+ { "Nepali", "ne" },
+ { "Norwegian", "nb" }, /* Yes, "nb", not the obsolete "no". */
+ { "Nyanja", "ny" },
+ { "Nynorsk", "nn" },
+ { "Oriya", "or" },
+ { "Oromo", "om" },
+ { "Panjabi", "pa" },
+ { "Pashto", "ps" },
+ { "Persian", "fa" },
+ { "Polish", "pl" },
+ { "Portuguese", "pt" },
+ { "Portuguese, Brazilian", "pt_BR" },
+ { "Punjabi", "pa" },
+ { "Pushto", "ps" },
+ { "Quechua", "qu" },
+ { "Romanian", "ro" },
+ { "Ruanda", "rw" },
+ { "Rundi", "rn" },
+ { "Russian", "ru" },
+ { "Sami", "se_NO" }, /* Not just "se". */
+ { "Sanskrit", "sa" },
+ { "Scottish", "gd" },
+ { "Serbian", "sr" },
+ { "Simplified Chinese", "zh_CN" },
+ { "Sindhi", "sd" },
+ { "Sinhalese", "si" },
+ { "Slovak", "sk" },
+ { "Slovenian", "sl" },
+ { "Somali", "so" },
+ { "Spanish", "es" },
+ { "Sundanese", "su" },
+ { "Swahili", "sw" },
+ { "Swedish", "sv" },
+ { "Tagalog", "tl" },
+ { "Tajik", "tg" },
+ { "Tajiki", "tg" },
+ { "Tamil", "ta" },
+ { "Tatar", "tt" },
+ { "Telugu", "te" },
+ { "Thai", "th" },
+ { "Tibetan", "bo" },
+ { "Tigrinya", "ti" },
+ { "Tongan", "to" },
+ { "Traditional Chinese", "zh_TW" },
+ { "Turkish", "tr" },
+ { "Turkmen", "tk" },
+ { "Uighur", "ug" },
+ { "Ukrainian", "uk" },
+ { "Urdu", "ur" },
+ { "Uzbek", "uz" },
+ { "Vietnamese", "vi" },
+ { "Welsh", "cy" },
+ { "Yiddish", "yi" }
+ };
+
+ /* Convert new-style locale names with language tags (ISO 639 and ISO 15924)
+ to Unix (ISO 639 and ISO 3166) names. */
+ typedef struct { const char langtag[7+1]; const char unixy[12+1]; }
+ langtag_entry;
+ static const langtag_entry langtag_table[] = {
+ /* MacOS X has "az-Arab", "az-Cyrl", "az-Latn".
+ The default script for az on Unix is Latin. */
+ { "az-Latn", "az" },
+ /* MacOS X has "ga-dots". Does not yet exist on Unix. */
+ { "ga-dots", "ga" },
+ /* MacOS X has "kk-Cyrl". Does not yet exist on Unix. */
+ /* MacOS X has "mn-Cyrl", "mn-Mong".
+ The default script for mn on Unix is Cyrillic. */
+ { "mn-Cyrl", "mn" },
+ /* MacOS X has "ms-Arab", "ms-Latn".
+ The default script for ms on Unix is Latin. */
+ { "ms-Latn", "ms" },
+ /* MacOS X has "tg-Cyrl".
+ The default script for tg on Unix is Cyrillic. */
+ { "tg-Cyrl", "tg" },
+ /* MacOS X has "tk-Cyrl". Does not yet exist on Unix. */
+ /* MacOS X has "tt-Cyrl".
+ The default script for tt on Unix is Cyrillic. */
+ { "tt-Cyrl", "tt" },
+ /* MacOS X has "zh-Hans", "zh-Hant".
+ Country codes are used to distinguish these on Unix. */
+ { "zh-Hans", "zh_CN" },
+ { "zh-Hant", "zh_TW" }
+ };
+
+ /* Convert script names (ISO 15924) to Unix conventions.
+ See http://www.unicode.org/iso15924/iso15924-codes.html */
+ typedef struct { const char script[4+1]; const char unixy[9+1]; }
+ script_entry;
+ static const script_entry script_table[] = {
+ { "Arab", "arabic" },
+ { "Cyrl", "cyrillic" },
+ { "Mong", "mongolian" }
+ };
+
+ /* Step 1: Convert using legacy_table. */
+ if (name[0] >= 'A' && name[0] <= 'Z')
+ {
+ unsigned int i1, i2;
+ i1 = 0;
+ i2 = sizeof (legacy_table) / sizeof (legacy_entry);
+ while (i2 - i1 > 1)
+ {
+ /* At this point we know that if name occurs in legacy_table,
+ its index must be >= i1 and < i2. */
+ unsigned int i = (i1 + i2) >> 1;
+ const legacy_entry *p = &legacy_table[i];
+ if (strcmp (name, p->legacy) < 0)
+ i2 = i;
+ else
+ i1 = i;
+ }
+ if (strcmp (name, legacy_table[i1].legacy) == 0)
+ {
+ strcpy (name, legacy_table[i1].unixy);
+ return;
+ }
+ }
+
+ /* Step 2: Convert using langtag_table and script_table. */
+ if (strlen (name) == 7 && name[2] == '-')
+ {
+ unsigned int i1, i2;
+ i1 = 0;
+ i2 = sizeof (langtag_table) / sizeof (langtag_entry);
+ while (i2 - i1 > 1)
+ {
+ /* At this point we know that if name occurs in langtag_table,
+ its index must be >= i1 and < i2. */
+ unsigned int i = (i1 + i2) >> 1;
+ const langtag_entry *p = &langtag_table[i];
+ if (strcmp (name, p->langtag) < 0)
+ i2 = i;
+ else
+ i1 = i;
+ }
+ if (strcmp (name, langtag_table[i1].langtag) == 0)
+ {
+ strcpy (name, langtag_table[i1].unixy);
+ return;
+ }
+
+ i1 = 0;
+ i2 = sizeof (script_table) / sizeof (script_entry);
+ while (i2 - i1 > 1)
+ {
+ /* At this point we know that if (name + 3) occurs in script_table,
+ its index must be >= i1 and < i2. */
+ unsigned int i = (i1 + i2) >> 1;
+ const script_entry *p = &script_table[i];
+ if (strcmp (name + 3, p->script) < 0)
+ i2 = i;
+ else
+ i1 = i;
+ }
+ if (strcmp (name + 3, script_table[i1].script) == 0)
+ {
+ name[2] = '@';
+ strcpy (name + 3, script_table[i1].unixy);
+ return;
+ }
+ }
+
+ /* Step 3: Convert new-style dash to Unix underscore. */
+ {
+ char *p;
+ for (p = name; *p != '\0'; p++)
+ if (*p == '-')
+ *p = '_';
+ }
+}
+
+#endif
+
+
+#if defined WIN32_NATIVE || defined __CYGWIN__ /* WIN32 or Cygwin */
+
+/* Canonicalize a Win32 native locale name to a Unix locale name.
+ NAME is a sufficiently large buffer.
+ On input, it contains the Win32 locale name.
+ On output, it contains the Unix locale name. */
+# if !defined IN_LIBINTL
+static
+# endif
+void
+gl_locale_name_canonicalize (char *name)
+{
+ /* FIXME: This is probably incomplete: it does not handle "zh-Hans" and
+ "zh-Hant". */
+ char *p;
+
+ for (p = name; *p != '\0'; p++)
+ if (*p == '-')
+ {
+ *p = '_';
+ p++;
+ for (; *p != '\0'; p++)
+ {
+ if (*p >= 'a' && *p <= 'z')
+ *p += 'A' - 'a';
+ if (*p == '-')
+ {
+ *p = '\0';
+ return;
+ }
+ }
+ return;
+ }
+}
+
+# if !defined IN_LIBINTL
+static
+# endif
+const char *
+gl_locale_name_from_win32_LANGID (LANGID langid)
+{
+ /* Activate the new code only when the GETTEXT_MUI environment variable is
+ set, for the time being, since the new code is not well tested. */
+ if (getenv ("GETTEXT_MUI") != NULL)
+ {
+ static char namebuf[256];
+
+ /* Query the system's notion of locale name.
+ On Windows95/98/ME, GetLocaleInfoA returns some incorrect results.
+ But we don't need to support systems that are so old. */
+ if (GetLocaleInfoA (MAKELCID (langid, SORT_DEFAULT), LOCALE_SNAME,
+ namebuf, sizeof (namebuf) - 1))
+ {
+ /* Convert it to a Unix locale name. */
+ gl_locale_name_canonicalize (namebuf);
+ return namebuf;
+ }
+ }
+ /* Internet Explorer has an LCID to RFC3066 name mapping stored in
+ HKEY_CLASSES_ROOT\Mime\Database\Rfc1766. But we better don't use that
+ since IE's i18n subsystem is known to be inconsistent with the Win32 base
+ (e.g. they have different character conversion facilities that produce
+ different results). */
+ /* Use our own table. */
+ {
+ int primary, sub;
+
+ /* Split into language and territory part. */
+ primary = PRIMARYLANGID (langid);
+ sub = SUBLANGID (langid);
+
+ /* Dispatch on language.
+ See also http://www.unicode.org/unicode/onlinedat/languages.html .
+ For details about languages, see http://www.ethnologue.com/ . */
+ switch (primary)
+ {
+ case LANG_AFRIKAANS:
+ switch (sub)
+ {
+ case SUBLANG_AFRIKAANS_SOUTH_AFRICA: return "af_ZA";
+ }
+ return "af";
+ case LANG_ALBANIAN:
+ switch (sub)
+ {
+ case SUBLANG_ALBANIAN_ALBANIA: return "sq_AL";
+ }
+ return "sq";
+ case LANG_ALSATIAN:
+ switch (sub)
+ {
+ case SUBLANG_ALSATIAN_FRANCE: return "gsw_FR";
+ }
+ return "gsw";
+ case LANG_AMHARIC:
+ switch (sub)
+ {
+ case SUBLANG_AMHARIC_ETHIOPIA: return "am_ET";
+ }
+ return "am";
+ case LANG_ARABIC:
+ switch (sub)
+ {
+ case SUBLANG_ARABIC_SAUDI_ARABIA: return "ar_SA";
+ case SUBLANG_ARABIC_IRAQ: return "ar_IQ";
+ case SUBLANG_ARABIC_EGYPT: return "ar_EG";
+ case SUBLANG_ARABIC_LIBYA: return "ar_LY";
+ case SUBLANG_ARABIC_ALGERIA: return "ar_DZ";
+ case SUBLANG_ARABIC_MOROCCO: return "ar_MA";
+ case SUBLANG_ARABIC_TUNISIA: return "ar_TN";
+ case SUBLANG_ARABIC_OMAN: return "ar_OM";
+ case SUBLANG_ARABIC_YEMEN: return "ar_YE";
+ case SUBLANG_ARABIC_SYRIA: return "ar_SY";
+ case SUBLANG_ARABIC_JORDAN: return "ar_JO";
+ case SUBLANG_ARABIC_LEBANON: return "ar_LB";
+ case SUBLANG_ARABIC_KUWAIT: return "ar_KW";
+ case SUBLANG_ARABIC_UAE: return "ar_AE";
+ case SUBLANG_ARABIC_BAHRAIN: return "ar_BH";
+ case SUBLANG_ARABIC_QATAR: return "ar_QA";
+ }
+ return "ar";
+ case LANG_ARMENIAN:
+ switch (sub)
+ {
+ case SUBLANG_ARMENIAN_ARMENIA: return "hy_AM";
+ }
+ return "hy";
+ case LANG_ASSAMESE:
+ switch (sub)
+ {
+ case SUBLANG_ASSAMESE_INDIA: return "as_IN";
+ }
+ return "as";
+ case LANG_AZERI:
+ switch (sub)
+ {
+ /* FIXME: Adjust this when Azerbaijani locales appear on Unix. */
+ case 0x1e: return "az@latin";
+ case SUBLANG_AZERI_LATIN: return "az_AZ@latin";
+ case 0x1d: return "az@cyrillic";
+ case SUBLANG_AZERI_CYRILLIC: return "az_AZ@cyrillic";
+ }
+ return "az";
+ case LANG_BASHKIR:
+ switch (sub)
+ {
+ case SUBLANG_BASHKIR_RUSSIA: return "ba_RU";
+ }
+ return "ba";
+ case LANG_BASQUE:
+ switch (sub)
+ {
+ case SUBLANG_BASQUE_BASQUE: return "eu_ES";
+ }
+ return "eu"; /* Ambiguous: could be "eu_ES" or "eu_FR". */
+ case LANG_BELARUSIAN:
+ switch (sub)
+ {
+ case SUBLANG_BELARUSIAN_BELARUS: return "be_BY";
+ }
+ return "be";
+ case LANG_BENGALI:
+ switch (sub)
+ {
+ case SUBLANG_BENGALI_INDIA: return "bn_IN";
+ case SUBLANG_BENGALI_BANGLADESH: return "bn_BD";
+ }
+ return "bn";
+ case LANG_BRETON:
+ switch (sub)
+ {
+ case SUBLANG_BRETON_FRANCE: return "br_FR";
+ }
+ return "br";
+ case LANG_BULGARIAN:
+ switch (sub)
+ {
+ case SUBLANG_BULGARIAN_BULGARIA: return "bg_BG";
+ }
+ return "bg";
+ case LANG_BURMESE:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "my_MM";
+ }
+ return "my";
+ case LANG_CAMBODIAN:
+ switch (sub)
+ {
+ case SUBLANG_CAMBODIAN_CAMBODIA: return "km_KH";
+ }
+ return "km";
+ case LANG_CATALAN:
+ switch (sub)
+ {
+ case SUBLANG_CATALAN_SPAIN: return "ca_ES";
+ }
+ return "ca";
+ case LANG_CHEROKEE:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "chr_US";
+ }
+ return "chr";
+ case LANG_CHINESE:
+ switch (sub)
+ {
+ case SUBLANG_CHINESE_TRADITIONAL: case 0x1f: return "zh_TW";
+ case SUBLANG_CHINESE_SIMPLIFIED: case 0x00: return "zh_CN";
+ case SUBLANG_CHINESE_HONGKONG: return "zh_HK"; /* traditional */
+ case SUBLANG_CHINESE_SINGAPORE: return "zh_SG"; /* simplified */
+ case SUBLANG_CHINESE_MACAU: return "zh_MO"; /* traditional */
+ }
+ return "zh";
+ case LANG_CORSICAN:
+ switch (sub)
+ {
+ case SUBLANG_CORSICAN_FRANCE: return "co_FR";
+ }
+ return "co";
+ case LANG_CROATIAN: /* LANG_CROATIAN == LANG_SERBIAN == LANG_BOSNIAN
+ * What used to be called Serbo-Croatian
+ * should really now be two separate
+ * languages because of political reasons.
+ * (Says tml, who knows nothing about Serbian
+ * or Croatian.)
+ * (I can feel those flames coming already.)
+ */
+ switch (sub)
+ {
+ /* Croatian */
+ case 0x00: return "hr";
+ case SUBLANG_CROATIAN_CROATIA: return "hr_HR";
+ case SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN: return "hr_BA";
+ /* Serbian */
+ case 0x1f: return "sr";
+ case 0x1c: return "sr"; /* latin */
+ case SUBLANG_SERBIAN_LATIN: return "sr_CS"; /* latin */
+ case 0x09: return "sr_RS"; /* latin */
+ case 0x0b: return "sr_ME"; /* latin */
+ case 0x06: return "sr_BA"; /* latin */
+ case 0x1b: return "sr@cyrillic";
+ case SUBLANG_SERBIAN_CYRILLIC: return "sr_CS@cyrillic";
+ case 0x0a: return "sr_RS@cyrillic";
+ case 0x0c: return "sr_ME@cyrillic";
+ case 0x07: return "sr_BA@cyrillic";
+ /* Bosnian */
+ case 0x1e: return "bs";
+ case 0x1a: return "bs"; /* latin */
+ case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN: return "bs_BA"; /* latin */
+ case 0x19: return "bs@cyrillic";
+ case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC: return "bs_BA@cyrillic";
+ }
+ return "hr";
+ case LANG_CZECH:
+ switch (sub)
+ {
+ case SUBLANG_CZECH_CZECH_REPUBLIC: return "cs_CZ";
+ }
+ return "cs";
+ case LANG_DANISH:
+ switch (sub)
+ {
+ case SUBLANG_DANISH_DENMARK: return "da_DK";
+ }
+ return "da";
+ case LANG_DARI:
+ /* FIXME: Adjust this when such locales appear on Unix. */
+ switch (sub)
+ {
+ case SUBLANG_DARI_AFGHANISTAN: return "prs_AF";
+ }
+ return "prs";
+ case LANG_DIVEHI:
+ switch (sub)
+ {
+ case SUBLANG_DIVEHI_MALDIVES: return "dv_MV";
+ }
+ return "dv";
+ case LANG_DUTCH:
+ switch (sub)
+ {
+ case SUBLANG_DUTCH: return "nl_NL";
+ case SUBLANG_DUTCH_BELGIAN: /* FLEMISH, VLAAMS */ return "nl_BE";
+ case SUBLANG_DUTCH_SURINAM: return "nl_SR";
+ }
+ return "nl";
+ case LANG_EDO:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "bin_NG";
+ }
+ return "bin";
+ case LANG_ENGLISH:
+ switch (sub)
+ {
+ /* SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. Heh. I thought
+ * English was the language spoken in England.
+ * Oh well.
+ */
+ case SUBLANG_ENGLISH_US: return "en_US";
+ case SUBLANG_ENGLISH_UK: return "en_GB";
+ case SUBLANG_ENGLISH_AUS: return "en_AU";
+ case SUBLANG_ENGLISH_CAN: return "en_CA";
+ case SUBLANG_ENGLISH_NZ: return "en_NZ";
+ case SUBLANG_ENGLISH_EIRE: return "en_IE";
+ case SUBLANG_ENGLISH_SOUTH_AFRICA: return "en_ZA";
+ case SUBLANG_ENGLISH_JAMAICA: return "en_JM";
+ case SUBLANG_ENGLISH_CARIBBEAN: return "en_GD"; /* Grenada? */
+ case SUBLANG_ENGLISH_BELIZE: return "en_BZ";
+ case SUBLANG_ENGLISH_TRINIDAD: return "en_TT";
+ case SUBLANG_ENGLISH_ZIMBABWE: return "en_ZW";
+ case SUBLANG_ENGLISH_PHILIPPINES: return "en_PH";
+ case SUBLANG_ENGLISH_INDONESIA: return "en_ID";
+ case SUBLANG_ENGLISH_HONGKONG: return "en_HK";
+ case SUBLANG_ENGLISH_INDIA: return "en_IN";
+ case SUBLANG_ENGLISH_MALAYSIA: return "en_MY";
+ case SUBLANG_ENGLISH_SINGAPORE: return "en_SG";
+ }
+ return "en";
+ case LANG_ESTONIAN:
+ switch (sub)
+ {
+ case SUBLANG_ESTONIAN_ESTONIA: return "et_EE";
+ }
+ return "et";
+ case LANG_FAEROESE:
+ switch (sub)
+ {
+ case SUBLANG_FAEROESE_FAROE_ISLANDS: return "fo_FO";
+ }
+ return "fo";
+ case LANG_FARSI:
+ switch (sub)
+ {
+ case SUBLANG_FARSI_IRAN: return "fa_IR";
+ }
+ return "fa";
+ case LANG_FINNISH:
+ switch (sub)
+ {
+ case SUBLANG_FINNISH_FINLAND: return "fi_FI";
+ }
+ return "fi";
+ case LANG_FRENCH:
+ switch (sub)
+ {
+ case SUBLANG_FRENCH: return "fr_FR";
+ case SUBLANG_FRENCH_BELGIAN: /* WALLOON */ return "fr_BE";
+ case SUBLANG_FRENCH_CANADIAN: return "fr_CA";
+ case SUBLANG_FRENCH_SWISS: return "fr_CH";
+ case SUBLANG_FRENCH_LUXEMBOURG: return "fr_LU";
+ case SUBLANG_FRENCH_MONACO: return "fr_MC";
+ case SUBLANG_FRENCH_WESTINDIES: return "fr"; /* Caribbean? */
+ case SUBLANG_FRENCH_REUNION: return "fr_RE";
+ case SUBLANG_FRENCH_CONGO: return "fr_CG";
+ case SUBLANG_FRENCH_SENEGAL: return "fr_SN";
+ case SUBLANG_FRENCH_CAMEROON: return "fr_CM";
+ case SUBLANG_FRENCH_COTEDIVOIRE: return "fr_CI";
+ case SUBLANG_FRENCH_MALI: return "fr_ML";
+ case SUBLANG_FRENCH_MOROCCO: return "fr_MA";
+ case SUBLANG_FRENCH_HAITI: return "fr_HT";
+ }
+ return "fr";
+ case LANG_FRISIAN:
+ switch (sub)
+ {
+ case SUBLANG_FRISIAN_NETHERLANDS: return "fy_NL";
+ }
+ return "fy";
+ case LANG_FULFULDE:
+ /* Spoken in Nigeria, Guinea, Senegal, Mali, Niger, Cameroon, Benin. */
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "ff_NG";
+ }
+ return "ff";
+ case LANG_GAELIC:
+ switch (sub)
+ {
+ case 0x01: /* SCOTTISH */
+ /* old, superseded by LANG_SCOTTISH_GAELIC */
+ return "gd_GB";
+ case SUBLANG_IRISH_IRELAND: return "ga_IE";
+ }
+ return "ga";
+ case LANG_GALICIAN:
+ switch (sub)
+ {
+ case SUBLANG_GALICIAN_SPAIN: return "gl_ES";
+ }
+ return "gl";
+ case LANG_GEORGIAN:
+ switch (sub)
+ {
+ case SUBLANG_GEORGIAN_GEORGIA: return "ka_GE";
+ }
+ return "ka";
+ case LANG_GERMAN:
+ switch (sub)
+ {
+ case SUBLANG_GERMAN: return "de_DE";
+ case SUBLANG_GERMAN_SWISS: return "de_CH";
+ case SUBLANG_GERMAN_AUSTRIAN: return "de_AT";
+ case SUBLANG_GERMAN_LUXEMBOURG: return "de_LU";
+ case SUBLANG_GERMAN_LIECHTENSTEIN: return "de_LI";
+ }
+ return "de";
+ case LANG_GREEK:
+ switch (sub)
+ {
+ case SUBLANG_GREEK_GREECE: return "el_GR";
+ }
+ return "el";
+ case LANG_GREENLANDIC:
+ switch (sub)
+ {
+ case SUBLANG_GREENLANDIC_GREENLAND: return "kl_GL";
+ }
+ return "kl";
+ case LANG_GUARANI:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "gn_PY";
+ }
+ return "gn";
+ case LANG_GUJARATI:
+ switch (sub)
+ {
+ case SUBLANG_GUJARATI_INDIA: return "gu_IN";
+ }
+ return "gu";
+ case LANG_HAUSA:
+ switch (sub)
+ {
+ case 0x1f: return "ha";
+ case SUBLANG_HAUSA_NIGERIA_LATIN: return "ha_NG";
+ }
+ return "ha";
+ case LANG_HAWAIIAN:
+ /* FIXME: Do they mean Hawaiian ("haw_US", 1000 speakers)
+ or Hawaii Creole English ("cpe_US", 600000 speakers)? */
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "cpe_US";
+ }
+ return "cpe";
+ case LANG_HEBREW:
+ switch (sub)
+ {
+ case SUBLANG_HEBREW_ISRAEL: return "he_IL";
+ }
+ return "he";
+ case LANG_HINDI:
+ switch (sub)
+ {
+ case SUBLANG_HINDI_INDIA: return "hi_IN";
+ }
+ return "hi";
+ case LANG_HUNGARIAN:
+ switch (sub)
+ {
+ case SUBLANG_HUNGARIAN_HUNGARY: return "hu_HU";
+ }
+ return "hu";
+ case LANG_IBIBIO:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "nic_NG";
+ }
+ return "nic";
+ case LANG_ICELANDIC:
+ switch (sub)
+ {
+ case SUBLANG_ICELANDIC_ICELAND: return "is_IS";
+ }
+ return "is";
+ case LANG_IGBO:
+ switch (sub)
+ {
+ case SUBLANG_IGBO_NIGERIA: return "ig_NG";
+ }
+ return "ig";
+ case LANG_INDONESIAN:
+ switch (sub)
+ {
+ case SUBLANG_INDONESIAN_INDONESIA: return "id_ID";
+ }
+ return "id";
+ case LANG_INUKTITUT:
+ switch (sub)
+ {
+ case 0x1e: return "iu"; /* syllabic */
+ case SUBLANG_INUKTITUT_CANADA: return "iu_CA"; /* syllabic */
+ case 0x1f: return "iu@latin";
+ case SUBLANG_INUKTITUT_CANADA_LATIN: return "iu_CA@latin";
+ }
+ return "iu";
+ case LANG_ITALIAN:
+ switch (sub)
+ {
+ case SUBLANG_ITALIAN: return "it_IT";
+ case SUBLANG_ITALIAN_SWISS: return "it_CH";
+ }
+ return "it";
+ case LANG_JAPANESE:
+ switch (sub)
+ {
+ case SUBLANG_JAPANESE_JAPAN: return "ja_JP";
+ }
+ return "ja";
+ case LANG_KANNADA:
+ switch (sub)
+ {
+ case SUBLANG_KANNADA_INDIA: return "kn_IN";
+ }
+ return "kn";
+ case LANG_KANURI:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "kr_NG";
+ }
+ return "kr";
+ case LANG_KASHMIRI:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "ks_PK";
+ case SUBLANG_KASHMIRI_INDIA: return "ks_IN";
+ }
+ return "ks";
+ case LANG_KAZAK:
+ switch (sub)
+ {
+ case SUBLANG_KAZAK_KAZAKHSTAN: return "kk_KZ";
+ }
+ return "kk";
+ case LANG_KICHE:
+ /* FIXME: Adjust this when such locales appear on Unix. */
+ switch (sub)
+ {
+ case SUBLANG_KICHE_GUATEMALA: return "qut_GT";
+ }
+ return "qut";
+ case LANG_KINYARWANDA:
+ switch (sub)
+ {
+ case SUBLANG_KINYARWANDA_RWANDA: return "rw_RW";
+ }
+ return "rw";
+ case LANG_KONKANI:
+ /* FIXME: Adjust this when such locales appear on Unix. */
+ switch (sub)
+ {
+ case SUBLANG_KONKANI_INDIA: return "kok_IN";
+ }
+ return "kok";
+ case LANG_KOREAN:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "ko_KR";
+ }
+ return "ko";
+ case LANG_KYRGYZ:
+ switch (sub)
+ {
+ case SUBLANG_KYRGYZ_KYRGYZSTAN: return "ky_KG";
+ }
+ return "ky";
+ case LANG_LAO:
+ switch (sub)
+ {
+ case SUBLANG_LAO_LAOS: return "lo_LA";
+ }
+ return "lo";
+ case LANG_LATIN:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "la_VA";
+ }
+ return "la";
+ case LANG_LATVIAN:
+ switch (sub)
+ {
+ case SUBLANG_LATVIAN_LATVIA: return "lv_LV";
+ }
+ return "lv";
+ case LANG_LITHUANIAN:
+ switch (sub)
+ {
+ case SUBLANG_LITHUANIAN_LITHUANIA: return "lt_LT";
+ }
+ return "lt";
+ case LANG_LUXEMBOURGISH:
+ switch (sub)
+ {
+ case SUBLANG_LUXEMBOURGISH_LUXEMBOURG: return "lb_LU";
+ }
+ return "lb";
+ case LANG_MACEDONIAN:
+ switch (sub)
+ {
+ case SUBLANG_MACEDONIAN_MACEDONIA: return "mk_MK";
+ }
+ return "mk";
+ case LANG_MALAY:
+ switch (sub)
+ {
+ case SUBLANG_MALAY_MALAYSIA: return "ms_MY";
+ case SUBLANG_MALAY_BRUNEI_DARUSSALAM: return "ms_BN";
+ }
+ return "ms";
+ case LANG_MALAYALAM:
+ switch (sub)
+ {
+ case SUBLANG_MALAYALAM_INDIA: return "ml_IN";
+ }
+ return "ml";
+ case LANG_MALTESE:
+ switch (sub)
+ {
+ case SUBLANG_MALTESE_MALTA: return "mt_MT";
+ }
+ return "mt";
+ case LANG_MANIPURI:
+ /* FIXME: Adjust this when such locales appear on Unix. */
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "mni_IN";
+ }
+ return "mni";
+ case LANG_MAORI:
+ switch (sub)
+ {
+ case SUBLANG_MAORI_NEW_ZEALAND: return "mi_NZ";
+ }
+ return "mi";
+ case LANG_MAPUDUNGUN:
+ switch (sub)
+ {
+ case SUBLANG_MAPUDUNGUN_CHILE: return "arn_CL";
+ }
+ return "arn";
+ case LANG_MARATHI:
+ switch (sub)
+ {
+ case SUBLANG_MARATHI_INDIA: return "mr_IN";
+ }
+ return "mr";
+ case LANG_MOHAWK:
+ switch (sub)
+ {
+ case SUBLANG_MOHAWK_CANADA: return "moh_CA";
+ }
+ return "moh";
+ case LANG_MONGOLIAN:
+ switch (sub)
+ {
+ case SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA: case 0x1e: return "mn_MN";
+ case SUBLANG_MONGOLIAN_PRC: case 0x1f: return "mn_CN";
+ }
+ return "mn"; /* Ambiguous: could be "mn_CN" or "mn_MN". */
+ case LANG_NEPALI:
+ switch (sub)
+ {
+ case SUBLANG_NEPALI_NEPAL: return "ne_NP";
+ case SUBLANG_NEPALI_INDIA: return "ne_IN";
+ }
+ return "ne";
+ case LANG_NORWEGIAN:
+ switch (sub)
+ {
+ case 0x1f: return "nb";
+ case SUBLANG_NORWEGIAN_BOKMAL: return "nb_NO";
+ case 0x1e: return "nn";
+ case SUBLANG_NORWEGIAN_NYNORSK: return "nn_NO";
+ }
+ return "no";
+ case LANG_OCCITAN:
+ switch (sub)
+ {
+ case SUBLANG_OCCITAN_FRANCE: return "oc_FR";
+ }
+ return "oc";
+ case LANG_ORIYA:
+ switch (sub)
+ {
+ case SUBLANG_ORIYA_INDIA: return "or_IN";
+ }
+ return "or";
+ case LANG_OROMO:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "om_ET";
+ }
+ return "om";
+ case LANG_PAPIAMENTU:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "pap_AN";
+ }
+ return "pap";
+ case LANG_PASHTO:
+ switch (sub)
+ {
+ case SUBLANG_PASHTO_AFGHANISTAN: return "ps_AF";
+ }
+ return "ps"; /* Ambiguous: could be "ps_PK" or "ps_AF". */
+ case LANG_POLISH:
+ switch (sub)
+ {
+ case SUBLANG_POLISH_POLAND: return "pl_PL";
+ }
+ return "pl";
+ case LANG_PORTUGUESE:
+ switch (sub)
+ {
+ /* Hmm. SUBLANG_PORTUGUESE_BRAZILIAN == SUBLANG_DEFAULT.
+ Same phenomenon as SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. */
+ case SUBLANG_PORTUGUESE_BRAZILIAN: return "pt_BR";
+ case SUBLANG_PORTUGUESE: return "pt_PT";
+ }
+ return "pt";
+ case LANG_PUNJABI:
+ switch (sub)
+ {
+ case SUBLANG_PUNJABI_INDIA: return "pa_IN"; /* Gurmukhi script */
+ case SUBLANG_PUNJABI_PAKISTAN: return "pa_PK"; /* Arabic script */
+ }
+ return "pa";
+ case LANG_QUECHUA:
+ /* Note: Microsoft uses the non-ISO language code "quz". */
+ switch (sub)
+ {
+ case SUBLANG_QUECHUA_BOLIVIA: return "qu_BO";
+ case SUBLANG_QUECHUA_ECUADOR: return "qu_EC";
+ case SUBLANG_QUECHUA_PERU: return "qu_PE";
+ }
+ return "qu";
+ case LANG_ROMANIAN:
+ switch (sub)
+ {
+ case SUBLANG_ROMANIAN_ROMANIA: return "ro_RO";
+ case SUBLANG_ROMANIAN_MOLDOVA: return "ro_MD";
+ }
+ return "ro";
+ case LANG_ROMANSH:
+ switch (sub)
+ {
+ case SUBLANG_ROMANSH_SWITZERLAND: return "rm_CH";
+ }
+ return "rm";
+ case LANG_RUSSIAN:
+ switch (sub)
+ {
+ case SUBLANG_RUSSIAN_RUSSIA: return "ru_RU";
+ case SUBLANG_RUSSIAN_MOLDAVIA: return "ru_MD";
+ }
+ return "ru"; /* Ambiguous: could be "ru_RU" or "ru_UA" or "ru_MD". */
+ case LANG_SAMI:
+ switch (sub)
+ {
+ /* Northern Sami */
+ case 0x00: return "se";
+ case SUBLANG_SAMI_NORTHERN_NORWAY: return "se_NO";
+ case SUBLANG_SAMI_NORTHERN_SWEDEN: return "se_SE";
+ case SUBLANG_SAMI_NORTHERN_FINLAND: return "se_FI";
+ /* Lule Sami */
+ case 0x1f: return "smj";
+ case SUBLANG_SAMI_LULE_NORWAY: return "smj_NO";
+ case SUBLANG_SAMI_LULE_SWEDEN: return "smj_SE";
+ /* Southern Sami */
+ case 0x1e: return "sma";
+ case SUBLANG_SAMI_SOUTHERN_NORWAY: return "sma_NO";
+ case SUBLANG_SAMI_SOUTHERN_SWEDEN: return "sma_SE";
+ /* Skolt Sami */
+ case 0x1d: return "sms";
+ case SUBLANG_SAMI_SKOLT_FINLAND: return "sms_FI";
+ /* Inari Sami */
+ case 0x1c: return "smn";
+ case SUBLANG_SAMI_INARI_FINLAND: return "smn_FI";
+ }
+ return "se"; /* or "smi"? */
+ case LANG_SANSKRIT:
+ switch (sub)
+ {
+ case SUBLANG_SANSKRIT_INDIA: return "sa_IN";
+ }
+ return "sa";
+ case LANG_SCOTTISH_GAELIC:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "gd_GB";
+ }
+ return "gd";
+ case LANG_SINDHI:
+ switch (sub)
+ {
+ case SUBLANG_SINDHI_INDIA: return "sd_IN";
+ case SUBLANG_SINDHI_PAKISTAN: return "sd_PK";
+ /*case SUBLANG_SINDHI_AFGHANISTAN: return "sd_AF";*/
+ }
+ return "sd";
+ case LANG_SINHALESE:
+ switch (sub)
+ {
+ case SUBLANG_SINHALESE_SRI_LANKA: return "si_LK";
+ }
+ return "si";
+ case LANG_SLOVAK:
+ switch (sub)
+ {
+ case SUBLANG_SLOVAK_SLOVAKIA: return "sk_SK";
+ }
+ return "sk";
+ case LANG_SLOVENIAN:
+ switch (sub)
+ {
+ case SUBLANG_SLOVENIAN_SLOVENIA: return "sl_SI";
+ }
+ return "sl";
+ case LANG_SOMALI:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "so_SO";
+ }
+ return "so";
+ case LANG_SORBIAN:
+ /* FIXME: Adjust this when such locales appear on Unix. */
+ switch (sub)
+ {
+ /* Upper Sorbian */
+ case 0x00: return "hsb";
+ case SUBLANG_UPPER_SORBIAN_GERMANY: return "hsb_DE";
+ /* Lower Sorbian */
+ case 0x1f: return "dsb";
+ case SUBLANG_LOWER_SORBIAN_GERMANY: return "dsb_DE";
+ }
+ return "wen";
+ case LANG_SOTHO:
+ /* <http://www.microsoft.com/globaldev/reference/lcid-all.mspx> calls
+ it "Sepedi"; according to
+ <http://www.ethnologue.com/show_language.asp?code=nso>
+ <http://www.ethnologue.com/show_language.asp?code=sot>
+ it's the same as Northern Sotho. */
+ switch (sub)
+ {
+ case SUBLANG_SOTHO_SOUTH_AFRICA: return "nso_ZA";
+ }
+ return "nso";
+ case LANG_SPANISH:
+ switch (sub)
+ {
+ case SUBLANG_SPANISH: return "es_ES";
+ case SUBLANG_SPANISH_MEXICAN: return "es_MX";
+ case SUBLANG_SPANISH_MODERN:
+ return "es_ES@modern"; /* not seen on Unix */
+ case SUBLANG_SPANISH_GUATEMALA: return "es_GT";
+ case SUBLANG_SPANISH_COSTA_RICA: return "es_CR";
+ case SUBLANG_SPANISH_PANAMA: return "es_PA";
+ case SUBLANG_SPANISH_DOMINICAN_REPUBLIC: return "es_DO";
+ case SUBLANG_SPANISH_VENEZUELA: return "es_VE";
+ case SUBLANG_SPANISH_COLOMBIA: return "es_CO";
+ case SUBLANG_SPANISH_PERU: return "es_PE";
+ case SUBLANG_SPANISH_ARGENTINA: return "es_AR";
+ case SUBLANG_SPANISH_ECUADOR: return "es_EC";
+ case SUBLANG_SPANISH_CHILE: return "es_CL";
+ case SUBLANG_SPANISH_URUGUAY: return "es_UY";
+ case SUBLANG_SPANISH_PARAGUAY: return "es_PY";
+ case SUBLANG_SPANISH_BOLIVIA: return "es_BO";
+ case SUBLANG_SPANISH_EL_SALVADOR: return "es_SV";
+ case SUBLANG_SPANISH_HONDURAS: return "es_HN";
+ case SUBLANG_SPANISH_NICARAGUA: return "es_NI";
+ case SUBLANG_SPANISH_PUERTO_RICO: return "es_PR";
+ case SUBLANG_SPANISH_US: return "es_US";
+ }
+ return "es";
+ case LANG_SUTU:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "bnt_TZ"; /* or "st_LS" or "nso_ZA"? */
+ }
+ return "bnt";
+ case LANG_SWAHILI:
+ switch (sub)
+ {
+ case SUBLANG_SWAHILI_KENYA: return "sw_KE";
+ }
+ return "sw";
+ case LANG_SWEDISH:
+ switch (sub)
+ {
+ case SUBLANG_SWEDISH_SWEDEN: return "sv_SE";
+ case SUBLANG_SWEDISH_FINLAND: return "sv_FI";
+ }
+ return "sv";
+ case LANG_SYRIAC:
+ switch (sub)
+ {
+ case SUBLANG_SYRIAC_SYRIA: return "syr_SY"; /* An extinct language. */
+ }
+ return "syr";
+ case LANG_TAGALOG:
+ switch (sub)
+ {
+ case SUBLANG_TAGALOG_PHILIPPINES: return "tl_PH"; /* or "fil_PH"? */
+ }
+ return "tl"; /* or "fil"? */
+ case LANG_TAJIK:
+ switch (sub)
+ {
+ case 0x1f: return "tg";
+ case SUBLANG_TAJIK_TAJIKISTAN: return "tg_TJ";
+ }
+ return "tg";
+ case LANG_TAMAZIGHT:
+ /* Note: Microsoft uses the non-ISO language code "tmz". */
+ switch (sub)
+ {
+ /* FIXME: Adjust this when Tamazight locales appear on Unix. */
+ case SUBLANG_TAMAZIGHT_ARABIC: return "ber_MA@arabic";
+ case 0x1f: return "ber@latin";
+ case SUBLANG_TAMAZIGHT_ALGERIA_LATIN: return "ber_DZ@latin";
+ }
+ return "ber";
+ case LANG_TAMIL:
+ switch (sub)
+ {
+ case SUBLANG_TAMIL_INDIA: return "ta_IN";
+ }
+ return "ta"; /* Ambiguous: could be "ta_IN" or "ta_LK" or "ta_SG". */
+ case LANG_TATAR:
+ switch (sub)
+ {
+ case SUBLANG_TATAR_RUSSIA: return "tt_RU";
+ }
+ return "tt";
+ case LANG_TELUGU:
+ switch (sub)
+ {
+ case SUBLANG_TELUGU_INDIA: return "te_IN";
+ }
+ return "te";
+ case LANG_THAI:
+ switch (sub)
+ {
+ case SUBLANG_THAI_THAILAND: return "th_TH";
+ }
+ return "th";
+ case LANG_TIBETAN:
+ switch (sub)
+ {
+ case SUBLANG_TIBETAN_PRC:
+ /* Most Tibetans would not like "bo_CN". But Tibet does not yet
+ have a country code of its own. */
+ return "bo";
+ case SUBLANG_TIBETAN_BHUTAN: return "bo_BT";
+ }
+ return "bo";
+ case LANG_TIGRINYA:
+ switch (sub)
+ {
+ case SUBLANG_TIGRINYA_ETHIOPIA: return "ti_ET";
+ case SUBLANG_TIGRINYA_ERITREA: return "ti_ER";
+ }
+ return "ti";
+ case LANG_TSONGA:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "ts_ZA";
+ }
+ return "ts";
+ case LANG_TSWANA:
+ /* Spoken in South Africa, Botswana. */
+ switch (sub)
+ {
+ case SUBLANG_TSWANA_SOUTH_AFRICA: return "tn_ZA";
+ }
+ return "tn";
+ case LANG_TURKISH:
+ switch (sub)
+ {
+ case SUBLANG_TURKISH_TURKEY: return "tr_TR";
+ }
+ return "tr";
+ case LANG_TURKMEN:
+ switch (sub)
+ {
+ case SUBLANG_TURKMEN_TURKMENISTAN: return "tk_TM";
+ }
+ return "tk";
+ case LANG_UIGHUR:
+ switch (sub)
+ {
+ case SUBLANG_UIGHUR_PRC: return "ug_CN";
+ }
+ return "ug";
+ case LANG_UKRAINIAN:
+ switch (sub)
+ {
+ case SUBLANG_UKRAINIAN_UKRAINE: return "uk_UA";
+ }
+ return "uk";
+ case LANG_URDU:
+ switch (sub)
+ {
+ case SUBLANG_URDU_PAKISTAN: return "ur_PK";
+ case SUBLANG_URDU_INDIA: return "ur_IN";
+ }
+ return "ur";
+ case LANG_UZBEK:
+ switch (sub)
+ {
+ case 0x1f: return "uz";
+ case SUBLANG_UZBEK_LATIN: return "uz_UZ";
+ case 0x1e: return "uz@cyrillic";
+ case SUBLANG_UZBEK_CYRILLIC: return "uz_UZ@cyrillic";
+ }
+ return "uz";
+ case LANG_VENDA:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "ve_ZA";
+ }
+ return "ve";
+ case LANG_VIETNAMESE:
+ switch (sub)
+ {
+ case SUBLANG_VIETNAMESE_VIETNAM: return "vi_VN";
+ }
+ return "vi";
+ case LANG_WELSH:
+ switch (sub)
+ {
+ case SUBLANG_WELSH_UNITED_KINGDOM: return "cy_GB";
+ }
+ return "cy";
+ case LANG_WOLOF:
+ switch (sub)
+ {
+ case SUBLANG_WOLOF_SENEGAL: return "wo_SN";
+ }
+ return "wo";
+ case LANG_XHOSA:
+ switch (sub)
+ {
+ case SUBLANG_XHOSA_SOUTH_AFRICA: return "xh_ZA";
+ }
+ return "xh";
+ case LANG_YAKUT:
+ switch (sub)
+ {
+ case SUBLANG_YAKUT_RUSSIA: return "sah_RU";
+ }
+ return "sah";
+ case LANG_YI:
+ switch (sub)
+ {
+ case SUBLANG_YI_PRC: return "ii_CN";
+ }
+ return "ii";
+ case LANG_YIDDISH:
+ switch (sub)
+ {
+ case SUBLANG_DEFAULT: return "yi_IL";
+ }
+ return "yi";
+ case LANG_YORUBA:
+ switch (sub)
+ {
+ case SUBLANG_YORUBA_NIGERIA: return "yo_NG";
+ }
+ return "yo";
+ case LANG_ZULU:
+ switch (sub)
+ {
+ case SUBLANG_ZULU_SOUTH_AFRICA: return "zu_ZA";
+ }
+ return "zu";
+ default: return "C";
+ }
+ }
+}
+
+# if !defined IN_LIBINTL
+static
+# endif
+const char *
+gl_locale_name_from_win32_LCID (LCID lcid)
+{
+ LANGID langid;
+
+ /* Strip off the sorting rules, keep only the language part. */
+ langid = LANGIDFROMLCID (lcid);
+
+ return gl_locale_name_from_win32_LANGID (langid);
+}
+
+#endif
+
+
+#if HAVE_USELOCALE /* glibc or MacOS X */
+
+/* Simple hash set of strings. We don't want to drag in lots of hash table
+ code here. */
+
+# define SIZE_BITS (sizeof (size_t) * CHAR_BIT)
+
+/* A hash function for NUL-terminated char* strings using
+ the method described by Bruno Haible.
+ See http://www.haible.de/bruno/hashfunc.html. */
+static size_t
+string_hash (const void *x)
+{
+ const char *s = (const char *) x;
+ size_t h = 0;
+
+ for (; *s; s++)
+ h = *s + ((h << 9) | (h >> (SIZE_BITS - 9)));
+
+ return h;
+}
+
+/* A hash table of fixed size. Multiple threads can access it read-only
+ simultaneously, but only one thread can insert into it at the same time. */
+
+/* A node in a hash bucket collision list. */
+struct hash_node
+ {
+ struct hash_node * volatile next;
+ char contents[100]; /* has variable size */
+ };
+
+# define HASH_TABLE_SIZE 257
+static struct hash_node * volatile struniq_hash_table[HASH_TABLE_SIZE]
+ /* = { NULL, ..., NULL } */;
+
+/* This lock protects the struniq_hash_table against multiple simultaneous
+ insertions. */
+gl_lock_define_initialized(static, struniq_lock)
+
+/* Store a copy of the given string in a string pool with indefinite extent.
+ Return a pointer to this copy. */
+static const char *
+struniq (const char *string)
+{
+ size_t hashcode = string_hash (string);
+ size_t slot = hashcode % HASH_TABLE_SIZE;
+ size_t size;
+ struct hash_node *new_node;
+ struct hash_node *p;
+ for (p = struniq_hash_table[slot]; p != NULL; p = p->next)
+ if (strcmp (p->contents, string) == 0)
+ return p->contents;
+ size = strlen (string) + 1;
+ new_node =
+ (struct hash_node *)
+ malloc (offsetof (struct hash_node, contents[0]) + size);
+ if (new_node == NULL)
+ /* Out of memory. Return a statically allocated string. */
+ return "C";
+ memcpy (new_node->contents, string, size);
+ /* Lock while inserting new_node. */
+ gl_lock_lock (struniq_lock);
+ /* Check whether another thread already added the string while we were
+ waiting on the lock. */
+ for (p = struniq_hash_table[slot]; p != NULL; p = p->next)
+ if (strcmp (p->contents, string) == 0)
+ {
+ free (new_node);
+ new_node = p;
+ goto done;
+ }
+ /* Really insert new_node into the hash table. Fill new_node entirely first,
+ because other threads may be iterating over the linked list. */
+ new_node->next = struniq_hash_table[slot];
+ struniq_hash_table[slot] = new_node;
+ done:
+ /* Unlock after new_node is inserted. */
+ gl_lock_unlock (struniq_lock);
+ return new_node->contents;
+}
+
+#endif
+
+
+#if defined IN_LIBINTL || HAVE_USELOCALE
+
+/* Like gl_locale_name_thread, except that the result is not in storage of
+ indefinite extent. */
+# if !defined IN_LIBINTL
+static
+# endif
+const char *
+gl_locale_name_thread_unsafe (int category, const char *categoryname)
+{
+# if HAVE_USELOCALE
+ {
+ locale_t thread_locale = uselocale (NULL);
+ if (thread_locale != LC_GLOBAL_LOCALE)
+ {
+# if __GLIBC__ >= 2
+ /* Work around an incorrect definition of the _NL_LOCALE_NAME macro in
+ glibc < 2.12.
+ See <http://sourceware.org/bugzilla/show_bug.cgi?id=10968>. */
+ const char *name =
+ nl_langinfo (_NL_ITEM ((category), _NL_ITEM_INDEX (-1)));
+ if (name[0] == '\0')
+ /* Fallback code for glibc < 2.4, which did not implement
+ nl_langinfo (_NL_LOCALE_NAME (category)). */
+ name = thread_locale->__names[category];
+ return name;
+# endif
+# if defined __APPLE__ && defined __MACH__ /* MacOS X */
+ /* The locale name is found deep in an undocumented data structure.
+ Since it's stored in a buffer of size 32 and newlocale() rejects
+ locale names of length > 31, we can assume that it is NUL terminated
+ in this buffer. But we need to make a copy of the locale name, of
+ indefinite extent. */
+ struct _xlocale_part1_v0 /* used in MacOS X 10.5 */
+ {
+ int32_t __refcount;
+ void (*__free_extra)(void *);
+ __darwin_mbstate_t __mbs[10];
+ int64_t __magic;
+ };
+ struct _xlocale_part1_v1 /* used in MacOS X >= 10.6.0 */
+ {
+ int32_t __refcount;
+ void (*__free_extra)(void *);
+ __darwin_mbstate_t __mbs[10];
+ /*pthread_lock_t*/ int __lock;
+ int64_t __magic;
+ };
+ struct _xlocale_part2
+ {
+ int64_t __magic;
+ unsigned char __collate_load_error;
+ unsigned char __collate_substitute_nontrivial;
+ unsigned char _messages_using_locale;
+ unsigned char _monetary_using_locale;
+ unsigned char _numeric_using_locale;
+ unsigned char _time_using_locale;
+ unsigned char __mlocale_changed;
+ unsigned char __nlocale_changed;
+ unsigned char __numeric_fp_cvt;
+ struct __xlocale_st_collate *__lc_collate;
+ struct __xlocale_st_runelocale *__lc_ctype;
+ struct __xlocale_st_messages *__lc_messages;
+ struct __xlocale_st_monetary *__lc_monetary;
+ struct __xlocale_st_numeric *__lc_numeric;
+ struct _xlocale *__lc_numeric_loc;
+ struct __xlocale_st_time *__lc_time;
+ /* more */
+ };
+ struct __xlocale_st_collate
+ {
+ int32_t __refcount;
+ void (*__free_extra)(void *);
+ char __encoding[32];
+ /* more */
+ };
+ struct __xlocale_st_runelocale
+ {
+ int32_t __refcount;
+ void (*__free_extra)(void *);
+ char __ctype_encoding[32];
+ /* more */
+ };
+ struct __xlocale_st_messages
+ {
+ int32_t __refcount;
+ void (*__free_extra)(void *);
+ char *_messages_locale_buf;
+ /* more */
+ };
+ struct __xlocale_st_monetary
+ {
+ int32_t __refcount;
+ void (*__free_extra)(void *);
+ char *_monetary_locale_buf;
+ /* more */
+ };
+ struct __xlocale_st_numeric {
+ int32_t __refcount;
+ void (*__free_extra)(void *);
+ char *_numeric_locale_buf;
+ /* more */
+ };
+ struct __xlocale_st_time {
+ int32_t __refcount;
+ void (*__free_extra)(void *);
+ char *_time_locale_buf;
+ /* more */
+ };
+ struct _xlocale_part2 *tlp;
+ if (((struct _xlocale_part1_v0 *) thread_locale)->__magic
+ == 0x786C6F63616C6530LL)
+ /* MacOS X 10.5 */
+ tlp =
+ (struct _xlocale_part2 *)
+ &((struct _xlocale_part1_v0 *) thread_locale)->__magic;
+ else if (((struct _xlocale_part1_v1 *) thread_locale)->__magic
+ == 0x786C6F63616C6530LL)
+ /* MacOS X >= 10.6.0 */
+ tlp =
+ (struct _xlocale_part2 *)
+ &((struct _xlocale_part1_v1 *) thread_locale)->__magic;
+ else
+ /* Unsupported version of MacOS X: The internals of 'struct _xlocale'
+ have changed again. */
+ return "";
+ switch (category)
+ {
+ case LC_CTYPE:
+ return tlp->__lc_ctype->__ctype_encoding;
+ case LC_NUMERIC:
+ return tlp->_numeric_using_locale
+ ? tlp->__lc_numeric->_numeric_locale_buf
+ : "C";
+ case LC_TIME:
+ return tlp->_time_using_locale
+ ? tlp->__lc_time->_time_locale_buf
+ : "C";
+ case LC_COLLATE:
+ return !tlp->__collate_load_error
+ ? tlp->__lc_collate->__encoding
+ : "C";
+ case LC_MONETARY:
+ return tlp->_monetary_using_locale
+ ? tlp->__lc_monetary->_monetary_locale_buf
+ : "C";
+ case LC_MESSAGES:
+ return tlp->_messages_using_locale
+ ? tlp->__lc_messages->_messages_locale_buf
+ : "C";
+ default: /* We shouldn't get here. */
+ return "";
+ }
+# endif
+ }
+ }
+# endif
+ return NULL;
+}
+
+#endif
+
+const char *
+gl_locale_name_thread (int category, const char *categoryname)
+{
+#if HAVE_USELOCALE
+ const char *name = gl_locale_name_thread_unsafe (category, categoryname);
+ if (name != NULL)
+ return struniq (name);
+#endif
+ return NULL;
+}
+
+/* XPG3 defines the result of 'setlocale (category, NULL)' as:
+ "Directs 'setlocale()' to query 'category' and return the current
+ setting of 'local'."
+ However it does not specify the exact format. Neither do SUSV2 and
+ ISO C 99. So we can use this feature only on selected systems (e.g.
+ those using GNU C Library). */
+#if defined _LIBC || (defined __GLIBC__ && __GLIBC__ >= 2)
+# define HAVE_LOCALE_NULL
+#endif
+
+const char *
+gl_locale_name_posix (int category, const char *categoryname)
+{
+ /* Use the POSIX methods of looking to 'LC_ALL', 'LC_xxx', and 'LANG'.
+ On some systems this can be done by the 'setlocale' function itself. */
+#if defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL
+ return setlocale (category, NULL);
+#else
+ /* On other systems we ignore what setlocale reports and instead look at the
+ environment variables directly. This is necessary
+ 1. on systems which have a facility for customizing the default locale
+ (MacOS X, native Windows, Cygwin) and where the system's setlocale()
+ function ignores this default locale (MacOS X, Cygwin), in two cases:
+ a. when the user missed to use the setlocale() override from libintl
+ (for example by not including <libintl.h>),
+ b. when setlocale supports only the "C" locale, such as on Cygwin
+ 1.5.x. In this case even the override from libintl cannot help.
+ 2. on all systems where setlocale supports only the "C" locale. */
+ /* Strictly speaking, it is a POSIX violation to look at the environment
+ variables regardless whether setlocale has been called or not. POSIX
+ says:
+ "For C-language programs, the POSIX locale shall be the
+ default locale when the setlocale() function is not called."
+ But we assume that all programs that use internationalized APIs call
+ setlocale (LC_ALL, ""). */
+ return gl_locale_name_environ (category, categoryname);
+#endif
+}
+
+const char *
+gl_locale_name_environ (int category, const char *categoryname)
+{
+ const char *retval;
+
+ /* Setting of LC_ALL overrides all other. */
+ retval = getenv ("LC_ALL");
+ if (retval != NULL && retval[0] != '\0')
+ return retval;
+ /* Next comes the name of the desired category. */
+ retval = getenv (categoryname);
+ if (retval != NULL && retval[0] != '\0')
+ return retval;
+ /* Last possibility is the LANG environment variable. */
+ retval = getenv ("LANG");
+ if (retval != NULL && retval[0] != '\0')
+ {
+#if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE
+ /* MacOS X 10.2 or newer.
+ Ignore invalid LANG value set by the Terminal application. */
+ if (strcmp (retval, "UTF-8") != 0)
+#endif
+#if defined __CYGWIN__
+ /* Cygwin.
+ Ignore dummy LANG value set by ~/.profile. */
+ if (strcmp (retval, "C.UTF-8") != 0)
+#endif
+ return retval;
+ }
+
+ return NULL;
+}
+
+const char *
+gl_locale_name_default (void)
+{
+ /* POSIX:2001 says:
+ "All implementations shall define a locale as the default locale, to be
+ invoked when no environment variables are set, or set to the empty
+ string. This default locale can be the POSIX locale or any other
+ implementation-defined locale. Some implementations may provide
+ facilities for local installation administrators to set the default
+ locale, customizing it for each location. POSIX:2001 does not require
+ such a facility.
+
+ The systems with such a facility are MacOS X and Windows: They provide a
+ GUI that allows the user to choose a locale.
+ - On MacOS X, by default, none of LC_* or LANG are set. Starting with
+ MacOS X 10.4 or 10.5, LANG is set for processes launched by the
+ 'Terminal' application (but sometimes to an incorrect value "UTF-8").
+ When no environment variable is set, setlocale (LC_ALL, "") uses the
+ "C" locale.
+ - On native Windows, by default, none of LC_* or LANG are set.
+ When no environment variable is set, setlocale (LC_ALL, "") uses the
+ locale chosen by the user.
+ - On Cygwin 1.5.x, by default, none of LC_* or LANG are set.
+ When no environment variable is set, setlocale (LC_ALL, "") uses the
+ "C" locale.
+ - On Cygwin 1.7, by default, LANG is set to "C.UTF-8" when the default
+ ~/.profile is executed.
+ When no environment variable is set, setlocale (LC_ALL, "") uses the
+ "C.UTF-8" locale, which operates in the same way as the "C" locale.
+ */
+
+#if !(HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE || defined WIN32_NATIVE || defined __CYGWIN__)
+
+ /* The system does not have a way of setting the locale, other than the
+ POSIX specified environment variables. We use C as default locale. */
+ return "C";
+
+#else
+
+ /* Return an XPG style locale name language[_territory][@modifier].
+ Don't even bother determining the codeset; it's not useful in this
+ context, because message catalogs are not specific to a single
+ codeset. */
+
+# if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE
+ /* MacOS X 10.2 or newer */
+ {
+ /* Cache the locale name, since CoreFoundation calls are expensive. */
+ static const char *cached_localename;
+
+ if (cached_localename == NULL)
+ {
+ char namebuf[256];
+# if HAVE_CFLOCALECOPYCURRENT /* MacOS X 10.3 or newer */
+ CFLocaleRef locale = CFLocaleCopyCurrent ();
+ CFStringRef name = CFLocaleGetIdentifier (locale);
+
+ if (CFStringGetCString (name, namebuf, sizeof (namebuf),
+ kCFStringEncodingASCII))
+ {
+ gl_locale_name_canonicalize (namebuf);
+ cached_localename = strdup (namebuf);
+ }
+ CFRelease (locale);
+# elif HAVE_CFPREFERENCESCOPYAPPVALUE /* MacOS X 10.2 or newer */
+ CFTypeRef value =
+ CFPreferencesCopyAppValue (CFSTR ("AppleLocale"),
+ kCFPreferencesCurrentApplication);
+ if (value != NULL
+ && CFGetTypeID (value) == CFStringGetTypeID ()
+ && CFStringGetCString ((CFStringRef)value,
+ namebuf, sizeof (namebuf),
+ kCFStringEncodingASCII))
+ {
+ gl_locale_name_canonicalize (namebuf);
+ cached_localename = strdup (namebuf);
+ }
+# endif
+ if (cached_localename == NULL)
+ cached_localename = "C";
+ }
+ return cached_localename;
+ }
+
+# endif
+
+# if defined WIN32_NATIVE || defined __CYGWIN__ /* WIN32 or Cygwin */
+ {
+ LCID lcid;
+
+ /* Use native Win32 API locale ID. */
+ lcid = GetThreadLocale ();
+
+ return gl_locale_name_from_win32_LCID (lcid);
+ }
+# endif
+#endif
+}
+
+/* Determine the current locale's name, and canonicalize it into XPG syntax
+ language[_territory][.codeset][@modifier]
+ The codeset part in the result is not reliable; the locale_charset()
+ should be used for codeset information instead.
+ The result must not be freed; it is statically allocated. */
+
+const char *
+gl_locale_name (int category, const char *categoryname)
+{
+ const char *retval;
+
+ retval = gl_locale_name_thread (category, categoryname);
+ if (retval != NULL)
+ return retval;
+
+ retval = gl_locale_name_posix (category, categoryname);
+ if (retval != NULL)
+ return retval;
+
+ return gl_locale_name_default ();
+}
diff --git a/intl/lock.c b/intl/lock.c
new file mode 100644
index 00000000..561423e0
--- /dev/null
+++ b/intl/lock.c
@@ -0,0 +1,1059 @@
+/* Locking in multithreaded situations.
+ Copyright (C) 2005-2008 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2005.
+ Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h,
+ gthr-win32.h. */
+
+#include <config.h>
+
+#include "lock.h"
+
+/* ========================================================================= */
+
+#if USE_POSIX_THREADS
+
+/* -------------------------- gl_lock_t datatype -------------------------- */
+
+/* ------------------------- gl_rwlock_t datatype ------------------------- */
+
+# if HAVE_PTHREAD_RWLOCK
+
+# if !defined PTHREAD_RWLOCK_INITIALIZER
+
+int
+glthread_rwlock_init_multithreaded (gl_rwlock_t *lock)
+{
+ int err;
+
+ err = pthread_rwlock_init (&lock->rwlock, NULL);
+ if (err != 0)
+ return err;
+ lock->initialized = 1;
+ return 0;
+}
+
+int
+glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock)
+{
+ if (!lock->initialized)
+ {
+ int err;
+
+ err = pthread_mutex_lock (&lock->guard);
+ if (err != 0)
+ return err;
+ if (!lock->initialized)
+ {
+ err = glthread_rwlock_init_multithreaded (lock);
+ if (err != 0)
+ {
+ pthread_mutex_unlock (&lock->guard);
+ return err;
+ }
+ }
+ err = pthread_mutex_unlock (&lock->guard);
+ if (err != 0)
+ return err;
+ }
+ return pthread_rwlock_rdlock (&lock->rwlock);
+}
+
+int
+glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock)
+{
+ if (!lock->initialized)
+ {
+ int err;
+
+ err = pthread_mutex_lock (&lock->guard);
+ if (err != 0)
+ return err;
+ if (!lock->initialized)
+ {
+ err = glthread_rwlock_init_multithreaded (lock);
+ if (err != 0)
+ {
+ pthread_mutex_unlock (&lock->guard);
+ return err;
+ }
+ }
+ err = pthread_mutex_unlock (&lock->guard);
+ if (err != 0)
+ return err;
+ }
+ return pthread_rwlock_wrlock (&lock->rwlock);
+}
+
+int
+glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock)
+{
+ if (!lock->initialized)
+ return EINVAL;
+ return pthread_rwlock_unlock (&lock->rwlock);
+}
+
+int
+glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock)
+{
+ int err;
+
+ if (!lock->initialized)
+ return EINVAL;
+ err = pthread_rwlock_destroy (&lock->rwlock);
+ if (err != 0)
+ return err;
+ lock->initialized = 0;
+ return 0;
+}
+
+# endif
+
+# else
+
+int
+glthread_rwlock_init_multithreaded (gl_rwlock_t *lock)
+{
+ int err;
+
+ err = pthread_mutex_init (&lock->lock, NULL);
+ if (err != 0)
+ return err;
+ err = pthread_cond_init (&lock->waiting_readers, NULL);
+ if (err != 0)
+ return err;
+ err = pthread_cond_init (&lock->waiting_writers, NULL);
+ if (err != 0)
+ return err;
+ lock->waiting_writers_count = 0;
+ lock->runcount = 0;
+ return 0;
+}
+
+int
+glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock)
+{
+ int err;
+
+ err = pthread_mutex_lock (&lock->lock);
+ if (err != 0)
+ return err;
+ /* Test whether only readers are currently running, and whether the runcount
+ field will not overflow. */
+ /* POSIX says: "It is implementation-defined whether the calling thread
+ acquires the lock when a writer does not hold the lock and there are
+ writers blocked on the lock." Let's say, no: give the writers a higher
+ priority. */
+ while (!(lock->runcount + 1 > 0 && lock->waiting_writers_count == 0))
+ {
+ /* This thread has to wait for a while. Enqueue it among the
+ waiting_readers. */
+ err = pthread_cond_wait (&lock->waiting_readers, &lock->lock);
+ if (err != 0)
+ {
+ pthread_mutex_unlock (&lock->lock);
+ return err;
+ }
+ }
+ lock->runcount++;
+ return pthread_mutex_unlock (&lock->lock);
+}
+
+int
+glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock)
+{
+ int err;
+
+ err = pthread_mutex_lock (&lock->lock);
+ if (err != 0)
+ return err;
+ /* Test whether no readers or writers are currently running. */
+ while (!(lock->runcount == 0))
+ {
+ /* This thread has to wait for a while. Enqueue it among the
+ waiting_writers. */
+ lock->waiting_writers_count++;
+ err = pthread_cond_wait (&lock->waiting_writers, &lock->lock);
+ if (err != 0)
+ {
+ lock->waiting_writers_count--;
+ pthread_mutex_unlock (&lock->lock);
+ return err;
+ }
+ lock->waiting_writers_count--;
+ }
+ lock->runcount--; /* runcount becomes -1 */
+ return pthread_mutex_unlock (&lock->lock);
+}
+
+int
+glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock)
+{
+ int err;
+
+ err = pthread_mutex_lock (&lock->lock);
+ if (err != 0)
+ return err;
+ if (lock->runcount < 0)
+ {
+ /* Drop a writer lock. */
+ if (!(lock->runcount == -1))
+ {
+ pthread_mutex_unlock (&lock->lock);
+ return EINVAL;
+ }
+ lock->runcount = 0;
+ }
+ else
+ {
+ /* Drop a reader lock. */
+ if (!(lock->runcount > 0))
+ {
+ pthread_mutex_unlock (&lock->lock);
+ return EINVAL;
+ }
+ lock->runcount--;
+ }
+ if (lock->runcount == 0)
+ {
+ /* POSIX recommends that "write locks shall take precedence over read
+ locks", to avoid "writer starvation". */
+ if (lock->waiting_writers_count > 0)
+ {
+ /* Wake up one of the waiting writers. */
+ err = pthread_cond_signal (&lock->waiting_writers);
+ if (err != 0)
+ {
+ pthread_mutex_unlock (&lock->lock);
+ return err;
+ }
+ }
+ else
+ {
+ /* Wake up all waiting readers. */
+ err = pthread_cond_broadcast (&lock->waiting_readers);
+ if (err != 0)
+ {
+ pthread_mutex_unlock (&lock->lock);
+ return err;
+ }
+ }
+ }
+ return pthread_mutex_unlock (&lock->lock);
+}
+
+int
+glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock)
+{
+ int err;
+
+ err = pthread_mutex_destroy (&lock->lock);
+ if (err != 0)
+ return err;
+ err = pthread_cond_destroy (&lock->waiting_readers);
+ if (err != 0)
+ return err;
+ err = pthread_cond_destroy (&lock->waiting_writers);
+ if (err != 0)
+ return err;
+ return 0;
+}
+
+# endif
+
+/* --------------------- gl_recursive_lock_t datatype --------------------- */
+
+# if HAVE_PTHREAD_MUTEX_RECURSIVE
+
+# if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
+
+int
+glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock)
+{
+ pthread_mutexattr_t attributes;
+ int err;
+
+ err = pthread_mutexattr_init (&attributes);
+ if (err != 0)
+ return err;
+ err = pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE);
+ if (err != 0)
+ {
+ pthread_mutexattr_destroy (&attributes);
+ return err;
+ }
+ err = pthread_mutex_init (lock, &attributes);
+ if (err != 0)
+ {
+ pthread_mutexattr_destroy (&attributes);
+ return err;
+ }
+ err = pthread_mutexattr_destroy (&attributes);
+ if (err != 0)
+ return err;
+ return 0;
+}
+
+# else
+
+int
+glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock)
+{
+ pthread_mutexattr_t attributes;
+ int err;
+
+ err = pthread_mutexattr_init (&attributes);
+ if (err != 0)
+ return err;
+ err = pthread_mutexattr_settype (&attributes, PTHREAD_MUTEX_RECURSIVE);
+ if (err != 0)
+ {
+ pthread_mutexattr_destroy (&attributes);
+ return err;
+ }
+ err = pthread_mutex_init (&lock->recmutex, &attributes);
+ if (err != 0)
+ {
+ pthread_mutexattr_destroy (&attributes);
+ return err;
+ }
+ err = pthread_mutexattr_destroy (&attributes);
+ if (err != 0)
+ return err;
+ lock->initialized = 1;
+ return 0;
+}
+
+int
+glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock)
+{
+ if (!lock->initialized)
+ {
+ int err;
+
+ err = pthread_mutex_lock (&lock->guard);
+ if (err != 0)
+ return err;
+ if (!lock->initialized)
+ {
+ err = glthread_recursive_lock_init_multithreaded (lock);
+ if (err != 0)
+ {
+ pthread_mutex_unlock (&lock->guard);
+ return err;
+ }
+ }
+ err = pthread_mutex_unlock (&lock->guard);
+ if (err != 0)
+ return err;
+ }
+ return pthread_mutex_lock (&lock->recmutex);
+}
+
+int
+glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock)
+{
+ if (!lock->initialized)
+ return EINVAL;
+ return pthread_mutex_unlock (&lock->recmutex);
+}
+
+int
+glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock)
+{
+ int err;
+
+ if (!lock->initialized)
+ return EINVAL;
+ err = pthread_mutex_destroy (&lock->recmutex);
+ if (err != 0)
+ return err;
+ lock->initialized = 0;
+ return 0;
+}
+
+# endif
+
+# else
+
+int
+glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock)
+{
+ int err;
+
+ err = pthread_mutex_init (&lock->mutex, NULL);
+ if (err != 0)
+ return err;
+ lock->owner = (pthread_t) 0;
+ lock->depth = 0;
+ return 0;
+}
+
+int
+glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock)
+{
+ pthread_t self = pthread_self ();
+ if (lock->owner != self)
+ {
+ int err;
+
+ err = pthread_mutex_lock (&lock->mutex);
+ if (err != 0)
+ return err;
+ lock->owner = self;
+ }
+ if (++(lock->depth) == 0) /* wraparound? */
+ {
+ lock->depth--;
+ return EAGAIN;
+ }
+ return 0;
+}
+
+int
+glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock)
+{
+ if (lock->owner != pthread_self ())
+ return EPERM;
+ if (lock->depth == 0)
+ return EINVAL;
+ if (--(lock->depth) == 0)
+ {
+ lock->owner = (pthread_t) 0;
+ return pthread_mutex_unlock (&lock->mutex);
+ }
+ else
+ return 0;
+}
+
+int
+glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock)
+{
+ if (lock->owner != (pthread_t) 0)
+ return EBUSY;
+ return pthread_mutex_destroy (&lock->mutex);
+}
+
+# endif
+
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+static const pthread_once_t fresh_once = PTHREAD_ONCE_INIT;
+
+int
+glthread_once_singlethreaded (pthread_once_t *once_control)
+{
+ /* We don't know whether pthread_once_t is an integer type, a floating-point
+ type, a pointer type, or a structure type. */
+ char *firstbyte = (char *)once_control;
+ if (*firstbyte == *(const char *)&fresh_once)
+ {
+ /* First time use of once_control. Invert the first byte. */
+ *firstbyte = ~ *(const char *)&fresh_once;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_PTH_THREADS
+
+/* Use the GNU Pth threads library. */
+
+/* -------------------------- gl_lock_t datatype -------------------------- */
+
+/* ------------------------- gl_rwlock_t datatype ------------------------- */
+
+/* --------------------- gl_recursive_lock_t datatype --------------------- */
+
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+static void
+glthread_once_call (void *arg)
+{
+ void (**gl_once_temp_addr) (void) = (void (**) (void)) arg;
+ void (*initfunction) (void) = *gl_once_temp_addr;
+ initfunction ();
+}
+
+int
+glthread_once_multithreaded (pth_once_t *once_control, void (*initfunction) (void))
+{
+ void (*temp) (void) = initfunction;
+ return (!pth_once (once_control, glthread_once_call, &temp) ? errno : 0);
+}
+
+int
+glthread_once_singlethreaded (pth_once_t *once_control)
+{
+ /* We know that pth_once_t is an integer type. */
+ if (*once_control == PTH_ONCE_INIT)
+ {
+ /* First time use of once_control. Invert the marker. */
+ *once_control = ~ PTH_ONCE_INIT;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_SOLARIS_THREADS
+
+/* Use the old Solaris threads library. */
+
+/* -------------------------- gl_lock_t datatype -------------------------- */
+
+/* ------------------------- gl_rwlock_t datatype ------------------------- */
+
+/* --------------------- gl_recursive_lock_t datatype --------------------- */
+
+int
+glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock)
+{
+ int err;
+
+ err = mutex_init (&lock->mutex, USYNC_THREAD, NULL);
+ if (err != 0)
+ return err;
+ lock->owner = (thread_t) 0;
+ lock->depth = 0;
+ return 0;
+}
+
+int
+glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock)
+{
+ thread_t self = thr_self ();
+ if (lock->owner != self)
+ {
+ int err;
+
+ err = mutex_lock (&lock->mutex);
+ if (err != 0)
+ return err;
+ lock->owner = self;
+ }
+ if (++(lock->depth) == 0) /* wraparound? */
+ {
+ lock->depth--;
+ return EAGAIN;
+ }
+ return 0;
+}
+
+int
+glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock)
+{
+ if (lock->owner != thr_self ())
+ return EPERM;
+ if (lock->depth == 0)
+ return EINVAL;
+ if (--(lock->depth) == 0)
+ {
+ lock->owner = (thread_t) 0;
+ return mutex_unlock (&lock->mutex);
+ }
+ else
+ return 0;
+}
+
+int
+glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock)
+{
+ if (lock->owner != (thread_t) 0)
+ return EBUSY;
+ return mutex_destroy (&lock->mutex);
+}
+
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+int
+glthread_once_multithreaded (gl_once_t *once_control, void (*initfunction) (void))
+{
+ if (!once_control->inited)
+ {
+ int err;
+
+ /* Use the mutex to guarantee that if another thread is already calling
+ the initfunction, this thread waits until it's finished. */
+ err = mutex_lock (&once_control->mutex);
+ if (err != 0)
+ return err;
+ if (!once_control->inited)
+ {
+ once_control->inited = 1;
+ initfunction ();
+ }
+ return mutex_unlock (&once_control->mutex);
+ }
+ else
+ return 0;
+}
+
+int
+glthread_once_singlethreaded (gl_once_t *once_control)
+{
+ /* We know that gl_once_t contains an integer type. */
+ if (!once_control->inited)
+ {
+ /* First time use of once_control. Invert the marker. */
+ once_control->inited = ~ 0;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_WIN32_THREADS
+
+/* -------------------------- gl_lock_t datatype -------------------------- */
+
+void
+glthread_lock_init_func (gl_lock_t *lock)
+{
+ InitializeCriticalSection (&lock->lock);
+ lock->guard.done = 1;
+}
+
+int
+glthread_lock_lock_func (gl_lock_t *lock)
+{
+ if (!lock->guard.done)
+ {
+ if (InterlockedIncrement (&lock->guard.started) == 0)
+ /* This thread is the first one to need this lock. Initialize it. */
+ glthread_lock_init (lock);
+ else
+ /* Yield the CPU while waiting for another thread to finish
+ initializing this lock. */
+ while (!lock->guard.done)
+ Sleep (0);
+ }
+ EnterCriticalSection (&lock->lock);
+ return 0;
+}
+
+int
+glthread_lock_unlock_func (gl_lock_t *lock)
+{
+ if (!lock->guard.done)
+ return EINVAL;
+ LeaveCriticalSection (&lock->lock);
+ return 0;
+}
+
+int
+glthread_lock_destroy_func (gl_lock_t *lock)
+{
+ if (!lock->guard.done)
+ return EINVAL;
+ DeleteCriticalSection (&lock->lock);
+ lock->guard.done = 0;
+ return 0;
+}
+
+/* ------------------------- gl_rwlock_t datatype ------------------------- */
+
+/* In this file, the waitqueues are implemented as circular arrays. */
+#define gl_waitqueue_t gl_carray_waitqueue_t
+
+static inline void
+gl_waitqueue_init (gl_waitqueue_t *wq)
+{
+ wq->array = NULL;
+ wq->count = 0;
+ wq->alloc = 0;
+ wq->offset = 0;
+}
+
+/* Enqueues the current thread, represented by an event, in a wait queue.
+ Returns INVALID_HANDLE_VALUE if an allocation failure occurs. */
+static HANDLE
+gl_waitqueue_add (gl_waitqueue_t *wq)
+{
+ HANDLE event;
+ unsigned int index;
+
+ if (wq->count == wq->alloc)
+ {
+ unsigned int new_alloc = 2 * wq->alloc + 1;
+ HANDLE *new_array =
+ (HANDLE *) realloc (wq->array, new_alloc * sizeof (HANDLE));
+ if (new_array == NULL)
+ /* No more memory. */
+ return INVALID_HANDLE_VALUE;
+ /* Now is a good opportunity to rotate the array so that its contents
+ starts at offset 0. */
+ if (wq->offset > 0)
+ {
+ unsigned int old_count = wq->count;
+ unsigned int old_alloc = wq->alloc;
+ unsigned int old_offset = wq->offset;
+ unsigned int i;
+ if (old_offset + old_count > old_alloc)
+ {
+ unsigned int limit = old_offset + old_count - old_alloc;
+ for (i = 0; i < limit; i++)
+ new_array[old_alloc + i] = new_array[i];
+ }
+ for (i = 0; i < old_count; i++)
+ new_array[i] = new_array[old_offset + i];
+ wq->offset = 0;
+ }
+ wq->array = new_array;
+ wq->alloc = new_alloc;
+ }
+ /* Whether the created event is a manual-reset one or an auto-reset one,
+ does not matter, since we will wait on it only once. */
+ event = CreateEvent (NULL, TRUE, FALSE, NULL);
+ if (event == INVALID_HANDLE_VALUE)
+ /* No way to allocate an event. */
+ return INVALID_HANDLE_VALUE;
+ index = wq->offset + wq->count;
+ if (index >= wq->alloc)
+ index -= wq->alloc;
+ wq->array[index] = event;
+ wq->count++;
+ return event;
+}
+
+/* Notifies the first thread from a wait queue and dequeues it. */
+static inline void
+gl_waitqueue_notify_first (gl_waitqueue_t *wq)
+{
+ SetEvent (wq->array[wq->offset + 0]);
+ wq->offset++;
+ wq->count--;
+ if (wq->count == 0 || wq->offset == wq->alloc)
+ wq->offset = 0;
+}
+
+/* Notifies all threads from a wait queue and dequeues them all. */
+static inline void
+gl_waitqueue_notify_all (gl_waitqueue_t *wq)
+{
+ unsigned int i;
+
+ for (i = 0; i < wq->count; i++)
+ {
+ unsigned int index = wq->offset + i;
+ if (index >= wq->alloc)
+ index -= wq->alloc;
+ SetEvent (wq->array[index]);
+ }
+ wq->count = 0;
+ wq->offset = 0;
+}
+
+void
+glthread_rwlock_init_func (gl_rwlock_t *lock)
+{
+ InitializeCriticalSection (&lock->lock);
+ gl_waitqueue_init (&lock->waiting_readers);
+ gl_waitqueue_init (&lock->waiting_writers);
+ lock->runcount = 0;
+ lock->guard.done = 1;
+}
+
+int
+glthread_rwlock_rdlock_func (gl_rwlock_t *lock)
+{
+ if (!lock->guard.done)
+ {
+ if (InterlockedIncrement (&lock->guard.started) == 0)
+ /* This thread is the first one to need this lock. Initialize it. */
+ glthread_rwlock_init (lock);
+ else
+ /* Yield the CPU while waiting for another thread to finish
+ initializing this lock. */
+ while (!lock->guard.done)
+ Sleep (0);
+ }
+ EnterCriticalSection (&lock->lock);
+ /* Test whether only readers are currently running, and whether the runcount
+ field will not overflow. */
+ if (!(lock->runcount + 1 > 0))
+ {
+ /* This thread has to wait for a while. Enqueue it among the
+ waiting_readers. */
+ HANDLE event = gl_waitqueue_add (&lock->waiting_readers);
+ if (event != INVALID_HANDLE_VALUE)
+ {
+ DWORD result;
+ LeaveCriticalSection (&lock->lock);
+ /* Wait until another thread signals this event. */
+ result = WaitForSingleObject (event, INFINITE);
+ if (result == WAIT_FAILED || result == WAIT_TIMEOUT)
+ abort ();
+ CloseHandle (event);
+ /* The thread which signalled the event already did the bookkeeping:
+ removed us from the waiting_readers, incremented lock->runcount. */
+ if (!(lock->runcount > 0))
+ abort ();
+ return 0;
+ }
+ else
+ {
+ /* Allocation failure. Weird. */
+ do
+ {
+ LeaveCriticalSection (&lock->lock);
+ Sleep (1);
+ EnterCriticalSection (&lock->lock);
+ }
+ while (!(lock->runcount + 1 > 0));
+ }
+ }
+ lock->runcount++;
+ LeaveCriticalSection (&lock->lock);
+ return 0;
+}
+
+int
+glthread_rwlock_wrlock_func (gl_rwlock_t *lock)
+{
+ if (!lock->guard.done)
+ {
+ if (InterlockedIncrement (&lock->guard.started) == 0)
+ /* This thread is the first one to need this lock. Initialize it. */
+ glthread_rwlock_init (lock);
+ else
+ /* Yield the CPU while waiting for another thread to finish
+ initializing this lock. */
+ while (!lock->guard.done)
+ Sleep (0);
+ }
+ EnterCriticalSection (&lock->lock);
+ /* Test whether no readers or writers are currently running. */
+ if (!(lock->runcount == 0))
+ {
+ /* This thread has to wait for a while. Enqueue it among the
+ waiting_writers. */
+ HANDLE event = gl_waitqueue_add (&lock->waiting_writers);
+ if (event != INVALID_HANDLE_VALUE)
+ {
+ DWORD result;
+ LeaveCriticalSection (&lock->lock);
+ /* Wait until another thread signals this event. */
+ result = WaitForSingleObject (event, INFINITE);
+ if (result == WAIT_FAILED || result == WAIT_TIMEOUT)
+ abort ();
+ CloseHandle (event);
+ /* The thread which signalled the event already did the bookkeeping:
+ removed us from the waiting_writers, set lock->runcount = -1. */
+ if (!(lock->runcount == -1))
+ abort ();
+ return 0;
+ }
+ else
+ {
+ /* Allocation failure. Weird. */
+ do
+ {
+ LeaveCriticalSection (&lock->lock);
+ Sleep (1);
+ EnterCriticalSection (&lock->lock);
+ }
+ while (!(lock->runcount == 0));
+ }
+ }
+ lock->runcount--; /* runcount becomes -1 */
+ LeaveCriticalSection (&lock->lock);
+ return 0;
+}
+
+int
+glthread_rwlock_unlock_func (gl_rwlock_t *lock)
+{
+ if (!lock->guard.done)
+ return EINVAL;
+ EnterCriticalSection (&lock->lock);
+ if (lock->runcount < 0)
+ {
+ /* Drop a writer lock. */
+ if (!(lock->runcount == -1))
+ abort ();
+ lock->runcount = 0;
+ }
+ else
+ {
+ /* Drop a reader lock. */
+ if (!(lock->runcount > 0))
+ {
+ LeaveCriticalSection (&lock->lock);
+ return EPERM;
+ }
+ lock->runcount--;
+ }
+ if (lock->runcount == 0)
+ {
+ /* POSIX recommends that "write locks shall take precedence over read
+ locks", to avoid "writer starvation". */
+ if (lock->waiting_writers.count > 0)
+ {
+ /* Wake up one of the waiting writers. */
+ lock->runcount--;
+ gl_waitqueue_notify_first (&lock->waiting_writers);
+ }
+ else
+ {
+ /* Wake up all waiting readers. */
+ lock->runcount += lock->waiting_readers.count;
+ gl_waitqueue_notify_all (&lock->waiting_readers);
+ }
+ }
+ LeaveCriticalSection (&lock->lock);
+ return 0;
+}
+
+int
+glthread_rwlock_destroy_func (gl_rwlock_t *lock)
+{
+ if (!lock->guard.done)
+ return EINVAL;
+ if (lock->runcount != 0)
+ return EBUSY;
+ DeleteCriticalSection (&lock->lock);
+ if (lock->waiting_readers.array != NULL)
+ free (lock->waiting_readers.array);
+ if (lock->waiting_writers.array != NULL)
+ free (lock->waiting_writers.array);
+ lock->guard.done = 0;
+ return 0;
+}
+
+/* --------------------- gl_recursive_lock_t datatype --------------------- */
+
+void
+glthread_recursive_lock_init_func (gl_recursive_lock_t *lock)
+{
+ lock->owner = 0;
+ lock->depth = 0;
+ InitializeCriticalSection (&lock->lock);
+ lock->guard.done = 1;
+}
+
+int
+glthread_recursive_lock_lock_func (gl_recursive_lock_t *lock)
+{
+ if (!lock->guard.done)
+ {
+ if (InterlockedIncrement (&lock->guard.started) == 0)
+ /* This thread is the first one to need this lock. Initialize it. */
+ glthread_recursive_lock_init (lock);
+ else
+ /* Yield the CPU while waiting for another thread to finish
+ initializing this lock. */
+ while (!lock->guard.done)
+ Sleep (0);
+ }
+ {
+ DWORD self = GetCurrentThreadId ();
+ if (lock->owner != self)
+ {
+ EnterCriticalSection (&lock->lock);
+ lock->owner = self;
+ }
+ if (++(lock->depth) == 0) /* wraparound? */
+ {
+ lock->depth--;
+ return EAGAIN;
+ }
+ }
+ return 0;
+}
+
+int
+glthread_recursive_lock_unlock_func (gl_recursive_lock_t *lock)
+{
+ if (lock->owner != GetCurrentThreadId ())
+ return EPERM;
+ if (lock->depth == 0)
+ return EINVAL;
+ if (--(lock->depth) == 0)
+ {
+ lock->owner = 0;
+ LeaveCriticalSection (&lock->lock);
+ }
+ return 0;
+}
+
+int
+glthread_recursive_lock_destroy_func (gl_recursive_lock_t *lock)
+{
+ if (lock->owner != 0)
+ return EBUSY;
+ DeleteCriticalSection (&lock->lock);
+ lock->guard.done = 0;
+ return 0;
+}
+
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+void
+glthread_once_func (gl_once_t *once_control, void (*initfunction) (void))
+{
+ if (once_control->inited <= 0)
+ {
+ if (InterlockedIncrement (&once_control->started) == 0)
+ {
+ /* This thread is the first one to come to this once_control. */
+ InitializeCriticalSection (&once_control->lock);
+ EnterCriticalSection (&once_control->lock);
+ once_control->inited = 0;
+ initfunction ();
+ once_control->inited = 1;
+ LeaveCriticalSection (&once_control->lock);
+ }
+ else
+ {
+ /* Undo last operation. */
+ InterlockedDecrement (&once_control->started);
+ /* Some other thread has already started the initialization.
+ Yield the CPU while waiting for the other thread to finish
+ initializing and taking the lock. */
+ while (once_control->inited < 0)
+ Sleep (0);
+ if (once_control->inited <= 0)
+ {
+ /* Take the lock. This blocks until the other thread has
+ finished calling the initfunction. */
+ EnterCriticalSection (&once_control->lock);
+ LeaveCriticalSection (&once_control->lock);
+ if (!(once_control->inited > 0))
+ abort ();
+ }
+ }
+ }
+}
+
+#endif
+
+/* ========================================================================= */
diff --git a/intl/lock.h b/intl/lock.h
new file mode 100644
index 00000000..b7e955aa
--- /dev/null
+++ b/intl/lock.h
@@ -0,0 +1,928 @@
+/* Locking in multithreaded situations.
+ Copyright (C) 2005-2008 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2005.
+ Based on GCC's gthr-posix.h, gthr-posix95.h, gthr-solaris.h,
+ gthr-win32.h. */
+
+/* This file contains locking primitives for use with a given thread library.
+ It does not contain primitives for creating threads or for other
+ synchronization primitives.
+
+ Normal (non-recursive) locks:
+ Type: gl_lock_t
+ Declaration: gl_lock_define(extern, name)
+ Initializer: gl_lock_define_initialized(, name)
+ Initialization: gl_lock_init (name);
+ Taking the lock: gl_lock_lock (name);
+ Releasing the lock: gl_lock_unlock (name);
+ De-initialization: gl_lock_destroy (name);
+ Equivalent functions with control of error handling:
+ Initialization: err = glthread_lock_init (&name);
+ Taking the lock: err = glthread_lock_lock (&name);
+ Releasing the lock: err = glthread_lock_unlock (&name);
+ De-initialization: err = glthread_lock_destroy (&name);
+
+ Read-Write (non-recursive) locks:
+ Type: gl_rwlock_t
+ Declaration: gl_rwlock_define(extern, name)
+ Initializer: gl_rwlock_define_initialized(, name)
+ Initialization: gl_rwlock_init (name);
+ Taking the lock: gl_rwlock_rdlock (name);
+ gl_rwlock_wrlock (name);
+ Releasing the lock: gl_rwlock_unlock (name);
+ De-initialization: gl_rwlock_destroy (name);
+ Equivalent functions with control of error handling:
+ Initialization: err = glthread_rwlock_init (&name);
+ Taking the lock: err = glthread_rwlock_rdlock (&name);
+ err = glthread_rwlock_wrlock (&name);
+ Releasing the lock: err = glthread_rwlock_unlock (&name);
+ De-initialization: err = glthread_rwlock_destroy (&name);
+
+ Recursive locks:
+ Type: gl_recursive_lock_t
+ Declaration: gl_recursive_lock_define(extern, name)
+ Initializer: gl_recursive_lock_define_initialized(, name)
+ Initialization: gl_recursive_lock_init (name);
+ Taking the lock: gl_recursive_lock_lock (name);
+ Releasing the lock: gl_recursive_lock_unlock (name);
+ De-initialization: gl_recursive_lock_destroy (name);
+ Equivalent functions with control of error handling:
+ Initialization: err = glthread_recursive_lock_init (&name);
+ Taking the lock: err = glthread_recursive_lock_lock (&name);
+ Releasing the lock: err = glthread_recursive_lock_unlock (&name);
+ De-initialization: err = glthread_recursive_lock_destroy (&name);
+
+ Once-only execution:
+ Type: gl_once_t
+ Initializer: gl_once_define(extern, name)
+ Execution: gl_once (name, initfunction);
+ Equivalent functions with control of error handling:
+ Execution: err = glthread_once (&name, initfunction);
+*/
+
+
+#ifndef _LOCK_H
+#define _LOCK_H
+
+#include <errno.h>
+#include <stdlib.h>
+
+/* ========================================================================= */
+
+#if USE_POSIX_THREADS
+
+/* Use the POSIX threads library. */
+
+# include <pthread.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# if PTHREAD_IN_USE_DETECTION_HARD
+
+/* The pthread_in_use() detection needs to be done at runtime. */
+# define pthread_in_use() \
+ glthread_in_use ()
+extern int glthread_in_use (void);
+
+# endif
+
+# if USE_POSIX_THREADS_WEAK
+
+/* Use weak references to the POSIX threads library. */
+
+/* Weak references avoid dragging in external libraries if the other parts
+ of the program don't use them. Here we use them, because we don't want
+ every program that uses libintl to depend on libpthread. This assumes
+ that libpthread would not be loaded after libintl; i.e. if libintl is
+ loaded first, by an executable that does not depend on libpthread, and
+ then a module is dynamically loaded that depends on libpthread, libintl
+ will not be multithread-safe. */
+
+/* The way to test at runtime whether libpthread is present is to test
+ whether a function pointer's value, such as &pthread_mutex_init, is
+ non-NULL. However, some versions of GCC have a bug through which, in
+ PIC mode, &foo != NULL always evaluates to true if there is a direct
+ call to foo(...) in the same function. To avoid this, we test the
+ address of a function in libpthread that we don't use. */
+
+# pragma weak pthread_mutex_init
+# pragma weak pthread_mutex_lock
+# pragma weak pthread_mutex_unlock
+# pragma weak pthread_mutex_destroy
+# pragma weak pthread_rwlock_init
+# pragma weak pthread_rwlock_rdlock
+# pragma weak pthread_rwlock_wrlock
+# pragma weak pthread_rwlock_unlock
+# pragma weak pthread_rwlock_destroy
+# pragma weak pthread_once
+# pragma weak pthread_cond_init
+# pragma weak pthread_cond_wait
+# pragma weak pthread_cond_signal
+# pragma weak pthread_cond_broadcast
+# pragma weak pthread_cond_destroy
+# pragma weak pthread_mutexattr_init
+# pragma weak pthread_mutexattr_settype
+# pragma weak pthread_mutexattr_destroy
+# ifndef pthread_self
+# pragma weak pthread_self
+# endif
+
+# if !PTHREAD_IN_USE_DETECTION_HARD
+# pragma weak pthread_cancel
+# define pthread_in_use() (pthread_cancel != NULL)
+# endif
+
+# else
+
+# if !PTHREAD_IN_USE_DETECTION_HARD
+# define pthread_in_use() 1
+# endif
+
+# endif
+
+/* -------------------------- gl_lock_t datatype -------------------------- */
+
+typedef pthread_mutex_t gl_lock_t;
+# define gl_lock_define(STORAGECLASS, NAME) \
+ STORAGECLASS pthread_mutex_t NAME;
+# define gl_lock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS pthread_mutex_t NAME = gl_lock_initializer;
+# define gl_lock_initializer \
+ PTHREAD_MUTEX_INITIALIZER
+# define glthread_lock_init(LOCK) \
+ (pthread_in_use () ? pthread_mutex_init (LOCK, NULL) : 0)
+# define glthread_lock_lock(LOCK) \
+ (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0)
+# define glthread_lock_unlock(LOCK) \
+ (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0)
+# define glthread_lock_destroy(LOCK) \
+ (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0)
+
+/* ------------------------- gl_rwlock_t datatype ------------------------- */
+
+# if HAVE_PTHREAD_RWLOCK
+
+# ifdef PTHREAD_RWLOCK_INITIALIZER
+
+typedef pthread_rwlock_t gl_rwlock_t;
+# define gl_rwlock_define(STORAGECLASS, NAME) \
+ STORAGECLASS pthread_rwlock_t NAME;
+# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS pthread_rwlock_t NAME = gl_rwlock_initializer;
+# define gl_rwlock_initializer \
+ PTHREAD_RWLOCK_INITIALIZER
+# define glthread_rwlock_init(LOCK) \
+ (pthread_in_use () ? pthread_rwlock_init (LOCK, NULL) : 0)
+# define glthread_rwlock_rdlock(LOCK) \
+ (pthread_in_use () ? pthread_rwlock_rdlock (LOCK) : 0)
+# define glthread_rwlock_wrlock(LOCK) \
+ (pthread_in_use () ? pthread_rwlock_wrlock (LOCK) : 0)
+# define glthread_rwlock_unlock(LOCK) \
+ (pthread_in_use () ? pthread_rwlock_unlock (LOCK) : 0)
+# define glthread_rwlock_destroy(LOCK) \
+ (pthread_in_use () ? pthread_rwlock_destroy (LOCK) : 0)
+
+# else
+
+typedef struct
+ {
+ int initialized;
+ pthread_mutex_t guard; /* protects the initialization */
+ pthread_rwlock_t rwlock; /* read-write lock */
+ }
+ gl_rwlock_t;
+# define gl_rwlock_define(STORAGECLASS, NAME) \
+ STORAGECLASS gl_rwlock_t NAME;
+# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
+# define gl_rwlock_initializer \
+ { 0, PTHREAD_MUTEX_INITIALIZER }
+# define glthread_rwlock_init(LOCK) \
+ (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0)
+# define glthread_rwlock_rdlock(LOCK) \
+ (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0)
+# define glthread_rwlock_wrlock(LOCK) \
+ (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0)
+# define glthread_rwlock_unlock(LOCK) \
+ (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0)
+# define glthread_rwlock_destroy(LOCK) \
+ (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0)
+extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock);
+extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock);
+extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock);
+extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock);
+extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock);
+
+# endif
+
+# else
+
+typedef struct
+ {
+ pthread_mutex_t lock; /* protects the remaining fields */
+ pthread_cond_t waiting_readers; /* waiting readers */
+ pthread_cond_t waiting_writers; /* waiting writers */
+ unsigned int waiting_writers_count; /* number of waiting writers */
+ int runcount; /* number of readers running, or -1 when a writer runs */
+ }
+ gl_rwlock_t;
+# define gl_rwlock_define(STORAGECLASS, NAME) \
+ STORAGECLASS gl_rwlock_t NAME;
+# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
+# define gl_rwlock_initializer \
+ { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0 }
+# define glthread_rwlock_init(LOCK) \
+ (pthread_in_use () ? glthread_rwlock_init_multithreaded (LOCK) : 0)
+# define glthread_rwlock_rdlock(LOCK) \
+ (pthread_in_use () ? glthread_rwlock_rdlock_multithreaded (LOCK) : 0)
+# define glthread_rwlock_wrlock(LOCK) \
+ (pthread_in_use () ? glthread_rwlock_wrlock_multithreaded (LOCK) : 0)
+# define glthread_rwlock_unlock(LOCK) \
+ (pthread_in_use () ? glthread_rwlock_unlock_multithreaded (LOCK) : 0)
+# define glthread_rwlock_destroy(LOCK) \
+ (pthread_in_use () ? glthread_rwlock_destroy_multithreaded (LOCK) : 0)
+extern int glthread_rwlock_init_multithreaded (gl_rwlock_t *lock);
+extern int glthread_rwlock_rdlock_multithreaded (gl_rwlock_t *lock);
+extern int glthread_rwlock_wrlock_multithreaded (gl_rwlock_t *lock);
+extern int glthread_rwlock_unlock_multithreaded (gl_rwlock_t *lock);
+extern int glthread_rwlock_destroy_multithreaded (gl_rwlock_t *lock);
+
+# endif
+
+/* --------------------- gl_recursive_lock_t datatype --------------------- */
+
+# if HAVE_PTHREAD_MUTEX_RECURSIVE
+
+# if defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER || defined PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
+
+typedef pthread_mutex_t gl_recursive_lock_t;
+# define gl_recursive_lock_define(STORAGECLASS, NAME) \
+ STORAGECLASS pthread_mutex_t NAME;
+# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS pthread_mutex_t NAME = gl_recursive_lock_initializer;
+# ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER
+# define gl_recursive_lock_initializer \
+ PTHREAD_RECURSIVE_MUTEX_INITIALIZER
+# else
+# define gl_recursive_lock_initializer \
+ PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
+# endif
+# define glthread_recursive_lock_init(LOCK) \
+ (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
+# define glthread_recursive_lock_lock(LOCK) \
+ (pthread_in_use () ? pthread_mutex_lock (LOCK) : 0)
+# define glthread_recursive_lock_unlock(LOCK) \
+ (pthread_in_use () ? pthread_mutex_unlock (LOCK) : 0)
+# define glthread_recursive_lock_destroy(LOCK) \
+ (pthread_in_use () ? pthread_mutex_destroy (LOCK) : 0)
+extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
+
+# else
+
+typedef struct
+ {
+ pthread_mutex_t recmutex; /* recursive mutex */
+ pthread_mutex_t guard; /* protects the initialization */
+ int initialized;
+ }
+ gl_recursive_lock_t;
+# define gl_recursive_lock_define(STORAGECLASS, NAME) \
+ STORAGECLASS gl_recursive_lock_t NAME;
+# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
+# define gl_recursive_lock_initializer \
+ { PTHREAD_MUTEX_INITIALIZER, PTHREAD_MUTEX_INITIALIZER, 0 }
+# define glthread_recursive_lock_init(LOCK) \
+ (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
+# define glthread_recursive_lock_lock(LOCK) \
+ (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
+# define glthread_recursive_lock_unlock(LOCK) \
+ (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
+# define glthread_recursive_lock_destroy(LOCK) \
+ (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
+extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
+extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
+extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
+extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
+
+# endif
+
+# else
+
+/* Old versions of POSIX threads on Solaris did not have recursive locks.
+ We have to implement them ourselves. */
+
+typedef struct
+ {
+ pthread_mutex_t mutex;
+ pthread_t owner;
+ unsigned long depth;
+ }
+ gl_recursive_lock_t;
+# define gl_recursive_lock_define(STORAGECLASS, NAME) \
+ STORAGECLASS gl_recursive_lock_t NAME;
+# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
+# define gl_recursive_lock_initializer \
+ { PTHREAD_MUTEX_INITIALIZER, (pthread_t) 0, 0 }
+# define glthread_recursive_lock_init(LOCK) \
+ (pthread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
+# define glthread_recursive_lock_lock(LOCK) \
+ (pthread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
+# define glthread_recursive_lock_unlock(LOCK) \
+ (pthread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
+# define glthread_recursive_lock_destroy(LOCK) \
+ (pthread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
+extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
+extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
+extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
+extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
+
+# endif
+
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+typedef pthread_once_t gl_once_t;
+# define gl_once_define(STORAGECLASS, NAME) \
+ STORAGECLASS pthread_once_t NAME = PTHREAD_ONCE_INIT;
+# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
+ (pthread_in_use () \
+ ? pthread_once (ONCE_CONTROL, INITFUNCTION) \
+ : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
+extern int glthread_once_singlethreaded (pthread_once_t *once_control);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_PTH_THREADS
+
+/* Use the GNU Pth threads library. */
+
+# include <pth.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# if USE_PTH_THREADS_WEAK
+
+/* Use weak references to the GNU Pth threads library. */
+
+# pragma weak pth_mutex_init
+# pragma weak pth_mutex_acquire
+# pragma weak pth_mutex_release
+# pragma weak pth_rwlock_init
+# pragma weak pth_rwlock_acquire
+# pragma weak pth_rwlock_release
+# pragma weak pth_once
+
+# pragma weak pth_cancel
+# define pth_in_use() (pth_cancel != NULL)
+
+# else
+
+# define pth_in_use() 1
+
+# endif
+
+/* -------------------------- gl_lock_t datatype -------------------------- */
+
+typedef pth_mutex_t gl_lock_t;
+# define gl_lock_define(STORAGECLASS, NAME) \
+ STORAGECLASS pth_mutex_t NAME;
+# define gl_lock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS pth_mutex_t NAME = gl_lock_initializer;
+# define gl_lock_initializer \
+ PTH_MUTEX_INIT
+# define glthread_lock_init(LOCK) \
+ (pth_in_use () && !pth_mutex_init (LOCK) ? errno : 0)
+# define glthread_lock_lock(LOCK) \
+ (pth_in_use () && !pth_mutex_acquire (LOCK, 0, NULL) ? errno : 0)
+# define glthread_lock_unlock(LOCK) \
+ (pth_in_use () && !pth_mutex_release (LOCK) ? errno : 0)
+# define glthread_lock_destroy(LOCK) \
+ ((void)(LOCK), 0)
+
+/* ------------------------- gl_rwlock_t datatype ------------------------- */
+
+typedef pth_rwlock_t gl_rwlock_t;
+# define gl_rwlock_define(STORAGECLASS, NAME) \
+ STORAGECLASS pth_rwlock_t NAME;
+# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS pth_rwlock_t NAME = gl_rwlock_initializer;
+# define gl_rwlock_initializer \
+ PTH_RWLOCK_INIT
+# define glthread_rwlock_init(LOCK) \
+ (pth_in_use () && !pth_rwlock_init (LOCK) ? errno : 0)
+# define glthread_rwlock_rdlock(LOCK) \
+ (pth_in_use () && !pth_rwlock_acquire (LOCK, PTH_RWLOCK_RD, 0, NULL) ? errno : 0)
+# define glthread_rwlock_wrlock(LOCK) \
+ (pth_in_use () && !pth_rwlock_acquire (LOCK, PTH_RWLOCK_RW, 0, NULL) ? errno : 0)
+# define glthread_rwlock_unlock(LOCK) \
+ (pth_in_use () && !pth_rwlock_release (LOCK) ? errno : 0)
+# define glthread_rwlock_destroy(LOCK) \
+ ((void)(LOCK), 0)
+
+/* --------------------- gl_recursive_lock_t datatype --------------------- */
+
+/* In Pth, mutexes are recursive by default. */
+typedef pth_mutex_t gl_recursive_lock_t;
+# define gl_recursive_lock_define(STORAGECLASS, NAME) \
+ STORAGECLASS pth_mutex_t NAME;
+# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS pth_mutex_t NAME = gl_recursive_lock_initializer;
+# define gl_recursive_lock_initializer \
+ PTH_MUTEX_INIT
+# define glthread_recursive_lock_init(LOCK) \
+ (pth_in_use () && !pth_mutex_init (LOCK) ? errno : 0)
+# define glthread_recursive_lock_lock(LOCK) \
+ (pth_in_use () && !pth_mutex_acquire (LOCK, 0, NULL) ? errno : 0)
+# define glthread_recursive_lock_unlock(LOCK) \
+ (pth_in_use () && !pth_mutex_release (LOCK) ? errno : 0)
+# define glthread_recursive_lock_destroy(LOCK) \
+ ((void)(LOCK), 0)
+
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+typedef pth_once_t gl_once_t;
+# define gl_once_define(STORAGECLASS, NAME) \
+ STORAGECLASS pth_once_t NAME = PTH_ONCE_INIT;
+# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
+ (pth_in_use () \
+ ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION) \
+ : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
+extern int glthread_once_multithreaded (pth_once_t *once_control, void (*initfunction) (void));
+extern int glthread_once_singlethreaded (pth_once_t *once_control);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_SOLARIS_THREADS
+
+/* Use the old Solaris threads library. */
+
+# include <thread.h>
+# include <synch.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+# if USE_SOLARIS_THREADS_WEAK
+
+/* Use weak references to the old Solaris threads library. */
+
+# pragma weak mutex_init
+# pragma weak mutex_lock
+# pragma weak mutex_unlock
+# pragma weak mutex_destroy
+# pragma weak rwlock_init
+# pragma weak rw_rdlock
+# pragma weak rw_wrlock
+# pragma weak rw_unlock
+# pragma weak rwlock_destroy
+# pragma weak thr_self
+
+# pragma weak thr_suspend
+# define thread_in_use() (thr_suspend != NULL)
+
+# else
+
+# define thread_in_use() 1
+
+# endif
+
+/* -------------------------- gl_lock_t datatype -------------------------- */
+
+typedef mutex_t gl_lock_t;
+# define gl_lock_define(STORAGECLASS, NAME) \
+ STORAGECLASS mutex_t NAME;
+# define gl_lock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS mutex_t NAME = gl_lock_initializer;
+# define gl_lock_initializer \
+ DEFAULTMUTEX
+# define glthread_lock_init(LOCK) \
+ (thread_in_use () ? mutex_init (LOCK, USYNC_THREAD, NULL) : 0)
+# define glthread_lock_lock(LOCK) \
+ (thread_in_use () ? mutex_lock (LOCK) : 0)
+# define glthread_lock_unlock(LOCK) \
+ (thread_in_use () ? mutex_unlock (LOCK) : 0)
+# define glthread_lock_destroy(LOCK) \
+ (thread_in_use () ? mutex_destroy (LOCK) : 0)
+
+/* ------------------------- gl_rwlock_t datatype ------------------------- */
+
+typedef rwlock_t gl_rwlock_t;
+# define gl_rwlock_define(STORAGECLASS, NAME) \
+ STORAGECLASS rwlock_t NAME;
+# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS rwlock_t NAME = gl_rwlock_initializer;
+# define gl_rwlock_initializer \
+ DEFAULTRWLOCK
+# define glthread_rwlock_init(LOCK) \
+ (thread_in_use () ? rwlock_init (LOCK, USYNC_THREAD, NULL) : 0)
+# define glthread_rwlock_rdlock(LOCK) \
+ (thread_in_use () ? rw_rdlock (LOCK) : 0)
+# define glthread_rwlock_wrlock(LOCK) \
+ (thread_in_use () ? rw_wrlock (LOCK) : 0)
+# define glthread_rwlock_unlock(LOCK) \
+ (thread_in_use () ? rw_unlock (LOCK) : 0)
+# define glthread_rwlock_destroy(LOCK) \
+ (thread_in_use () ? rwlock_destroy (LOCK) : 0)
+
+/* --------------------- gl_recursive_lock_t datatype --------------------- */
+
+/* Old Solaris threads did not have recursive locks.
+ We have to implement them ourselves. */
+
+typedef struct
+ {
+ mutex_t mutex;
+ thread_t owner;
+ unsigned long depth;
+ }
+ gl_recursive_lock_t;
+# define gl_recursive_lock_define(STORAGECLASS, NAME) \
+ STORAGECLASS gl_recursive_lock_t NAME;
+# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
+# define gl_recursive_lock_initializer \
+ { DEFAULTMUTEX, (thread_t) 0, 0 }
+# define glthread_recursive_lock_init(LOCK) \
+ (thread_in_use () ? glthread_recursive_lock_init_multithreaded (LOCK) : 0)
+# define glthread_recursive_lock_lock(LOCK) \
+ (thread_in_use () ? glthread_recursive_lock_lock_multithreaded (LOCK) : 0)
+# define glthread_recursive_lock_unlock(LOCK) \
+ (thread_in_use () ? glthread_recursive_lock_unlock_multithreaded (LOCK) : 0)
+# define glthread_recursive_lock_destroy(LOCK) \
+ (thread_in_use () ? glthread_recursive_lock_destroy_multithreaded (LOCK) : 0)
+extern int glthread_recursive_lock_init_multithreaded (gl_recursive_lock_t *lock);
+extern int glthread_recursive_lock_lock_multithreaded (gl_recursive_lock_t *lock);
+extern int glthread_recursive_lock_unlock_multithreaded (gl_recursive_lock_t *lock);
+extern int glthread_recursive_lock_destroy_multithreaded (gl_recursive_lock_t *lock);
+
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+typedef struct
+ {
+ volatile int inited;
+ mutex_t mutex;
+ }
+ gl_once_t;
+# define gl_once_define(STORAGECLASS, NAME) \
+ STORAGECLASS gl_once_t NAME = { 0, DEFAULTMUTEX };
+# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
+ (thread_in_use () \
+ ? glthread_once_multithreaded (ONCE_CONTROL, INITFUNCTION) \
+ : (glthread_once_singlethreaded (ONCE_CONTROL) ? (INITFUNCTION (), 0) : 0))
+extern int glthread_once_multithreaded (gl_once_t *once_control, void (*initfunction) (void));
+extern int glthread_once_singlethreaded (gl_once_t *once_control);
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
+
+/* ========================================================================= */
+
+#if USE_WIN32_THREADS
+
+# include <windows.h>
+
+# ifdef __cplusplus
+extern "C" {
+# endif
+
+/* We can use CRITICAL_SECTION directly, rather than the Win32 Event, Mutex,
+ Semaphore types, because
+ - we need only to synchronize inside a single process (address space),
+ not inter-process locking,
+ - we don't need to support trylock operations. (TryEnterCriticalSection
+ does not work on Windows 95/98/ME. Packages that need trylock usually
+ define their own mutex type.) */
+
+/* There is no way to statically initialize a CRITICAL_SECTION. It needs
+ to be done lazily, once only. For this we need spinlocks. */
+
+typedef struct { volatile int done; volatile long started; } gl_spinlock_t;
+
+/* -------------------------- gl_lock_t datatype -------------------------- */
+
+typedef struct
+ {
+ gl_spinlock_t guard; /* protects the initialization */
+ CRITICAL_SECTION lock;
+ }
+ gl_lock_t;
+# define gl_lock_define(STORAGECLASS, NAME) \
+ STORAGECLASS gl_lock_t NAME;
+# define gl_lock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS gl_lock_t NAME = gl_lock_initializer;
+# define gl_lock_initializer \
+ { { 0, -1 } }
+# define glthread_lock_init(LOCK) \
+ (glthread_lock_init_func (LOCK), 0)
+# define glthread_lock_lock(LOCK) \
+ glthread_lock_lock_func (LOCK)
+# define glthread_lock_unlock(LOCK) \
+ glthread_lock_unlock_func (LOCK)
+# define glthread_lock_destroy(LOCK) \
+ glthread_lock_destroy_func (LOCK)
+extern void glthread_lock_init_func (gl_lock_t *lock);
+extern int glthread_lock_lock_func (gl_lock_t *lock);
+extern int glthread_lock_unlock_func (gl_lock_t *lock);
+extern int glthread_lock_destroy_func (gl_lock_t *lock);
+
+/* ------------------------- gl_rwlock_t datatype ------------------------- */
+
+/* It is impossible to implement read-write locks using plain locks, without
+ introducing an extra thread dedicated to managing read-write locks.
+ Therefore here we need to use the low-level Event type. */
+
+typedef struct
+ {
+ HANDLE *array; /* array of waiting threads, each represented by an event */
+ unsigned int count; /* number of waiting threads */
+ unsigned int alloc; /* length of allocated array */
+ unsigned int offset; /* index of first waiting thread in array */
+ }
+ gl_carray_waitqueue_t;
+typedef struct
+ {
+ gl_spinlock_t guard; /* protects the initialization */
+ CRITICAL_SECTION lock; /* protects the remaining fields */
+ gl_carray_waitqueue_t waiting_readers; /* waiting readers */
+ gl_carray_waitqueue_t waiting_writers; /* waiting writers */
+ int runcount; /* number of readers running, or -1 when a writer runs */
+ }
+ gl_rwlock_t;
+# define gl_rwlock_define(STORAGECLASS, NAME) \
+ STORAGECLASS gl_rwlock_t NAME;
+# define gl_rwlock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS gl_rwlock_t NAME = gl_rwlock_initializer;
+# define gl_rwlock_initializer \
+ { { 0, -1 } }
+# define glthread_rwlock_init(LOCK) \
+ (glthread_rwlock_init_func (LOCK), 0)
+# define glthread_rwlock_rdlock(LOCK) \
+ glthread_rwlock_rdlock_func (LOCK)
+# define glthread_rwlock_wrlock(LOCK) \
+ glthread_rwlock_wrlock_func (LOCK)
+# define glthread_rwlock_unlock(LOCK) \
+ glthread_rwlock_unlock_func (LOCK)
+# define glthread_rwlock_destroy(LOCK) \
+ glthread_rwlock_destroy_func (LOCK)
+extern void glthread_rwlock_init_func (gl_rwlock_t *lock);
+extern int glthread_rwlock_rdlock_func (gl_rwlock_t *lock);
+extern int glthread_rwlock_wrlock_func (gl_rwlock_t *lock);
+extern int glthread_rwlock_unlock_func (gl_rwlock_t *lock);
+extern int glthread_rwlock_destroy_func (gl_rwlock_t *lock);
+
+/* --------------------- gl_recursive_lock_t datatype --------------------- */
+
+/* The Win32 documentation says that CRITICAL_SECTION already implements a
+ recursive lock. But we need not rely on it: It's easy to implement a
+ recursive lock without this assumption. */
+
+typedef struct
+ {
+ gl_spinlock_t guard; /* protects the initialization */
+ DWORD owner;
+ unsigned long depth;
+ CRITICAL_SECTION lock;
+ }
+ gl_recursive_lock_t;
+# define gl_recursive_lock_define(STORAGECLASS, NAME) \
+ STORAGECLASS gl_recursive_lock_t NAME;
+# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME) \
+ STORAGECLASS gl_recursive_lock_t NAME = gl_recursive_lock_initializer;
+# define gl_recursive_lock_initializer \
+ { { 0, -1 }, 0, 0 }
+# define glthread_recursive_lock_init(LOCK) \
+ (glthread_recursive_lock_init_func (LOCK), 0)
+# define glthread_recursive_lock_lock(LOCK) \
+ glthread_recursive_lock_lock_func (LOCK)
+# define glthread_recursive_lock_unlock(LOCK) \
+ glthread_recursive_lock_unlock_func (LOCK)
+# define glthread_recursive_lock_destroy(LOCK) \
+ glthread_recursive_lock_destroy_func (LOCK)
+extern void glthread_recursive_lock_init_func (gl_recursive_lock_t *lock);
+extern int glthread_recursive_lock_lock_func (gl_recursive_lock_t *lock);
+extern int glthread_recursive_lock_unlock_func (gl_recursive_lock_t *lock);
+extern int glthread_recursive_lock_destroy_func (gl_recursive_lock_t *lock);
+
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+typedef struct
+ {
+ volatile int inited;
+ volatile long started;
+ CRITICAL_SECTION lock;
+ }
+ gl_once_t;
+# define gl_once_define(STORAGECLASS, NAME) \
+ STORAGECLASS gl_once_t NAME = { -1, -1 };
+# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
+ (glthread_once_func (ONCE_CONTROL, INITFUNCTION), 0)
+extern void glthread_once_func (gl_once_t *once_control, void (*initfunction) (void));
+
+# ifdef __cplusplus
+}
+# endif
+
+#endif
+
+/* ========================================================================= */
+
+#if !(USE_POSIX_THREADS || USE_PTH_THREADS || USE_SOLARIS_THREADS || USE_WIN32_THREADS)
+
+/* Provide dummy implementation if threads are not supported. */
+
+/* -------------------------- gl_lock_t datatype -------------------------- */
+
+typedef int gl_lock_t;
+# define gl_lock_define(STORAGECLASS, NAME)
+# define gl_lock_define_initialized(STORAGECLASS, NAME)
+# define glthread_lock_init(NAME) 0
+# define glthread_lock_lock(NAME) 0
+# define glthread_lock_unlock(NAME) 0
+# define glthread_lock_destroy(NAME) 0
+
+/* ------------------------- gl_rwlock_t datatype ------------------------- */
+
+typedef int gl_rwlock_t;
+# define gl_rwlock_define(STORAGECLASS, NAME)
+# define gl_rwlock_define_initialized(STORAGECLASS, NAME)
+# define glthread_rwlock_init(NAME) 0
+# define glthread_rwlock_rdlock(NAME) 0
+# define glthread_rwlock_wrlock(NAME) 0
+# define glthread_rwlock_unlock(NAME) 0
+# define glthread_rwlock_destroy(NAME) 0
+
+/* --------------------- gl_recursive_lock_t datatype --------------------- */
+
+typedef int gl_recursive_lock_t;
+# define gl_recursive_lock_define(STORAGECLASS, NAME)
+# define gl_recursive_lock_define_initialized(STORAGECLASS, NAME)
+# define glthread_recursive_lock_init(NAME) 0
+# define glthread_recursive_lock_lock(NAME) 0
+# define glthread_recursive_lock_unlock(NAME) 0
+# define glthread_recursive_lock_destroy(NAME) 0
+
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+typedef int gl_once_t;
+# define gl_once_define(STORAGECLASS, NAME) \
+ STORAGECLASS gl_once_t NAME = 0;
+# define glthread_once(ONCE_CONTROL, INITFUNCTION) \
+ (*(ONCE_CONTROL) == 0 ? (*(ONCE_CONTROL) = ~ 0, INITFUNCTION (), 0) : 0)
+
+#endif
+
+/* ========================================================================= */
+
+/* Macros with built-in error handling. */
+
+/* -------------------------- gl_lock_t datatype -------------------------- */
+
+#define gl_lock_init(NAME) \
+ do \
+ { \
+ if (glthread_lock_init (&NAME)) \
+ abort (); \
+ } \
+ while (0)
+#define gl_lock_lock(NAME) \
+ do \
+ { \
+ if (glthread_lock_lock (&NAME)) \
+ abort (); \
+ } \
+ while (0)
+#define gl_lock_unlock(NAME) \
+ do \
+ { \
+ if (glthread_lock_unlock (&NAME)) \
+ abort (); \
+ } \
+ while (0)
+#define gl_lock_destroy(NAME) \
+ do \
+ { \
+ if (glthread_lock_destroy (&NAME)) \
+ abort (); \
+ } \
+ while (0)
+
+/* ------------------------- gl_rwlock_t datatype ------------------------- */
+
+#define gl_rwlock_init(NAME) \
+ do \
+ { \
+ if (glthread_rwlock_init (&NAME)) \
+ abort (); \
+ } \
+ while (0)
+#define gl_rwlock_rdlock(NAME) \
+ do \
+ { \
+ if (glthread_rwlock_rdlock (&NAME)) \
+ abort (); \
+ } \
+ while (0)
+#define gl_rwlock_wrlock(NAME) \
+ do \
+ { \
+ if (glthread_rwlock_wrlock (&NAME)) \
+ abort (); \
+ } \
+ while (0)
+#define gl_rwlock_unlock(NAME) \
+ do \
+ { \
+ if (glthread_rwlock_unlock (&NAME)) \
+ abort (); \
+ } \
+ while (0)
+#define gl_rwlock_destroy(NAME) \
+ do \
+ { \
+ if (glthread_rwlock_destroy (&NAME)) \
+ abort (); \
+ } \
+ while (0)
+
+/* --------------------- gl_recursive_lock_t datatype --------------------- */
+
+#define gl_recursive_lock_init(NAME) \
+ do \
+ { \
+ if (glthread_recursive_lock_init (&NAME)) \
+ abort (); \
+ } \
+ while (0)
+#define gl_recursive_lock_lock(NAME) \
+ do \
+ { \
+ if (glthread_recursive_lock_lock (&NAME)) \
+ abort (); \
+ } \
+ while (0)
+#define gl_recursive_lock_unlock(NAME) \
+ do \
+ { \
+ if (glthread_recursive_lock_unlock (&NAME)) \
+ abort (); \
+ } \
+ while (0)
+#define gl_recursive_lock_destroy(NAME) \
+ do \
+ { \
+ if (glthread_recursive_lock_destroy (&NAME)) \
+ abort (); \
+ } \
+ while (0)
+
+/* -------------------------- gl_once_t datatype -------------------------- */
+
+#define gl_once(NAME, INITFUNCTION) \
+ do \
+ { \
+ if (glthread_once (&NAME, INITFUNCTION)) \
+ abort (); \
+ } \
+ while (0)
+
+/* ========================================================================= */
+
+#endif /* _LOCK_H */
diff --git a/intl/log.c b/intl/log.c
new file mode 100644
index 00000000..a3e4b272
--- /dev/null
+++ b/intl/log.c
@@ -0,0 +1,128 @@
+/* Log file output.
+ Copyright (C) 2003, 2005, 2009 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+/* Written by Bruno Haible <bruno@clisp.org>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Handle multi-threaded applications. */
+#ifdef _LIBC
+# include <bits/libc-lock.h>
+#else
+# include "lock.h"
+#endif
+
+/* Separator between msgctxt and msgid in .mo files. */
+#define MSGCTXT_SEPARATOR '\004' /* EOT */
+
+/* Print an ASCII string with quotes and escape sequences where needed. */
+static void
+print_escaped (FILE *stream, const char *str, const char *str_end)
+{
+ putc ('"', stream);
+ for (; str != str_end; str++)
+ if (*str == '\n')
+ {
+ fputs ("\\n\"", stream);
+ if (str + 1 == str_end)
+ return;
+ fputs ("\n\"", stream);
+ }
+ else
+ {
+ if (*str == '"' || *str == '\\')
+ putc ('\\', stream);
+ putc (*str, stream);
+ }
+ putc ('"', stream);
+}
+
+static char *last_logfilename = NULL;
+static FILE *last_logfile = NULL;
+__libc_lock_define_initialized (static, lock)
+
+static inline void
+_nl_log_untranslated_locked (const char *logfilename, const char *domainname,
+ const char *msgid1, const char *msgid2, int plural)
+{
+ FILE *logfile;
+ const char *separator;
+
+ /* Can we reuse the last opened logfile? */
+ if (last_logfilename == NULL || strcmp (logfilename, last_logfilename) != 0)
+ {
+ /* Close the last used logfile. */
+ if (last_logfilename != NULL)
+ {
+ if (last_logfile != NULL)
+ {
+ fclose (last_logfile);
+ last_logfile = NULL;
+ }
+ free (last_logfilename);
+ last_logfilename = NULL;
+ }
+ /* Open the logfile. */
+ last_logfilename = (char *) malloc (strlen (logfilename) + 1);
+ if (last_logfilename == NULL)
+ return;
+ strcpy (last_logfilename, logfilename);
+ last_logfile = fopen (logfilename, "a");
+ if (last_logfile == NULL)
+ return;
+ }
+ logfile = last_logfile;
+
+ fprintf (logfile, "domain ");
+ print_escaped (logfile, domainname, domainname + strlen (domainname));
+ separator = strchr (msgid1, MSGCTXT_SEPARATOR);
+ if (separator != NULL)
+ {
+ /* The part before the MSGCTXT_SEPARATOR is the msgctxt. */
+ fprintf (logfile, "\nmsgctxt ");
+ print_escaped (logfile, msgid1, separator);
+ msgid1 = separator + 1;
+ }
+ fprintf (logfile, "\nmsgid ");
+ print_escaped (logfile, msgid1, msgid1 + strlen (msgid1));
+ if (plural)
+ {
+ fprintf (logfile, "\nmsgid_plural ");
+ print_escaped (logfile, msgid2, msgid2 + strlen (msgid2));
+ fprintf (logfile, "\nmsgstr[0] \"\"\n");
+ }
+ else
+ fprintf (logfile, "\nmsgstr \"\"\n");
+ putc ('\n', logfile);
+}
+
+/* Add to the log file an entry denoting a failed translation. */
+void
+_nl_log_untranslated (const char *logfilename, const char *domainname,
+ const char *msgid1, const char *msgid2, int plural)
+{
+ __libc_lock_lock (lock);
+ _nl_log_untranslated_locked (logfilename, domainname, msgid1, msgid2, plural);
+ __libc_lock_unlock (lock);
+}
diff --git a/intl/ngettext.c b/intl/ngettext.c
new file mode 100644
index 00000000..a33529c2
--- /dev/null
+++ b/intl/ngettext.c
@@ -0,0 +1,65 @@
+/* Implementation of ngettext(3) function.
+ Copyright (C) 1995, 1997, 2000-2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef _LIBC
+# define __need_NULL
+# include <stddef.h>
+#else
+# include <stdlib.h> /* Just for NULL. */
+#endif
+
+#include "gettextP.h"
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+#include <locale.h>
+
+/* @@ end of prolog @@ */
+
+/* Names for the libintl functions are a problem. They must not clash
+ with existing names and they should follow ANSI C. But this source
+ code is also used in GNU C Library where the names have a __
+ prefix. So we have to make a difference here. */
+#ifdef _LIBC
+# define NGETTEXT __ngettext
+# define DCNGETTEXT __dcngettext
+#else
+# define NGETTEXT libintl_ngettext
+# define DCNGETTEXT libintl_dcngettext
+#endif
+
+/* Look up MSGID in the current default message catalog for the current
+ LC_MESSAGES locale. If not found, returns MSGID itself (the default
+ text). */
+char *
+NGETTEXT (const char *msgid1, const char *msgid2, unsigned long int n)
+{
+ return DCNGETTEXT (NULL, msgid1, msgid2, n, LC_MESSAGES);
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library. */
+weak_alias (__ngettext, ngettext);
+#endif
diff --git a/intl/os2compat.c b/intl/os2compat.c
new file mode 100644
index 00000000..d041de2a
--- /dev/null
+++ b/intl/os2compat.c
@@ -0,0 +1,98 @@
+/* OS/2 compatibility functions.
+ Copyright (C) 2001-2002 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#define OS2_AWARE
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+
+/* A version of getenv() that works from DLLs */
+extern unsigned long DosScanEnv (const unsigned char *pszName, unsigned char **ppszValue);
+
+char *
+_nl_getenv (const char *name)
+{
+ unsigned char *value;
+ if (DosScanEnv (name, &value))
+ return NULL;
+ else
+ return value;
+}
+
+/* A fixed size buffer. */
+char libintl_nl_default_dirname[MAXPATHLEN+1];
+
+char *_nlos2_libdir = NULL;
+char *_nlos2_localealiaspath = NULL;
+char *_nlos2_localedir = NULL;
+
+static __attribute__((constructor)) void
+nlos2_initialize ()
+{
+ char *root = getenv ("UNIXROOT");
+ char *gnulocaledir = getenv ("GNULOCALEDIR");
+
+ _nlos2_libdir = gnulocaledir;
+ if (!_nlos2_libdir)
+ {
+ if (root)
+ {
+ size_t sl = strlen (root);
+ _nlos2_libdir = (char *) malloc (sl + strlen (LIBDIR) + 1);
+ memcpy (_nlos2_libdir, root, sl);
+ memcpy (_nlos2_libdir + sl, LIBDIR, strlen (LIBDIR) + 1);
+ }
+ else
+ _nlos2_libdir = LIBDIR;
+ }
+
+ _nlos2_localealiaspath = gnulocaledir;
+ if (!_nlos2_localealiaspath)
+ {
+ if (root)
+ {
+ size_t sl = strlen (root);
+ _nlos2_localealiaspath = (char *) malloc (sl + strlen (LOCALE_ALIAS_PATH) + 1);
+ memcpy (_nlos2_localealiaspath, root, sl);
+ memcpy (_nlos2_localealiaspath + sl, LOCALE_ALIAS_PATH, strlen (LOCALE_ALIAS_PATH) + 1);
+ }
+ else
+ _nlos2_localealiaspath = LOCALE_ALIAS_PATH;
+ }
+
+ _nlos2_localedir = gnulocaledir;
+ if (!_nlos2_localedir)
+ {
+ if (root)
+ {
+ size_t sl = strlen (root);
+ _nlos2_localedir = (char *) malloc (sl + strlen (LOCALEDIR) + 1);
+ memcpy (_nlos2_localedir, root, sl);
+ memcpy (_nlos2_localedir + sl, LOCALEDIR, strlen (LOCALEDIR) + 1);
+ }
+ else
+ _nlos2_localedir = LOCALEDIR;
+ }
+
+ if (strlen (_nlos2_localedir) <= MAXPATHLEN)
+ strcpy (libintl_nl_default_dirname, _nlos2_localedir);
+}
diff --git a/intl/os2compat.h b/intl/os2compat.h
new file mode 100644
index 00000000..702031c1
--- /dev/null
+++ b/intl/os2compat.h
@@ -0,0 +1,46 @@
+/* OS/2 compatibility defines.
+ This file is intended to be included from config.h
+ Copyright (C) 2001-2002 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+/* When included from os2compat.h we need all the original definitions */
+#ifndef OS2_AWARE
+
+#undef LIBDIR
+#define LIBDIR _nlos2_libdir
+extern char *_nlos2_libdir;
+
+#undef LOCALEDIR
+#define LOCALEDIR _nlos2_localedir
+extern char *_nlos2_localedir;
+
+#undef LOCALE_ALIAS_PATH
+#define LOCALE_ALIAS_PATH _nlos2_localealiaspath
+extern char *_nlos2_localealiaspath;
+
+#endif
+
+#undef HAVE_STRCASECMP
+#define HAVE_STRCASECMP 1
+#define strcasecmp stricmp
+#define strncasecmp strnicmp
+
+/* We have our own getenv() which works even if library is compiled as DLL */
+#define getenv _nl_getenv
+
+/* Older versions of gettext used -1 as the value of LC_MESSAGES */
+#define LC_MESSAGES_COMPAT (-1)
diff --git a/intl/osdep.c b/intl/osdep.c
new file mode 100644
index 00000000..3cc35c03
--- /dev/null
+++ b/intl/osdep.c
@@ -0,0 +1,26 @@
+/* OS dependent parts of libintl.
+ Copyright (C) 2001-2002, 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#if defined __CYGWIN__
+# include "intl-exports.c"
+#elif defined __EMX__
+# include "os2compat.c"
+#else
+/* Avoid AIX compiler warning. */
+typedef int dummy;
+#endif
diff --git a/intl/plural-exp.c b/intl/plural-exp.c
new file mode 100644
index 00000000..751a688e
--- /dev/null
+++ b/intl/plural-exp.c
@@ -0,0 +1,155 @@
+/* Expression parsing for plural form selection.
+ Copyright (C) 2000-2001, 2003, 2005-2007 Free Software Foundation, Inc.
+ Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "plural-exp.h"
+
+#if (defined __GNUC__ && !(__APPLE_CC__ > 1) && !defined __cplusplus) \
+ || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
+
+/* These structs are the constant expression for the germanic plural
+ form determination. It represents the expression "n != 1". */
+static const struct expression plvar =
+{
+ .nargs = 0,
+ .operation = var,
+};
+static const struct expression plone =
+{
+ .nargs = 0,
+ .operation = num,
+ .val =
+ {
+ .num = 1
+ }
+};
+struct expression GERMANIC_PLURAL =
+{
+ .nargs = 2,
+ .operation = not_equal,
+ .val =
+ {
+ .args =
+ {
+ [0] = (struct expression *) &plvar,
+ [1] = (struct expression *) &plone
+ }
+ }
+};
+
+# define INIT_GERMANIC_PLURAL()
+
+#else
+
+/* For compilers without support for ISO C 99 struct/union initializers:
+ Initialization at run-time. */
+
+static struct expression plvar;
+static struct expression plone;
+struct expression GERMANIC_PLURAL;
+
+static void
+init_germanic_plural ()
+{
+ if (plone.val.num == 0)
+ {
+ plvar.nargs = 0;
+ plvar.operation = var;
+
+ plone.nargs = 0;
+ plone.operation = num;
+ plone.val.num = 1;
+
+ GERMANIC_PLURAL.nargs = 2;
+ GERMANIC_PLURAL.operation = not_equal;
+ GERMANIC_PLURAL.val.args[0] = &plvar;
+ GERMANIC_PLURAL.val.args[1] = &plone;
+ }
+}
+
+# define INIT_GERMANIC_PLURAL() init_germanic_plural ()
+
+#endif
+
+void
+internal_function
+EXTRACT_PLURAL_EXPRESSION (const char *nullentry,
+ const struct expression **pluralp,
+ unsigned long int *npluralsp)
+{
+ if (nullentry != NULL)
+ {
+ const char *plural;
+ const char *nplurals;
+
+ plural = strstr (nullentry, "plural=");
+ nplurals = strstr (nullentry, "nplurals=");
+ if (plural == NULL || nplurals == NULL)
+ goto no_plural;
+ else
+ {
+ char *endp;
+ unsigned long int n;
+ struct parse_args args;
+
+ /* First get the number. */
+ nplurals += 9;
+ while (*nplurals != '\0' && isspace ((unsigned char) *nplurals))
+ ++nplurals;
+ if (!(*nplurals >= '0' && *nplurals <= '9'))
+ goto no_plural;
+#if defined HAVE_STRTOUL || defined _LIBC
+ n = strtoul (nplurals, &endp, 10);
+#else
+ for (endp = nplurals, n = 0; *endp >= '0' && *endp <= '9'; endp++)
+ n = n * 10 + (*endp - '0');
+#endif
+ if (nplurals == endp)
+ goto no_plural;
+ *npluralsp = n;
+
+ /* Due to the restrictions bison imposes onto the interface of the
+ scanner function we have to put the input string and the result
+ passed up from the parser into the same structure which address
+ is passed down to the parser. */
+ plural += 7;
+ args.cp = plural;
+ if (PLURAL_PARSE (&args) != 0)
+ goto no_plural;
+ *pluralp = args.res;
+ }
+ }
+ else
+ {
+ /* By default we are using the Germanic form: singular form only
+ for `one', the plural form otherwise. Yes, this is also what
+ English is using since English is a Germanic language. */
+ no_plural:
+ INIT_GERMANIC_PLURAL ();
+ *pluralp = &GERMANIC_PLURAL;
+ *npluralsp = 2;
+ }
+}
diff --git a/intl/plural-exp.h b/intl/plural-exp.h
new file mode 100644
index 00000000..d6cb8c51
--- /dev/null
+++ b/intl/plural-exp.h
@@ -0,0 +1,129 @@
+/* Expression parsing and evaluation for plural form selection.
+ Copyright (C) 2000-2003, 2005-2007 Free Software Foundation, Inc.
+ Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifndef _PLURAL_EXP_H
+#define _PLURAL_EXP_H
+
+#ifndef internal_function
+# define internal_function
+#endif
+
+#ifndef attribute_hidden
+# define attribute_hidden
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+enum expression_operator
+{
+ /* Without arguments: */
+ var, /* The variable "n". */
+ num, /* Decimal number. */
+ /* Unary operators: */
+ lnot, /* Logical NOT. */
+ /* Binary operators: */
+ mult, /* Multiplication. */
+ divide, /* Division. */
+ module, /* Modulo operation. */
+ plus, /* Addition. */
+ minus, /* Subtraction. */
+ less_than, /* Comparison. */
+ greater_than, /* Comparison. */
+ less_or_equal, /* Comparison. */
+ greater_or_equal, /* Comparison. */
+ equal, /* Comparison for equality. */
+ not_equal, /* Comparison for inequality. */
+ land, /* Logical AND. */
+ lor, /* Logical OR. */
+ /* Ternary operators: */
+ qmop /* Question mark operator. */
+};
+
+/* This is the representation of the expressions to determine the
+ plural form. */
+struct expression
+{
+ int nargs; /* Number of arguments. */
+ enum expression_operator operation;
+ union
+ {
+ unsigned long int num; /* Number value for `num'. */
+ struct expression *args[3]; /* Up to three arguments. */
+ } val;
+};
+
+/* This is the data structure to pass information to the parser and get
+ the result in a thread-safe way. */
+struct parse_args
+{
+ const char *cp;
+ struct expression *res;
+};
+
+
+/* Names for the libintl functions are a problem. This source code is used
+ 1. in the GNU C Library library,
+ 2. in the GNU libintl library,
+ 3. in the GNU gettext tools.
+ The function names in each situation must be different, to allow for
+ binary incompatible changes in 'struct expression'. Furthermore,
+ 1. in the GNU C Library library, the names have a __ prefix,
+ 2.+3. in the GNU libintl library and in the GNU gettext tools, the names
+ must follow ANSI C and not start with __.
+ So we have to distinguish the three cases. */
+#ifdef _LIBC
+# define FREE_EXPRESSION __gettext_free_exp
+# define PLURAL_PARSE __gettextparse
+# define GERMANIC_PLURAL __gettext_germanic_plural
+# define EXTRACT_PLURAL_EXPRESSION __gettext_extract_plural
+#elif defined (IN_LIBINTL)
+# define FREE_EXPRESSION libintl_gettext_free_exp
+# define PLURAL_PARSE libintl_gettextparse
+# define GERMANIC_PLURAL libintl_gettext_germanic_plural
+# define EXTRACT_PLURAL_EXPRESSION libintl_gettext_extract_plural
+#else
+# define FREE_EXPRESSION free_plural_expression
+# define PLURAL_PARSE parse_plural_expression
+# define GERMANIC_PLURAL germanic_plural
+# define EXTRACT_PLURAL_EXPRESSION extract_plural_expression
+#endif
+
+extern void FREE_EXPRESSION (struct expression *exp)
+ internal_function;
+extern int PLURAL_PARSE (void *arg);
+extern struct expression GERMANIC_PLURAL attribute_hidden;
+extern void EXTRACT_PLURAL_EXPRESSION (const char *nullentry,
+ const struct expression **pluralp,
+ unsigned long int *npluralsp)
+ internal_function;
+
+#if !defined (_LIBC) && !defined (IN_LIBINTL) && !defined (IN_LIBGLOCALE)
+extern unsigned long int plural_eval (const struct expression *pexp,
+ unsigned long int n);
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _PLURAL_EXP_H */
diff --git a/intl/plural.c b/intl/plural.c
new file mode 100644
index 00000000..7a4d947a
--- /dev/null
+++ b/intl/plural.c
@@ -0,0 +1,1961 @@
+/* A Bison parser, made by GNU Bison 2.3a. */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "2.3a"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 1
+
+/* Using locations. */
+#define YYLSP_NEEDED 0
+
+/* Substitute the variable and function names. */
+#define yyparse __gettextparse
+#define yylex __gettextlex
+#define yyerror __gettexterror
+#define yylval __gettextlval
+#define yychar __gettextchar
+#define yydebug __gettextdebug
+#define yynerrs __gettextnerrs
+
+
+/* Copy the first part of user declarations. */
+/* Line 164 of yacc.c. */
+#line 1 "plural.y"
+
+/* Expression parsing for plural form selection.
+ Copyright (C) 2000-2001, 2003, 2005-2006 Free Software Foundation, Inc.
+ Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+/* For bison < 2.0, the bison generated parser uses alloca. AIX 3 forces us
+ to put this declaration at the beginning of the file. The declaration in
+ bison's skeleton file comes too late. This must come before <config.h>
+ because <config.h> may include arbitrary system headers.
+ This can go away once the AM_INTL_SUBDIR macro requires bison >= 2.0. */
+#if defined _AIX && !defined __GNUC__
+ #pragma alloca
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include "plural-exp.h"
+
+/* The main function generated by the parser is called __gettextparse,
+ but we want it to be called PLURAL_PARSE. */
+#ifndef _LIBC
+# define __gettextparse PLURAL_PARSE
+#endif
+
+#define YYLEX_PARAM &((struct parse_args *) arg)->cp
+#define YYPARSE_PARAM arg
+
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ EQUOP2 = 258,
+ CMPOP2 = 259,
+ ADDOP2 = 260,
+ MULOP2 = 261,
+ NUMBER = 262
+ };
+#endif
+/* Tokens. */
+#define EQUOP2 258
+#define CMPOP2 259
+#define ADDOP2 260
+#define MULOP2 261
+#define NUMBER 262
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+{/* Line 191 of yacc.c. */
+#line 51 "plural.y"
+
+ unsigned long int num;
+ enum expression_operator op;
+ struct expression *exp;
+}
+/* Line 191 of yacc.c. */
+#line 175 "plural.c"
+ YYSTYPE;
+# define YYSTYPE_IS_TRIVIAL 1
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+#endif
+
+
+
+
+/* Copy the second part of user declarations. */
+/* Line 221 of yacc.c. */
+#line 57 "plural.y"
+
+/* Prototypes for local functions. */
+static int yylex (YYSTYPE *lval, const char **pexp);
+static void yyerror (const char *str);
+
+/* Allocation of expressions. */
+
+static struct expression *
+new_exp (int nargs, enum expression_operator op,
+ struct expression * const *args)
+{
+ int i;
+ struct expression *newp;
+
+ /* If any of the argument could not be malloc'ed, just return NULL. */
+ for (i = nargs - 1; i >= 0; i--)
+ if (args[i] == NULL)
+ goto fail;
+
+ /* Allocate a new expression. */
+ newp = (struct expression *) malloc (sizeof (*newp));
+ if (newp != NULL)
+ {
+ newp->nargs = nargs;
+ newp->operation = op;
+ for (i = nargs - 1; i >= 0; i--)
+ newp->val.args[i] = args[i];
+ return newp;
+ }
+
+ fail:
+ for (i = nargs - 1; i >= 0; i--)
+ FREE_EXPRESSION (args[i]);
+
+ return NULL;
+}
+
+static inline struct expression *
+new_exp_0 (enum expression_operator op)
+{
+ return new_exp (0, op, NULL);
+}
+
+static inline struct expression *
+new_exp_1 (enum expression_operator op, struct expression *right)
+{
+ struct expression *args[1];
+
+ args[0] = right;
+ return new_exp (1, op, args);
+}
+
+static struct expression *
+new_exp_2 (enum expression_operator op, struct expression *left,
+ struct expression *right)
+{
+ struct expression *args[2];
+
+ args[0] = left;
+ args[1] = right;
+ return new_exp (2, op, args);
+}
+
+static inline struct expression *
+new_exp_3 (enum expression_operator op, struct expression *bexp,
+ struct expression *tbranch, struct expression *fbranch)
+{
+ struct expression *args[3];
+
+ args[0] = bexp;
+ args[1] = tbranch;
+ args[2] = fbranch;
+ return new_exp (3, op, args);
+}
+
+
+/* Line 221 of yacc.c. */
+#line 265 "plural.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions. */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int yyi)
+#else
+static int
+YYID (yyi)
+ int yyi;
+#endif
+{
+ return yyi;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined _STDLIB_H \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss;
+ YYSTYPE yyvs;
+ };
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (YYID (0))
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack, Stack, yysize); \
+ Stack = &yyptr->Stack; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 9
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 54
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 16
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 3
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 13
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 27
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 262
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const yytype_uint8 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 10, 2, 2, 2, 2, 5, 2,
+ 14, 15, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 12, 2,
+ 2, 2, 2, 3, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 13, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 4, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 6, 7,
+ 8, 9, 11
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const yytype_uint8 yyprhs[] =
+{
+ 0, 0, 3, 5, 11, 15, 19, 23, 27, 31,
+ 35, 38, 40, 42
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yytype_int8 yyrhs[] =
+{
+ 17, 0, -1, 18, -1, 18, 3, 18, 12, 18,
+ -1, 18, 4, 18, -1, 18, 5, 18, -1, 18,
+ 6, 18, -1, 18, 7, 18, -1, 18, 8, 18,
+ -1, 18, 9, 18, -1, 10, 18, -1, 13, -1,
+ 11, -1, 14, 18, 15, -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const yytype_uint8 yyrline[] =
+{
+ 0, 154, 154, 162, 166, 170, 174, 178, 182, 186,
+ 190, 194, 198, 203
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "'?'", "'|'", "'&'", "EQUOP2", "CMPOP2",
+ "ADDOP2", "MULOP2", "'!'", "NUMBER", "':'", "'n'", "'('", "')'",
+ "$accept", "start", "exp", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 63, 124, 38, 258, 259, 260, 261,
+ 33, 262, 58, 110, 40, 41
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint8 yyr1[] =
+{
+ 0, 16, 17, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 1, 5, 3, 3, 3, 3, 3, 3,
+ 2, 1, 1, 3
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint8 yydefact[] =
+{
+ 0, 0, 12, 11, 0, 0, 2, 10, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 13, 0, 4,
+ 5, 6, 7, 8, 9, 0, 3
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int8 yydefgoto[] =
+{
+ -1, 5, 6
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -10
+static const yytype_int8 yypact[] =
+{
+ -9, -9, -10, -10, -9, 8, 36, -10, 13, -10,
+ -9, -9, -9, -9, -9, -9, -9, -10, 26, 41,
+ 45, 18, -2, 14, -10, -9, 36
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const yytype_int8 yypgoto[] =
+{
+ -10, -10, -1
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -1
+static const yytype_uint8 yytable[] =
+{
+ 7, 1, 2, 8, 3, 4, 15, 16, 9, 18,
+ 19, 20, 21, 22, 23, 24, 10, 11, 12, 13,
+ 14, 15, 16, 16, 26, 14, 15, 16, 17, 10,
+ 11, 12, 13, 14, 15, 16, 0, 0, 25, 10,
+ 11, 12, 13, 14, 15, 16, 12, 13, 14, 15,
+ 16, 13, 14, 15, 16
+};
+
+static const yytype_int8 yycheck[] =
+{
+ 1, 10, 11, 4, 13, 14, 8, 9, 0, 10,
+ 11, 12, 13, 14, 15, 16, 3, 4, 5, 6,
+ 7, 8, 9, 9, 25, 7, 8, 9, 15, 3,
+ 4, 5, 6, 7, 8, 9, -1, -1, 12, 3,
+ 4, 5, 6, 7, 8, 9, 5, 6, 7, 8,
+ 9, 6, 7, 8, 9
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint8 yystos[] =
+{
+ 0, 10, 11, 13, 14, 17, 18, 18, 18, 0,
+ 3, 4, 5, 6, 7, 8, 9, 15, 18, 18,
+ 18, 18, 18, 18, 18, 12, 18
+};
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+
+#define YYFAIL goto yyerrlab
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK (1); \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (YYID (0))
+
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
+
+#ifndef YY_LOCATION_PRINT
+# if YYLTYPE_IS_TRIVIAL
+# define YY_LOCATION_PRINT(File, Loc) \
+ fprintf (File, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (&yylval, YYLEX_PARAM)
+#else
+# define YYLEX yylex (&yylval)
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+#endif
+{
+ if (!yyvaluep)
+ return;
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+ YYUSE (yyoutput);
+# endif
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+#endif
+{
+ if (yytype < YYNTOKENS)
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep);
+ YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
+#else
+static void
+yy_stack_print (yybottom, yytop)
+ yytype_int16 *yybottom;
+ yytype_int16 *yytop;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; yybottom <= yytop; yybottom++)
+ {
+ int yybot = *yybottom;
+ YYFPRINTF (stderr, " %d", yybot);
+ }
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
+#else
+static void
+yy_reduce_print (yyvsp, yyrule)
+ YYSTYPE *yyvsp;
+ int yyrule;
+#endif
+{
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ unsigned long int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ fprintf (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ );
+ fprintf (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyvsp, Rule); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+ const char *yystr;
+#endif
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+#endif
+{
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ if (! yyres)
+ return yystrlen (yystr);
+
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+ YYCHAR while in state YYSTATE. Return the number of bytes copied,
+ including the terminating null byte. If YYRESULT is null, do not
+ copy anything; just return the number of bytes that would be
+ copied. As a special case, return 0 if an ordinary "syntax error"
+ message will do. Return YYSIZE_MAXIMUM if overflow occurs during
+ size calculation. */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+ int yyn = yypact[yystate];
+
+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+ return 0;
+ else
+ {
+ int yytype = YYTRANSLATE (yychar);
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ int yysize_overflow = 0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ int yyx;
+
+# if 0
+ /* This is so xgettext sees the translatable formats that are
+ constructed on the fly. */
+ YY_("syntax error, unexpected %s");
+ YY_("syntax error, unexpected %s, expecting %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+ char *yyfmt;
+ char const *yyf;
+ static char const yyunexpected[] = "syntax error, unexpected %s";
+ static char const yyexpecting[] = ", expecting %s";
+ static char const yyor[] = " or %s";
+ char yyformat[sizeof yyunexpected
+ + sizeof yyexpecting - 1
+ + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+ * (sizeof yyor - 1))];
+ char const *yyprefix = yyexpecting;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 1;
+
+ yyarg[0] = yytname[yytype];
+ yyfmt = yystpcpy (yyformat, yyunexpected);
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ yyformat[sizeof yyunexpected - 1] = '\0';
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+ yyfmt = yystpcpy (yyfmt, yyprefix);
+ yyprefix = yyor;
+ }
+
+ yyf = YY_(yyformat);
+ yysize1 = yysize + yystrlen (yyf);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+
+ if (yysize_overflow)
+ return YYSIZE_MAXIMUM;
+
+ if (yyresult)
+ {
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ char *yyp = yyresult;
+ int yyi = 0;
+ while ((*yyp = *yyf) != '\0')
+ {
+ if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyf += 2;
+ }
+ else
+ {
+ yyp++;
+ yyf++;
+ }
+ }
+ }
+ return yysize;
+ }
+}
+#endif /* YYERROR_VERBOSE */
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep)
+ const char *yymsg;
+ int yytype;
+ YYSTYPE *yyvaluep;
+#endif
+{
+ YYUSE (yyvaluep);
+
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ switch (yytype)
+ {
+
+ default:
+ break;
+ }
+}
+
+
+/* Prevent warnings from -Wmissing-prototypes. */
+
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+ /* The lookahead symbol. */
+int yychar;
+
+/* The semantic value of the lookahead symbol. */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far. */
+int yynerrs;
+
+ int yystate;
+ int yyn;
+ int yyresult;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+ /* Lookahead token as an internal (translated) token number. */
+ int yytoken = 0;
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+ /* Three stacks and their tools:
+ `yyss': related to states,
+ `yyvs': related to semantic values,
+ `yyls': related to locations.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss = yyssa;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs = yyvsa;
+ YYSTYPE *yyvsp;
+
+
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
+
+ YYSIZE_T yystacksize = YYINITDEPTH;
+
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ yyssp = yyss;
+ yyvsp = yyvs;
+
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss);
+ YYSTACK_RELOCATE (yyvs);
+
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ if (yystate == YYFINAL)
+ YYACCEPT;
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+ /* Do appropriate processing given the current state. Read a
+ lookahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to lookahead token. */
+ yyn = yypact[yystate];
+ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a lookahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the lookahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token. */
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ *++yyvsp = yylval;
+
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 2:
+/* Line 1269 of yacc.c. */
+#line 155 "plural.y"
+ {
+ if ((yyvsp[(1) - (1)].exp) == NULL)
+ YYABORT;
+ ((struct parse_args *) arg)->res = (yyvsp[(1) - (1)].exp);
+ }
+ break;
+
+ case 3:
+/* Line 1269 of yacc.c. */
+#line 163 "plural.y"
+ {
+ (yyval.exp) = new_exp_3 (qmop, (yyvsp[(1) - (5)].exp), (yyvsp[(3) - (5)].exp), (yyvsp[(5) - (5)].exp));
+ }
+ break;
+
+ case 4:
+/* Line 1269 of yacc.c. */
+#line 167 "plural.y"
+ {
+ (yyval.exp) = new_exp_2 (lor, (yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp));
+ }
+ break;
+
+ case 5:
+/* Line 1269 of yacc.c. */
+#line 171 "plural.y"
+ {
+ (yyval.exp) = new_exp_2 (land, (yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp));
+ }
+ break;
+
+ case 6:
+/* Line 1269 of yacc.c. */
+#line 175 "plural.y"
+ {
+ (yyval.exp) = new_exp_2 ((yyvsp[(2) - (3)].op), (yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp));
+ }
+ break;
+
+ case 7:
+/* Line 1269 of yacc.c. */
+#line 179 "plural.y"
+ {
+ (yyval.exp) = new_exp_2 ((yyvsp[(2) - (3)].op), (yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp));
+ }
+ break;
+
+ case 8:
+/* Line 1269 of yacc.c. */
+#line 183 "plural.y"
+ {
+ (yyval.exp) = new_exp_2 ((yyvsp[(2) - (3)].op), (yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp));
+ }
+ break;
+
+ case 9:
+/* Line 1269 of yacc.c. */
+#line 187 "plural.y"
+ {
+ (yyval.exp) = new_exp_2 ((yyvsp[(2) - (3)].op), (yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp));
+ }
+ break;
+
+ case 10:
+/* Line 1269 of yacc.c. */
+#line 191 "plural.y"
+ {
+ (yyval.exp) = new_exp_1 (lnot, (yyvsp[(2) - (2)].exp));
+ }
+ break;
+
+ case 11:
+/* Line 1269 of yacc.c. */
+#line 195 "plural.y"
+ {
+ (yyval.exp) = new_exp_0 (var);
+ }
+ break;
+
+ case 12:
+/* Line 1269 of yacc.c. */
+#line 199 "plural.y"
+ {
+ if (((yyval.exp) = new_exp_0 (num)) != NULL)
+ (yyval.exp)->val.num = (yyvsp[(1) - (1)].num);
+ }
+ break;
+
+ case 13:
+/* Line 1269 of yacc.c. */
+#line 204 "plural.y"
+ {
+ (yyval.exp) = (yyvsp[(2) - (3)].exp);
+ }
+ break;
+
+
+/* Line 1269 of yacc.c. */
+#line 1572 "plural.c"
+ default: break;
+ }
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (YY_("syntax error"));
+#else
+ {
+ YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+ if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+ {
+ YYSIZE_T yyalloc = 2 * yysize;
+ if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+ yyalloc = YYSTACK_ALLOC_MAXIMUM;
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+ if (yymsg)
+ yymsg_alloc = yyalloc;
+ else
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ }
+ }
+
+ if (0 < yysize && yysize <= yymsg_alloc)
+ {
+ (void) yysyntax_error (yymsg, yystate, yychar);
+ yyerror (yymsg);
+ }
+ else
+ {
+ yyerror (YY_("syntax error"));
+ if (yysize != 0)
+ goto yyexhaustedlab;
+ }
+ }
+#endif
+ }
+
+
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse lookahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse lookahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (yyn != YYPACT_NINF)
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ *++yyvsp = yylval;
+
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#ifndef yyoverflow
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEMPTY)
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval);
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ /* Make sure YYID is used. */
+ return YYID (yyresult);
+}
+
+
+/* Line 1486 of yacc.c. */
+#line 209 "plural.y"
+
+
+void
+internal_function
+FREE_EXPRESSION (struct expression *exp)
+{
+ if (exp == NULL)
+ return;
+
+ /* Handle the recursive case. */
+ switch (exp->nargs)
+ {
+ case 3:
+ FREE_EXPRESSION (exp->val.args[2]);
+ /* FALLTHROUGH */
+ case 2:
+ FREE_EXPRESSION (exp->val.args[1]);
+ /* FALLTHROUGH */
+ case 1:
+ FREE_EXPRESSION (exp->val.args[0]);
+ /* FALLTHROUGH */
+ default:
+ break;
+ }
+
+ free (exp);
+}
+
+
+static int
+yylex (YYSTYPE *lval, const char **pexp)
+{
+ const char *exp = *pexp;
+ int result;
+
+ while (1)
+ {
+ if (exp[0] == '\0')
+ {
+ *pexp = exp;
+ return YYEOF;
+ }
+
+ if (exp[0] != ' ' && exp[0] != '\t')
+ break;
+
+ ++exp;
+ }
+
+ result = *exp++;
+ switch (result)
+ {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ {
+ unsigned long int n = result - '0';
+ while (exp[0] >= '0' && exp[0] <= '9')
+ {
+ n *= 10;
+ n += exp[0] - '0';
+ ++exp;
+ }
+ lval->num = n;
+ result = NUMBER;
+ }
+ break;
+
+ case '=':
+ if (exp[0] == '=')
+ {
+ ++exp;
+ lval->op = equal;
+ result = EQUOP2;
+ }
+ else
+ result = YYERRCODE;
+ break;
+
+ case '!':
+ if (exp[0] == '=')
+ {
+ ++exp;
+ lval->op = not_equal;
+ result = EQUOP2;
+ }
+ break;
+
+ case '&':
+ case '|':
+ if (exp[0] == result)
+ ++exp;
+ else
+ result = YYERRCODE;
+ break;
+
+ case '<':
+ if (exp[0] == '=')
+ {
+ ++exp;
+ lval->op = less_or_equal;
+ }
+ else
+ lval->op = less_than;
+ result = CMPOP2;
+ break;
+
+ case '>':
+ if (exp[0] == '=')
+ {
+ ++exp;
+ lval->op = greater_or_equal;
+ }
+ else
+ lval->op = greater_than;
+ result = CMPOP2;
+ break;
+
+ case '*':
+ lval->op = mult;
+ result = MULOP2;
+ break;
+
+ case '/':
+ lval->op = divide;
+ result = MULOP2;
+ break;
+
+ case '%':
+ lval->op = module;
+ result = MULOP2;
+ break;
+
+ case '+':
+ lval->op = plus;
+ result = ADDOP2;
+ break;
+
+ case '-':
+ lval->op = minus;
+ result = ADDOP2;
+ break;
+
+ case 'n':
+ case '?':
+ case ':':
+ case '(':
+ case ')':
+ /* Nothing, just return the character. */
+ break;
+
+ case ';':
+ case '\n':
+ case '\0':
+ /* Be safe and let the user call this function again. */
+ --exp;
+ result = YYEOF;
+ break;
+
+ default:
+ result = YYERRCODE;
+#if YYDEBUG != 0
+ --exp;
+#endif
+ break;
+ }
+
+ *pexp = exp;
+
+ return result;
+}
+
+
+static void
+yyerror (const char *str)
+{
+ /* Do nothing. We don't print error messages here. */
+}
+
diff --git a/intl/plural.y b/intl/plural.y
new file mode 100644
index 00000000..ec36a09b
--- /dev/null
+++ b/intl/plural.y
@@ -0,0 +1,385 @@
+%{
+/* Expression parsing for plural form selection.
+ Copyright (C) 2000-2001, 2003, 2005-2006 Free Software Foundation, Inc.
+ Written by Ulrich Drepper <drepper@cygnus.com>, 2000.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+/* For bison < 2.0, the bison generated parser uses alloca. AIX 3 forces us
+ to put this declaration at the beginning of the file. The declaration in
+ bison's skeleton file comes too late. This must come before <config.h>
+ because <config.h> may include arbitrary system headers.
+ This can go away once the AM_INTL_SUBDIR macro requires bison >= 2.0. */
+#if defined _AIX && !defined __GNUC__
+ #pragma alloca
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include "plural-exp.h"
+
+/* The main function generated by the parser is called __gettextparse,
+ but we want it to be called PLURAL_PARSE. */
+#ifndef _LIBC
+# define __gettextparse PLURAL_PARSE
+#endif
+
+#define YYLEX_PARAM &((struct parse_args *) arg)->cp
+#define YYPARSE_PARAM arg
+%}
+%pure_parser
+%expect 7
+
+%union {
+ unsigned long int num;
+ enum expression_operator op;
+ struct expression *exp;
+}
+
+%{
+/* Prototypes for local functions. */
+static int yylex (YYSTYPE *lval, const char **pexp);
+static void yyerror (const char *str);
+
+/* Allocation of expressions. */
+
+static struct expression *
+new_exp (int nargs, enum expression_operator op,
+ struct expression * const *args)
+{
+ int i;
+ struct expression *newp;
+
+ /* If any of the argument could not be malloc'ed, just return NULL. */
+ for (i = nargs - 1; i >= 0; i--)
+ if (args[i] == NULL)
+ goto fail;
+
+ /* Allocate a new expression. */
+ newp = (struct expression *) malloc (sizeof (*newp));
+ if (newp != NULL)
+ {
+ newp->nargs = nargs;
+ newp->operation = op;
+ for (i = nargs - 1; i >= 0; i--)
+ newp->val.args[i] = args[i];
+ return newp;
+ }
+
+ fail:
+ for (i = nargs - 1; i >= 0; i--)
+ FREE_EXPRESSION (args[i]);
+
+ return NULL;
+}
+
+static inline struct expression *
+new_exp_0 (enum expression_operator op)
+{
+ return new_exp (0, op, NULL);
+}
+
+static inline struct expression *
+new_exp_1 (enum expression_operator op, struct expression *right)
+{
+ struct expression *args[1];
+
+ args[0] = right;
+ return new_exp (1, op, args);
+}
+
+static struct expression *
+new_exp_2 (enum expression_operator op, struct expression *left,
+ struct expression *right)
+{
+ struct expression *args[2];
+
+ args[0] = left;
+ args[1] = right;
+ return new_exp (2, op, args);
+}
+
+static inline struct expression *
+new_exp_3 (enum expression_operator op, struct expression *bexp,
+ struct expression *tbranch, struct expression *fbranch)
+{
+ struct expression *args[3];
+
+ args[0] = bexp;
+ args[1] = tbranch;
+ args[2] = fbranch;
+ return new_exp (3, op, args);
+}
+
+%}
+
+/* This declares that all operators have the same associativity and the
+ precedence order as in C. See [Harbison, Steele: C, A Reference Manual].
+ There is no unary minus and no bitwise operators.
+ Operators with the same syntactic behaviour have been merged into a single
+ token, to save space in the array generated by bison. */
+%right '?' /* ? */
+%left '|' /* || */
+%left '&' /* && */
+%left EQUOP2 /* == != */
+%left CMPOP2 /* < > <= >= */
+%left ADDOP2 /* + - */
+%left MULOP2 /* * / % */
+%right '!' /* ! */
+
+%token <op> EQUOP2 CMPOP2 ADDOP2 MULOP2
+%token <num> NUMBER
+%type <exp> exp
+
+%%
+
+start: exp
+ {
+ if ($1 == NULL)
+ YYABORT;
+ ((struct parse_args *) arg)->res = $1;
+ }
+ ;
+
+exp: exp '?' exp ':' exp
+ {
+ $$ = new_exp_3 (qmop, $1, $3, $5);
+ }
+ | exp '|' exp
+ {
+ $$ = new_exp_2 (lor, $1, $3);
+ }
+ | exp '&' exp
+ {
+ $$ = new_exp_2 (land, $1, $3);
+ }
+ | exp EQUOP2 exp
+ {
+ $$ = new_exp_2 ($2, $1, $3);
+ }
+ | exp CMPOP2 exp
+ {
+ $$ = new_exp_2 ($2, $1, $3);
+ }
+ | exp ADDOP2 exp
+ {
+ $$ = new_exp_2 ($2, $1, $3);
+ }
+ | exp MULOP2 exp
+ {
+ $$ = new_exp_2 ($2, $1, $3);
+ }
+ | '!' exp
+ {
+ $$ = new_exp_1 (lnot, $2);
+ }
+ | 'n'
+ {
+ $$ = new_exp_0 (var);
+ }
+ | NUMBER
+ {
+ if (($$ = new_exp_0 (num)) != NULL)
+ $$->val.num = $1;
+ }
+ | '(' exp ')'
+ {
+ $$ = $2;
+ }
+ ;
+
+%%
+
+void
+internal_function
+FREE_EXPRESSION (struct expression *exp)
+{
+ if (exp == NULL)
+ return;
+
+ /* Handle the recursive case. */
+ switch (exp->nargs)
+ {
+ case 3:
+ FREE_EXPRESSION (exp->val.args[2]);
+ /* FALLTHROUGH */
+ case 2:
+ FREE_EXPRESSION (exp->val.args[1]);
+ /* FALLTHROUGH */
+ case 1:
+ FREE_EXPRESSION (exp->val.args[0]);
+ /* FALLTHROUGH */
+ default:
+ break;
+ }
+
+ free (exp);
+}
+
+
+static int
+yylex (YYSTYPE *lval, const char **pexp)
+{
+ const char *exp = *pexp;
+ int result;
+
+ while (1)
+ {
+ if (exp[0] == '\0')
+ {
+ *pexp = exp;
+ return YYEOF;
+ }
+
+ if (exp[0] != ' ' && exp[0] != '\t')
+ break;
+
+ ++exp;
+ }
+
+ result = *exp++;
+ switch (result)
+ {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ {
+ unsigned long int n = result - '0';
+ while (exp[0] >= '0' && exp[0] <= '9')
+ {
+ n *= 10;
+ n += exp[0] - '0';
+ ++exp;
+ }
+ lval->num = n;
+ result = NUMBER;
+ }
+ break;
+
+ case '=':
+ if (exp[0] == '=')
+ {
+ ++exp;
+ lval->op = equal;
+ result = EQUOP2;
+ }
+ else
+ result = YYERRCODE;
+ break;
+
+ case '!':
+ if (exp[0] == '=')
+ {
+ ++exp;
+ lval->op = not_equal;
+ result = EQUOP2;
+ }
+ break;
+
+ case '&':
+ case '|':
+ if (exp[0] == result)
+ ++exp;
+ else
+ result = YYERRCODE;
+ break;
+
+ case '<':
+ if (exp[0] == '=')
+ {
+ ++exp;
+ lval->op = less_or_equal;
+ }
+ else
+ lval->op = less_than;
+ result = CMPOP2;
+ break;
+
+ case '>':
+ if (exp[0] == '=')
+ {
+ ++exp;
+ lval->op = greater_or_equal;
+ }
+ else
+ lval->op = greater_than;
+ result = CMPOP2;
+ break;
+
+ case '*':
+ lval->op = mult;
+ result = MULOP2;
+ break;
+
+ case '/':
+ lval->op = divide;
+ result = MULOP2;
+ break;
+
+ case '%':
+ lval->op = module;
+ result = MULOP2;
+ break;
+
+ case '+':
+ lval->op = plus;
+ result = ADDOP2;
+ break;
+
+ case '-':
+ lval->op = minus;
+ result = ADDOP2;
+ break;
+
+ case 'n':
+ case '?':
+ case ':':
+ case '(':
+ case ')':
+ /* Nothing, just return the character. */
+ break;
+
+ case ';':
+ case '\n':
+ case '\0':
+ /* Be safe and let the user call this function again. */
+ --exp;
+ result = YYEOF;
+ break;
+
+ default:
+ result = YYERRCODE;
+#if YYDEBUG != 0
+ --exp;
+#endif
+ break;
+ }
+
+ *pexp = exp;
+
+ return result;
+}
+
+
+static void
+yyerror (const char *str)
+{
+ /* Do nothing. We don't print error messages here. */
+}
diff --git a/intl/printf-args.c b/intl/printf-args.c
new file mode 100644
index 00000000..44e50a33
--- /dev/null
+++ b/intl/printf-args.c
@@ -0,0 +1,188 @@
+/* Decomposed printf argument list.
+ Copyright (C) 1999, 2002-2003, 2005-2007 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+/* This file can be parametrized with the following macros:
+ ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions.
+ PRINTF_FETCHARGS Name of the function to be defined.
+ STATIC Set to 'static' to declare the function static. */
+
+#ifndef PRINTF_FETCHARGS
+# include <config.h>
+#endif
+
+/* Specification. */
+#ifndef PRINTF_FETCHARGS
+# include "printf-args.h"
+#endif
+
+#ifdef STATIC
+STATIC
+#endif
+int
+PRINTF_FETCHARGS (va_list args, arguments *a)
+{
+ size_t i;
+ argument *ap;
+
+ for (i = 0, ap = &a->arg[0]; i < a->count; i++, ap++)
+ switch (ap->type)
+ {
+ case TYPE_SCHAR:
+ ap->a.a_schar = va_arg (args, /*signed char*/ int);
+ break;
+ case TYPE_UCHAR:
+ ap->a.a_uchar = va_arg (args, /*unsigned char*/ int);
+ break;
+ case TYPE_SHORT:
+ ap->a.a_short = va_arg (args, /*short*/ int);
+ break;
+ case TYPE_USHORT:
+ ap->a.a_ushort = va_arg (args, /*unsigned short*/ int);
+ break;
+ case TYPE_INT:
+ ap->a.a_int = va_arg (args, int);
+ break;
+ case TYPE_UINT:
+ ap->a.a_uint = va_arg (args, unsigned int);
+ break;
+ case TYPE_LONGINT:
+ ap->a.a_longint = va_arg (args, long int);
+ break;
+ case TYPE_ULONGINT:
+ ap->a.a_ulongint = va_arg (args, unsigned long int);
+ break;
+#if HAVE_LONG_LONG_INT
+ case TYPE_LONGLONGINT:
+ ap->a.a_longlongint = va_arg (args, long long int);
+ break;
+ case TYPE_ULONGLONGINT:
+ ap->a.a_ulonglongint = va_arg (args, unsigned long long int);
+ break;
+#endif
+ case TYPE_DOUBLE:
+ ap->a.a_double = va_arg (args, double);
+ break;
+ case TYPE_LONGDOUBLE:
+ ap->a.a_longdouble = va_arg (args, long double);
+ break;
+ case TYPE_CHAR:
+ ap->a.a_char = va_arg (args, int);
+ break;
+#if HAVE_WINT_T
+ case TYPE_WIDE_CHAR:
+ /* Although ISO C 99 7.24.1.(2) says that wint_t is "unchanged by
+ default argument promotions", this is not the case in mingw32,
+ where wint_t is 'unsigned short'. */
+ ap->a.a_wide_char =
+ (sizeof (wint_t) < sizeof (int)
+ ? va_arg (args, int)
+ : va_arg (args, wint_t));
+ break;
+#endif
+ case TYPE_STRING:
+ ap->a.a_string = va_arg (args, const char *);
+ /* A null pointer is an invalid argument for "%s", but in practice
+ it occurs quite frequently in printf statements that produce
+ debug output. Use a fallback in this case. */
+ if (ap->a.a_string == NULL)
+ ap->a.a_string = "(NULL)";
+ break;
+#if HAVE_WCHAR_T
+ case TYPE_WIDE_STRING:
+ ap->a.a_wide_string = va_arg (args, const wchar_t *);
+ /* A null pointer is an invalid argument for "%ls", but in practice
+ it occurs quite frequently in printf statements that produce
+ debug output. Use a fallback in this case. */
+ if (ap->a.a_wide_string == NULL)
+ {
+ static const wchar_t wide_null_string[] =
+ {
+ (wchar_t)'(',
+ (wchar_t)'N', (wchar_t)'U', (wchar_t)'L', (wchar_t)'L',
+ (wchar_t)')',
+ (wchar_t)0
+ };
+ ap->a.a_wide_string = wide_null_string;
+ }
+ break;
+#endif
+ case TYPE_POINTER:
+ ap->a.a_pointer = va_arg (args, void *);
+ break;
+ case TYPE_COUNT_SCHAR_POINTER:
+ ap->a.a_count_schar_pointer = va_arg (args, signed char *);
+ break;
+ case TYPE_COUNT_SHORT_POINTER:
+ ap->a.a_count_short_pointer = va_arg (args, short *);
+ break;
+ case TYPE_COUNT_INT_POINTER:
+ ap->a.a_count_int_pointer = va_arg (args, int *);
+ break;
+ case TYPE_COUNT_LONGINT_POINTER:
+ ap->a.a_count_longint_pointer = va_arg (args, long int *);
+ break;
+#if HAVE_LONG_LONG_INT
+ case TYPE_COUNT_LONGLONGINT_POINTER:
+ ap->a.a_count_longlongint_pointer = va_arg (args, long long int *);
+ break;
+#endif
+#if ENABLE_UNISTDIO
+ /* The unistdio extensions. */
+ case TYPE_U8_STRING:
+ ap->a.a_u8_string = va_arg (args, const uint8_t *);
+ /* A null pointer is an invalid argument for "%U", but in practice
+ it occurs quite frequently in printf statements that produce
+ debug output. Use a fallback in this case. */
+ if (ap->a.a_u8_string == NULL)
+ {
+ static const uint8_t u8_null_string[] =
+ { '(', 'N', 'U', 'L', 'L', ')', 0 };
+ ap->a.a_u8_string = u8_null_string;
+ }
+ break;
+ case TYPE_U16_STRING:
+ ap->a.a_u16_string = va_arg (args, const uint16_t *);
+ /* A null pointer is an invalid argument for "%lU", but in practice
+ it occurs quite frequently in printf statements that produce
+ debug output. Use a fallback in this case. */
+ if (ap->a.a_u16_string == NULL)
+ {
+ static const uint16_t u16_null_string[] =
+ { '(', 'N', 'U', 'L', 'L', ')', 0 };
+ ap->a.a_u16_string = u16_null_string;
+ }
+ break;
+ case TYPE_U32_STRING:
+ ap->a.a_u32_string = va_arg (args, const uint32_t *);
+ /* A null pointer is an invalid argument for "%llU", but in practice
+ it occurs quite frequently in printf statements that produce
+ debug output. Use a fallback in this case. */
+ if (ap->a.a_u32_string == NULL)
+ {
+ static const uint32_t u32_null_string[] =
+ { '(', 'N', 'U', 'L', 'L', ')', 0 };
+ ap->a.a_u32_string = u32_null_string;
+ }
+ break;
+#endif
+ default:
+ /* Unknown type. */
+ return -1;
+ }
+ return 0;
+}
diff --git a/intl/printf-args.h b/intl/printf-args.h
new file mode 100644
index 00000000..f95e6bd9
--- /dev/null
+++ b/intl/printf-args.h
@@ -0,0 +1,155 @@
+/* Decomposed printf argument list.
+ Copyright (C) 1999, 2002-2003, 2006-2007 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifndef _PRINTF_ARGS_H
+#define _PRINTF_ARGS_H
+
+/* This file can be parametrized with the following macros:
+ ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions.
+ PRINTF_FETCHARGS Name of the function to be declared.
+ STATIC Set to 'static' to declare the function static. */
+
+/* Default parameters. */
+#ifndef PRINTF_FETCHARGS
+# define PRINTF_FETCHARGS printf_fetchargs
+#endif
+
+/* Get size_t. */
+#include <stddef.h>
+
+/* Get wchar_t. */
+#if HAVE_WCHAR_T
+# include <stddef.h>
+#endif
+
+/* Get wint_t. */
+#if HAVE_WINT_T
+# include <wchar.h>
+#endif
+
+/* Get va_list. */
+#include <stdarg.h>
+
+
+/* Argument types */
+typedef enum
+{
+ TYPE_NONE,
+ TYPE_SCHAR,
+ TYPE_UCHAR,
+ TYPE_SHORT,
+ TYPE_USHORT,
+ TYPE_INT,
+ TYPE_UINT,
+ TYPE_LONGINT,
+ TYPE_ULONGINT,
+#if HAVE_LONG_LONG_INT
+ TYPE_LONGLONGINT,
+ TYPE_ULONGLONGINT,
+#endif
+ TYPE_DOUBLE,
+ TYPE_LONGDOUBLE,
+ TYPE_CHAR,
+#if HAVE_WINT_T
+ TYPE_WIDE_CHAR,
+#endif
+ TYPE_STRING,
+#if HAVE_WCHAR_T
+ TYPE_WIDE_STRING,
+#endif
+ TYPE_POINTER,
+ TYPE_COUNT_SCHAR_POINTER,
+ TYPE_COUNT_SHORT_POINTER,
+ TYPE_COUNT_INT_POINTER,
+ TYPE_COUNT_LONGINT_POINTER
+#if HAVE_LONG_LONG_INT
+, TYPE_COUNT_LONGLONGINT_POINTER
+#endif
+#if ENABLE_UNISTDIO
+ /* The unistdio extensions. */
+, TYPE_U8_STRING
+, TYPE_U16_STRING
+, TYPE_U32_STRING
+#endif
+} arg_type;
+
+/* Polymorphic argument */
+typedef struct
+{
+ arg_type type;
+ union
+ {
+ signed char a_schar;
+ unsigned char a_uchar;
+ short a_short;
+ unsigned short a_ushort;
+ int a_int;
+ unsigned int a_uint;
+ long int a_longint;
+ unsigned long int a_ulongint;
+#if HAVE_LONG_LONG_INT
+ long long int a_longlongint;
+ unsigned long long int a_ulonglongint;
+#endif
+ float a_float;
+ double a_double;
+ long double a_longdouble;
+ int a_char;
+#if HAVE_WINT_T
+ wint_t a_wide_char;
+#endif
+ const char* a_string;
+#if HAVE_WCHAR_T
+ const wchar_t* a_wide_string;
+#endif
+ void* a_pointer;
+ signed char * a_count_schar_pointer;
+ short * a_count_short_pointer;
+ int * a_count_int_pointer;
+ long int * a_count_longint_pointer;
+#if HAVE_LONG_LONG_INT
+ long long int * a_count_longlongint_pointer;
+#endif
+#if ENABLE_UNISTDIO
+ /* The unistdio extensions. */
+ const uint8_t * a_u8_string;
+ const uint16_t * a_u16_string;
+ const uint32_t * a_u32_string;
+#endif
+ }
+ a;
+}
+argument;
+
+typedef struct
+{
+ size_t count;
+ argument *arg;
+}
+arguments;
+
+
+/* Fetch the arguments, putting them into a. */
+#ifdef STATIC
+STATIC
+#else
+extern
+#endif
+int PRINTF_FETCHARGS (va_list args, arguments *a);
+
+#endif /* _PRINTF_ARGS_H */
diff --git a/intl/printf-parse.c b/intl/printf-parse.c
new file mode 100644
index 00000000..3f3174d0
--- /dev/null
+++ b/intl/printf-parse.c
@@ -0,0 +1,628 @@
+/* Formatted output to strings.
+ Copyright (C) 1999-2000, 2002-2003, 2006-2008 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+/* This file can be parametrized with the following macros:
+ CHAR_T The element type of the format string.
+ CHAR_T_ONLY_ASCII Set to 1 to enable verification that all characters
+ in the format string are ASCII.
+ DIRECTIVE Structure denoting a format directive.
+ Depends on CHAR_T.
+ DIRECTIVES Structure denoting the set of format directives of a
+ format string. Depends on CHAR_T.
+ PRINTF_PARSE Function that parses a format string.
+ Depends on CHAR_T.
+ STATIC Set to 'static' to declare the function static.
+ ENABLE_UNISTDIO Set to 1 to enable the unistdio extensions. */
+
+#ifndef PRINTF_PARSE
+# include <config.h>
+#endif
+
+/* Specification. */
+#ifndef PRINTF_PARSE
+# include "printf-parse.h"
+#endif
+
+/* Default parameters. */
+#ifndef PRINTF_PARSE
+# define PRINTF_PARSE printf_parse
+# define CHAR_T char
+# define DIRECTIVE char_directive
+# define DIRECTIVES char_directives
+#endif
+
+/* Get size_t, NULL. */
+#include <stddef.h>
+
+/* Get intmax_t. */
+#if defined IN_LIBINTL || defined IN_LIBASPRINTF
+# if HAVE_STDINT_H_WITH_UINTMAX
+# include <stdint.h>
+# endif
+# if HAVE_INTTYPES_H_WITH_UINTMAX
+# include <inttypes.h>
+# endif
+#else
+# include <stdint.h>
+#endif
+
+/* malloc(), realloc(), free(). */
+#include <stdlib.h>
+
+/* errno. */
+#include <errno.h>
+
+/* Checked size_t computations. */
+#include "xsize.h"
+
+#if CHAR_T_ONLY_ASCII
+/* c_isascii(). */
+# include "c-ctype.h"
+#endif
+
+#ifdef STATIC
+STATIC
+#endif
+int
+PRINTF_PARSE (const CHAR_T *format, DIRECTIVES *d, arguments *a)
+{
+ const CHAR_T *cp = format; /* pointer into format */
+ size_t arg_posn = 0; /* number of regular arguments consumed */
+ size_t d_allocated; /* allocated elements of d->dir */
+ size_t a_allocated; /* allocated elements of a->arg */
+ size_t max_width_length = 0;
+ size_t max_precision_length = 0;
+
+ d->count = 0;
+ d_allocated = 1;
+ d->dir = (DIRECTIVE *) malloc (d_allocated * sizeof (DIRECTIVE));
+ if (d->dir == NULL)
+ /* Out of memory. */
+ goto out_of_memory_1;
+
+ a->count = 0;
+ a_allocated = 0;
+ a->arg = NULL;
+
+#define REGISTER_ARG(_index_,_type_) \
+ { \
+ size_t n = (_index_); \
+ if (n >= a_allocated) \
+ { \
+ size_t memory_size; \
+ argument *memory; \
+ \
+ a_allocated = xtimes (a_allocated, 2); \
+ if (a_allocated <= n) \
+ a_allocated = xsum (n, 1); \
+ memory_size = xtimes (a_allocated, sizeof (argument)); \
+ if (size_overflow_p (memory_size)) \
+ /* Overflow, would lead to out of memory. */ \
+ goto out_of_memory; \
+ memory = (argument *) (a->arg \
+ ? realloc (a->arg, memory_size) \
+ : malloc (memory_size)); \
+ if (memory == NULL) \
+ /* Out of memory. */ \
+ goto out_of_memory; \
+ a->arg = memory; \
+ } \
+ while (a->count <= n) \
+ a->arg[a->count++].type = TYPE_NONE; \
+ if (a->arg[n].type == TYPE_NONE) \
+ a->arg[n].type = (_type_); \
+ else if (a->arg[n].type != (_type_)) \
+ /* Ambiguous type for positional argument. */ \
+ goto error; \
+ }
+
+ while (*cp != '\0')
+ {
+ CHAR_T c = *cp++;
+ if (c == '%')
+ {
+ size_t arg_index = ARG_NONE;
+ DIRECTIVE *dp = &d->dir[d->count]; /* pointer to next directive */
+
+ /* Initialize the next directive. */
+ dp->dir_start = cp - 1;
+ dp->flags = 0;
+ dp->width_start = NULL;
+ dp->width_end = NULL;
+ dp->width_arg_index = ARG_NONE;
+ dp->precision_start = NULL;
+ dp->precision_end = NULL;
+ dp->precision_arg_index = ARG_NONE;
+ dp->arg_index = ARG_NONE;
+
+ /* Test for positional argument. */
+ if (*cp >= '0' && *cp <= '9')
+ {
+ const CHAR_T *np;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ ;
+ if (*np == '$')
+ {
+ size_t n = 0;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ n = xsum (xtimes (n, 10), *np - '0');
+ if (n == 0)
+ /* Positional argument 0. */
+ goto error;
+ if (size_overflow_p (n))
+ /* n too large, would lead to out of memory later. */
+ goto error;
+ arg_index = n - 1;
+ cp = np + 1;
+ }
+ }
+
+ /* Read the flags. */
+ for (;;)
+ {
+ if (*cp == '\'')
+ {
+ dp->flags |= FLAG_GROUP;
+ cp++;
+ }
+ else if (*cp == '-')
+ {
+ dp->flags |= FLAG_LEFT;
+ cp++;
+ }
+ else if (*cp == '+')
+ {
+ dp->flags |= FLAG_SHOWSIGN;
+ cp++;
+ }
+ else if (*cp == ' ')
+ {
+ dp->flags |= FLAG_SPACE;
+ cp++;
+ }
+ else if (*cp == '#')
+ {
+ dp->flags |= FLAG_ALT;
+ cp++;
+ }
+ else if (*cp == '0')
+ {
+ dp->flags |= FLAG_ZERO;
+ cp++;
+ }
+ else
+ break;
+ }
+
+ /* Parse the field width. */
+ if (*cp == '*')
+ {
+ dp->width_start = cp;
+ cp++;
+ dp->width_end = cp;
+ if (max_width_length < 1)
+ max_width_length = 1;
+
+ /* Test for positional argument. */
+ if (*cp >= '0' && *cp <= '9')
+ {
+ const CHAR_T *np;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ ;
+ if (*np == '$')
+ {
+ size_t n = 0;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ n = xsum (xtimes (n, 10), *np - '0');
+ if (n == 0)
+ /* Positional argument 0. */
+ goto error;
+ if (size_overflow_p (n))
+ /* n too large, would lead to out of memory later. */
+ goto error;
+ dp->width_arg_index = n - 1;
+ cp = np + 1;
+ }
+ }
+ if (dp->width_arg_index == ARG_NONE)
+ {
+ dp->width_arg_index = arg_posn++;
+ if (dp->width_arg_index == ARG_NONE)
+ /* arg_posn wrapped around. */
+ goto error;
+ }
+ REGISTER_ARG (dp->width_arg_index, TYPE_INT);
+ }
+ else if (*cp >= '0' && *cp <= '9')
+ {
+ size_t width_length;
+
+ dp->width_start = cp;
+ for (; *cp >= '0' && *cp <= '9'; cp++)
+ ;
+ dp->width_end = cp;
+ width_length = dp->width_end - dp->width_start;
+ if (max_width_length < width_length)
+ max_width_length = width_length;
+ }
+
+ /* Parse the precision. */
+ if (*cp == '.')
+ {
+ cp++;
+ if (*cp == '*')
+ {
+ dp->precision_start = cp - 1;
+ cp++;
+ dp->precision_end = cp;
+ if (max_precision_length < 2)
+ max_precision_length = 2;
+
+ /* Test for positional argument. */
+ if (*cp >= '0' && *cp <= '9')
+ {
+ const CHAR_T *np;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ ;
+ if (*np == '$')
+ {
+ size_t n = 0;
+
+ for (np = cp; *np >= '0' && *np <= '9'; np++)
+ n = xsum (xtimes (n, 10), *np - '0');
+ if (n == 0)
+ /* Positional argument 0. */
+ goto error;
+ if (size_overflow_p (n))
+ /* n too large, would lead to out of memory
+ later. */
+ goto error;
+ dp->precision_arg_index = n - 1;
+ cp = np + 1;
+ }
+ }
+ if (dp->precision_arg_index == ARG_NONE)
+ {
+ dp->precision_arg_index = arg_posn++;
+ if (dp->precision_arg_index == ARG_NONE)
+ /* arg_posn wrapped around. */
+ goto error;
+ }
+ REGISTER_ARG (dp->precision_arg_index, TYPE_INT);
+ }
+ else
+ {
+ size_t precision_length;
+
+ dp->precision_start = cp - 1;
+ for (; *cp >= '0' && *cp <= '9'; cp++)
+ ;
+ dp->precision_end = cp;
+ precision_length = dp->precision_end - dp->precision_start;
+ if (max_precision_length < precision_length)
+ max_precision_length = precision_length;
+ }
+ }
+
+ {
+ arg_type type;
+
+ /* Parse argument type/size specifiers. */
+ {
+ int flags = 0;
+
+ for (;;)
+ {
+ if (*cp == 'h')
+ {
+ flags |= (1 << (flags & 1));
+ cp++;
+ }
+ else if (*cp == 'L')
+ {
+ flags |= 4;
+ cp++;
+ }
+ else if (*cp == 'l')
+ {
+ flags += 8;
+ cp++;
+ }
+ else if (*cp == 'j')
+ {
+ if (sizeof (intmax_t) > sizeof (long))
+ {
+ /* intmax_t = long long */
+ flags += 16;
+ }
+ else if (sizeof (intmax_t) > sizeof (int))
+ {
+ /* intmax_t = long */
+ flags += 8;
+ }
+ cp++;
+ }
+ else if (*cp == 'z' || *cp == 'Z')
+ {
+ /* 'z' is standardized in ISO C 99, but glibc uses 'Z'
+ because the warning facility in gcc-2.95.2 understands
+ only 'Z' (see gcc-2.95.2/gcc/c-common.c:1784). */
+ if (sizeof (size_t) > sizeof (long))
+ {
+ /* size_t = long long */
+ flags += 16;
+ }
+ else if (sizeof (size_t) > sizeof (int))
+ {
+ /* size_t = long */
+ flags += 8;
+ }
+ cp++;
+ }
+ else if (*cp == 't')
+ {
+ if (sizeof (ptrdiff_t) > sizeof (long))
+ {
+ /* ptrdiff_t = long long */
+ flags += 16;
+ }
+ else if (sizeof (ptrdiff_t) > sizeof (int))
+ {
+ /* ptrdiff_t = long */
+ flags += 8;
+ }
+ cp++;
+ }
+#if defined __APPLE__ && defined __MACH__
+ /* On MacOS X 10.3, PRIdMAX is defined as "qd".
+ We cannot change it to "lld" because PRIdMAX must also
+ be understood by the system's printf routines. */
+ else if (*cp == 'q')
+ {
+ if (64 / 8 > sizeof (long))
+ {
+ /* int64_t = long long */
+ flags += 16;
+ }
+ else
+ {
+ /* int64_t = long */
+ flags += 8;
+ }
+ cp++;
+ }
+#endif
+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+ /* On native Win32, PRIdMAX is defined as "I64d".
+ We cannot change it to "lld" because PRIdMAX must also
+ be understood by the system's printf routines. */
+ else if (*cp == 'I' && cp[1] == '6' && cp[2] == '4')
+ {
+ if (64 / 8 > sizeof (long))
+ {
+ /* __int64 = long long */
+ flags += 16;
+ }
+ else
+ {
+ /* __int64 = long */
+ flags += 8;
+ }
+ cp += 3;
+ }
+#endif
+ else
+ break;
+ }
+
+ /* Read the conversion character. */
+ c = *cp++;
+ switch (c)
+ {
+ case 'd': case 'i':
+#if HAVE_LONG_LONG_INT
+ /* If 'long long' exists and is larger than 'long': */
+ if (flags >= 16 || (flags & 4))
+ type = TYPE_LONGLONGINT;
+ else
+#endif
+ /* If 'long long' exists and is the same as 'long', we parse
+ "lld" into TYPE_LONGINT. */
+ if (flags >= 8)
+ type = TYPE_LONGINT;
+ else if (flags & 2)
+ type = TYPE_SCHAR;
+ else if (flags & 1)
+ type = TYPE_SHORT;
+ else
+ type = TYPE_INT;
+ break;
+ case 'o': case 'u': case 'x': case 'X':
+#if HAVE_LONG_LONG_INT
+ /* If 'long long' exists and is larger than 'long': */
+ if (flags >= 16 || (flags & 4))
+ type = TYPE_ULONGLONGINT;
+ else
+#endif
+ /* If 'unsigned long long' exists and is the same as
+ 'unsigned long', we parse "llu" into TYPE_ULONGINT. */
+ if (flags >= 8)
+ type = TYPE_ULONGINT;
+ else if (flags & 2)
+ type = TYPE_UCHAR;
+ else if (flags & 1)
+ type = TYPE_USHORT;
+ else
+ type = TYPE_UINT;
+ break;
+ case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
+ case 'a': case 'A':
+ if (flags >= 16 || (flags & 4))
+ type = TYPE_LONGDOUBLE;
+ else
+ type = TYPE_DOUBLE;
+ break;
+ case 'c':
+ if (flags >= 8)
+#if HAVE_WINT_T
+ type = TYPE_WIDE_CHAR;
+#else
+ goto error;
+#endif
+ else
+ type = TYPE_CHAR;
+ break;
+#if HAVE_WINT_T
+ case 'C':
+ type = TYPE_WIDE_CHAR;
+ c = 'c';
+ break;
+#endif
+ case 's':
+ if (flags >= 8)
+#if HAVE_WCHAR_T
+ type = TYPE_WIDE_STRING;
+#else
+ goto error;
+#endif
+ else
+ type = TYPE_STRING;
+ break;
+#if HAVE_WCHAR_T
+ case 'S':
+ type = TYPE_WIDE_STRING;
+ c = 's';
+ break;
+#endif
+ case 'p':
+ type = TYPE_POINTER;
+ break;
+ case 'n':
+#if HAVE_LONG_LONG_INT
+ /* If 'long long' exists and is larger than 'long': */
+ if (flags >= 16 || (flags & 4))
+ type = TYPE_COUNT_LONGLONGINT_POINTER;
+ else
+#endif
+ /* If 'long long' exists and is the same as 'long', we parse
+ "lln" into TYPE_COUNT_LONGINT_POINTER. */
+ if (flags >= 8)
+ type = TYPE_COUNT_LONGINT_POINTER;
+ else if (flags & 2)
+ type = TYPE_COUNT_SCHAR_POINTER;
+ else if (flags & 1)
+ type = TYPE_COUNT_SHORT_POINTER;
+ else
+ type = TYPE_COUNT_INT_POINTER;
+ break;
+#if ENABLE_UNISTDIO
+ /* The unistdio extensions. */
+ case 'U':
+ if (flags >= 16)
+ type = TYPE_U32_STRING;
+ else if (flags >= 8)
+ type = TYPE_U16_STRING;
+ else
+ type = TYPE_U8_STRING;
+ break;
+#endif
+ case '%':
+ type = TYPE_NONE;
+ break;
+ default:
+ /* Unknown conversion character. */
+ goto error;
+ }
+ }
+
+ if (type != TYPE_NONE)
+ {
+ dp->arg_index = arg_index;
+ if (dp->arg_index == ARG_NONE)
+ {
+ dp->arg_index = arg_posn++;
+ if (dp->arg_index == ARG_NONE)
+ /* arg_posn wrapped around. */
+ goto error;
+ }
+ REGISTER_ARG (dp->arg_index, type);
+ }
+ dp->conversion = c;
+ dp->dir_end = cp;
+ }
+
+ d->count++;
+ if (d->count >= d_allocated)
+ {
+ size_t memory_size;
+ DIRECTIVE *memory;
+
+ d_allocated = xtimes (d_allocated, 2);
+ memory_size = xtimes (d_allocated, sizeof (DIRECTIVE));
+ if (size_overflow_p (memory_size))
+ /* Overflow, would lead to out of memory. */
+ goto out_of_memory;
+ memory = (DIRECTIVE *) realloc (d->dir, memory_size);
+ if (memory == NULL)
+ /* Out of memory. */
+ goto out_of_memory;
+ d->dir = memory;
+ }
+ }
+#if CHAR_T_ONLY_ASCII
+ else if (!c_isascii (c))
+ {
+ /* Non-ASCII character. Not supported. */
+ goto error;
+ }
+#endif
+ }
+ d->dir[d->count].dir_start = cp;
+
+ d->max_width_length = max_width_length;
+ d->max_precision_length = max_precision_length;
+ return 0;
+
+error:
+ if (a->arg)
+ free (a->arg);
+ if (d->dir)
+ free (d->dir);
+ errno = EINVAL;
+ return -1;
+
+out_of_memory:
+ if (a->arg)
+ free (a->arg);
+ if (d->dir)
+ free (d->dir);
+out_of_memory_1:
+ errno = ENOMEM;
+ return -1;
+}
+
+#undef PRINTF_PARSE
+#undef DIRECTIVES
+#undef DIRECTIVE
+#undef CHAR_T_ONLY_ASCII
+#undef CHAR_T
diff --git a/intl/printf-parse.h b/intl/printf-parse.h
new file mode 100644
index 00000000..51ead29e
--- /dev/null
+++ b/intl/printf-parse.h
@@ -0,0 +1,75 @@
+/* Parse printf format string.
+ Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifndef _PRINTF_PARSE_H
+#define _PRINTF_PARSE_H
+
+#include "printf-args.h"
+
+
+/* Flags */
+#define FLAG_GROUP 1 /* ' flag */
+#define FLAG_LEFT 2 /* - flag */
+#define FLAG_SHOWSIGN 4 /* + flag */
+#define FLAG_SPACE 8 /* space flag */
+#define FLAG_ALT 16 /* # flag */
+#define FLAG_ZERO 32
+
+/* arg_index value indicating that no argument is consumed. */
+#define ARG_NONE (~(size_t)0)
+
+/* A parsed directive. */
+typedef struct
+{
+ const char* dir_start;
+ const char* dir_end;
+ int flags;
+ const char* width_start;
+ const char* width_end;
+ size_t width_arg_index;
+ const char* precision_start;
+ const char* precision_end;
+ size_t precision_arg_index;
+ char conversion; /* d i o u x X f e E g G c s p n U % but not C S */
+ size_t arg_index;
+}
+char_directive;
+
+/* A parsed format string. */
+typedef struct
+{
+ size_t count;
+ char_directive *dir;
+ size_t max_width_length;
+ size_t max_precision_length;
+}
+char_directives;
+
+
+/* Parses the format string. Fills in the number N of directives, and fills
+ in directives[0], ..., directives[N-1], and sets directives[N].dir_start
+ to the end of the format string. Also fills in the arg_type fields of the
+ arguments and the needed count of arguments. */
+#ifdef STATIC
+STATIC
+#else
+extern
+#endif
+int printf_parse (const char *format, char_directives *d, arguments *a);
+
+#endif /* _PRINTF_PARSE_H */
diff --git a/intl/printf.c b/intl/printf.c
new file mode 100644
index 00000000..b7cdc5d8
--- /dev/null
+++ b/intl/printf.c
@@ -0,0 +1,429 @@
+/* Formatted output to strings, using POSIX/XSI format strings with positions.
+ Copyright (C) 2003, 2006-2007, 2009 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2003.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+# define HAVE_ALLOCA 1
+#else
+# ifdef _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+# else
+# if defined HAVE_ALLOCA_H || defined _LIBC
+# include <alloca.h>
+# else
+# ifdef _AIX
+ #pragma alloca
+# else
+# ifndef alloca
+char *alloca ();
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#include <stdio.h>
+
+#if !HAVE_POSIX_PRINTF
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Some systems, like OSF/1 4.0 and Woe32, don't have EOVERFLOW. */
+#ifndef EOVERFLOW
+# define EOVERFLOW E2BIG
+#endif
+
+/* When building a DLL, we must export some functions. Note that because
+ the functions are only defined for binary backward compatibility, we
+ don't need to use __declspec(dllimport) in any case. */
+#if HAVE_VISIBILITY && BUILDING_DLL
+# define DLL_EXPORTED __attribute__((__visibility__("default")))
+#elif defined _MSC_VER && BUILDING_DLL
+# define DLL_EXPORTED __declspec(dllexport)
+#else
+# define DLL_EXPORTED
+#endif
+
+#define STATIC static
+
+/* This needs to be consistent with libgnuintl.h.in. */
+#if defined __NetBSD__ || defined __BEOS__ || defined __CYGWIN__ || defined __MINGW32__
+/* Don't break __attribute__((format(printf,M,N))).
+ This redefinition is only possible because the libc in NetBSD, Cygwin,
+ mingw does not have a function __printf__. */
+# define libintl_printf __printf__
+#endif
+
+/* Define auxiliary functions declared in "printf-args.h". */
+#include "printf-args.c"
+
+/* Define auxiliary functions declared in "printf-parse.h". */
+#include "printf-parse.c"
+
+/* Define functions declared in "vasnprintf.h". */
+#define vasnprintf libintl_vasnprintf
+#include "vasnprintf.c"
+#if 0 /* not needed */
+#define asnprintf libintl_asnprintf
+#include "asnprintf.c"
+#endif
+
+DLL_EXPORTED
+int
+libintl_vfprintf (FILE *stream, const char *format, va_list args)
+{
+ if (strchr (format, '$') == NULL)
+ return vfprintf (stream, format, args);
+ else
+ {
+ size_t length;
+ char *result = libintl_vasnprintf (NULL, &length, format, args);
+ int retval = -1;
+ if (result != NULL)
+ {
+ size_t written = fwrite (result, 1, length, stream);
+ free (result);
+ if (written == length)
+ {
+ if (length > INT_MAX)
+ errno = EOVERFLOW;
+ else
+ retval = length;
+ }
+ }
+ return retval;
+ }
+}
+
+DLL_EXPORTED
+int
+libintl_fprintf (FILE *stream, const char *format, ...)
+{
+ va_list args;
+ int retval;
+
+ va_start (args, format);
+ retval = libintl_vfprintf (stream, format, args);
+ va_end (args);
+ return retval;
+}
+
+DLL_EXPORTED
+int
+libintl_vprintf (const char *format, va_list args)
+{
+ return libintl_vfprintf (stdout, format, args);
+}
+
+DLL_EXPORTED
+int
+libintl_printf (const char *format, ...)
+{
+ va_list args;
+ int retval;
+
+ va_start (args, format);
+ retval = libintl_vprintf (format, args);
+ va_end (args);
+ return retval;
+}
+
+DLL_EXPORTED
+int
+libintl_vsprintf (char *resultbuf, const char *format, va_list args)
+{
+ if (strchr (format, '$') == NULL)
+ return vsprintf (resultbuf, format, args);
+ else
+ {
+ size_t length = (size_t) ~0 / (4 * sizeof (char));
+ char *result = libintl_vasnprintf (resultbuf, &length, format, args);
+ if (result != resultbuf)
+ {
+ free (result);
+ return -1;
+ }
+ if (length > INT_MAX)
+ {
+ errno = EOVERFLOW;
+ return -1;
+ }
+ else
+ return length;
+ }
+}
+
+DLL_EXPORTED
+int
+libintl_sprintf (char *resultbuf, const char *format, ...)
+{
+ va_list args;
+ int retval;
+
+ va_start (args, format);
+ retval = libintl_vsprintf (resultbuf, format, args);
+ va_end (args);
+ return retval;
+}
+
+#if HAVE_SNPRINTF
+
+# if HAVE_DECL__SNPRINTF
+ /* Windows. */
+# define system_vsnprintf _vsnprintf
+# else
+ /* Unix. */
+# define system_vsnprintf vsnprintf
+# endif
+
+DLL_EXPORTED
+int
+libintl_vsnprintf (char *resultbuf, size_t length, const char *format, va_list args)
+{
+ if (strchr (format, '$') == NULL)
+ return system_vsnprintf (resultbuf, length, format, args);
+ else
+ {
+ size_t maxlength = length;
+ char *result = libintl_vasnprintf (resultbuf, &length, format, args);
+ if (result != resultbuf)
+ {
+ if (maxlength > 0)
+ {
+ size_t pruned_length =
+ (length < maxlength ? length : maxlength - 1);
+ memcpy (resultbuf, result, pruned_length);
+ resultbuf[pruned_length] = '\0';
+ }
+ free (result);
+ }
+ if (length > INT_MAX)
+ {
+ errno = EOVERFLOW;
+ return -1;
+ }
+ else
+ return length;
+ }
+}
+
+DLL_EXPORTED
+int
+libintl_snprintf (char *resultbuf, size_t length, const char *format, ...)
+{
+ va_list args;
+ int retval;
+
+ va_start (args, format);
+ retval = libintl_vsnprintf (resultbuf, length, format, args);
+ va_end (args);
+ return retval;
+}
+
+#endif
+
+#if HAVE_ASPRINTF
+
+DLL_EXPORTED
+int
+libintl_vasprintf (char **resultp, const char *format, va_list args)
+{
+ size_t length;
+ char *result = libintl_vasnprintf (NULL, &length, format, args);
+ if (result == NULL)
+ return -1;
+ if (length > INT_MAX)
+ {
+ free (result);
+ errno = EOVERFLOW;
+ return -1;
+ }
+ *resultp = result;
+ return length;
+}
+
+DLL_EXPORTED
+int
+libintl_asprintf (char **resultp, const char *format, ...)
+{
+ va_list args;
+ int retval;
+
+ va_start (args, format);
+ retval = libintl_vasprintf (resultp, format, args);
+ va_end (args);
+ return retval;
+}
+
+#endif
+
+#if HAVE_FWPRINTF
+
+#include <wchar.h>
+
+#define WIDE_CHAR_VERSION 1
+
+#include "wprintf-parse.h"
+/* Define auxiliary functions declared in "wprintf-parse.h". */
+#define CHAR_T wchar_t
+#define DIRECTIVE wchar_t_directive
+#define DIRECTIVES wchar_t_directives
+#define PRINTF_PARSE wprintf_parse
+#include "printf-parse.c"
+
+/* Define functions declared in "vasnprintf.h". */
+#define vasnwprintf libintl_vasnwprintf
+#include "vasnprintf.c"
+#if 0 /* not needed */
+#define asnwprintf libintl_asnwprintf
+#include "asnprintf.c"
+#endif
+
+# if HAVE_DECL__SNWPRINTF
+ /* Windows. */
+# define system_vswprintf _vsnwprintf
+# else
+ /* Unix. */
+# define system_vswprintf vswprintf
+# endif
+
+DLL_EXPORTED
+int
+libintl_vfwprintf (FILE *stream, const wchar_t *format, va_list args)
+{
+ if (wcschr (format, '$') == NULL)
+ return vfwprintf (stream, format, args);
+ else
+ {
+ size_t length;
+ wchar_t *result = libintl_vasnwprintf (NULL, &length, format, args);
+ int retval = -1;
+ if (result != NULL)
+ {
+ size_t i;
+ for (i = 0; i < length; i++)
+ if (fputwc (result[i], stream) == WEOF)
+ break;
+ free (result);
+ if (i == length)
+ {
+ if (length > INT_MAX)
+ errno = EOVERFLOW;
+ else
+ retval = length;
+ }
+ }
+ return retval;
+ }
+}
+
+DLL_EXPORTED
+int
+libintl_fwprintf (FILE *stream, const wchar_t *format, ...)
+{
+ va_list args;
+ int retval;
+
+ va_start (args, format);
+ retval = libintl_vfwprintf (stream, format, args);
+ va_end (args);
+ return retval;
+}
+
+DLL_EXPORTED
+int
+libintl_vwprintf (const wchar_t *format, va_list args)
+{
+ return libintl_vfwprintf (stdout, format, args);
+}
+
+DLL_EXPORTED
+int
+libintl_wprintf (const wchar_t *format, ...)
+{
+ va_list args;
+ int retval;
+
+ va_start (args, format);
+ retval = libintl_vwprintf (format, args);
+ va_end (args);
+ return retval;
+}
+
+DLL_EXPORTED
+int
+libintl_vswprintf (wchar_t *resultbuf, size_t length, const wchar_t *format, va_list args)
+{
+ if (wcschr (format, '$') == NULL)
+ return system_vswprintf (resultbuf, length, format, args);
+ else
+ {
+ size_t maxlength = length;
+ wchar_t *result = libintl_vasnwprintf (resultbuf, &length, format, args);
+ if (result != resultbuf)
+ {
+ if (maxlength > 0)
+ {
+ size_t pruned_length =
+ (length < maxlength ? length : maxlength - 1);
+ memcpy (resultbuf, result, pruned_length * sizeof (wchar_t));
+ resultbuf[pruned_length] = 0;
+ }
+ free (result);
+ /* Unlike vsnprintf, which has to return the number of character that
+ would have been produced if the resultbuf had been sufficiently
+ large, the vswprintf function has to return a negative value if
+ the resultbuf was not sufficiently large. */
+ if (length >= maxlength)
+ return -1;
+ }
+ if (length > INT_MAX)
+ {
+ errno = EOVERFLOW;
+ return -1;
+ }
+ else
+ return length;
+ }
+}
+
+DLL_EXPORTED
+int
+libintl_swprintf (wchar_t *resultbuf, size_t length, const wchar_t *format, ...)
+{
+ va_list args;
+ int retval;
+
+ va_start (args, format);
+ retval = libintl_vswprintf (resultbuf, length, format, args);
+ va_end (args);
+ return retval;
+}
+
+#endif
+
+#endif
diff --git a/intl/ref-add.sin b/intl/ref-add.sin
new file mode 100644
index 00000000..3678c289
--- /dev/null
+++ b/intl/ref-add.sin
@@ -0,0 +1,31 @@
+# Add this package to a list of references stored in a text file.
+#
+# Copyright (C) 2000 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Library General Public License as published
+# by the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+# USA.
+#
+# Written by Bruno Haible <haible@clisp.cons.org>.
+#
+/^# Packages using this file: / {
+ s/# Packages using this file://
+ ta
+ :a
+ s/ @PACKAGE@ / @PACKAGE@ /
+ tb
+ s/ $/ @PACKAGE@ /
+ :b
+ s/^/# Packages using this file:/
+}
diff --git a/intl/ref-del.sin b/intl/ref-del.sin
new file mode 100644
index 00000000..0c12d8e9
--- /dev/null
+++ b/intl/ref-del.sin
@@ -0,0 +1,26 @@
+# Remove this package from a list of references stored in a text file.
+#
+# Copyright (C) 2000 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Library General Public License as published
+# by the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+# USA.
+#
+# Written by Bruno Haible <haible@clisp.cons.org>.
+#
+/^# Packages using this file: / {
+ s/# Packages using this file://
+ s/ @PACKAGE@ / /
+ s/^/# Packages using this file:/
+}
diff --git a/intl/relocatable.c b/intl/relocatable.c
new file mode 100644
index 00000000..f1bed781
--- /dev/null
+++ b/intl/relocatable.c
@@ -0,0 +1,493 @@
+/* Provide relocatable packages.
+ Copyright (C) 2003-2006, 2008-2009 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2003.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+
+/* Tell glibc's <stdio.h> to provide a prototype for getline().
+ This must come before <config.h> because <config.h> may include
+ <features.h>, and once <features.h> has been included, it's too late. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
+#include <config.h>
+
+/* Specification. */
+#include "relocatable.h"
+
+#if ENABLE_RELOCATABLE
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef NO_XMALLOC
+# define xmalloc malloc
+#else
+# include "xalloc.h"
+#endif
+
+#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif
+
+#if DEPENDS_ON_LIBCHARSET
+# include <libcharset.h>
+#endif
+#if DEPENDS_ON_LIBICONV && HAVE_ICONV
+# include <iconv.h>
+#endif
+#if DEPENDS_ON_LIBINTL && ENABLE_NLS
+# include <libintl.h>
+#endif
+
+/* Faked cheap 'bool'. */
+#undef bool
+#undef false
+#undef true
+#define bool int
+#define false 0
+#define true 1
+
+/* Pathname support.
+ ISSLASH(C) tests whether C is a directory separator character.
+ IS_PATH_WITH_DIR(P) tests whether P contains a directory specification.
+ */
+#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
+ /* Win32, Cygwin, OS/2, DOS */
+# define ISSLASH(C) ((C) == '/' || (C) == '\\')
+# define HAS_DEVICE(P) \
+ ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
+ && (P)[1] == ':')
+# define IS_PATH_WITH_DIR(P) \
+ (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
+# define FILE_SYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0)
+#else
+ /* Unix */
+# define ISSLASH(C) ((C) == '/')
+# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
+# define FILE_SYSTEM_PREFIX_LEN(P) 0
+#endif
+
+/* Original installation prefix. */
+static char *orig_prefix;
+static size_t orig_prefix_len;
+/* Current installation prefix. */
+static char *curr_prefix;
+static size_t curr_prefix_len;
+/* These prefixes do not end in a slash. Anything that will be concatenated
+ to them must start with a slash. */
+
+/* Sets the original and the current installation prefix of this module.
+ Relocation simply replaces a pathname starting with the original prefix
+ by the corresponding pathname with the current prefix instead. Both
+ prefixes should be directory names without trailing slash (i.e. use ""
+ instead of "/"). */
+static void
+set_this_relocation_prefix (const char *orig_prefix_arg,
+ const char *curr_prefix_arg)
+{
+ if (orig_prefix_arg != NULL && curr_prefix_arg != NULL
+ /* Optimization: if orig_prefix and curr_prefix are equal, the
+ relocation is a nop. */
+ && strcmp (orig_prefix_arg, curr_prefix_arg) != 0)
+ {
+ /* Duplicate the argument strings. */
+ char *memory;
+
+ orig_prefix_len = strlen (orig_prefix_arg);
+ curr_prefix_len = strlen (curr_prefix_arg);
+ memory = (char *) xmalloc (orig_prefix_len + 1 + curr_prefix_len + 1);
+#ifdef NO_XMALLOC
+ if (memory != NULL)
+#endif
+ {
+ memcpy (memory, orig_prefix_arg, orig_prefix_len + 1);
+ orig_prefix = memory;
+ memory += orig_prefix_len + 1;
+ memcpy (memory, curr_prefix_arg, curr_prefix_len + 1);
+ curr_prefix = memory;
+ return;
+ }
+ }
+ orig_prefix = NULL;
+ curr_prefix = NULL;
+ /* Don't worry about wasted memory here - this function is usually only
+ called once. */
+}
+
+/* Sets the original and the current installation prefix of the package.
+ Relocation simply replaces a pathname starting with the original prefix
+ by the corresponding pathname with the current prefix instead. Both
+ prefixes should be directory names without trailing slash (i.e. use ""
+ instead of "/"). */
+void
+set_relocation_prefix (const char *orig_prefix_arg, const char *curr_prefix_arg)
+{
+ set_this_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
+
+ /* Now notify all dependent libraries. */
+#if DEPENDS_ON_LIBCHARSET
+ libcharset_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
+#endif
+#if DEPENDS_ON_LIBICONV && HAVE_ICONV && _LIBICONV_VERSION >= 0x0109
+ libiconv_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
+#endif
+#if DEPENDS_ON_LIBINTL && ENABLE_NLS && defined libintl_set_relocation_prefix
+ libintl_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
+#endif
+}
+
+#if !defined IN_LIBRARY || (defined PIC && defined INSTALLDIR)
+
+/* Convenience function:
+ Computes the current installation prefix, based on the original
+ installation prefix, the original installation directory of a particular
+ file, and the current pathname of this file.
+ Returns it, freshly allocated. Returns NULL upon failure. */
+#ifdef IN_LIBRARY
+#define compute_curr_prefix local_compute_curr_prefix
+static
+#endif
+char *
+compute_curr_prefix (const char *orig_installprefix,
+ const char *orig_installdir,
+ const char *curr_pathname)
+{
+ char *curr_installdir;
+ const char *rel_installdir;
+
+ if (curr_pathname == NULL)
+ return NULL;
+
+ /* Determine the relative installation directory, relative to the prefix.
+ This is simply the difference between orig_installprefix and
+ orig_installdir. */
+ if (strncmp (orig_installprefix, orig_installdir, strlen (orig_installprefix))
+ != 0)
+ /* Shouldn't happen - nothing should be installed outside $(prefix). */
+ return NULL;
+ rel_installdir = orig_installdir + strlen (orig_installprefix);
+
+ /* Determine the current installation directory. */
+ {
+ const char *p_base = curr_pathname + FILE_SYSTEM_PREFIX_LEN (curr_pathname);
+ const char *p = curr_pathname + strlen (curr_pathname);
+ char *q;
+
+ while (p > p_base)
+ {
+ p--;
+ if (ISSLASH (*p))
+ break;
+ }
+
+ q = (char *) xmalloc (p - curr_pathname + 1);
+#ifdef NO_XMALLOC
+ if (q == NULL)
+ return NULL;
+#endif
+ memcpy (q, curr_pathname, p - curr_pathname);
+ q[p - curr_pathname] = '\0';
+ curr_installdir = q;
+ }
+
+ /* Compute the current installation prefix by removing the trailing
+ rel_installdir from it. */
+ {
+ const char *rp = rel_installdir + strlen (rel_installdir);
+ const char *cp = curr_installdir + strlen (curr_installdir);
+ const char *cp_base =
+ curr_installdir + FILE_SYSTEM_PREFIX_LEN (curr_installdir);
+
+ while (rp > rel_installdir && cp > cp_base)
+ {
+ bool same = false;
+ const char *rpi = rp;
+ const char *cpi = cp;
+
+ while (rpi > rel_installdir && cpi > cp_base)
+ {
+ rpi--;
+ cpi--;
+ if (ISSLASH (*rpi) || ISSLASH (*cpi))
+ {
+ if (ISSLASH (*rpi) && ISSLASH (*cpi))
+ same = true;
+ break;
+ }
+ /* Do case-insensitive comparison if the file system is always or
+ often case-insensitive. It's better to accept the comparison
+ if the difference is only in case, rather than to fail. */
+#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
+ /* Win32, Cygwin, OS/2, DOS - case insignificant file system */
+ if ((*rpi >= 'a' && *rpi <= 'z' ? *rpi - 'a' + 'A' : *rpi)
+ != (*cpi >= 'a' && *cpi <= 'z' ? *cpi - 'a' + 'A' : *cpi))
+ break;
+#else
+ if (*rpi != *cpi)
+ break;
+#endif
+ }
+ if (!same)
+ break;
+ /* The last pathname component was the same. opi and cpi now point
+ to the slash before it. */
+ rp = rpi;
+ cp = cpi;
+ }
+
+ if (rp > rel_installdir)
+ {
+ /* Unexpected: The curr_installdir does not end with rel_installdir. */
+ free (curr_installdir);
+ return NULL;
+ }
+
+ {
+ size_t curr_prefix_len = cp - curr_installdir;
+ char *curr_prefix;
+
+ curr_prefix = (char *) xmalloc (curr_prefix_len + 1);
+#ifdef NO_XMALLOC
+ if (curr_prefix == NULL)
+ {
+ free (curr_installdir);
+ return NULL;
+ }
+#endif
+ memcpy (curr_prefix, curr_installdir, curr_prefix_len);
+ curr_prefix[curr_prefix_len] = '\0';
+
+ free (curr_installdir);
+
+ return curr_prefix;
+ }
+ }
+}
+
+#endif /* !IN_LIBRARY || PIC */
+
+#if defined PIC && defined INSTALLDIR
+
+/* Full pathname of shared library, or NULL. */
+static char *shared_library_fullname;
+
+#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__
+
+/* Determine the full pathname of the shared library when it is loaded. */
+
+BOOL WINAPI
+DllMain (HINSTANCE module_handle, DWORD event, LPVOID reserved)
+{
+ (void) reserved;
+
+ if (event == DLL_PROCESS_ATTACH)
+ {
+ /* The DLL is being loaded into an application's address range. */
+ static char location[MAX_PATH];
+
+ if (!GetModuleFileName (module_handle, location, sizeof (location)))
+ /* Shouldn't happen. */
+ return FALSE;
+
+ if (!IS_PATH_WITH_DIR (location))
+ /* Shouldn't happen. */
+ return FALSE;
+
+ {
+#if defined __CYGWIN__
+ /* On Cygwin, we need to convert paths coming from Win32 system calls
+ to the Unix-like slashified notation. */
+ static char location_as_posix_path[2 * MAX_PATH];
+ /* There's no error return defined for cygwin_conv_to_posix_path.
+ See cygwin-api/func-cygwin-conv-to-posix-path.html.
+ Does it overflow the buffer of expected size MAX_PATH or does it
+ truncate the path? I don't know. Let's catch both. */
+ cygwin_conv_to_posix_path (location, location_as_posix_path);
+ location_as_posix_path[MAX_PATH - 1] = '\0';
+ if (strlen (location_as_posix_path) >= MAX_PATH - 1)
+ /* A sign of buffer overflow or path truncation. */
+ return FALSE;
+ shared_library_fullname = strdup (location_as_posix_path);
+#else
+ shared_library_fullname = strdup (location);
+#endif
+ }
+ }
+
+ return TRUE;
+}
+
+#else /* Unix except Cygwin */
+
+static void
+find_shared_library_fullname ()
+{
+#if defined __linux__ && __GLIBC__ >= 2
+ /* Linux has /proc/self/maps. glibc 2 has the getline() function. */
+ FILE *fp;
+
+ /* Open the current process' maps file. It describes one VMA per line. */
+ fp = fopen ("/proc/self/maps", "r");
+ if (fp)
+ {
+ unsigned long address = (unsigned long) &find_shared_library_fullname;
+ for (;;)
+ {
+ unsigned long start, end;
+ int c;
+
+ if (fscanf (fp, "%lx-%lx", &start, &end) != 2)
+ break;
+ if (address >= start && address <= end - 1)
+ {
+ /* Found it. Now see if this line contains a filename. */
+ while (c = getc (fp), c != EOF && c != '\n' && c != '/')
+ continue;
+ if (c == '/')
+ {
+ size_t size;
+ int len;
+
+ ungetc (c, fp);
+ shared_library_fullname = NULL; size = 0;
+ len = getline (&shared_library_fullname, &size, fp);
+ if (len >= 0)
+ {
+ /* Success: filled shared_library_fullname. */
+ if (len > 0 && shared_library_fullname[len - 1] == '\n')
+ shared_library_fullname[len - 1] = '\0';
+ }
+ }
+ break;
+ }
+ while (c = getc (fp), c != EOF && c != '\n')
+ continue;
+ }
+ fclose (fp);
+ }
+#endif
+}
+
+#endif /* (WIN32 or Cygwin) / (Unix except Cygwin) */
+
+/* Return the full pathname of the current shared library.
+ Return NULL if unknown.
+ Guaranteed to work only on Linux, Cygwin and Woe32. */
+static char *
+get_shared_library_fullname ()
+{
+#if !(defined _WIN32 || defined __WIN32__ || defined __CYGWIN__)
+ static bool tried_find_shared_library_fullname;
+ if (!tried_find_shared_library_fullname)
+ {
+ find_shared_library_fullname ();
+ tried_find_shared_library_fullname = true;
+ }
+#endif
+ return shared_library_fullname;
+}
+
+#endif /* PIC */
+
+/* Returns the pathname, relocated according to the current installation
+ directory.
+ The returned string is either PATHNAME unmodified or a freshly allocated
+ string that you can free with free() after casting it to 'char *'. */
+const char *
+relocate (const char *pathname)
+{
+#if defined PIC && defined INSTALLDIR
+ static int initialized;
+
+ /* Initialization code for a shared library. */
+ if (!initialized)
+ {
+ /* At this point, orig_prefix and curr_prefix likely have already been
+ set through the main program's set_program_name_and_installdir
+ function. This is sufficient in the case that the library has
+ initially been installed in the same orig_prefix. But we can do
+ better, to also cover the cases that 1. it has been installed
+ in a different prefix before being moved to orig_prefix and (later)
+ to curr_prefix, 2. unlike the program, it has not moved away from
+ orig_prefix. */
+ const char *orig_installprefix = INSTALLPREFIX;
+ const char *orig_installdir = INSTALLDIR;
+ char *curr_prefix_better;
+
+ curr_prefix_better =
+ compute_curr_prefix (orig_installprefix, orig_installdir,
+ get_shared_library_fullname ());
+
+ set_relocation_prefix (orig_installprefix,
+ curr_prefix_better != NULL
+ ? curr_prefix_better
+ : curr_prefix);
+
+ if (curr_prefix_better != NULL)
+ free (curr_prefix_better);
+
+ initialized = 1;
+ }
+#endif
+
+ /* Note: It is not necessary to perform case insensitive comparison here,
+ even for DOS-like file systems, because the pathname argument was
+ typically created from the same Makefile variable as orig_prefix came
+ from. */
+ if (orig_prefix != NULL && curr_prefix != NULL
+ && strncmp (pathname, orig_prefix, orig_prefix_len) == 0)
+ {
+ if (pathname[orig_prefix_len] == '\0')
+ {
+ /* pathname equals orig_prefix. */
+ char *result = (char *) xmalloc (strlen (curr_prefix) + 1);
+
+#ifdef NO_XMALLOC
+ if (result != NULL)
+#endif
+ {
+ strcpy (result, curr_prefix);
+ return result;
+ }
+ }
+ else if (ISSLASH (pathname[orig_prefix_len]))
+ {
+ /* pathname starts with orig_prefix. */
+ const char *pathname_tail = &pathname[orig_prefix_len];
+ char *result =
+ (char *) xmalloc (curr_prefix_len + strlen (pathname_tail) + 1);
+
+#ifdef NO_XMALLOC
+ if (result != NULL)
+#endif
+ {
+ memcpy (result, curr_prefix, curr_prefix_len);
+ strcpy (result + curr_prefix_len, pathname_tail);
+ return result;
+ }
+ }
+ }
+ /* Nothing to relocate. */
+ return pathname;
+}
+
+#endif
diff --git a/intl/relocatable.h b/intl/relocatable.h
new file mode 100644
index 00000000..3acb5343
--- /dev/null
+++ b/intl/relocatable.h
@@ -0,0 +1,83 @@
+/* Provide relocatable packages.
+ Copyright (C) 2003, 2005, 2008 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2003.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifndef _RELOCATABLE_H
+#define _RELOCATABLE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* This can be enabled through the configure --enable-relocatable option. */
+#if ENABLE_RELOCATABLE
+
+/* When building a DLL, we must export some functions. Note that because
+ this is a private .h file, we don't need to use __declspec(dllimport)
+ in any case. */
+#if HAVE_VISIBILITY && BUILDING_DLL
+# define RELOCATABLE_DLL_EXPORTED __attribute__((__visibility__("default")))
+#elif defined _MSC_VER && BUILDING_DLL
+# define RELOCATABLE_DLL_EXPORTED __declspec(dllexport)
+#else
+# define RELOCATABLE_DLL_EXPORTED
+#endif
+
+/* Sets the original and the current installation prefix of the package.
+ Relocation simply replaces a pathname starting with the original prefix
+ by the corresponding pathname with the current prefix instead. Both
+ prefixes should be directory names without trailing slash (i.e. use ""
+ instead of "/"). */
+extern RELOCATABLE_DLL_EXPORTED void
+ set_relocation_prefix (const char *orig_prefix,
+ const char *curr_prefix);
+
+/* Returns the pathname, relocated according to the current installation
+ directory.
+ The returned string is either PATHNAME unmodified or a freshly allocated
+ string that you can free with free() after casting it to 'char *'. */
+extern const char * relocate (const char *pathname);
+
+/* Memory management: relocate() potentially allocates memory, because it has
+ to construct a fresh pathname. If this is a problem because your program
+ calls relocate() frequently, think about caching the result. Or free the
+ return value if it was different from the argument pathname. */
+
+/* Convenience function:
+ Computes the current installation prefix, based on the original
+ installation prefix, the original installation directory of a particular
+ file, and the current pathname of this file.
+ Returns it, freshly allocated. Returns NULL upon failure. */
+extern char * compute_curr_prefix (const char *orig_installprefix,
+ const char *orig_installdir,
+ const char *curr_pathname);
+
+#else
+
+/* By default, we use the hardwired pathnames. */
+#define relocate(pathname) (pathname)
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RELOCATABLE_H */
diff --git a/intl/setlocale.c b/intl/setlocale.c
new file mode 100644
index 00000000..2a5e2605
--- /dev/null
+++ b/intl/setlocale.c
@@ -0,0 +1,1015 @@
+/* setlocale() function that respects the locale chosen by the user.
+ Copyright (C) 2009 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2009.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Override setlocale() and newlocale() so that when the default locale is
+ requested (locale = "") and no relevant environment variable is set, the
+ locale chosen by the user is used.
+ This matters on MacOS X 10 and Windows.
+ See the comments in localename.c, function gl_locale_name_default. */
+
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* When building a DLL, we must export some functions. Note that because
+ the functions are only defined for binary backward compatibility, we
+ don't need to use __declspec(dllimport) in any case. */
+#if HAVE_VISIBILITY && BUILDING_DLL
+# define DLL_EXPORTED __attribute__((__visibility__("default")))
+#elif defined _MSC_VER && BUILDING_DLL
+# define DLL_EXPORTED __declspec(dllexport)
+#else
+# define DLL_EXPORTED
+#endif
+
+#include "gettextP.h"
+
+#if (defined __APPLE__ && defined __MACH__) || defined _WIN32 || defined __WIN32__ || defined __CYGWIN__
+
+# undef setlocale
+# undef newlocale
+
+/* Return string representation of locale category CATEGORY. */
+static const char *
+category_to_name (int category)
+{
+ const char *retval;
+
+ switch (category)
+ {
+ case LC_COLLATE:
+ retval = "LC_COLLATE";
+ break;
+ case LC_CTYPE:
+ retval = "LC_CTYPE";
+ break;
+ case LC_MONETARY:
+ retval = "LC_MONETARY";
+ break;
+ case LC_NUMERIC:
+ retval = "LC_NUMERIC";
+ break;
+ case LC_TIME:
+ retval = "LC_TIME";
+ break;
+ case LC_MESSAGES:
+ retval = "LC_MESSAGES";
+ break;
+ default:
+ /* If you have a better idea for a default value let me know. */
+ retval = "LC_XXX";
+ }
+
+ return retval;
+}
+
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+
+/* The native Win32 setlocale() function expects locale names of the form
+ "German" or "German_Germany" or "DEU", but not "de" or "de_DE". We need
+ to convert the names from the form with ISO 639 language code and ISO 3166
+ country code to the form with English names or with three-letter identifier.
+ The three-letter identifiers known by a Windows XP SP2 or SP3 are:
+ AFK Afrikaans_South Africa.1252
+ ARA Arabic_Saudi Arabia.1256
+ ARB Arabic_Lebanon.1256
+ ARE Arabic_Egypt.1256
+ ARG Arabic_Algeria.1256
+ ARH Arabic_Bahrain.1256
+ ARI Arabic_Iraq.1256
+ ARJ Arabic_Jordan.1256
+ ARK Arabic_Kuwait.1256
+ ARL Arabic_Libya.1256
+ ARM Arabic_Morocco.1256
+ ARO Arabic_Oman.1256
+ ARQ Arabic_Qatar.1256
+ ARS Arabic_Syria.1256
+ ART Arabic_Tunisia.1256
+ ARU Arabic_U.A.E..1256
+ ARY Arabic_Yemen.1256
+ AZE Azeri (Latin)_Azerbaijan.1254
+ BEL Belarusian_Belarus.1251
+ BGR Bulgarian_Bulgaria.1251
+ BSB Bosnian_Bosnia and Herzegovina.1250
+ BSC Bosnian (Cyrillic)_Bosnia and Herzegovina.1250 (wrong encoding!)
+ CAT Catalan_Spain.1252
+ CHH Chinese_Hong Kong S.A.R..950
+ CHI Chinese_Singapore.936
+ CHS Chinese_People's Republic of China.936
+ CHT Chinese_Taiwan.950
+ CSY Czech_Czech Republic.1250
+ CYM Welsh_United Kingdom.1252
+ DAN Danish_Denmark.1252
+ DEA German_Austria.1252
+ DEC German_Liechtenstein.1252
+ DEL German_Luxembourg.1252
+ DES German_Switzerland.1252
+ DEU German_Germany.1252
+ ELL Greek_Greece.1253
+ ENA English_Australia.1252
+ ENB English_Caribbean.1252
+ ENC English_Canada.1252
+ ENG English_United Kingdom.1252
+ ENI English_Ireland.1252
+ ENJ English_Jamaica.1252
+ ENL English_Belize.1252
+ ENP English_Republic of the Philippines.1252
+ ENS English_South Africa.1252
+ ENT English_Trinidad and Tobago.1252
+ ENU English_United States.1252
+ ENW English_Zimbabwe.1252
+ ENZ English_New Zealand.1252
+ ESA Spanish_Panama.1252
+ ESB Spanish_Bolivia.1252
+ ESC Spanish_Costa Rica.1252
+ ESD Spanish_Dominican Republic.1252
+ ESE Spanish_El Salvador.1252
+ ESF Spanish_Ecuador.1252
+ ESG Spanish_Guatemala.1252
+ ESH Spanish_Honduras.1252
+ ESI Spanish_Nicaragua.1252
+ ESL Spanish_Chile.1252
+ ESM Spanish_Mexico.1252
+ ESN Spanish_Spain.1252
+ ESO Spanish_Colombia.1252
+ ESP Spanish_Spain.1252
+ ESR Spanish_Peru.1252
+ ESS Spanish_Argentina.1252
+ ESU Spanish_Puerto Rico.1252
+ ESV Spanish_Venezuela.1252
+ ESY Spanish_Uruguay.1252
+ ESZ Spanish_Paraguay.1252
+ ETI Estonian_Estonia.1257
+ EUQ Basque_Spain.1252
+ FAR Farsi_Iran.1256
+ FIN Finnish_Finland.1252
+ FOS Faroese_Faroe Islands.1252
+ FPO Filipino_Philippines.1252
+ FRA French_France.1252
+ FRB French_Belgium.1252
+ FRC French_Canada.1252
+ FRL French_Luxembourg.1252
+ FRM French_Principality of Monaco.1252
+ FRS French_Switzerland.1252
+ FYN Frisian_Netherlands.1252
+ GLC Galician_Spain.1252
+ HEB Hebrew_Israel.1255
+ HRB Croatian_Bosnia and Herzegovina.1250
+ HRV Croatian_Croatia.1250
+ HUN Hungarian_Hungary.1250
+ IND Indonesian_Indonesia.1252
+ IRE Irish_Ireland.1252
+ ISL Icelandic_Iceland.1252
+ ITA Italian_Italy.1252
+ ITS Italian_Switzerland.1252
+ IUK Inuktitut (Latin)_Canada.1252
+ JPN Japanese_Japan.932
+ KKZ Kazakh_Kazakhstan.1251
+ KOR Korean_Korea.949
+ KYR Kyrgyz_Kyrgyzstan.1251
+ LBX Luxembourgish_Luxembourg.1252
+ LTH Lithuanian_Lithuania.1257
+ LVI Latvian_Latvia.1257
+ MKI FYRO Macedonian_Former Yugoslav Republic of Macedonia.1251
+ MON Mongolian_Mongolia.1251
+ MPD Mapudungun_Chile.1252
+ MSB Malay_Brunei Darussalam.1252
+ MSL Malay_Malaysia.1252
+ MWK Mohawk_Canada.1252
+ NLB Dutch_Belgium.1252
+ NLD Dutch_Netherlands.1252
+ NON Norwegian-Nynorsk_Norway.1252
+ NOR Norwegian (Bokmål)_Norway.1252
+ NSO Northern Sotho_South Africa.1252
+ PLK Polish_Poland.1250
+ PTB Portuguese_Brazil.1252
+ PTG Portuguese_Portugal.1252
+ QUB Quechua_Bolivia.1252
+ QUE Quechua_Ecuador.1252
+ QUP Quechua_Peru.1252
+ RMC Romansh_Switzerland.1252
+ ROM Romanian_Romania.1250
+ RUS Russian_Russia.1251
+ SKY Slovak_Slovakia.1250
+ SLV Slovenian_Slovenia.1250
+ SMA Sami (Southern)_Norway.1252
+ SMB Sami (Southern)_Sweden.1252
+ SME Sami (Northern)_Norway.1252
+ SMF Sami (Northern)_Sweden.1252
+ SMG Sami (Northern)_Finland.1252
+ SMJ Sami (Lule)_Norway.1252
+ SMK Sami (Lule)_Sweden.1252
+ SMN Sami (Inari)_Finland.1252
+ SMS Sami (Skolt)_Finland.1252
+ SQI Albanian_Albania.1250
+ SRB Serbian (Cyrillic)_Serbia and Montenegro.1251
+ SRL Serbian (Latin)_Serbia and Montenegro.1250
+ SRN Serbian (Cyrillic)_Bosnia and Herzegovina.1251
+ SRS Serbian (Latin)_Bosnia and Herzegovina.1250
+ SVE Swedish_Sweden.1252
+ SVF Swedish_Finland.1252
+ SWK Swahili_Kenya.1252
+ THA Thai_Thailand.874
+ TRK Turkish_Turkey.1254
+ TSN Tswana_South Africa.1252
+ TTT Tatar_Russia.1251
+ UKR Ukrainian_Ukraine.1251
+ URD Urdu_Islamic Republic of Pakistan.1256
+ USA English_United States.1252
+ UZB Uzbek (Latin)_Uzbekistan.1254
+ VIT Vietnamese_Viet Nam.1258
+ XHO Xhosa_South Africa.1252
+ ZHH Chinese_Hong Kong S.A.R..950
+ ZHI Chinese_Singapore.936
+ ZHM Chinese_Macau S.A.R..950
+ ZUL Zulu_South Africa.1252
+ */
+
+/* Table from ISO 639 language code, optionally with country or script suffix,
+ to English name.
+ Keep in sync with the gl_locale_name_from_win32_LANGID function in
+ localename.c! */
+struct table_entry
+{
+ const char *code;
+ const char *english;
+};
+static const struct table_entry language_table[] =
+ {
+ { "af", "Afrikaans" },
+ { "am", "Amharic" },
+ { "ar", "Arabic" },
+ { "arn", "Mapudungun" },
+ { "as", "Assamese" },
+ { "az@cyrillic", "Azeri (Cyrillic)" },
+ { "az@latin", "Azeri (Latin)" },
+ { "ba", "Bashkir" },
+ { "be", "Belarusian" },
+ { "ber", "Tamazight" },
+ { "ber@arabic", "Tamazight (Arabic)" },
+ { "ber@latin", "Tamazight (Latin)" },
+ { "bg", "Bulgarian" },
+ { "bin", "Edo" },
+ { "bn", "Bengali" },
+ { "bn_BD", "Bengali (Bangladesh)" },
+ { "bn_IN", "Bengali (India)" },
+ { "bnt", "Sutu" },
+ { "bo", "Tibetan" },
+ { "br", "Breton" },
+ { "bs", "BSB" }, /* "Bosnian (Latin)" */
+ { "bs@cyrillic", "BSC" }, /* Bosnian (Cyrillic) */
+ { "ca", "Catalan" },
+ { "chr", "Cherokee" },
+ { "co", "Corsican" },
+ { "cpe", "Hawaiian" },
+ { "cs", "Czech" },
+ { "cy", "Welsh" },
+ { "da", "Danish" },
+ { "de", "German" },
+ { "dsb", "Lower Sorbian" },
+ { "dv", "Divehi" },
+ { "el", "Greek" },
+ { "en", "English" },
+ { "es", "Spanish" },
+ { "et", "Estonian" },
+ { "eu", "Basque" },
+ { "fa", "Farsi" },
+ { "ff", "Fulfulde" },
+ { "fi", "Finnish" },
+ { "fo", "Faroese" }, /* "Faeroese" does not work */
+ { "fr", "French" },
+ { "fy", "Frisian" },
+ { "ga", "IRE" }, /* Gaelic (Ireland) */
+ { "gd", "Gaelic (Scotland)" },
+ { "gd", "Scottish Gaelic" },
+ { "gl", "Galician" },
+ { "gn", "Guarani" },
+ { "gsw", "Alsatian" },
+ { "gu", "Gujarati" },
+ { "ha", "Hausa" },
+ { "he", "Hebrew" },
+ { "hi", "Hindi" },
+ { "hr", "Croatian" },
+ { "hsb", "Upper Sorbian" },
+ { "hu", "Hungarian" },
+ { "hy", "Armenian" },
+ { "id", "Indonesian" },
+ { "ig", "Igbo" },
+ { "ii", "Yi" },
+ { "is", "Icelandic" },
+ { "it", "Italian" },
+ { "iu", "IUK" }, /* Inuktitut */
+ { "ja", "Japanese" },
+ { "ka", "Georgian" },
+ { "kk", "Kazakh" },
+ { "kl", "Greenlandic" },
+ { "km", "Cambodian" },
+ { "km", "Khmer" },
+ { "kn", "Kannada" },
+ { "ko", "Korean" },
+ { "kok", "Konkani" },
+ { "kr", "Kanuri" },
+ { "ks", "Kashmiri" },
+ { "ks_IN", "Kashmiri_India" },
+ { "ks_PK", "Kashmiri (Arabic)_Pakistan" },
+ { "ky", "Kyrgyz" },
+ { "la", "Latin" },
+ { "lb", "Luxembourgish" },
+ { "lo", "Lao" },
+ { "lt", "Lithuanian" },
+ { "lv", "Latvian" },
+ { "mi", "Maori" },
+ { "mk", "FYRO Macedonian" },
+ { "mk", "Macedonian" },
+ { "ml", "Malayalam" },
+ { "mn", "Mongolian" },
+ { "mni", "Manipuri" },
+ { "moh", "Mohawk" },
+ { "mr", "Marathi" },
+ { "ms", "Malay" },
+ { "mt", "Maltese" },
+ { "my", "Burmese" },
+ { "nb", "NOR" }, /* Norwegian Bokmål */
+ { "ne", "Nepali" },
+ { "nic", "Ibibio" },
+ { "nl", "Dutch" },
+ { "nn", "NON" }, /* Norwegian Nynorsk */
+ { "no", "Norwegian" },
+ { "nso", "Northern Sotho" },
+ { "nso", "Sepedi" },
+ { "oc", "Occitan" },
+ { "om", "Oromo" },
+ { "or", "Oriya" },
+ { "pa", "Punjabi" },
+ { "pap", "Papiamentu" },
+ { "pl", "Polish" },
+ { "prs", "Dari" },
+ { "ps", "Pashto" },
+ { "pt", "Portuguese" },
+ { "qu", "Quechua" },
+ { "qut", "K'iche'" },
+ { "rm", "Romansh" },
+ { "ro", "Romanian" },
+ { "ru", "Russian" },
+ { "rw", "Kinyarwanda" },
+ { "sa", "Sanskrit" },
+ { "sah", "Yakut" },
+ { "sd", "Sindhi" },
+ { "se", "Sami (Northern)" },
+ { "se", "Northern Sami" },
+ { "si", "Sinhalese" },
+ { "sk", "Slovak" },
+ { "sl", "Slovenian" },
+ { "sma", "Sami (Southern)" },
+ { "sma", "Southern Sami" },
+ { "smj", "Sami (Lule)" },
+ { "smj", "Lule Sami" },
+ { "smn", "Sami (Inari)" },
+ { "smn", "Inari Sami" },
+ { "sms", "Sami (Skolt)" },
+ { "sms", "Skolt Sami" },
+ { "so", "Somali" },
+ { "sq", "Albanian" },
+ { "sr", "Serbian (Latin)" },
+ { "sr@cyrillic", "SRB" }, /* Serbian (Cyrillic) */
+ { "sw", "Swahili" },
+ { "syr", "Syriac" },
+ { "ta", "Tamil" },
+ { "te", "Telugu" },
+ { "tg", "Tajik" },
+ { "th", "Thai" },
+ { "ti", "Tigrinya" },
+ { "tk", "Turkmen" },
+ { "tl", "Filipino" },
+ { "tn", "Tswana" },
+ { "tr", "Turkish" },
+ { "ts", "Tsonga" },
+ { "tt", "Tatar" },
+ { "ug", "Uighur" },
+ { "uk", "Ukrainian" },
+ { "ur", "Urdu" },
+ { "uz", "Uzbek" },
+ { "uz", "Uzbek (Latin)" },
+ { "uz@cyrillic", "Uzbek (Cyrillic)" },
+ { "ve", "Venda" },
+ { "vi", "Vietnamese" },
+ { "wen", "Sorbian" },
+ { "wo", "Wolof" },
+ { "xh", "Xhosa" },
+ { "yi", "Yiddish" },
+ { "yo", "Yoruba" },
+ { "zh", "Chinese" },
+ { "zu", "Zulu" }
+ };
+
+/* Table from ISO 3166 country code to English name.
+ Keep in sync with the gl_locale_name_from_win32_LANGID function in
+ localename.c! */
+static const struct table_entry country_table[] =
+ {
+ { "AE", "U.A.E." },
+ { "AF", "Afghanistan" },
+ { "AL", "Albania" },
+ { "AM", "Armenia" },
+ { "AN", "Netherlands Antilles" },
+ { "AR", "Argentina" },
+ { "AT", "Austria" },
+ { "AU", "Australia" },
+ { "AZ", "Azerbaijan" },
+ { "BA", "Bosnia and Herzegovina" },
+ { "BD", "Bangladesh" },
+ { "BE", "Belgium" },
+ { "BG", "Bulgaria" },
+ { "BH", "Bahrain" },
+ { "BN", "Brunei Darussalam" },
+ { "BO", "Bolivia" },
+ { "BR", "Brazil" },
+ { "BT", "Bhutan" },
+ { "BY", "Belarus" },
+ { "BZ", "Belize" },
+ { "CA", "Canada" },
+ { "CG", "Congo" },
+ { "CH", "Switzerland" },
+ { "CI", "Cote d'Ivoire" },
+ { "CL", "Chile" },
+ { "CM", "Cameroon" },
+ { "CN", "People's Republic of China" },
+ { "CO", "Colombia" },
+ { "CR", "Costa Rica" },
+ { "CS", "Serbia and Montenegro" },
+ { "CZ", "Czech Republic" },
+ { "DE", "Germany" },
+ { "DK", "Denmark" },
+ { "DO", "Dominican Republic" },
+ { "DZ", "Algeria" },
+ { "EC", "Ecuador" },
+ { "EE", "Estonia" },
+ { "EG", "Egypt" },
+ { "ER", "Eritrea" },
+ { "ES", "Spain" },
+ { "ET", "Ethiopia" },
+ { "FI", "Finland" },
+ { "FO", "Faroe Islands" },
+ { "FR", "France" },
+ { "GB", "United Kingdom" },
+ { "GD", "Caribbean" },
+ { "GE", "Georgia" },
+ { "GL", "Greenland" },
+ { "GR", "Greece" },
+ { "GT", "Guatemala" },
+ { "HK", "Hong Kong" },
+ { "HK", "Hong Kong S.A.R." },
+ { "HN", "Honduras" },
+ { "HR", "Croatia" },
+ { "HT", "Haiti" },
+ { "HU", "Hungary" },
+ { "ID", "Indonesia" },
+ { "IE", "Ireland" },
+ { "IL", "Israel" },
+ { "IN", "India" },
+ { "IQ", "Iraq" },
+ { "IR", "Iran" },
+ { "IS", "Iceland" },
+ { "IT", "Italy" },
+ { "JM", "Jamaica" },
+ { "JO", "Jordan" },
+ { "JP", "Japan" },
+ { "KE", "Kenya" },
+ { "KG", "Kyrgyzstan" },
+ { "KH", "Cambodia" },
+ { "KR", "South Korea" },
+ { "KW", "Kuwait" },
+ { "KZ", "Kazakhstan" },
+ { "LA", "Laos" },
+ { "LB", "Lebanon" },
+ { "LI", "Liechtenstein" },
+ { "LK", "Sri Lanka" },
+ { "LT", "Lithuania" },
+ { "LU", "Luxembourg" },
+ { "LV", "Latvia" },
+ { "LY", "Libya" },
+ { "MA", "Morocco" },
+ { "MC", "Principality of Monaco" },
+ { "MD", "Moldava" },
+ { "MD", "Moldova" },
+ { "ME", "Montenegro" },
+ { "MK", "Former Yugoslav Republic of Macedonia" },
+ { "ML", "Mali" },
+ { "MM", "Myanmar" },
+ { "MN", "Mongolia" },
+ { "MO", "Macau S.A.R." },
+ { "MT", "Malta" },
+ { "MV", "Maldives" },
+ { "MX", "Mexico" },
+ { "MY", "Malaysia" },
+ { "NG", "Nigeria" },
+ { "NI", "Nicaragua" },
+ { "NL", "Netherlands" },
+ { "NO", "Norway" },
+ { "NP", "Nepal" },
+ { "NZ", "New Zealand" },
+ { "OM", "Oman" },
+ { "PA", "Panama" },
+ { "PE", "Peru" },
+ { "PH", "Philippines" },
+ { "PK", "Islamic Republic of Pakistan" },
+ { "PL", "Poland" },
+ { "PR", "Puerto Rico" },
+ { "PT", "Portugal" },
+ { "PY", "Paraguay" },
+ { "QA", "Qatar" },
+ { "RE", "Reunion" },
+ { "RO", "Romania" },
+ { "RS", "Serbia" },
+ { "RU", "Russia" },
+ { "RW", "Rwanda" },
+ { "SA", "Saudi Arabia" },
+ { "SE", "Sweden" },
+ { "SG", "Singapore" },
+ { "SI", "Slovenia" },
+ { "SK", "Slovak" },
+ { "SN", "Senegal" },
+ { "SO", "Somalia" },
+ { "SR", "Suriname" },
+ { "SV", "El Salvador" },
+ { "SY", "Syria" },
+ { "TH", "Thailand" },
+ { "TJ", "Tajikistan" },
+ { "TM", "Turkmenistan" },
+ { "TN", "Tunisia" },
+ { "TR", "Turkey" },
+ { "TT", "Trinidad and Tobago" },
+ { "TW", "Taiwan" },
+ { "TZ", "Tanzania" },
+ { "UA", "Ukraine" },
+ { "US", "United States" },
+ { "UY", "Uruguay" },
+ { "VA", "Vatican" },
+ { "VE", "Venezuela" },
+ { "VN", "Viet Nam" },
+ { "YE", "Yemen" },
+ { "ZA", "South Africa" },
+ { "ZW", "Zimbabwe" }
+ };
+
+/* Given a string STRING, find the set of indices i such that TABLE[i].code is
+ the given STRING. It is a range [lo,hi-1]. */
+typedef struct { size_t lo; size_t hi; } range_t;
+static void
+search (const struct table_entry *table, size_t table_size, const char *string,
+ range_t *result)
+{
+ /* The table is sorted. Perform a binary search. */
+ size_t hi = table_size;
+ size_t lo = 0;
+ while (lo < hi)
+ {
+ /* Invariant:
+ for i < lo, strcmp (table[i].code, string) < 0,
+ for i >= hi, strcmp (table[i].code, string) > 0. */
+ size_t mid = (hi + lo) >> 1; /* >= lo, < hi */
+ int cmp = strcmp (table[mid].code, string);
+ if (cmp < 0)
+ lo = mid + 1;
+ else if (cmp > 0)
+ hi = mid;
+ else
+ {
+ /* Found an i with
+ strcmp (language_table[i].code, string) == 0.
+ Find the entire interval of such i. */
+ {
+ size_t i;
+
+ for (i = mid; i > lo; )
+ {
+ i--;
+ if (strcmp (table[i].code, string) < 0)
+ {
+ lo = i + 1;
+ break;
+ }
+ }
+ }
+ {
+ size_t i;
+
+ for (i = mid; i < hi; i++)
+ {
+ if (strcmp (table[i].code, string) > 0)
+ {
+ hi = i;
+ break;
+ }
+ }
+ }
+ /* The set of i with
+ strcmp (language_table[i].code, string) == 0
+ is the interval [lo, hi-1]. */
+ break;
+ }
+ }
+ result->lo = lo;
+ result->hi = hi;
+}
+
+/* Like setlocale, but accept also locale names in the form ll or ll_CC,
+ where ll is an ISO 639 language code and CC is an ISO 3166 country code. */
+static char *
+setlocale_unixlike (int category, const char *locale)
+{
+ char *result;
+ char llCC_buf[64];
+ char ll_buf[64];
+ char CC_buf[64];
+
+ /* First, try setlocale with the original argument unchanged. */
+ result = setlocale (category, locale);
+ if (result != NULL)
+ return result;
+
+ /* Otherwise, assume the argument is in the form
+ language[_territory][.codeset][@modifier]
+ and try to map it using the tables. */
+ if (strlen (locale) < sizeof (llCC_buf))
+ {
+ /* Second try: Remove the codeset part. */
+ {
+ const char *p = locale;
+ char *q = llCC_buf;
+
+ /* Copy the part before the dot. */
+ for (; *p != '\0' && *p != '.'; p++, q++)
+ *q = *p;
+ if (*p == '.')
+ /* Skip the part up to the '@', if any. */
+ for (; *p != '\0' && *p != '@'; p++)
+ ;
+ /* Copy the part starting with '@', if any. */
+ for (; *p != '\0'; p++, q++)
+ *q = *p;
+ *q = '\0';
+ }
+ /* llCC_buf now contains
+ language[_territory][@modifier]
+ */
+ if (strcmp (llCC_buf, locale) != 0)
+ {
+ result = setlocale (category, llCC_buf);
+ if (result != NULL)
+ return result;
+ }
+ /* Look it up in language_table. */
+ {
+ range_t range;
+ size_t i;
+
+ search (language_table,
+ sizeof (language_table) / sizeof (language_table[0]),
+ llCC_buf,
+ &range);
+
+ for (i = range.lo; i < range.hi; i++)
+ {
+ /* Try the replacement in language_table[i]. */
+ result = setlocale (category, language_table[i].english);
+ if (result != NULL)
+ return result;
+ }
+ }
+ /* Split language[_territory][@modifier]
+ into ll_buf = language[@modifier]
+ and CC_buf = territory
+ */
+ {
+ const char *underscore = strchr (llCC_buf, '_');
+ if (underscore != NULL)
+ {
+ const char *territory_start = underscore + 1;
+ const char *territory_end = strchr (territory_start, '@');
+ if (territory_end == NULL)
+ territory_end = territory_start + strlen (territory_start);
+
+ memcpy (ll_buf, llCC_buf, underscore - llCC_buf);
+ strcpy (ll_buf + (underscore - llCC_buf), territory_end);
+
+ memcpy (CC_buf, territory_start, territory_end - territory_start);
+ CC_buf[territory_end - territory_start] = '\0';
+
+ {
+ /* Look up ll_buf in language_table
+ and CC_buf in country_table. */
+ range_t language_range;
+
+ search (language_table,
+ sizeof (language_table) / sizeof (language_table[0]),
+ ll_buf,
+ &language_range);
+ if (language_range.lo < language_range.hi)
+ {
+ range_t country_range;
+
+ search (country_table,
+ sizeof (country_table) / sizeof (country_table[0]),
+ CC_buf,
+ &country_range);
+ if (country_range.lo < country_range.hi)
+ {
+ size_t i;
+ size_t j;
+
+ for (i = language_range.lo; i < language_range.hi; i++)
+ for (j = country_range.lo; j < country_range.hi; j++)
+ {
+ /* Concatenate the replacements. */
+ const char *part1 = language_table[i].english;
+ size_t part1_len = strlen (part1);
+ const char *part2 = country_table[j].english;
+ size_t part2_len = strlen (part2) + 1;
+ char buf[64+64];
+
+ if (!(part1_len + 1 + part2_len <= sizeof (buf)))
+ abort ();
+ memcpy (buf, part1, part1_len);
+ buf[part1_len] = '_';
+ memcpy (buf + part1_len + 1, part2, part2_len);
+
+ /* Try the concatenated replacements. */
+ result = setlocale (category, buf);
+ if (result != NULL)
+ return result;
+ }
+ }
+
+ /* Try omitting the country entirely. This may set a locale
+ corresponding to the wrong country, but is better than
+ failing entirely. */
+ {
+ size_t i;
+
+ for (i = language_range.lo; i < language_range.hi; i++)
+ {
+ /* Try only the language replacement. */
+ result =
+ setlocale (category, language_table[i].english);
+ if (result != NULL)
+ return result;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Failed. */
+ return NULL;
+}
+
+# else
+# define setlocale_unixlike setlocale
+# endif
+
+# if LC_MESSAGES == 1729
+
+/* The system does not store an LC_MESSAGES locale category. Do it here. */
+static char lc_messages_name[64] = "C";
+
+/* Like setlocale, but support also LC_MESSAGES. */
+static char *
+setlocale_single (int category, const char *locale)
+{
+ if (category == LC_MESSAGES)
+ {
+ if (locale != NULL)
+ {
+ lc_messages_name[sizeof (lc_messages_name) - 1] = '\0';
+ strncpy (lc_messages_name, locale, sizeof (lc_messages_name) - 1);
+ }
+ return lc_messages_name;
+ }
+ else
+ return setlocale_unixlike (category, locale);
+}
+
+# else
+# define setlocale_single setlocale_unixlike
+# endif
+
+DLL_EXPORTED
+char *
+libintl_setlocale (int category, const char *locale)
+{
+ if (locale != NULL && locale[0] == '\0')
+ {
+ /* A request to the set the current locale to the default locale. */
+ if (category == LC_ALL)
+ {
+ /* Set LC_CTYPE first. Then the other categories. */
+ static int const categories[] =
+ {
+ LC_NUMERIC,
+ LC_TIME,
+ LC_COLLATE,
+ LC_MONETARY,
+ LC_MESSAGES
+ };
+ char *saved_locale;
+ const char *base_name;
+ unsigned int i;
+
+ /* Back up the old locale, in case one of the steps fails. */
+ saved_locale = setlocale (LC_ALL, NULL);
+ if (saved_locale == NULL)
+ return NULL;
+ saved_locale = strdup (saved_locale);
+ if (saved_locale == NULL)
+ return NULL;
+
+ /* Set LC_CTYPE category. Set all other categories (except possibly
+ LC_MESSAGES) to the same value in the same call; this is likely to
+ save calls. */
+ base_name =
+ gl_locale_name_environ (LC_CTYPE, category_to_name (LC_CTYPE));
+ if (base_name == NULL)
+ base_name = gl_locale_name_default ();
+
+ if (setlocale_unixlike (LC_ALL, base_name) == NULL)
+ goto fail;
+
+ for (i = 0; i < sizeof (categories) / sizeof (categories[0]); i++)
+ {
+ int cat = categories[i];
+ const char *name;
+
+ name = gl_locale_name_environ (cat, category_to_name (cat));
+ if (name == NULL)
+ name = gl_locale_name_default ();
+
+ /* If name is the same as base_name, it has already been set
+ through the setlocale call before the loop. */
+ if (strcmp (name, base_name) != 0
+# if LC_MESSAGES == 1729
+ || cat == LC_MESSAGES
+# endif
+ )
+ if (setlocale_single (cat, name) == NULL)
+ goto fail;
+ }
+
+ /* All steps were successful. */
+ free (saved_locale);
+ return setlocale (LC_ALL, NULL);
+
+ fail:
+ if (saved_locale[0] != '\0') /* don't risk an endless recursion */
+ setlocale (LC_ALL, saved_locale);
+ free (saved_locale);
+ return NULL;
+ }
+ else
+ {
+ const char *name =
+ gl_locale_name_environ (category, category_to_name (category));
+ if (name == NULL)
+ name = gl_locale_name_default ();
+
+ return setlocale_single (category, name);
+ }
+ }
+ else
+ return setlocale_single (category, locale);
+}
+
+# if HAVE_NEWLOCALE
+
+DLL_EXPORTED
+locale_t
+libintl_newlocale (int category_mask, const char *locale, locale_t base)
+{
+ if (category_mask != 0 && locale != NULL && locale[0] == '\0')
+ {
+ /* A request to construct a locale_t object that refers to the default
+ locale. */
+
+ /* Set LC_CTYPE first. Then the other categories. */
+ static struct { int cat; int mask; } const categories[] =
+ {
+ { LC_CTYPE, LC_CTYPE_MASK },
+ { LC_NUMERIC, LC_NUMERIC_MASK },
+ { LC_TIME, LC_TIME_MASK },
+ { LC_COLLATE, LC_COLLATE_MASK },
+ { LC_MONETARY, LC_MONETARY_MASK },
+ { LC_MESSAGES, LC_MESSAGES_MASK }
+ };
+
+ locale_t orig_base = base;
+
+ if ((LC_ALL_MASK & ~category_mask) == 0)
+ {
+ const char *base_name;
+ unsigned int i;
+
+ /* Set LC_CTYPE category. Set all other categories (except possibly
+ LC_MESSAGES) to the same value in the same call; this is likely to
+ save calls. */
+ base_name =
+ gl_locale_name_environ (LC_CTYPE, category_to_name (LC_CTYPE));
+ if (base_name == NULL)
+ base_name = gl_locale_name_default ();
+
+ base = newlocale (LC_ALL_MASK, base_name, base);
+ if (base == NULL)
+ return NULL;
+
+ for (i = 1; i < sizeof (categories) / sizeof (categories[0]); i++)
+ {
+ int category = categories[i].cat;
+ int category_mask = categories[i].mask;
+ const char *name;
+
+ name =
+ gl_locale_name_environ (category, category_to_name (category));
+ if (name == NULL)
+ name = gl_locale_name_default ();
+
+ /* If name is the same as base_name, it has already been set
+ through the setlocale call before the loop. */
+ if (strcmp (name, base_name) != 0)
+ {
+ locale_t copy = newlocale (category_mask, name, base);
+ if (copy == NULL)
+ goto fail;
+ /* No need to call freelocale (base) if copy != base; the
+ newlocale function already takes care of doing it. */
+ base = copy;
+ }
+ }
+ }
+ else
+ {
+ unsigned int i;
+
+ for (i = 0; i < sizeof (categories) / sizeof (categories[0]); i++)
+ {
+ int cat_mask = categories[i].mask;
+
+ if ((category_mask & cat_mask) != 0)
+ {
+ int cat = categories[i].cat;
+ const char *name;
+ locale_t copy;
+
+ name = gl_locale_name_environ (cat, category_to_name (cat));
+ if (name == NULL)
+ name = gl_locale_name_default ();
+
+ copy = newlocale (cat_mask, name, base);
+ if (copy == NULL)
+ goto fail;
+ /* No need to call freelocale (base) if copy != base; the
+ newlocale function already takes care of doing it. */
+ base = copy;
+ }
+ }
+ }
+
+ /* All steps were successful. */
+ return base;
+
+ fail:
+ if (base != NULL && orig_base == NULL)
+ {
+ int saved_errno = errno;
+ freelocale (base);
+ errno = saved_errno;
+ }
+ return NULL;
+ }
+ else
+ return newlocale (category_mask, locale, base);
+}
+
+# endif
+
+#endif
diff --git a/intl/textdomain.c b/intl/textdomain.c
new file mode 100644
index 00000000..70131bc8
--- /dev/null
+++ b/intl/textdomain.c
@@ -0,0 +1,127 @@
+/* Implementation of the textdomain(3) function.
+ Copyright (C) 1995-1998, 2000-2003, 2005-2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "gettextP.h"
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+/* Handle multi-threaded applications. */
+#ifdef _LIBC
+# include <bits/libc-lock.h>
+# define gl_rwlock_define __libc_rwlock_define
+# define gl_rwlock_wrlock __libc_rwlock_wrlock
+# define gl_rwlock_unlock __libc_rwlock_unlock
+#else
+# include "lock.h"
+#endif
+
+/* @@ end of prolog @@ */
+
+
+/* Names for the libintl functions are a problem. They must not clash
+ with existing names and they should follow ANSI C. But this source
+ code is also used in GNU C Library where the names have a __
+ prefix. So we have to make a difference here. */
+#ifdef _LIBC
+# define TEXTDOMAIN __textdomain
+# ifndef strdup
+# define strdup(str) __strdup (str)
+# endif
+#else
+# define TEXTDOMAIN libintl_textdomain
+#endif
+
+/* Lock variable to protect the global data in the gettext implementation. */
+gl_rwlock_define (extern, _nl_state_lock attribute_hidden)
+
+/* Set the current default message catalog to DOMAINNAME.
+ If DOMAINNAME is null, return the current default.
+ If DOMAINNAME is "", reset to the default of "messages". */
+char *
+TEXTDOMAIN (const char *domainname)
+{
+ char *new_domain;
+ char *old_domain;
+
+ /* A NULL pointer requests the current setting. */
+ if (domainname == NULL)
+ return (char *) _nl_current_default_domain;
+
+ gl_rwlock_wrlock (_nl_state_lock);
+
+ old_domain = (char *) _nl_current_default_domain;
+
+ /* If domain name is the null string set to default domain "messages". */
+ if (domainname[0] == '\0'
+ || strcmp (domainname, _nl_default_default_domain) == 0)
+ {
+ _nl_current_default_domain = _nl_default_default_domain;
+ new_domain = (char *) _nl_current_default_domain;
+ }
+ else if (strcmp (domainname, old_domain) == 0)
+ /* This can happen and people will use it to signal that some
+ environment variable changed. */
+ new_domain = old_domain;
+ else
+ {
+ /* If the following malloc fails `_nl_current_default_domain'
+ will be NULL. This value will be returned and so signals we
+ are out of core. */
+#if defined _LIBC || defined HAVE_STRDUP
+ new_domain = strdup (domainname);
+#else
+ size_t len = strlen (domainname) + 1;
+ new_domain = (char *) malloc (len);
+ if (new_domain != NULL)
+ memcpy (new_domain, domainname, len);
+#endif
+
+ if (new_domain != NULL)
+ _nl_current_default_domain = new_domain;
+ }
+
+ /* We use this possibility to signal a change of the loaded catalogs
+ since this is most likely the case and there is no other easy we
+ to do it. Do it only when the call was successful. */
+ if (new_domain != NULL)
+ {
+ ++_nl_msg_cat_cntr;
+
+ if (old_domain != new_domain && old_domain != _nl_default_default_domain)
+ free (old_domain);
+ }
+
+ gl_rwlock_unlock (_nl_state_lock);
+
+ return new_domain;
+}
+
+#ifdef _LIBC
+/* Alias for function name in GNU C Library. */
+weak_alias (__textdomain, textdomain);
+#endif
diff --git a/intl/threadlib.c b/intl/threadlib.c
new file mode 100644
index 00000000..cb4fe4f0
--- /dev/null
+++ b/intl/threadlib.c
@@ -0,0 +1,75 @@
+/* Multithreading primitives.
+ Copyright (C) 2005-2009 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2005. */
+
+#include <config.h>
+
+/* ========================================================================= */
+
+#if USE_POSIX_THREADS
+
+/* Use the POSIX threads library. */
+
+# include <pthread.h>
+# include <stdlib.h>
+
+# if PTHREAD_IN_USE_DETECTION_HARD
+
+/* The function to be executed by a dummy thread. */
+static void *
+dummy_thread_func (void *arg)
+{
+ return arg;
+}
+
+int
+glthread_in_use (void)
+{
+ static int tested;
+ static int result; /* 1: linked with -lpthread, 0: only with libc */
+
+ if (!tested)
+ {
+ pthread_t thread;
+
+ if (pthread_create (&thread, NULL, dummy_thread_func, NULL) != 0)
+ /* Thread creation failed. */
+ result = 0;
+ else
+ {
+ /* Thread creation works. */
+ void *retval;
+ if (pthread_join (thread, &retval) != 0)
+ abort ();
+ result = 1;
+ }
+ tested = 1;
+ }
+ return result;
+}
+
+# endif
+
+#endif
+
+/* ========================================================================= */
+
+/* This declaration is solely to ensure that after preprocessing
+ this file is never empty. */
+typedef int dummy;
diff --git a/intl/tsearch.c b/intl/tsearch.c
new file mode 100644
index 00000000..5f2da1b4
--- /dev/null
+++ b/intl/tsearch.c
@@ -0,0 +1,684 @@
+/* Copyright (C) 1995, 1996, 1997, 2000, 2006 Free Software Foundation, Inc.
+ Contributed by Bernd Schmidt <crux@Pool.Informatik.RWTH-Aachen.DE>, 1997.
+
+ NOTE: The canonical source of this file is maintained with the GNU C
+ Library. Bugs can be reported to bug-glibc@gnu.org.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+/* Tree search for red/black trees.
+ The algorithm for adding nodes is taken from one of the many "Algorithms"
+ books by Robert Sedgewick, although the implementation differs.
+ The algorithm for deleting nodes can probably be found in a book named
+ "Introduction to Algorithms" by Cormen/Leiserson/Rivest. At least that's
+ the book that my professor took most algorithms from during the "Data
+ Structures" course...
+
+ Totally public domain. */
+
+/* Red/black trees are binary trees in which the edges are colored either red
+ or black. They have the following properties:
+ 1. The number of black edges on every path from the root to a leaf is
+ constant.
+ 2. No two red edges are adjacent.
+ Therefore there is an upper bound on the length of every path, it's
+ O(log n) where n is the number of nodes in the tree. No path can be longer
+ than 1+2*P where P is the length of the shortest path in the tree.
+ Useful for the implementation:
+ 3. If one of the children of a node is NULL, then the other one is red
+ (if it exists).
+
+ In the implementation, not the edges are colored, but the nodes. The color
+ interpreted as the color of the edge leading to this node. The color is
+ meaningless for the root node, but we color the root node black for
+ convenience. All added nodes are red initially.
+
+ Adding to a red/black tree is rather easy. The right place is searched
+ with a usual binary tree search. Additionally, whenever a node N is
+ reached that has two red successors, the successors are colored black and
+ the node itself colored red. This moves red edges up the tree where they
+ pose less of a problem once we get to really insert the new node. Changing
+ N's color to red may violate rule 2, however, so rotations may become
+ necessary to restore the invariants. Adding a new red leaf may violate
+ the same rule, so afterwards an additional check is run and the tree
+ possibly rotated.
+
+ Deleting is hairy. There are mainly two nodes involved: the node to be
+ deleted (n1), and another node that is to be unchained from the tree (n2).
+ If n1 has a successor (the node with a smallest key that is larger than
+ n1), then the successor becomes n2 and its contents are copied into n1,
+ otherwise n1 becomes n2.
+ Unchaining a node may violate rule 1: if n2 is black, one subtree is
+ missing one black edge afterwards. The algorithm must try to move this
+ error upwards towards the root, so that the subtree that does not have
+ enough black edges becomes the whole tree. Once that happens, the error
+ has disappeared. It may not be necessary to go all the way up, since it
+ is possible that rotations and recoloring can fix the error before that.
+
+ Although the deletion algorithm must walk upwards through the tree, we
+ do not store parent pointers in the nodes. Instead, delete allocates a
+ small array of parent pointers and fills it while descending the tree.
+ Since we know that the length of a path is O(log n), where n is the number
+ of nodes, this is likely to use less memory. */
+
+/* Tree rotations look like this:
+ A C
+ / \ / \
+ B C A G
+ / \ / \ --> / \
+ D E F G B F
+ / \
+ D E
+
+ In this case, A has been rotated left. This preserves the ordering of the
+ binary tree. */
+
+#include <config.h>
+
+/* Specification. */
+#ifdef IN_LIBINTL
+# include "tsearch.h"
+#else
+# include <search.h>
+#endif
+
+#include <stdlib.h>
+
+typedef int (*__compar_fn_t) (const void *, const void *);
+typedef void (*__action_fn_t) (const void *, VISIT, int);
+
+#ifndef weak_alias
+# define __tsearch tsearch
+# define __tfind tfind
+# define __tdelete tdelete
+# define __twalk twalk
+#endif
+
+#ifndef internal_function
+/* Inside GNU libc we mark some function in a special way. In other
+ environments simply ignore the marking. */
+# define internal_function
+#endif
+
+typedef struct node_t
+{
+ /* Callers expect this to be the first element in the structure - do not
+ move! */
+ const void *key;
+ struct node_t *left;
+ struct node_t *right;
+ unsigned int red:1;
+} *node;
+typedef const struct node_t *const_node;
+
+#undef DEBUGGING
+
+#ifdef DEBUGGING
+
+/* Routines to check tree invariants. */
+
+#include <assert.h>
+
+#define CHECK_TREE(a) check_tree(a)
+
+static void
+check_tree_recurse (node p, int d_sofar, int d_total)
+{
+ if (p == NULL)
+ {
+ assert (d_sofar == d_total);
+ return;
+ }
+
+ check_tree_recurse (p->left, d_sofar + (p->left && !p->left->red), d_total);
+ check_tree_recurse (p->right, d_sofar + (p->right && !p->right->red), d_total);
+ if (p->left)
+ assert (!(p->left->red && p->red));
+ if (p->right)
+ assert (!(p->right->red && p->red));
+}
+
+static void
+check_tree (node root)
+{
+ int cnt = 0;
+ node p;
+ if (root == NULL)
+ return;
+ root->red = 0;
+ for(p = root->left; p; p = p->left)
+ cnt += !p->red;
+ check_tree_recurse (root, 0, cnt);
+}
+
+
+#else
+
+#define CHECK_TREE(a)
+
+#endif
+
+/* Possibly "split" a node with two red successors, and/or fix up two red
+ edges in a row. ROOTP is a pointer to the lowest node we visited, PARENTP
+ and GPARENTP pointers to its parent/grandparent. P_R and GP_R contain the
+ comparison values that determined which way was taken in the tree to reach
+ ROOTP. MODE is 1 if we need not do the split, but must check for two red
+ edges between GPARENTP and ROOTP. */
+static void
+maybe_split_for_insert (node *rootp, node *parentp, node *gparentp,
+ int p_r, int gp_r, int mode)
+{
+ node root = *rootp;
+ node *rp, *lp;
+ rp = &(*rootp)->right;
+ lp = &(*rootp)->left;
+
+ /* See if we have to split this node (both successors red). */
+ if (mode == 1
+ || ((*rp) != NULL && (*lp) != NULL && (*rp)->red && (*lp)->red))
+ {
+ /* This node becomes red, its successors black. */
+ root->red = 1;
+ if (*rp)
+ (*rp)->red = 0;
+ if (*lp)
+ (*lp)->red = 0;
+
+ /* If the parent of this node is also red, we have to do
+ rotations. */
+ if (parentp != NULL && (*parentp)->red)
+ {
+ node gp = *gparentp;
+ node p = *parentp;
+ /* There are two main cases:
+ 1. The edge types (left or right) of the two red edges differ.
+ 2. Both red edges are of the same type.
+ There exist two symmetries of each case, so there is a total of
+ 4 cases. */
+ if ((p_r > 0) != (gp_r > 0))
+ {
+ /* Put the child at the top of the tree, with its parent
+ and grandparent as successors. */
+ p->red = 1;
+ gp->red = 1;
+ root->red = 0;
+ if (p_r < 0)
+ {
+ /* Child is left of parent. */
+ p->left = *rp;
+ *rp = p;
+ gp->right = *lp;
+ *lp = gp;
+ }
+ else
+ {
+ /* Child is right of parent. */
+ p->right = *lp;
+ *lp = p;
+ gp->left = *rp;
+ *rp = gp;
+ }
+ *gparentp = root;
+ }
+ else
+ {
+ *gparentp = *parentp;
+ /* Parent becomes the top of the tree, grandparent and
+ child are its successors. */
+ p->red = 0;
+ gp->red = 1;
+ if (p_r < 0)
+ {
+ /* Left edges. */
+ gp->left = p->right;
+ p->right = gp;
+ }
+ else
+ {
+ /* Right edges. */
+ gp->right = p->left;
+ p->left = gp;
+ }
+ }
+ }
+ }
+}
+
+/* Find or insert datum into search tree.
+ KEY is the key to be located, ROOTP is the address of tree root,
+ COMPAR the ordering function. */
+void *
+__tsearch (const void *key, void **vrootp, __compar_fn_t compar)
+{
+ node q;
+ node *parentp = NULL, *gparentp = NULL;
+ node *rootp = (node *) vrootp;
+ node *nextp;
+ int r = 0, p_r = 0, gp_r = 0; /* No they might not, Mr Compiler. */
+
+ if (rootp == NULL)
+ return NULL;
+
+ /* This saves some additional tests below. */
+ if (*rootp != NULL)
+ (*rootp)->red = 0;
+
+ CHECK_TREE (*rootp);
+
+ nextp = rootp;
+ while (*nextp != NULL)
+ {
+ node root = *rootp;
+ r = (*compar) (key, root->key);
+ if (r == 0)
+ return root;
+
+ maybe_split_for_insert (rootp, parentp, gparentp, p_r, gp_r, 0);
+ /* If that did any rotations, parentp and gparentp are now garbage.
+ That doesn't matter, because the values they contain are never
+ used again in that case. */
+
+ nextp = r < 0 ? &root->left : &root->right;
+ if (*nextp == NULL)
+ break;
+
+ gparentp = parentp;
+ parentp = rootp;
+ rootp = nextp;
+
+ gp_r = p_r;
+ p_r = r;
+ }
+
+ q = (struct node_t *) malloc (sizeof (struct node_t));
+ if (q != NULL)
+ {
+ *nextp = q; /* link new node to old */
+ q->key = key; /* initialize new node */
+ q->red = 1;
+ q->left = q->right = NULL;
+
+ if (nextp != rootp)
+ /* There may be two red edges in a row now, which we must avoid by
+ rotating the tree. */
+ maybe_split_for_insert (nextp, rootp, parentp, r, p_r, 1);
+ }
+
+ return q;
+}
+#ifdef weak_alias
+weak_alias (__tsearch, tsearch)
+#endif
+
+
+/* Find datum in search tree.
+ KEY is the key to be located, ROOTP is the address of tree root,
+ COMPAR the ordering function. */
+void *
+__tfind (key, vrootp, compar)
+ const void *key;
+ void *const *vrootp;
+ __compar_fn_t compar;
+{
+ node *rootp = (node *) vrootp;
+
+ if (rootp == NULL)
+ return NULL;
+
+ CHECK_TREE (*rootp);
+
+ while (*rootp != NULL)
+ {
+ node root = *rootp;
+ int r;
+
+ r = (*compar) (key, root->key);
+ if (r == 0)
+ return root;
+
+ rootp = r < 0 ? &root->left : &root->right;
+ }
+ return NULL;
+}
+#ifdef weak_alias
+weak_alias (__tfind, tfind)
+#endif
+
+
+/* Delete node with given key.
+ KEY is the key to be deleted, ROOTP is the address of the root of tree,
+ COMPAR the comparison function. */
+void *
+__tdelete (const void *key, void **vrootp, __compar_fn_t compar)
+{
+ node p, q, r, retval;
+ int cmp;
+ node *rootp = (node *) vrootp;
+ node root, unchained;
+ /* Stack of nodes so we remember the parents without recursion. It's
+ _very_ unlikely that there are paths longer than 40 nodes. The tree
+ would need to have around 250.000 nodes. */
+ int stacksize = 100;
+ int sp = 0;
+ node *nodestack[100];
+
+ if (rootp == NULL)
+ return NULL;
+ p = *rootp;
+ if (p == NULL)
+ return NULL;
+
+ CHECK_TREE (p);
+
+ while ((cmp = (*compar) (key, (*rootp)->key)) != 0)
+ {
+ if (sp == stacksize)
+ abort ();
+
+ nodestack[sp++] = rootp;
+ p = *rootp;
+ rootp = ((cmp < 0)
+ ? &(*rootp)->left
+ : &(*rootp)->right);
+ if (*rootp == NULL)
+ return NULL;
+ }
+
+ /* This is bogus if the node to be deleted is the root... this routine
+ really should return an integer with 0 for success, -1 for failure
+ and errno = ESRCH or something. */
+ retval = p;
+
+ /* We don't unchain the node we want to delete. Instead, we overwrite
+ it with its successor and unchain the successor. If there is no
+ successor, we really unchain the node to be deleted. */
+
+ root = *rootp;
+
+ r = root->right;
+ q = root->left;
+
+ if (q == NULL || r == NULL)
+ unchained = root;
+ else
+ {
+ node *parent = rootp, *up = &root->right;
+ for (;;)
+ {
+ if (sp == stacksize)
+ abort ();
+ nodestack[sp++] = parent;
+ parent = up;
+ if ((*up)->left == NULL)
+ break;
+ up = &(*up)->left;
+ }
+ unchained = *up;
+ }
+
+ /* We know that either the left or right successor of UNCHAINED is NULL.
+ R becomes the other one, it is chained into the parent of UNCHAINED. */
+ r = unchained->left;
+ if (r == NULL)
+ r = unchained->right;
+ if (sp == 0)
+ *rootp = r;
+ else
+ {
+ q = *nodestack[sp-1];
+ if (unchained == q->right)
+ q->right = r;
+ else
+ q->left = r;
+ }
+
+ if (unchained != root)
+ root->key = unchained->key;
+ if (!unchained->red)
+ {
+ /* Now we lost a black edge, which means that the number of black
+ edges on every path is no longer constant. We must balance the
+ tree. */
+ /* NODESTACK now contains all parents of R. R is likely to be NULL
+ in the first iteration. */
+ /* NULL nodes are considered black throughout - this is necessary for
+ correctness. */
+ while (sp > 0 && (r == NULL || !r->red))
+ {
+ node *pp = nodestack[sp - 1];
+ p = *pp;
+ /* Two symmetric cases. */
+ if (r == p->left)
+ {
+ /* Q is R's brother, P is R's parent. The subtree with root
+ R has one black edge less than the subtree with root Q. */
+ q = p->right;
+ if (q->red)
+ {
+ /* If Q is red, we know that P is black. We rotate P left
+ so that Q becomes the top node in the tree, with P below
+ it. P is colored red, Q is colored black.
+ This action does not change the black edge count for any
+ leaf in the tree, but we will be able to recognize one
+ of the following situations, which all require that Q
+ is black. */
+ q->red = 0;
+ p->red = 1;
+ /* Left rotate p. */
+ p->right = q->left;
+ q->left = p;
+ *pp = q;
+ /* Make sure pp is right if the case below tries to use
+ it. */
+ nodestack[sp++] = pp = &q->left;
+ q = p->right;
+ }
+ /* We know that Q can't be NULL here. We also know that Q is
+ black. */
+ if ((q->left == NULL || !q->left->red)
+ && (q->right == NULL || !q->right->red))
+ {
+ /* Q has two black successors. We can simply color Q red.
+ The whole subtree with root P is now missing one black
+ edge. Note that this action can temporarily make the
+ tree invalid (if P is red). But we will exit the loop
+ in that case and set P black, which both makes the tree
+ valid and also makes the black edge count come out
+ right. If P is black, we are at least one step closer
+ to the root and we'll try again the next iteration. */
+ q->red = 1;
+ r = p;
+ }
+ else
+ {
+ /* Q is black, one of Q's successors is red. We can
+ repair the tree with one operation and will exit the
+ loop afterwards. */
+ if (q->right == NULL || !q->right->red)
+ {
+ /* The left one is red. We perform the same action as
+ in maybe_split_for_insert where two red edges are
+ adjacent but point in different directions:
+ Q's left successor (let's call it Q2) becomes the
+ top of the subtree we are looking at, its parent (Q)
+ and grandparent (P) become its successors. The former
+ successors of Q2 are placed below P and Q.
+ P becomes black, and Q2 gets the color that P had.
+ This changes the black edge count only for node R and
+ its successors. */
+ node q2 = q->left;
+ q2->red = p->red;
+ p->right = q2->left;
+ q->left = q2->right;
+ q2->right = q;
+ q2->left = p;
+ *pp = q2;
+ p->red = 0;
+ }
+ else
+ {
+ /* It's the right one. Rotate P left. P becomes black,
+ and Q gets the color that P had. Q's right successor
+ also becomes black. This changes the black edge
+ count only for node R and its successors. */
+ q->red = p->red;
+ p->red = 0;
+
+ q->right->red = 0;
+
+ /* left rotate p */
+ p->right = q->left;
+ q->left = p;
+ *pp = q;
+ }
+
+ /* We're done. */
+ sp = 1;
+ r = NULL;
+ }
+ }
+ else
+ {
+ /* Comments: see above. */
+ q = p->left;
+ if (q->red)
+ {
+ q->red = 0;
+ p->red = 1;
+ p->left = q->right;
+ q->right = p;
+ *pp = q;
+ nodestack[sp++] = pp = &q->right;
+ q = p->left;
+ }
+ if ((q->right == NULL || !q->right->red)
+ && (q->left == NULL || !q->left->red))
+ {
+ q->red = 1;
+ r = p;
+ }
+ else
+ {
+ if (q->left == NULL || !q->left->red)
+ {
+ node q2 = q->right;
+ q2->red = p->red;
+ p->left = q2->right;
+ q->right = q2->left;
+ q2->left = q;
+ q2->right = p;
+ *pp = q2;
+ p->red = 0;
+ }
+ else
+ {
+ q->red = p->red;
+ p->red = 0;
+ q->left->red = 0;
+ p->left = q->right;
+ q->right = p;
+ *pp = q;
+ }
+ sp = 1;
+ r = NULL;
+ }
+ }
+ --sp;
+ }
+ if (r != NULL)
+ r->red = 0;
+ }
+
+ free (unchained);
+ return retval;
+}
+#ifdef weak_alias
+weak_alias (__tdelete, tdelete)
+#endif
+
+
+/* Walk the nodes of a tree.
+ ROOT is the root of the tree to be walked, ACTION the function to be
+ called at each node. LEVEL is the level of ROOT in the whole tree. */
+static void
+internal_function
+trecurse (const void *vroot, __action_fn_t action, int level)
+{
+ const_node root = (const_node) vroot;
+
+ if (root->left == NULL && root->right == NULL)
+ (*action) (root, leaf, level);
+ else
+ {
+ (*action) (root, preorder, level);
+ if (root->left != NULL)
+ trecurse (root->left, action, level + 1);
+ (*action) (root, postorder, level);
+ if (root->right != NULL)
+ trecurse (root->right, action, level + 1);
+ (*action) (root, endorder, level);
+ }
+}
+
+
+/* Walk the nodes of a tree.
+ ROOT is the root of the tree to be walked, ACTION the function to be
+ called at each node. */
+void
+__twalk (const void *vroot, __action_fn_t action)
+{
+ const_node root = (const_node) vroot;
+
+ CHECK_TREE (root);
+
+ if (root != NULL && action != NULL)
+ trecurse (root, action, 0);
+}
+#ifdef weak_alias
+weak_alias (__twalk, twalk)
+#endif
+
+
+#ifdef _LIBC
+
+/* The standardized functions miss an important functionality: the
+ tree cannot be removed easily. We provide a function to do this. */
+static void
+internal_function
+tdestroy_recurse (node root, __free_fn_t freefct)
+{
+ if (root->left != NULL)
+ tdestroy_recurse (root->left, freefct);
+ if (root->right != NULL)
+ tdestroy_recurse (root->right, freefct);
+ (*freefct) ((void *) root->key);
+ /* Free the node itself. */
+ free (root);
+}
+
+void
+__tdestroy (void *vroot, __free_fn_t freefct)
+{
+ node root = (node) vroot;
+
+ CHECK_TREE (root);
+
+ if (root != NULL)
+ tdestroy_recurse (root, freefct);
+}
+weak_alias (__tdestroy, tdestroy)
+
+#endif /* _LIBC */
diff --git a/intl/tsearch.h b/intl/tsearch.h
new file mode 100644
index 00000000..3d3fd14c
--- /dev/null
+++ b/intl/tsearch.h
@@ -0,0 +1,83 @@
+/* Binary tree data structure.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifndef _TSEARCH_H
+#define _TSEARCH_H
+
+#if HAVE_TSEARCH
+
+/* Get tseach(), tfind(), tdelete(), twalk() declarations. */
+#include <search.h>
+
+#else
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* See <http://www.opengroup.org/susv3xbd/search.h.html>,
+ <http://www.opengroup.org/susv3xsh/tsearch.html>
+ for details. */
+
+typedef enum
+{
+ preorder,
+ postorder,
+ endorder,
+ leaf
+}
+VISIT;
+
+/* Searches an element in the tree *VROOTP that compares equal to KEY.
+ If one is found, it is returned. Otherwise, a new element equal to KEY
+ is inserted in the tree and is returned. */
+extern void * tsearch (const void *key, void **vrootp,
+ int (*compar) (const void *, const void *));
+
+/* Searches an element in the tree *VROOTP that compares equal to KEY.
+ If one is found, it is returned. Otherwise, NULL is returned. */
+extern void * tfind (const void *key, void *const *vrootp,
+ int (*compar) (const void *, const void *));
+
+/* Searches an element in the tree *VROOTP that compares equal to KEY.
+ If one is found, it is removed from the tree, and its parent node is
+ returned. Otherwise, NULL is returned. */
+extern void * tdelete (const void *key, void **vrootp,
+ int (*compar) (const void *, const void *));
+
+/* Perform a depth-first, left-to-right traversal of the tree VROOT.
+ The ACTION function is called:
+ - for non-leaf nodes: 3 times, before the left subtree traversal,
+ after the left subtree traversal but before the right subtree traversal,
+ and after the right subtree traversal,
+ - for leaf nodes: once.
+ The arguments passed to ACTION are:
+ 1. the node; it can be casted to a 'const void * const *', i.e. into a
+ pointer to the key,
+ 2. an indicator which visit of the node this is,
+ 3. the level of the node in the tree (0 for the root). */
+extern void twalk (const void *vroot,
+ void (*action) (const void *, VISIT, int));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#endif /* _TSEARCH_H */
diff --git a/intl/vasnprintf.c b/intl/vasnprintf.c
new file mode 100644
index 00000000..8a07ca6e
--- /dev/null
+++ b/intl/vasnprintf.c
@@ -0,0 +1,5568 @@
+/* vsprintf with automatic memory allocation.
+ Copyright (C) 1999, 2002-2010 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+/* This file can be parametrized with the following macros:
+ VASNPRINTF The name of the function being defined.
+ FCHAR_T The element type of the format string.
+ DCHAR_T The element type of the destination (result) string.
+ FCHAR_T_ONLY_ASCII Set to 1 to enable verification that all characters
+ in the format string are ASCII. MUST be set if
+ FCHAR_T and DCHAR_T are not the same type.
+ DIRECTIVE Structure denoting a format directive.
+ Depends on FCHAR_T.
+ DIRECTIVES Structure denoting the set of format directives of a
+ format string. Depends on FCHAR_T.
+ PRINTF_PARSE Function that parses a format string.
+ Depends on FCHAR_T.
+ DCHAR_CPY memcpy like function for DCHAR_T[] arrays.
+ DCHAR_SET memset like function for DCHAR_T[] arrays.
+ DCHAR_MBSNLEN mbsnlen like function for DCHAR_T[] arrays.
+ SNPRINTF The system's snprintf (or similar) function.
+ This may be either snprintf or swprintf.
+ TCHAR_T The element type of the argument and result string
+ of the said SNPRINTF function. This may be either
+ char or wchar_t. The code exploits that
+ sizeof (TCHAR_T) | sizeof (DCHAR_T) and
+ alignof (TCHAR_T) <= alignof (DCHAR_T).
+ DCHAR_IS_TCHAR Set to 1 if DCHAR_T and TCHAR_T are the same type.
+ DCHAR_CONV_FROM_ENCODING A function to convert from char[] to DCHAR[].
+ DCHAR_IS_UINT8_T Set to 1 if DCHAR_T is uint8_t.
+ DCHAR_IS_UINT16_T Set to 1 if DCHAR_T is uint16_t.
+ DCHAR_IS_UINT32_T Set to 1 if DCHAR_T is uint32_t. */
+
+/* Tell glibc's <stdio.h> to provide a prototype for snprintf().
+ This must come before <config.h> because <config.h> may include
+ <features.h>, and once <features.h> has been included, it's too late. */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE 1
+#endif
+
+#ifndef VASNPRINTF
+# include <config.h>
+#endif
+#ifndef IN_LIBINTL
+# include <alloca.h>
+#endif
+
+/* Specification. */
+#ifndef VASNPRINTF
+# if WIDE_CHAR_VERSION
+# include "vasnwprintf.h"
+# else
+# include "vasnprintf.h"
+# endif
+#endif
+
+#include <locale.h> /* localeconv() */
+#include <stdio.h> /* snprintf(), sprintf() */
+#include <stdlib.h> /* abort(), malloc(), realloc(), free() */
+#include <string.h> /* memcpy(), strlen() */
+#include <errno.h> /* errno */
+#include <limits.h> /* CHAR_BIT */
+#include <float.h> /* DBL_MAX_EXP, LDBL_MAX_EXP */
+#if HAVE_NL_LANGINFO
+# include <langinfo.h>
+#endif
+#ifndef VASNPRINTF
+# if WIDE_CHAR_VERSION
+# include "wprintf-parse.h"
+# else
+# include "printf-parse.h"
+# endif
+#endif
+
+/* Checked size_t computations. */
+#include "xsize.h"
+
+#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
+# include <math.h>
+# include "float+.h"
+#endif
+
+#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL
+# include <math.h>
+# include "isnand-nolibm.h"
+#endif
+
+#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE) && !defined IN_LIBINTL
+# include <math.h>
+# include "isnanl-nolibm.h"
+# include "fpucw.h"
+#endif
+
+#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
+# include <math.h>
+# include "isnand-nolibm.h"
+# include "printf-frexp.h"
+#endif
+
+#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
+# include <math.h>
+# include "isnanl-nolibm.h"
+# include "printf-frexpl.h"
+# include "fpucw.h"
+#endif
+
+/* Default parameters. */
+#ifndef VASNPRINTF
+# if WIDE_CHAR_VERSION
+# define VASNPRINTF vasnwprintf
+# define FCHAR_T wchar_t
+# define DCHAR_T wchar_t
+# define TCHAR_T wchar_t
+# define DCHAR_IS_TCHAR 1
+# define DIRECTIVE wchar_t_directive
+# define DIRECTIVES wchar_t_directives
+# define PRINTF_PARSE wprintf_parse
+# define DCHAR_CPY wmemcpy
+# define DCHAR_SET wmemset
+# else
+# define VASNPRINTF vasnprintf
+# define FCHAR_T char
+# define DCHAR_T char
+# define TCHAR_T char
+# define DCHAR_IS_TCHAR 1
+# define DIRECTIVE char_directive
+# define DIRECTIVES char_directives
+# define PRINTF_PARSE printf_parse
+# define DCHAR_CPY memcpy
+# define DCHAR_SET memset
+# endif
+#endif
+#if WIDE_CHAR_VERSION
+ /* TCHAR_T is wchar_t. */
+# define USE_SNPRINTF 1
+# if HAVE_DECL__SNWPRINTF
+ /* On Windows, the function swprintf() has a different signature than
+ on Unix; we use the function _snwprintf() or - on mingw - snwprintf()
+ instead. The mingw function snwprintf() has fewer bugs than the
+ MSVCRT function _snwprintf(), so prefer that. */
+# if defined __MINGW32__
+# define SNPRINTF snwprintf
+# else
+# define SNPRINTF _snwprintf
+# endif
+# else
+ /* Unix. */
+# define SNPRINTF swprintf
+# endif
+#else
+ /* TCHAR_T is char. */
+ /* Use snprintf if it exists under the name 'snprintf' or '_snprintf'.
+ But don't use it on BeOS, since BeOS snprintf produces no output if the
+ size argument is >= 0x3000000.
+ Also don't use it on Linux libc5, since there snprintf with size = 1
+ writes any output without bounds, like sprintf. */
+# if (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) && !defined __BEOS__ && !(__GNU_LIBRARY__ == 1)
+# define USE_SNPRINTF 1
+# else
+# define USE_SNPRINTF 0
+# endif
+# if HAVE_DECL__SNPRINTF
+ /* Windows. The mingw function snprintf() has fewer bugs than the MSVCRT
+ function _snprintf(), so prefer that. */
+# if defined __MINGW32__
+# define SNPRINTF snprintf
+ /* Here we need to call the native snprintf, not rpl_snprintf. */
+# undef snprintf
+# else
+# define SNPRINTF _snprintf
+# endif
+# else
+ /* Unix. */
+# define SNPRINTF snprintf
+ /* Here we need to call the native snprintf, not rpl_snprintf. */
+# undef snprintf
+# endif
+#endif
+/* Here we need to call the native sprintf, not rpl_sprintf. */
+#undef sprintf
+
+/* GCC >= 4.0 with -Wall emits unjustified "... may be used uninitialized"
+ warnings in this file. Use -Dlint to suppress them. */
+#ifdef lint
+# define IF_LINT(Code) Code
+#else
+# define IF_LINT(Code) /* empty */
+#endif
+
+/* Avoid some warnings from "gcc -Wshadow".
+ This file doesn't use the exp() and remainder() functions. */
+#undef exp
+#define exp expo
+#undef remainder
+#define remainder rem
+
+#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && !WIDE_CHAR_VERSION
+# if (HAVE_STRNLEN && !defined _AIX)
+# define local_strnlen strnlen
+# else
+# ifndef local_strnlen_defined
+# define local_strnlen_defined 1
+static size_t
+local_strnlen (const char *string, size_t maxlen)
+{
+ const char *end = memchr (string, '\0', maxlen);
+ return end ? (size_t) (end - string) : maxlen;
+}
+# endif
+# endif
+#endif
+
+#if (((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && WIDE_CHAR_VERSION) || ((!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && !WIDE_CHAR_VERSION && DCHAR_IS_TCHAR)) && HAVE_WCHAR_T
+# if HAVE_WCSLEN
+# define local_wcslen wcslen
+# else
+ /* Solaris 2.5.1 has wcslen() in a separate library libw.so. To avoid
+ a dependency towards this library, here is a local substitute.
+ Define this substitute only once, even if this file is included
+ twice in the same compilation unit. */
+# ifndef local_wcslen_defined
+# define local_wcslen_defined 1
+static size_t
+local_wcslen (const wchar_t *s)
+{
+ const wchar_t *ptr;
+
+ for (ptr = s; *ptr != (wchar_t) 0; ptr++)
+ ;
+ return ptr - s;
+}
+# endif
+# endif
+#endif
+
+#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99) && HAVE_WCHAR_T && WIDE_CHAR_VERSION
+# if HAVE_WCSNLEN
+# define local_wcsnlen wcsnlen
+# else
+# ifndef local_wcsnlen_defined
+# define local_wcsnlen_defined 1
+static size_t
+local_wcsnlen (const wchar_t *s, size_t maxlen)
+{
+ const wchar_t *ptr;
+
+ for (ptr = s; maxlen > 0 && *ptr != (wchar_t) 0; ptr++, maxlen--)
+ ;
+ return ptr - s;
+}
+# endif
+# endif
+#endif
+
+#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL
+/* Determine the decimal-point character according to the current locale. */
+# ifndef decimal_point_char_defined
+# define decimal_point_char_defined 1
+static char
+decimal_point_char (void)
+{
+ const char *point;
+ /* Determine it in a multithread-safe way. We know nl_langinfo is
+ multithread-safe on glibc systems and MacOS X systems, but is not required
+ to be multithread-safe by POSIX. sprintf(), however, is multithread-safe.
+ localeconv() is rarely multithread-safe. */
+# if HAVE_NL_LANGINFO && (__GLIBC__ || (defined __APPLE__ && defined __MACH__))
+ point = nl_langinfo (RADIXCHAR);
+# elif 1
+ char pointbuf[5];
+ sprintf (pointbuf, "%#.0f", 1.0);
+ point = &pointbuf[1];
+# else
+ point = localeconv () -> decimal_point;
+# endif
+ /* The decimal point is always a single byte: either '.' or ','. */
+ return (point[0] != '\0' ? point[0] : '.');
+}
+# endif
+#endif
+
+#if NEED_PRINTF_INFINITE_DOUBLE && !NEED_PRINTF_DOUBLE && !defined IN_LIBINTL
+
+/* Equivalent to !isfinite(x) || x == 0, but does not require libm. */
+static int
+is_infinite_or_zero (double x)
+{
+ return isnand (x) || x + x == x;
+}
+
+#endif
+
+#if NEED_PRINTF_INFINITE_LONG_DOUBLE && !NEED_PRINTF_LONG_DOUBLE && !defined IN_LIBINTL
+
+/* Equivalent to !isfinite(x) || x == 0, but does not require libm. */
+static int
+is_infinite_or_zerol (long double x)
+{
+ return isnanl (x) || x + x == x;
+}
+
+#endif
+
+#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
+
+/* Converting 'long double' to decimal without rare rounding bugs requires
+ real bignums. We use the naming conventions of GNU gmp, but vastly simpler
+ (and slower) algorithms. */
+
+typedef unsigned int mp_limb_t;
+# define GMP_LIMB_BITS 32
+typedef int mp_limb_verify[2 * (sizeof (mp_limb_t) * CHAR_BIT == GMP_LIMB_BITS) - 1];
+
+typedef unsigned long long mp_twolimb_t;
+# define GMP_TWOLIMB_BITS 64
+typedef int mp_twolimb_verify[2 * (sizeof (mp_twolimb_t) * CHAR_BIT == GMP_TWOLIMB_BITS) - 1];
+
+/* Representation of a bignum >= 0. */
+typedef struct
+{
+ size_t nlimbs;
+ mp_limb_t *limbs; /* Bits in little-endian order, allocated with malloc(). */
+} mpn_t;
+
+/* Compute the product of two bignums >= 0.
+ Return the allocated memory in case of success, NULL in case of memory
+ allocation failure. */
+static void *
+multiply (mpn_t src1, mpn_t src2, mpn_t *dest)
+{
+ const mp_limb_t *p1;
+ const mp_limb_t *p2;
+ size_t len1;
+ size_t len2;
+
+ if (src1.nlimbs <= src2.nlimbs)
+ {
+ len1 = src1.nlimbs;
+ p1 = src1.limbs;
+ len2 = src2.nlimbs;
+ p2 = src2.limbs;
+ }
+ else
+ {
+ len1 = src2.nlimbs;
+ p1 = src2.limbs;
+ len2 = src1.nlimbs;
+ p2 = src1.limbs;
+ }
+ /* Now 0 <= len1 <= len2. */
+ if (len1 == 0)
+ {
+ /* src1 or src2 is zero. */
+ dest->nlimbs = 0;
+ dest->limbs = (mp_limb_t *) malloc (1);
+ }
+ else
+ {
+ /* Here 1 <= len1 <= len2. */
+ size_t dlen;
+ mp_limb_t *dp;
+ size_t k, i, j;
+
+ dlen = len1 + len2;
+ dp = (mp_limb_t *) malloc (dlen * sizeof (mp_limb_t));
+ if (dp == NULL)
+ return NULL;
+ for (k = len2; k > 0; )
+ dp[--k] = 0;
+ for (i = 0; i < len1; i++)
+ {
+ mp_limb_t digit1 = p1[i];
+ mp_twolimb_t carry = 0;
+ for (j = 0; j < len2; j++)
+ {
+ mp_limb_t digit2 = p2[j];
+ carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2;
+ carry += dp[i + j];
+ dp[i + j] = (mp_limb_t) carry;
+ carry = carry >> GMP_LIMB_BITS;
+ }
+ dp[i + len2] = (mp_limb_t) carry;
+ }
+ /* Normalise. */
+ while (dlen > 0 && dp[dlen - 1] == 0)
+ dlen--;
+ dest->nlimbs = dlen;
+ dest->limbs = dp;
+ }
+ return dest->limbs;
+}
+
+/* Compute the quotient of a bignum a >= 0 and a bignum b > 0.
+ a is written as a = q * b + r with 0 <= r < b. q is the quotient, r
+ the remainder.
+ Finally, round-to-even is performed: If r > b/2 or if r = b/2 and q is odd,
+ q is incremented.
+ Return the allocated memory in case of success, NULL in case of memory
+ allocation failure. */
+static void *
+divide (mpn_t a, mpn_t b, mpn_t *q)
+{
+ /* Algorithm:
+ First normalise a and b: a=[a[m-1],...,a[0]], b=[b[n-1],...,b[0]]
+ with m>=0 and n>0 (in base beta = 2^GMP_LIMB_BITS).
+ If m<n, then q:=0 and r:=a.
+ If m>=n=1, perform a single-precision division:
+ r:=0, j:=m,
+ while j>0 do
+ {Here (q[m-1]*beta^(m-1)+...+q[j]*beta^j) * b[0] + r*beta^j =
+ = a[m-1]*beta^(m-1)+...+a[j]*beta^j und 0<=r<b[0]<beta}
+ j:=j-1, r:=r*beta+a[j], q[j]:=floor(r/b[0]), r:=r-b[0]*q[j].
+ Normalise [q[m-1],...,q[0]], yields q.
+ If m>=n>1, perform a multiple-precision division:
+ We have a/b < beta^(m-n+1).
+ s:=intDsize-1-(highest bit in b[n-1]), 0<=s<intDsize.
+ Shift a and b left by s bits, copying them. r:=a.
+ r=[r[m],...,r[0]], b=[b[n-1],...,b[0]] with b[n-1]>=beta/2.
+ For j=m-n,...,0: {Here 0 <= r < b*beta^(j+1).}
+ Compute q* :
+ q* := floor((r[j+n]*beta+r[j+n-1])/b[n-1]).
+ In case of overflow (q* >= beta) set q* := beta-1.
+ Compute c2 := ((r[j+n]*beta+r[j+n-1]) - q* * b[n-1])*beta + r[j+n-2]
+ and c3 := b[n-2] * q*.
+ {We have 0 <= c2 < 2*beta^2, even 0 <= c2 < beta^2 if no overflow
+ occurred. Furthermore 0 <= c3 < beta^2.
+ If there was overflow and
+ r[j+n]*beta+r[j+n-1] - q* * b[n-1] >= beta, i.e. c2 >= beta^2,
+ the next test can be skipped.}
+ While c3 > c2, {Here 0 <= c2 < c3 < beta^2}
+ Put q* := q* - 1, c2 := c2 + b[n-1]*beta, c3 := c3 - b[n-2].
+ If q* > 0:
+ Put r := r - b * q* * beta^j. In detail:
+ [r[n+j],...,r[j]] := [r[n+j],...,r[j]] - q* * [b[n-1],...,b[0]].
+ hence: u:=0, for i:=0 to n-1 do
+ u := u + q* * b[i],
+ r[j+i]:=r[j+i]-(u mod beta) (+ beta, if carry),
+ u:=u div beta (+ 1, if carry in subtraction)
+ r[n+j]:=r[n+j]-u.
+ {Since always u = (q* * [b[i-1],...,b[0]] div beta^i) + 1
+ < q* + 1 <= beta,
+ the carry u does not overflow.}
+ If a negative carry occurs, put q* := q* - 1
+ and [r[n+j],...,r[j]] := [r[n+j],...,r[j]] + [0,b[n-1],...,b[0]].
+ Set q[j] := q*.
+ Normalise [q[m-n],..,q[0]]; this yields the quotient q.
+ Shift [r[n-1],...,r[0]] right by s bits and normalise; this yields the
+ rest r.
+ The room for q[j] can be allocated at the memory location of r[n+j].
+ Finally, round-to-even:
+ Shift r left by 1 bit.
+ If r > b or if r = b and q[0] is odd, q := q+1.
+ */
+ const mp_limb_t *a_ptr = a.limbs;
+ size_t a_len = a.nlimbs;
+ const mp_limb_t *b_ptr = b.limbs;
+ size_t b_len = b.nlimbs;
+ mp_limb_t *roomptr;
+ mp_limb_t *tmp_roomptr = NULL;
+ mp_limb_t *q_ptr;
+ size_t q_len;
+ mp_limb_t *r_ptr;
+ size_t r_len;
+
+ /* Allocate room for a_len+2 digits.
+ (Need a_len+1 digits for the real division and 1 more digit for the
+ final rounding of q.) */
+ roomptr = (mp_limb_t *) malloc ((a_len + 2) * sizeof (mp_limb_t));
+ if (roomptr == NULL)
+ return NULL;
+
+ /* Normalise a. */
+ while (a_len > 0 && a_ptr[a_len - 1] == 0)
+ a_len--;
+
+ /* Normalise b. */
+ for (;;)
+ {
+ if (b_len == 0)
+ /* Division by zero. */
+ abort ();
+ if (b_ptr[b_len - 1] == 0)
+ b_len--;
+ else
+ break;
+ }
+
+ /* Here m = a_len >= 0 and n = b_len > 0. */
+
+ if (a_len < b_len)
+ {
+ /* m<n: trivial case. q=0, r := copy of a. */
+ r_ptr = roomptr;
+ r_len = a_len;
+ memcpy (r_ptr, a_ptr, a_len * sizeof (mp_limb_t));
+ q_ptr = roomptr + a_len;
+ q_len = 0;
+ }
+ else if (b_len == 1)
+ {
+ /* n=1: single precision division.
+ beta^(m-1) <= a < beta^m ==> beta^(m-2) <= a/b < beta^m */
+ r_ptr = roomptr;
+ q_ptr = roomptr + 1;
+ {
+ mp_limb_t den = b_ptr[0];
+ mp_limb_t remainder = 0;
+ const mp_limb_t *sourceptr = a_ptr + a_len;
+ mp_limb_t *destptr = q_ptr + a_len;
+ size_t count;
+ for (count = a_len; count > 0; count--)
+ {
+ mp_twolimb_t num =
+ ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--sourceptr;
+ *--destptr = num / den;
+ remainder = num % den;
+ }
+ /* Normalise and store r. */
+ if (remainder > 0)
+ {
+ r_ptr[0] = remainder;
+ r_len = 1;
+ }
+ else
+ r_len = 0;
+ /* Normalise q. */
+ q_len = a_len;
+ if (q_ptr[q_len - 1] == 0)
+ q_len--;
+ }
+ }
+ else
+ {
+ /* n>1: multiple precision division.
+ beta^(m-1) <= a < beta^m, beta^(n-1) <= b < beta^n ==>
+ beta^(m-n-1) <= a/b < beta^(m-n+1). */
+ /* Determine s. */
+ size_t s;
+ {
+ mp_limb_t msd = b_ptr[b_len - 1]; /* = b[n-1], > 0 */
+ s = 31;
+ if (msd >= 0x10000)
+ {
+ msd = msd >> 16;
+ s -= 16;
+ }
+ if (msd >= 0x100)
+ {
+ msd = msd >> 8;
+ s -= 8;
+ }
+ if (msd >= 0x10)
+ {
+ msd = msd >> 4;
+ s -= 4;
+ }
+ if (msd >= 0x4)
+ {
+ msd = msd >> 2;
+ s -= 2;
+ }
+ if (msd >= 0x2)
+ {
+ msd = msd >> 1;
+ s -= 1;
+ }
+ }
+ /* 0 <= s < GMP_LIMB_BITS.
+ Copy b, shifting it left by s bits. */
+ if (s > 0)
+ {
+ tmp_roomptr = (mp_limb_t *) malloc (b_len * sizeof (mp_limb_t));
+ if (tmp_roomptr == NULL)
+ {
+ free (roomptr);
+ return NULL;
+ }
+ {
+ const mp_limb_t *sourceptr = b_ptr;
+ mp_limb_t *destptr = tmp_roomptr;
+ mp_twolimb_t accu = 0;
+ size_t count;
+ for (count = b_len; count > 0; count--)
+ {
+ accu += (mp_twolimb_t) *sourceptr++ << s;
+ *destptr++ = (mp_limb_t) accu;
+ accu = accu >> GMP_LIMB_BITS;
+ }
+ /* accu must be zero, since that was how s was determined. */
+ if (accu != 0)
+ abort ();
+ }
+ b_ptr = tmp_roomptr;
+ }
+ /* Copy a, shifting it left by s bits, yields r.
+ Memory layout:
+ At the beginning: r = roomptr[0..a_len],
+ at the end: r = roomptr[0..b_len-1], q = roomptr[b_len..a_len] */
+ r_ptr = roomptr;
+ if (s == 0)
+ {
+ memcpy (r_ptr, a_ptr, a_len * sizeof (mp_limb_t));
+ r_ptr[a_len] = 0;
+ }
+ else
+ {
+ const mp_limb_t *sourceptr = a_ptr;
+ mp_limb_t *destptr = r_ptr;
+ mp_twolimb_t accu = 0;
+ size_t count;
+ for (count = a_len; count > 0; count--)
+ {
+ accu += (mp_twolimb_t) *sourceptr++ << s;
+ *destptr++ = (mp_limb_t) accu;
+ accu = accu >> GMP_LIMB_BITS;
+ }
+ *destptr++ = (mp_limb_t) accu;
+ }
+ q_ptr = roomptr + b_len;
+ q_len = a_len - b_len + 1; /* q will have m-n+1 limbs */
+ {
+ size_t j = a_len - b_len; /* m-n */
+ mp_limb_t b_msd = b_ptr[b_len - 1]; /* b[n-1] */
+ mp_limb_t b_2msd = b_ptr[b_len - 2]; /* b[n-2] */
+ mp_twolimb_t b_msdd = /* b[n-1]*beta+b[n-2] */
+ ((mp_twolimb_t) b_msd << GMP_LIMB_BITS) | b_2msd;
+ /* Division loop, traversed m-n+1 times.
+ j counts down, b is unchanged, beta/2 <= b[n-1] < beta. */
+ for (;;)
+ {
+ mp_limb_t q_star;
+ mp_limb_t c1;
+ if (r_ptr[j + b_len] < b_msd) /* r[j+n] < b[n-1] ? */
+ {
+ /* Divide r[j+n]*beta+r[j+n-1] by b[n-1], no overflow. */
+ mp_twolimb_t num =
+ ((mp_twolimb_t) r_ptr[j + b_len] << GMP_LIMB_BITS)
+ | r_ptr[j + b_len - 1];
+ q_star = num / b_msd;
+ c1 = num % b_msd;
+ }
+ else
+ {
+ /* Overflow, hence r[j+n]*beta+r[j+n-1] >= beta*b[n-1]. */
+ q_star = (mp_limb_t)~(mp_limb_t)0; /* q* = beta-1 */
+ /* Test whether r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] >= beta
+ <==> r[j+n]*beta+r[j+n-1] + b[n-1] >= beta*b[n-1]+beta
+ <==> b[n-1] < floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta)
+ {<= beta !}.
+ If yes, jump directly to the subtraction loop.
+ (Otherwise, r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] < beta
+ <==> floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta) = b[n-1] ) */
+ if (r_ptr[j + b_len] > b_msd
+ || (c1 = r_ptr[j + b_len - 1] + b_msd) < b_msd)
+ /* r[j+n] >= b[n-1]+1 or
+ r[j+n] = b[n-1] and the addition r[j+n-1]+b[n-1] gives a
+ carry. */
+ goto subtract;
+ }
+ /* q_star = q*,
+ c1 = (r[j+n]*beta+r[j+n-1]) - q* * b[n-1] (>=0, <beta). */
+ {
+ mp_twolimb_t c2 = /* c1*beta+r[j+n-2] */
+ ((mp_twolimb_t) c1 << GMP_LIMB_BITS) | r_ptr[j + b_len - 2];
+ mp_twolimb_t c3 = /* b[n-2] * q* */
+ (mp_twolimb_t) b_2msd * (mp_twolimb_t) q_star;
+ /* While c2 < c3, increase c2 and decrease c3.
+ Consider c3-c2. While it is > 0, decrease it by
+ b[n-1]*beta+b[n-2]. Because of b[n-1]*beta+b[n-2] >= beta^2/2
+ this can happen only twice. */
+ if (c3 > c2)
+ {
+ q_star = q_star - 1; /* q* := q* - 1 */
+ if (c3 - c2 > b_msdd)
+ q_star = q_star - 1; /* q* := q* - 1 */
+ }
+ }
+ if (q_star > 0)
+ subtract:
+ {
+ /* Subtract r := r - b * q* * beta^j. */
+ mp_limb_t cr;
+ {
+ const mp_limb_t *sourceptr = b_ptr;
+ mp_limb_t *destptr = r_ptr + j;
+ mp_twolimb_t carry = 0;
+ size_t count;
+ for (count = b_len; count > 0; count--)
+ {
+ /* Here 0 <= carry <= q*. */
+ carry =
+ carry
+ + (mp_twolimb_t) q_star * (mp_twolimb_t) *sourceptr++
+ + (mp_limb_t) ~(*destptr);
+ /* Here 0 <= carry <= beta*q* + beta-1. */
+ *destptr++ = ~(mp_limb_t) carry;
+ carry = carry >> GMP_LIMB_BITS; /* <= q* */
+ }
+ cr = (mp_limb_t) carry;
+ }
+ /* Subtract cr from r_ptr[j + b_len], then forget about
+ r_ptr[j + b_len]. */
+ if (cr > r_ptr[j + b_len])
+ {
+ /* Subtraction gave a carry. */
+ q_star = q_star - 1; /* q* := q* - 1 */
+ /* Add b back. */
+ {
+ const mp_limb_t *sourceptr = b_ptr;
+ mp_limb_t *destptr = r_ptr + j;
+ mp_limb_t carry = 0;
+ size_t count;
+ for (count = b_len; count > 0; count--)
+ {
+ mp_limb_t source1 = *sourceptr++;
+ mp_limb_t source2 = *destptr;
+ *destptr++ = source1 + source2 + carry;
+ carry =
+ (carry
+ ? source1 >= (mp_limb_t) ~source2
+ : source1 > (mp_limb_t) ~source2);
+ }
+ }
+ /* Forget about the carry and about r[j+n]. */
+ }
+ }
+ /* q* is determined. Store it as q[j]. */
+ q_ptr[j] = q_star;
+ if (j == 0)
+ break;
+ j--;
+ }
+ }
+ r_len = b_len;
+ /* Normalise q. */
+ if (q_ptr[q_len - 1] == 0)
+ q_len--;
+# if 0 /* Not needed here, since we need r only to compare it with b/2, and
+ b is shifted left by s bits. */
+ /* Shift r right by s bits. */
+ if (s > 0)
+ {
+ mp_limb_t ptr = r_ptr + r_len;
+ mp_twolimb_t accu = 0;
+ size_t count;
+ for (count = r_len; count > 0; count--)
+ {
+ accu = (mp_twolimb_t) (mp_limb_t) accu << GMP_LIMB_BITS;
+ accu += (mp_twolimb_t) *--ptr << (GMP_LIMB_BITS - s);
+ *ptr = (mp_limb_t) (accu >> GMP_LIMB_BITS);
+ }
+ }
+# endif
+ /* Normalise r. */
+ while (r_len > 0 && r_ptr[r_len - 1] == 0)
+ r_len--;
+ }
+ /* Compare r << 1 with b. */
+ if (r_len > b_len)
+ goto increment_q;
+ {
+ size_t i;
+ for (i = b_len;;)
+ {
+ mp_limb_t r_i =
+ (i <= r_len && i > 0 ? r_ptr[i - 1] >> (GMP_LIMB_BITS - 1) : 0)
+ | (i < r_len ? r_ptr[i] << 1 : 0);
+ mp_limb_t b_i = (i < b_len ? b_ptr[i] : 0);
+ if (r_i > b_i)
+ goto increment_q;
+ if (r_i < b_i)
+ goto keep_q;
+ if (i == 0)
+ break;
+ i--;
+ }
+ }
+ if (q_len > 0 && ((q_ptr[0] & 1) != 0))
+ /* q is odd. */
+ increment_q:
+ {
+ size_t i;
+ for (i = 0; i < q_len; i++)
+ if (++(q_ptr[i]) != 0)
+ goto keep_q;
+ q_ptr[q_len++] = 1;
+ }
+ keep_q:
+ if (tmp_roomptr != NULL)
+ free (tmp_roomptr);
+ q->limbs = q_ptr;
+ q->nlimbs = q_len;
+ return roomptr;
+}
+
+/* Convert a bignum a >= 0, multiplied with 10^extra_zeroes, to decimal
+ representation.
+ Destroys the contents of a.
+ Return the allocated memory - containing the decimal digits in low-to-high
+ order, terminated with a NUL character - in case of success, NULL in case
+ of memory allocation failure. */
+static char *
+convert_to_decimal (mpn_t a, size_t extra_zeroes)
+{
+ mp_limb_t *a_ptr = a.limbs;
+ size_t a_len = a.nlimbs;
+ /* 0.03345 is slightly larger than log(2)/(9*log(10)). */
+ size_t c_len = 9 * ((size_t)(a_len * (GMP_LIMB_BITS * 0.03345f)) + 1);
+ char *c_ptr = (char *) malloc (xsum (c_len, extra_zeroes));
+ if (c_ptr != NULL)
+ {
+ char *d_ptr = c_ptr;
+ for (; extra_zeroes > 0; extra_zeroes--)
+ *d_ptr++ = '0';
+ while (a_len > 0)
+ {
+ /* Divide a by 10^9, in-place. */
+ mp_limb_t remainder = 0;
+ mp_limb_t *ptr = a_ptr + a_len;
+ size_t count;
+ for (count = a_len; count > 0; count--)
+ {
+ mp_twolimb_t num =
+ ((mp_twolimb_t) remainder << GMP_LIMB_BITS) | *--ptr;
+ *ptr = num / 1000000000;
+ remainder = num % 1000000000;
+ }
+ /* Store the remainder as 9 decimal digits. */
+ for (count = 9; count > 0; count--)
+ {
+ *d_ptr++ = '0' + (remainder % 10);
+ remainder = remainder / 10;
+ }
+ /* Normalize a. */
+ if (a_ptr[a_len - 1] == 0)
+ a_len--;
+ }
+ /* Remove leading zeroes. */
+ while (d_ptr > c_ptr && d_ptr[-1] == '0')
+ d_ptr--;
+ /* But keep at least one zero. */
+ if (d_ptr == c_ptr)
+ *d_ptr++ = '0';
+ /* Terminate the string. */
+ *d_ptr = '\0';
+ }
+ return c_ptr;
+}
+
+# if NEED_PRINTF_LONG_DOUBLE
+
+/* Assuming x is finite and >= 0:
+ write x as x = 2^e * m, where m is a bignum.
+ Return the allocated memory in case of success, NULL in case of memory
+ allocation failure. */
+static void *
+decode_long_double (long double x, int *ep, mpn_t *mp)
+{
+ mpn_t m;
+ int exp;
+ long double y;
+ size_t i;
+
+ /* Allocate memory for result. */
+ m.nlimbs = (LDBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
+ m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t));
+ if (m.limbs == NULL)
+ return NULL;
+ /* Split into exponential part and mantissa. */
+ y = frexpl (x, &exp);
+ if (!(y >= 0.0L && y < 1.0L))
+ abort ();
+ /* x = 2^exp * y = 2^(exp - LDBL_MANT_BIT) * (y * LDBL_MANT_BIT), and the
+ latter is an integer. */
+ /* Convert the mantissa (y * LDBL_MANT_BIT) to a sequence of limbs.
+ I'm not sure whether it's safe to cast a 'long double' value between
+ 2^31 and 2^32 to 'unsigned int', therefore play safe and cast only
+ 'long double' values between 0 and 2^16 (to 'unsigned int' or 'int',
+ doesn't matter). */
+# if (LDBL_MANT_BIT % GMP_LIMB_BITS) != 0
+# if (LDBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2
+ {
+ mp_limb_t hi, lo;
+ y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % (GMP_LIMB_BITS / 2));
+ hi = (int) y;
+ y -= hi;
+ if (!(y >= 0.0L && y < 1.0L))
+ abort ();
+ y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
+ lo = (int) y;
+ y -= lo;
+ if (!(y >= 0.0L && y < 1.0L))
+ abort ();
+ m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | lo;
+ }
+# else
+ {
+ mp_limb_t d;
+ y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % GMP_LIMB_BITS);
+ d = (int) y;
+ y -= d;
+ if (!(y >= 0.0L && y < 1.0L))
+ abort ();
+ m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = d;
+ }
+# endif
+# endif
+ for (i = LDBL_MANT_BIT / GMP_LIMB_BITS; i > 0; )
+ {
+ mp_limb_t hi, lo;
+ y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
+ hi = (int) y;
+ y -= hi;
+ if (!(y >= 0.0L && y < 1.0L))
+ abort ();
+ y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
+ lo = (int) y;
+ y -= lo;
+ if (!(y >= 0.0L && y < 1.0L))
+ abort ();
+ m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo;
+ }
+#if 0 /* On FreeBSD 6.1/x86, 'long double' numbers sometimes have excess
+ precision. */
+ if (!(y == 0.0L))
+ abort ();
+#endif
+ /* Normalise. */
+ while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0)
+ m.nlimbs--;
+ *mp = m;
+ *ep = exp - LDBL_MANT_BIT;
+ return m.limbs;
+}
+
+# endif
+
+# if NEED_PRINTF_DOUBLE
+
+/* Assuming x is finite and >= 0:
+ write x as x = 2^e * m, where m is a bignum.
+ Return the allocated memory in case of success, NULL in case of memory
+ allocation failure. */
+static void *
+decode_double (double x, int *ep, mpn_t *mp)
+{
+ mpn_t m;
+ int exp;
+ double y;
+ size_t i;
+
+ /* Allocate memory for result. */
+ m.nlimbs = (DBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
+ m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t));
+ if (m.limbs == NULL)
+ return NULL;
+ /* Split into exponential part and mantissa. */
+ y = frexp (x, &exp);
+ if (!(y >= 0.0 && y < 1.0))
+ abort ();
+ /* x = 2^exp * y = 2^(exp - DBL_MANT_BIT) * (y * DBL_MANT_BIT), and the
+ latter is an integer. */
+ /* Convert the mantissa (y * DBL_MANT_BIT) to a sequence of limbs.
+ I'm not sure whether it's safe to cast a 'double' value between
+ 2^31 and 2^32 to 'unsigned int', therefore play safe and cast only
+ 'double' values between 0 and 2^16 (to 'unsigned int' or 'int',
+ doesn't matter). */
+# if (DBL_MANT_BIT % GMP_LIMB_BITS) != 0
+# if (DBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2
+ {
+ mp_limb_t hi, lo;
+ y *= (mp_limb_t) 1 << (DBL_MANT_BIT % (GMP_LIMB_BITS / 2));
+ hi = (int) y;
+ y -= hi;
+ if (!(y >= 0.0 && y < 1.0))
+ abort ();
+ y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
+ lo = (int) y;
+ y -= lo;
+ if (!(y >= 0.0 && y < 1.0))
+ abort ();
+ m.limbs[DBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | lo;
+ }
+# else
+ {
+ mp_limb_t d;
+ y *= (mp_limb_t) 1 << (DBL_MANT_BIT % GMP_LIMB_BITS);
+ d = (int) y;
+ y -= d;
+ if (!(y >= 0.0 && y < 1.0))
+ abort ();
+ m.limbs[DBL_MANT_BIT / GMP_LIMB_BITS] = d;
+ }
+# endif
+# endif
+ for (i = DBL_MANT_BIT / GMP_LIMB_BITS; i > 0; )
+ {
+ mp_limb_t hi, lo;
+ y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
+ hi = (int) y;
+ y -= hi;
+ if (!(y >= 0.0 && y < 1.0))
+ abort ();
+ y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
+ lo = (int) y;
+ y -= lo;
+ if (!(y >= 0.0 && y < 1.0))
+ abort ();
+ m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo;
+ }
+ if (!(y == 0.0))
+ abort ();
+ /* Normalise. */
+ while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0)
+ m.nlimbs--;
+ *mp = m;
+ *ep = exp - DBL_MANT_BIT;
+ return m.limbs;
+}
+
+# endif
+
+/* Assuming x = 2^e * m is finite and >= 0, and n is an integer:
+ Returns the decimal representation of round (x * 10^n).
+ Return the allocated memory - containing the decimal digits in low-to-high
+ order, terminated with a NUL character - in case of success, NULL in case
+ of memory allocation failure. */
+static char *
+scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n)
+{
+ int s;
+ size_t extra_zeroes;
+ unsigned int abs_n;
+ unsigned int abs_s;
+ mp_limb_t *pow5_ptr;
+ size_t pow5_len;
+ unsigned int s_limbs;
+ unsigned int s_bits;
+ mpn_t pow5;
+ mpn_t z;
+ void *z_memory;
+ char *digits;
+
+ if (memory == NULL)
+ return NULL;
+ /* x = 2^e * m, hence
+ y = round (2^e * 10^n * m) = round (2^(e+n) * 5^n * m)
+ = round (2^s * 5^n * m). */
+ s = e + n;
+ extra_zeroes = 0;
+ /* Factor out a common power of 10 if possible. */
+ if (s > 0 && n > 0)
+ {
+ extra_zeroes = (s < n ? s : n);
+ s -= extra_zeroes;
+ n -= extra_zeroes;
+ }
+ /* Here y = round (2^s * 5^n * m) * 10^extra_zeroes.
+ Before converting to decimal, we need to compute
+ z = round (2^s * 5^n * m). */
+ /* Compute 5^|n|, possibly shifted by |s| bits if n and s have the same
+ sign. 2.322 is slightly larger than log(5)/log(2). */
+ abs_n = (n >= 0 ? n : -n);
+ abs_s = (s >= 0 ? s : -s);
+ pow5_ptr = (mp_limb_t *) malloc (((int)(abs_n * (2.322f / GMP_LIMB_BITS)) + 1
+ + abs_s / GMP_LIMB_BITS + 1)
+ * sizeof (mp_limb_t));
+ if (pow5_ptr == NULL)
+ {
+ free (memory);
+ return NULL;
+ }
+ /* Initialize with 1. */
+ pow5_ptr[0] = 1;
+ pow5_len = 1;
+ /* Multiply with 5^|n|. */
+ if (abs_n > 0)
+ {
+ static mp_limb_t const small_pow5[13 + 1] =
+ {
+ 1, 5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125, 9765625,
+ 48828125, 244140625, 1220703125
+ };
+ unsigned int n13;
+ for (n13 = 0; n13 <= abs_n; n13 += 13)
+ {
+ mp_limb_t digit1 = small_pow5[n13 + 13 <= abs_n ? 13 : abs_n - n13];
+ size_t j;
+ mp_twolimb_t carry = 0;
+ for (j = 0; j < pow5_len; j++)
+ {
+ mp_limb_t digit2 = pow5_ptr[j];
+ carry += (mp_twolimb_t) digit1 * (mp_twolimb_t) digit2;
+ pow5_ptr[j] = (mp_limb_t) carry;
+ carry = carry >> GMP_LIMB_BITS;
+ }
+ if (carry > 0)
+ pow5_ptr[pow5_len++] = (mp_limb_t) carry;
+ }
+ }
+ s_limbs = abs_s / GMP_LIMB_BITS;
+ s_bits = abs_s % GMP_LIMB_BITS;
+ if (n >= 0 ? s >= 0 : s <= 0)
+ {
+ /* Multiply with 2^|s|. */
+ if (s_bits > 0)
+ {
+ mp_limb_t *ptr = pow5_ptr;
+ mp_twolimb_t accu = 0;
+ size_t count;
+ for (count = pow5_len; count > 0; count--)
+ {
+ accu += (mp_twolimb_t) *ptr << s_bits;
+ *ptr++ = (mp_limb_t) accu;
+ accu = accu >> GMP_LIMB_BITS;
+ }
+ if (accu > 0)
+ {
+ *ptr = (mp_limb_t) accu;
+ pow5_len++;
+ }
+ }
+ if (s_limbs > 0)
+ {
+ size_t count;
+ for (count = pow5_len; count > 0;)
+ {
+ count--;
+ pow5_ptr[s_limbs + count] = pow5_ptr[count];
+ }
+ for (count = s_limbs; count > 0;)
+ {
+ count--;
+ pow5_ptr[count] = 0;
+ }
+ pow5_len += s_limbs;
+ }
+ pow5.limbs = pow5_ptr;
+ pow5.nlimbs = pow5_len;
+ if (n >= 0)
+ {
+ /* Multiply m with pow5. No division needed. */
+ z_memory = multiply (m, pow5, &z);
+ }
+ else
+ {
+ /* Divide m by pow5 and round. */
+ z_memory = divide (m, pow5, &z);
+ }
+ }
+ else
+ {
+ pow5.limbs = pow5_ptr;
+ pow5.nlimbs = pow5_len;
+ if (n >= 0)
+ {
+ /* n >= 0, s < 0.
+ Multiply m with pow5, then divide by 2^|s|. */
+ mpn_t numerator;
+ mpn_t denominator;
+ void *tmp_memory;
+ tmp_memory = multiply (m, pow5, &numerator);
+ if (tmp_memory == NULL)
+ {
+ free (pow5_ptr);
+ free (memory);
+ return NULL;
+ }
+ /* Construct 2^|s|. */
+ {
+ mp_limb_t *ptr = pow5_ptr + pow5_len;
+ size_t i;
+ for (i = 0; i < s_limbs; i++)
+ ptr[i] = 0;
+ ptr[s_limbs] = (mp_limb_t) 1 << s_bits;
+ denominator.limbs = ptr;
+ denominator.nlimbs = s_limbs + 1;
+ }
+ z_memory = divide (numerator, denominator, &z);
+ free (tmp_memory);
+ }
+ else
+ {
+ /* n < 0, s > 0.
+ Multiply m with 2^s, then divide by pow5. */
+ mpn_t numerator;
+ mp_limb_t *num_ptr;
+ num_ptr = (mp_limb_t *) malloc ((m.nlimbs + s_limbs + 1)
+ * sizeof (mp_limb_t));
+ if (num_ptr == NULL)
+ {
+ free (pow5_ptr);
+ free (memory);
+ return NULL;
+ }
+ {
+ mp_limb_t *destptr = num_ptr;
+ {
+ size_t i;
+ for (i = 0; i < s_limbs; i++)
+ *destptr++ = 0;
+ }
+ if (s_bits > 0)
+ {
+ const mp_limb_t *sourceptr = m.limbs;
+ mp_twolimb_t accu = 0;
+ size_t count;
+ for (count = m.nlimbs; count > 0; count--)
+ {
+ accu += (mp_twolimb_t) *sourceptr++ << s_bits;
+ *destptr++ = (mp_limb_t) accu;
+ accu = accu >> GMP_LIMB_BITS;
+ }
+ if (accu > 0)
+ *destptr++ = (mp_limb_t) accu;
+ }
+ else
+ {
+ const mp_limb_t *sourceptr = m.limbs;
+ size_t count;
+ for (count = m.nlimbs; count > 0; count--)
+ *destptr++ = *sourceptr++;
+ }
+ numerator.limbs = num_ptr;
+ numerator.nlimbs = destptr - num_ptr;
+ }
+ z_memory = divide (numerator, pow5, &z);
+ free (num_ptr);
+ }
+ }
+ free (pow5_ptr);
+ free (memory);
+
+ /* Here y = round (x * 10^n) = z * 10^extra_zeroes. */
+
+ if (z_memory == NULL)
+ return NULL;
+ digits = convert_to_decimal (z, extra_zeroes);
+ free (z_memory);
+ return digits;
+}
+
+# if NEED_PRINTF_LONG_DOUBLE
+
+/* Assuming x is finite and >= 0, and n is an integer:
+ Returns the decimal representation of round (x * 10^n).
+ Return the allocated memory - containing the decimal digits in low-to-high
+ order, terminated with a NUL character - in case of success, NULL in case
+ of memory allocation failure. */
+static char *
+scale10_round_decimal_long_double (long double x, int n)
+{
+ int e IF_LINT(= 0);
+ mpn_t m;
+ void *memory = decode_long_double (x, &e, &m);
+ return scale10_round_decimal_decoded (e, m, memory, n);
+}
+
+# endif
+
+# if NEED_PRINTF_DOUBLE
+
+/* Assuming x is finite and >= 0, and n is an integer:
+ Returns the decimal representation of round (x * 10^n).
+ Return the allocated memory - containing the decimal digits in low-to-high
+ order, terminated with a NUL character - in case of success, NULL in case
+ of memory allocation failure. */
+static char *
+scale10_round_decimal_double (double x, int n)
+{
+ int e IF_LINT(= 0);
+ mpn_t m;
+ void *memory = decode_double (x, &e, &m);
+ return scale10_round_decimal_decoded (e, m, memory, n);
+}
+
+# endif
+
+# if NEED_PRINTF_LONG_DOUBLE
+
+/* Assuming x is finite and > 0:
+ Return an approximation for n with 10^n <= x < 10^(n+1).
+ The approximation is usually the right n, but may be off by 1 sometimes. */
+static int
+floorlog10l (long double x)
+{
+ int exp;
+ long double y;
+ double z;
+ double l;
+
+ /* Split into exponential part and mantissa. */
+ y = frexpl (x, &exp);
+ if (!(y >= 0.0L && y < 1.0L))
+ abort ();
+ if (y == 0.0L)
+ return INT_MIN;
+ if (y < 0.5L)
+ {
+ while (y < (1.0L / (1 << (GMP_LIMB_BITS / 2)) / (1 << (GMP_LIMB_BITS / 2))))
+ {
+ y *= 1.0L * (1 << (GMP_LIMB_BITS / 2)) * (1 << (GMP_LIMB_BITS / 2));
+ exp -= GMP_LIMB_BITS;
+ }
+ if (y < (1.0L / (1 << 16)))
+ {
+ y *= 1.0L * (1 << 16);
+ exp -= 16;
+ }
+ if (y < (1.0L / (1 << 8)))
+ {
+ y *= 1.0L * (1 << 8);
+ exp -= 8;
+ }
+ if (y < (1.0L / (1 << 4)))
+ {
+ y *= 1.0L * (1 << 4);
+ exp -= 4;
+ }
+ if (y < (1.0L / (1 << 2)))
+ {
+ y *= 1.0L * (1 << 2);
+ exp -= 2;
+ }
+ if (y < (1.0L / (1 << 1)))
+ {
+ y *= 1.0L * (1 << 1);
+ exp -= 1;
+ }
+ }
+ if (!(y >= 0.5L && y < 1.0L))
+ abort ();
+ /* Compute an approximation for l = log2(x) = exp + log2(y). */
+ l = exp;
+ z = y;
+ if (z < 0.70710678118654752444)
+ {
+ z *= 1.4142135623730950488;
+ l -= 0.5;
+ }
+ if (z < 0.8408964152537145431)
+ {
+ z *= 1.1892071150027210667;
+ l -= 0.25;
+ }
+ if (z < 0.91700404320467123175)
+ {
+ z *= 1.0905077326652576592;
+ l -= 0.125;
+ }
+ if (z < 0.9576032806985736469)
+ {
+ z *= 1.0442737824274138403;
+ l -= 0.0625;
+ }
+ /* Now 0.95 <= z <= 1.01. */
+ z = 1 - z;
+ /* log2(1-z) = 1/log(2) * (- z - z^2/2 - z^3/3 - z^4/4 - ...)
+ Four terms are enough to get an approximation with error < 10^-7. */
+ l -= 1.4426950408889634074 * z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25)));
+ /* Finally multiply with log(2)/log(10), yields an approximation for
+ log10(x). */
+ l *= 0.30102999566398119523;
+ /* Round down to the next integer. */
+ return (int) l + (l < 0 ? -1 : 0);
+}
+
+# endif
+
+# if NEED_PRINTF_DOUBLE
+
+/* Assuming x is finite and > 0:
+ Return an approximation for n with 10^n <= x < 10^(n+1).
+ The approximation is usually the right n, but may be off by 1 sometimes. */
+static int
+floorlog10 (double x)
+{
+ int exp;
+ double y;
+ double z;
+ double l;
+
+ /* Split into exponential part and mantissa. */
+ y = frexp (x, &exp);
+ if (!(y >= 0.0 && y < 1.0))
+ abort ();
+ if (y == 0.0)
+ return INT_MIN;
+ if (y < 0.5)
+ {
+ while (y < (1.0 / (1 << (GMP_LIMB_BITS / 2)) / (1 << (GMP_LIMB_BITS / 2))))
+ {
+ y *= 1.0 * (1 << (GMP_LIMB_BITS / 2)) * (1 << (GMP_LIMB_BITS / 2));
+ exp -= GMP_LIMB_BITS;
+ }
+ if (y < (1.0 / (1 << 16)))
+ {
+ y *= 1.0 * (1 << 16);
+ exp -= 16;
+ }
+ if (y < (1.0 / (1 << 8)))
+ {
+ y *= 1.0 * (1 << 8);
+ exp -= 8;
+ }
+ if (y < (1.0 / (1 << 4)))
+ {
+ y *= 1.0 * (1 << 4);
+ exp -= 4;
+ }
+ if (y < (1.0 / (1 << 2)))
+ {
+ y *= 1.0 * (1 << 2);
+ exp -= 2;
+ }
+ if (y < (1.0 / (1 << 1)))
+ {
+ y *= 1.0 * (1 << 1);
+ exp -= 1;
+ }
+ }
+ if (!(y >= 0.5 && y < 1.0))
+ abort ();
+ /* Compute an approximation for l = log2(x) = exp + log2(y). */
+ l = exp;
+ z = y;
+ if (z < 0.70710678118654752444)
+ {
+ z *= 1.4142135623730950488;
+ l -= 0.5;
+ }
+ if (z < 0.8408964152537145431)
+ {
+ z *= 1.1892071150027210667;
+ l -= 0.25;
+ }
+ if (z < 0.91700404320467123175)
+ {
+ z *= 1.0905077326652576592;
+ l -= 0.125;
+ }
+ if (z < 0.9576032806985736469)
+ {
+ z *= 1.0442737824274138403;
+ l -= 0.0625;
+ }
+ /* Now 0.95 <= z <= 1.01. */
+ z = 1 - z;
+ /* log2(1-z) = 1/log(2) * (- z - z^2/2 - z^3/3 - z^4/4 - ...)
+ Four terms are enough to get an approximation with error < 10^-7. */
+ l -= 1.4426950408889634074 * z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25)));
+ /* Finally multiply with log(2)/log(10), yields an approximation for
+ log10(x). */
+ l *= 0.30102999566398119523;
+ /* Round down to the next integer. */
+ return (int) l + (l < 0 ? -1 : 0);
+}
+
+# endif
+
+/* Tests whether a string of digits consists of exactly PRECISION zeroes and
+ a single '1' digit. */
+static int
+is_borderline (const char *digits, size_t precision)
+{
+ for (; precision > 0; precision--, digits++)
+ if (*digits != '0')
+ return 0;
+ if (*digits != '1')
+ return 0;
+ digits++;
+ return *digits == '\0';
+}
+
+#endif
+
+#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99
+
+/* Use a different function name, to make it possible that the 'wchar_t'
+ parametrization and the 'char' parametrization get compiled in the same
+ translation unit. */
+# if WIDE_CHAR_VERSION
+# define MAX_ROOM_NEEDED wmax_room_needed
+# else
+# define MAX_ROOM_NEEDED max_room_needed
+# endif
+
+/* Returns the number of TCHAR_T units needed as temporary space for the result
+ of sprintf or SNPRINTF of a single conversion directive. */
+static inline size_t
+MAX_ROOM_NEEDED (const arguments *ap, size_t arg_index, FCHAR_T conversion,
+ arg_type type, int flags, size_t width, int has_precision,
+ size_t precision, int pad_ourselves)
+{
+ size_t tmp_length;
+
+ switch (conversion)
+ {
+ case 'd': case 'i': case 'u':
+# if HAVE_LONG_LONG_INT
+ if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
+ * 0.30103 /* binary -> decimal */
+ )
+ + 1; /* turn floor into ceil */
+ else
+# endif
+ if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long) * CHAR_BIT
+ * 0.30103 /* binary -> decimal */
+ )
+ + 1; /* turn floor into ceil */
+ else
+ tmp_length =
+ (unsigned int) (sizeof (unsigned int) * CHAR_BIT
+ * 0.30103 /* binary -> decimal */
+ )
+ + 1; /* turn floor into ceil */
+ if (tmp_length < precision)
+ tmp_length = precision;
+ /* Multiply by 2, as an estimate for FLAG_GROUP. */
+ tmp_length = xsum (tmp_length, tmp_length);
+ /* Add 1, to account for a leading sign. */
+ tmp_length = xsum (tmp_length, 1);
+ break;
+
+ case 'o':
+# if HAVE_LONG_LONG_INT
+ if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
+ * 0.333334 /* binary -> octal */
+ )
+ + 1; /* turn floor into ceil */
+ else
+# endif
+ if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long) * CHAR_BIT
+ * 0.333334 /* binary -> octal */
+ )
+ + 1; /* turn floor into ceil */
+ else
+ tmp_length =
+ (unsigned int) (sizeof (unsigned int) * CHAR_BIT
+ * 0.333334 /* binary -> octal */
+ )
+ + 1; /* turn floor into ceil */
+ if (tmp_length < precision)
+ tmp_length = precision;
+ /* Add 1, to account for a leading sign. */
+ tmp_length = xsum (tmp_length, 1);
+ break;
+
+ case 'x': case 'X':
+# if HAVE_LONG_LONG_INT
+ if (type == TYPE_LONGLONGINT || type == TYPE_ULONGLONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long long) * CHAR_BIT
+ * 0.25 /* binary -> hexadecimal */
+ )
+ + 1; /* turn floor into ceil */
+ else
+# endif
+ if (type == TYPE_LONGINT || type == TYPE_ULONGINT)
+ tmp_length =
+ (unsigned int) (sizeof (unsigned long) * CHAR_BIT
+ * 0.25 /* binary -> hexadecimal */
+ )
+ + 1; /* turn floor into ceil */
+ else
+ tmp_length =
+ (unsigned int) (sizeof (unsigned int) * CHAR_BIT
+ * 0.25 /* binary -> hexadecimal */
+ )
+ + 1; /* turn floor into ceil */
+ if (tmp_length < precision)
+ tmp_length = precision;
+ /* Add 2, to account for a leading sign or alternate form. */
+ tmp_length = xsum (tmp_length, 2);
+ break;
+
+ case 'f': case 'F':
+ if (type == TYPE_LONGDOUBLE)
+ tmp_length =
+ (unsigned int) (LDBL_MAX_EXP
+ * 0.30103 /* binary -> decimal */
+ * 2 /* estimate for FLAG_GROUP */
+ )
+ + 1 /* turn floor into ceil */
+ + 10; /* sign, decimal point etc. */
+ else
+ tmp_length =
+ (unsigned int) (DBL_MAX_EXP
+ * 0.30103 /* binary -> decimal */
+ * 2 /* estimate for FLAG_GROUP */
+ )
+ + 1 /* turn floor into ceil */
+ + 10; /* sign, decimal point etc. */
+ tmp_length = xsum (tmp_length, precision);
+ break;
+
+ case 'e': case 'E': case 'g': case 'G':
+ tmp_length =
+ 12; /* sign, decimal point, exponent etc. */
+ tmp_length = xsum (tmp_length, precision);
+ break;
+
+ case 'a': case 'A':
+ if (type == TYPE_LONGDOUBLE)
+ tmp_length =
+ (unsigned int) (LDBL_DIG
+ * 0.831 /* decimal -> hexadecimal */
+ )
+ + 1; /* turn floor into ceil */
+ else
+ tmp_length =
+ (unsigned int) (DBL_DIG
+ * 0.831 /* decimal -> hexadecimal */
+ )
+ + 1; /* turn floor into ceil */
+ if (tmp_length < precision)
+ tmp_length = precision;
+ /* Account for sign, decimal point etc. */
+ tmp_length = xsum (tmp_length, 12);
+ break;
+
+ case 'c':
+# if HAVE_WINT_T && !WIDE_CHAR_VERSION
+ if (type == TYPE_WIDE_CHAR)
+ tmp_length = MB_CUR_MAX;
+ else
+# endif
+ tmp_length = 1;
+ break;
+
+ case 's':
+# if HAVE_WCHAR_T
+ if (type == TYPE_WIDE_STRING)
+ {
+# if WIDE_CHAR_VERSION
+ /* ISO C says about %ls in fwprintf:
+ "If the precision is not specified or is greater than the size
+ of the array, the array shall contain a null wide character."
+ So if there is a precision, we must not use wcslen. */
+ const wchar_t *arg = ap->arg[arg_index].a.a_wide_string;
+
+ if (has_precision)
+ tmp_length = local_wcsnlen (arg, precision);
+ else
+ tmp_length = local_wcslen (arg);
+# else
+ /* ISO C says about %ls in fprintf:
+ "If a precision is specified, no more than that many bytes are
+ written (including shift sequences, if any), and the array
+ shall contain a null wide character if, to equal the multibyte
+ character sequence length given by the precision, the function
+ would need to access a wide character one past the end of the
+ array."
+ So if there is a precision, we must not use wcslen. */
+ /* This case has already been handled separately in VASNPRINTF. */
+ abort ();
+# endif
+ }
+ else
+# endif
+ {
+# if WIDE_CHAR_VERSION
+ /* ISO C says about %s in fwprintf:
+ "If the precision is not specified or is greater than the size
+ of the converted array, the converted array shall contain a
+ null wide character."
+ So if there is a precision, we must not use strlen. */
+ /* This case has already been handled separately in VASNPRINTF. */
+ abort ();
+# else
+ /* ISO C says about %s in fprintf:
+ "If the precision is not specified or greater than the size of
+ the array, the array shall contain a null character."
+ So if there is a precision, we must not use strlen. */
+ const char *arg = ap->arg[arg_index].a.a_string;
+
+ if (has_precision)
+ tmp_length = local_strnlen (arg, precision);
+ else
+ tmp_length = strlen (arg);
+# endif
+ }
+ break;
+
+ case 'p':
+ tmp_length =
+ (unsigned int) (sizeof (void *) * CHAR_BIT
+ * 0.25 /* binary -> hexadecimal */
+ )
+ + 1 /* turn floor into ceil */
+ + 2; /* account for leading 0x */
+ break;
+
+ default:
+ abort ();
+ }
+
+ if (!pad_ourselves)
+ {
+# if ENABLE_UNISTDIO
+ /* Padding considers the number of characters, therefore the number of
+ elements after padding may be
+ > max (tmp_length, width)
+ but is certainly
+ <= tmp_length + width. */
+ tmp_length = xsum (tmp_length, width);
+# else
+ /* Padding considers the number of elements, says POSIX. */
+ if (tmp_length < width)
+ tmp_length = width;
+# endif
+ }
+
+ tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
+
+ return tmp_length;
+}
+
+#endif
+
+DCHAR_T *
+VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
+ const FCHAR_T *format, va_list args)
+{
+ DIRECTIVES d;
+ arguments a;
+
+ if (PRINTF_PARSE (format, &d, &a) < 0)
+ /* errno is already set. */
+ return NULL;
+
+#define CLEANUP() \
+ free (d.dir); \
+ if (a.arg) \
+ free (a.arg);
+
+ if (PRINTF_FETCHARGS (args, &a) < 0)
+ {
+ CLEANUP ();
+ errno = EINVAL;
+ return NULL;
+ }
+
+ {
+ size_t buf_neededlength;
+ TCHAR_T *buf;
+ TCHAR_T *buf_malloced;
+ const FCHAR_T *cp;
+ size_t i;
+ DIRECTIVE *dp;
+ /* Output string accumulator. */
+ DCHAR_T *result;
+ size_t allocated;
+ size_t length;
+
+ /* Allocate a small buffer that will hold a directive passed to
+ sprintf or snprintf. */
+ buf_neededlength =
+ xsum4 (7, d.max_width_length, d.max_precision_length, 6);
+#if HAVE_ALLOCA
+ if (buf_neededlength < 4000 / sizeof (TCHAR_T))
+ {
+ buf = (TCHAR_T *) alloca (buf_neededlength * sizeof (TCHAR_T));
+ buf_malloced = NULL;
+ }
+ else
+#endif
+ {
+ size_t buf_memsize = xtimes (buf_neededlength, sizeof (TCHAR_T));
+ if (size_overflow_p (buf_memsize))
+ goto out_of_memory_1;
+ buf = (TCHAR_T *) malloc (buf_memsize);
+ if (buf == NULL)
+ goto out_of_memory_1;
+ buf_malloced = buf;
+ }
+
+ if (resultbuf != NULL)
+ {
+ result = resultbuf;
+ allocated = *lengthp;
+ }
+ else
+ {
+ result = NULL;
+ allocated = 0;
+ }
+ length = 0;
+ /* Invariants:
+ result is either == resultbuf or == NULL or malloc-allocated.
+ If length > 0, then result != NULL. */
+
+ /* Ensures that allocated >= needed. Aborts through a jump to
+ out_of_memory if needed is SIZE_MAX or otherwise too big. */
+#define ENSURE_ALLOCATION(needed) \
+ if ((needed) > allocated) \
+ { \
+ size_t memory_size; \
+ DCHAR_T *memory; \
+ \
+ allocated = (allocated > 0 ? xtimes (allocated, 2) : 12); \
+ if ((needed) > allocated) \
+ allocated = (needed); \
+ memory_size = xtimes (allocated, sizeof (DCHAR_T)); \
+ if (size_overflow_p (memory_size)) \
+ goto out_of_memory; \
+ if (result == resultbuf || result == NULL) \
+ memory = (DCHAR_T *) malloc (memory_size); \
+ else \
+ memory = (DCHAR_T *) realloc (result, memory_size); \
+ if (memory == NULL) \
+ goto out_of_memory; \
+ if (result == resultbuf && length > 0) \
+ DCHAR_CPY (memory, result, length); \
+ result = memory; \
+ }
+
+ for (cp = format, i = 0, dp = &d.dir[0]; ; cp = dp->dir_end, i++, dp++)
+ {
+ if (cp != dp->dir_start)
+ {
+ size_t n = dp->dir_start - cp;
+ size_t augmented_length = xsum (length, n);
+
+ ENSURE_ALLOCATION (augmented_length);
+ /* This copies a piece of FCHAR_T[] into a DCHAR_T[]. Here we
+ need that the format string contains only ASCII characters
+ if FCHAR_T and DCHAR_T are not the same type. */
+ if (sizeof (FCHAR_T) == sizeof (DCHAR_T))
+ {
+ DCHAR_CPY (result + length, (const DCHAR_T *) cp, n);
+ length = augmented_length;
+ }
+ else
+ {
+ do
+ result[length++] = (unsigned char) *cp++;
+ while (--n > 0);
+ }
+ }
+ if (i == d.count)
+ break;
+
+ /* Execute a single directive. */
+ if (dp->conversion == '%')
+ {
+ size_t augmented_length;
+
+ if (!(dp->arg_index == ARG_NONE))
+ abort ();
+ augmented_length = xsum (length, 1);
+ ENSURE_ALLOCATION (augmented_length);
+ result[length] = '%';
+ length = augmented_length;
+ }
+ else
+ {
+ if (!(dp->arg_index != ARG_NONE))
+ abort ();
+
+ if (dp->conversion == 'n')
+ {
+ switch (a.arg[dp->arg_index].type)
+ {
+ case TYPE_COUNT_SCHAR_POINTER:
+ *a.arg[dp->arg_index].a.a_count_schar_pointer = length;
+ break;
+ case TYPE_COUNT_SHORT_POINTER:
+ *a.arg[dp->arg_index].a.a_count_short_pointer = length;
+ break;
+ case TYPE_COUNT_INT_POINTER:
+ *a.arg[dp->arg_index].a.a_count_int_pointer = length;
+ break;
+ case TYPE_COUNT_LONGINT_POINTER:
+ *a.arg[dp->arg_index].a.a_count_longint_pointer = length;
+ break;
+#if HAVE_LONG_LONG_INT
+ case TYPE_COUNT_LONGLONGINT_POINTER:
+ *a.arg[dp->arg_index].a.a_count_longlongint_pointer = length;
+ break;
+#endif
+ default:
+ abort ();
+ }
+ }
+#if ENABLE_UNISTDIO
+ /* The unistdio extensions. */
+ else if (dp->conversion == 'U')
+ {
+ arg_type type = a.arg[dp->arg_index].type;
+ int flags = dp->flags;
+ int has_width;
+ size_t width;
+ int has_precision;
+ size_t precision;
+
+ has_width = 0;
+ width = 0;
+ if (dp->width_start != dp->width_end)
+ {
+ if (dp->width_arg_index != ARG_NONE)
+ {
+ int arg;
+
+ if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+ abort ();
+ arg = a.arg[dp->width_arg_index].a.a_int;
+ if (arg < 0)
+ {
+ /* "A negative field width is taken as a '-' flag
+ followed by a positive field width." */
+ flags |= FLAG_LEFT;
+ width = (unsigned int) (-arg);
+ }
+ else
+ width = arg;
+ }
+ else
+ {
+ const FCHAR_T *digitp = dp->width_start;
+
+ do
+ width = xsum (xtimes (width, 10), *digitp++ - '0');
+ while (digitp != dp->width_end);
+ }
+ has_width = 1;
+ }
+
+ has_precision = 0;
+ precision = 0;
+ if (dp->precision_start != dp->precision_end)
+ {
+ if (dp->precision_arg_index != ARG_NONE)
+ {
+ int arg;
+
+ if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+ abort ();
+ arg = a.arg[dp->precision_arg_index].a.a_int;
+ /* "A negative precision is taken as if the precision
+ were omitted." */
+ if (arg >= 0)
+ {
+ precision = arg;
+ has_precision = 1;
+ }
+ }
+ else
+ {
+ const FCHAR_T *digitp = dp->precision_start + 1;
+
+ precision = 0;
+ while (digitp != dp->precision_end)
+ precision = xsum (xtimes (precision, 10), *digitp++ - '0');
+ has_precision = 1;
+ }
+ }
+
+ switch (type)
+ {
+ case TYPE_U8_STRING:
+ {
+ const uint8_t *arg = a.arg[dp->arg_index].a.a_u8_string;
+ const uint8_t *arg_end;
+ size_t characters;
+
+ if (has_precision)
+ {
+ /* Use only PRECISION characters, from the left. */
+ arg_end = arg;
+ characters = 0;
+ for (; precision > 0; precision--)
+ {
+ int count = u8_strmblen (arg_end);
+ if (count == 0)
+ break;
+ if (count < 0)
+ {
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ CLEANUP ();
+ errno = EILSEQ;
+ return NULL;
+ }
+ arg_end += count;
+ characters++;
+ }
+ }
+ else if (has_width)
+ {
+ /* Use the entire string, and count the number of
+ characters. */
+ arg_end = arg;
+ characters = 0;
+ for (;;)
+ {
+ int count = u8_strmblen (arg_end);
+ if (count == 0)
+ break;
+ if (count < 0)
+ {
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ CLEANUP ();
+ errno = EILSEQ;
+ return NULL;
+ }
+ arg_end += count;
+ characters++;
+ }
+ }
+ else
+ {
+ /* Use the entire string. */
+ arg_end = arg + u8_strlen (arg);
+ /* The number of characters doesn't matter. */
+ characters = 0;
+ }
+
+ if (has_width && width > characters
+ && !(dp->flags & FLAG_LEFT))
+ {
+ size_t n = width - characters;
+ ENSURE_ALLOCATION (xsum (length, n));
+ DCHAR_SET (result + length, ' ', n);
+ length += n;
+ }
+
+# if DCHAR_IS_UINT8_T
+ {
+ size_t n = arg_end - arg;
+ ENSURE_ALLOCATION (xsum (length, n));
+ DCHAR_CPY (result + length, arg, n);
+ length += n;
+ }
+# else
+ { /* Convert. */
+ DCHAR_T *converted = result + length;
+ size_t converted_len = allocated - length;
+# if DCHAR_IS_TCHAR
+ /* Convert from UTF-8 to locale encoding. */
+ converted =
+ u8_conv_to_encoding (locale_charset (),
+ iconveh_question_mark,
+ arg, arg_end - arg, NULL,
+ converted, &converted_len);
+# else
+ /* Convert from UTF-8 to UTF-16/UTF-32. */
+ converted =
+ U8_TO_DCHAR (arg, arg_end - arg,
+ converted, &converted_len);
+# endif
+ if (converted == NULL)
+ {
+ int saved_errno = errno;
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ CLEANUP ();
+ errno = saved_errno;
+ return NULL;
+ }
+ if (converted != result + length)
+ {
+ ENSURE_ALLOCATION (xsum (length, converted_len));
+ DCHAR_CPY (result + length, converted, converted_len);
+ free (converted);
+ }
+ length += converted_len;
+ }
+# endif
+
+ if (has_width && width > characters
+ && (dp->flags & FLAG_LEFT))
+ {
+ size_t n = width - characters;
+ ENSURE_ALLOCATION (xsum (length, n));
+ DCHAR_SET (result + length, ' ', n);
+ length += n;
+ }
+ }
+ break;
+
+ case TYPE_U16_STRING:
+ {
+ const uint16_t *arg = a.arg[dp->arg_index].a.a_u16_string;
+ const uint16_t *arg_end;
+ size_t characters;
+
+ if (has_precision)
+ {
+ /* Use only PRECISION characters, from the left. */
+ arg_end = arg;
+ characters = 0;
+ for (; precision > 0; precision--)
+ {
+ int count = u16_strmblen (arg_end);
+ if (count == 0)
+ break;
+ if (count < 0)
+ {
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ CLEANUP ();
+ errno = EILSEQ;
+ return NULL;
+ }
+ arg_end += count;
+ characters++;
+ }
+ }
+ else if (has_width)
+ {
+ /* Use the entire string, and count the number of
+ characters. */
+ arg_end = arg;
+ characters = 0;
+ for (;;)
+ {
+ int count = u16_strmblen (arg_end);
+ if (count == 0)
+ break;
+ if (count < 0)
+ {
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ CLEANUP ();
+ errno = EILSEQ;
+ return NULL;
+ }
+ arg_end += count;
+ characters++;
+ }
+ }
+ else
+ {
+ /* Use the entire string. */
+ arg_end = arg + u16_strlen (arg);
+ /* The number of characters doesn't matter. */
+ characters = 0;
+ }
+
+ if (has_width && width > characters
+ && !(dp->flags & FLAG_LEFT))
+ {
+ size_t n = width - characters;
+ ENSURE_ALLOCATION (xsum (length, n));
+ DCHAR_SET (result + length, ' ', n);
+ length += n;
+ }
+
+# if DCHAR_IS_UINT16_T
+ {
+ size_t n = arg_end - arg;
+ ENSURE_ALLOCATION (xsum (length, n));
+ DCHAR_CPY (result + length, arg, n);
+ length += n;
+ }
+# else
+ { /* Convert. */
+ DCHAR_T *converted = result + length;
+ size_t converted_len = allocated - length;
+# if DCHAR_IS_TCHAR
+ /* Convert from UTF-16 to locale encoding. */
+ converted =
+ u16_conv_to_encoding (locale_charset (),
+ iconveh_question_mark,
+ arg, arg_end - arg, NULL,
+ converted, &converted_len);
+# else
+ /* Convert from UTF-16 to UTF-8/UTF-32. */
+ converted =
+ U16_TO_DCHAR (arg, arg_end - arg,
+ converted, &converted_len);
+# endif
+ if (converted == NULL)
+ {
+ int saved_errno = errno;
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ CLEANUP ();
+ errno = saved_errno;
+ return NULL;
+ }
+ if (converted != result + length)
+ {
+ ENSURE_ALLOCATION (xsum (length, converted_len));
+ DCHAR_CPY (result + length, converted, converted_len);
+ free (converted);
+ }
+ length += converted_len;
+ }
+# endif
+
+ if (has_width && width > characters
+ && (dp->flags & FLAG_LEFT))
+ {
+ size_t n = width - characters;
+ ENSURE_ALLOCATION (xsum (length, n));
+ DCHAR_SET (result + length, ' ', n);
+ length += n;
+ }
+ }
+ break;
+
+ case TYPE_U32_STRING:
+ {
+ const uint32_t *arg = a.arg[dp->arg_index].a.a_u32_string;
+ const uint32_t *arg_end;
+ size_t characters;
+
+ if (has_precision)
+ {
+ /* Use only PRECISION characters, from the left. */
+ arg_end = arg;
+ characters = 0;
+ for (; precision > 0; precision--)
+ {
+ int count = u32_strmblen (arg_end);
+ if (count == 0)
+ break;
+ if (count < 0)
+ {
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ CLEANUP ();
+ errno = EILSEQ;
+ return NULL;
+ }
+ arg_end += count;
+ characters++;
+ }
+ }
+ else if (has_width)
+ {
+ /* Use the entire string, and count the number of
+ characters. */
+ arg_end = arg;
+ characters = 0;
+ for (;;)
+ {
+ int count = u32_strmblen (arg_end);
+ if (count == 0)
+ break;
+ if (count < 0)
+ {
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ CLEANUP ();
+ errno = EILSEQ;
+ return NULL;
+ }
+ arg_end += count;
+ characters++;
+ }
+ }
+ else
+ {
+ /* Use the entire string. */
+ arg_end = arg + u32_strlen (arg);
+ /* The number of characters doesn't matter. */
+ characters = 0;
+ }
+
+ if (has_width && width > characters
+ && !(dp->flags & FLAG_LEFT))
+ {
+ size_t n = width - characters;
+ ENSURE_ALLOCATION (xsum (length, n));
+ DCHAR_SET (result + length, ' ', n);
+ length += n;
+ }
+
+# if DCHAR_IS_UINT32_T
+ {
+ size_t n = arg_end - arg;
+ ENSURE_ALLOCATION (xsum (length, n));
+ DCHAR_CPY (result + length, arg, n);
+ length += n;
+ }
+# else
+ { /* Convert. */
+ DCHAR_T *converted = result + length;
+ size_t converted_len = allocated - length;
+# if DCHAR_IS_TCHAR
+ /* Convert from UTF-32 to locale encoding. */
+ converted =
+ u32_conv_to_encoding (locale_charset (),
+ iconveh_question_mark,
+ arg, arg_end - arg, NULL,
+ converted, &converted_len);
+# else
+ /* Convert from UTF-32 to UTF-8/UTF-16. */
+ converted =
+ U32_TO_DCHAR (arg, arg_end - arg,
+ converted, &converted_len);
+# endif
+ if (converted == NULL)
+ {
+ int saved_errno = errno;
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ CLEANUP ();
+ errno = saved_errno;
+ return NULL;
+ }
+ if (converted != result + length)
+ {
+ ENSURE_ALLOCATION (xsum (length, converted_len));
+ DCHAR_CPY (result + length, converted, converted_len);
+ free (converted);
+ }
+ length += converted_len;
+ }
+# endif
+
+ if (has_width && width > characters
+ && (dp->flags & FLAG_LEFT))
+ {
+ size_t n = width - characters;
+ ENSURE_ALLOCATION (xsum (length, n));
+ DCHAR_SET (result + length, ' ', n);
+ length += n;
+ }
+ }
+ break;
+
+ default:
+ abort ();
+ }
+ }
+#endif
+#if (!USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || (NEED_PRINTF_DIRECTIVE_LS && !defined IN_LIBINTL)) && HAVE_WCHAR_T
+ else if (dp->conversion == 's'
+# if WIDE_CHAR_VERSION
+ && a.arg[dp->arg_index].type != TYPE_WIDE_STRING
+# else
+ && a.arg[dp->arg_index].type == TYPE_WIDE_STRING
+# endif
+ )
+ {
+ /* The normal handling of the 's' directive below requires
+ allocating a temporary buffer. The determination of its
+ length (tmp_length), in the case when a precision is
+ specified, below requires a conversion between a char[]
+ string and a wchar_t[] wide string. It could be done, but
+ we have no guarantee that the implementation of sprintf will
+ use the exactly same algorithm. Without this guarantee, it
+ is possible to have buffer overrun bugs. In order to avoid
+ such bugs, we implement the entire processing of the 's'
+ directive ourselves. */
+ int flags = dp->flags;
+ int has_width;
+ size_t width;
+ int has_precision;
+ size_t precision;
+
+ has_width = 0;
+ width = 0;
+ if (dp->width_start != dp->width_end)
+ {
+ if (dp->width_arg_index != ARG_NONE)
+ {
+ int arg;
+
+ if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+ abort ();
+ arg = a.arg[dp->width_arg_index].a.a_int;
+ if (arg < 0)
+ {
+ /* "A negative field width is taken as a '-' flag
+ followed by a positive field width." */
+ flags |= FLAG_LEFT;
+ width = (unsigned int) (-arg);
+ }
+ else
+ width = arg;
+ }
+ else
+ {
+ const FCHAR_T *digitp = dp->width_start;
+
+ do
+ width = xsum (xtimes (width, 10), *digitp++ - '0');
+ while (digitp != dp->width_end);
+ }
+ has_width = 1;
+ }
+
+ has_precision = 0;
+ precision = 6;
+ if (dp->precision_start != dp->precision_end)
+ {
+ if (dp->precision_arg_index != ARG_NONE)
+ {
+ int arg;
+
+ if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+ abort ();
+ arg = a.arg[dp->precision_arg_index].a.a_int;
+ /* "A negative precision is taken as if the precision
+ were omitted." */
+ if (arg >= 0)
+ {
+ precision = arg;
+ has_precision = 1;
+ }
+ }
+ else
+ {
+ const FCHAR_T *digitp = dp->precision_start + 1;
+
+ precision = 0;
+ while (digitp != dp->precision_end)
+ precision = xsum (xtimes (precision, 10), *digitp++ - '0');
+ has_precision = 1;
+ }
+ }
+
+# if WIDE_CHAR_VERSION
+ /* %s in vasnwprintf. See the specification of fwprintf. */
+ {
+ const char *arg = a.arg[dp->arg_index].a.a_string;
+ const char *arg_end;
+ size_t characters;
+
+ if (has_precision)
+ {
+ /* Use only as many bytes as needed to produce PRECISION
+ wide characters, from the left. */
+# if HAVE_MBRTOWC
+ mbstate_t state;
+ memset (&state, '\0', sizeof (mbstate_t));
+# endif
+ arg_end = arg;
+ characters = 0;
+ for (; precision > 0; precision--)
+ {
+ int count;
+# if HAVE_MBRTOWC
+ count = mbrlen (arg_end, MB_CUR_MAX, &state);
+# else
+ count = mblen (arg_end, MB_CUR_MAX);
+# endif
+ if (count == 0)
+ /* Found the terminating NUL. */
+ break;
+ if (count < 0)
+ {
+ /* Invalid or incomplete multibyte character. */
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ CLEANUP ();
+ errno = EILSEQ;
+ return NULL;
+ }
+ arg_end += count;
+ characters++;
+ }
+ }
+ else if (has_width)
+ {
+ /* Use the entire string, and count the number of wide
+ characters. */
+# if HAVE_MBRTOWC
+ mbstate_t state;
+ memset (&state, '\0', sizeof (mbstate_t));
+# endif
+ arg_end = arg;
+ characters = 0;
+ for (;;)
+ {
+ int count;
+# if HAVE_MBRTOWC
+ count = mbrlen (arg_end, MB_CUR_MAX, &state);
+# else
+ count = mblen (arg_end, MB_CUR_MAX);
+# endif
+ if (count == 0)
+ /* Found the terminating NUL. */
+ break;
+ if (count < 0)
+ {
+ /* Invalid or incomplete multibyte character. */
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ CLEANUP ();
+ errno = EILSEQ;
+ return NULL;
+ }
+ arg_end += count;
+ characters++;
+ }
+ }
+ else
+ {
+ /* Use the entire string. */
+ arg_end = arg + strlen (arg);
+ /* The number of characters doesn't matter. */
+ characters = 0;
+ }
+
+ if (has_width && width > characters
+ && !(dp->flags & FLAG_LEFT))
+ {
+ size_t n = width - characters;
+ ENSURE_ALLOCATION (xsum (length, n));
+ DCHAR_SET (result + length, ' ', n);
+ length += n;
+ }
+
+ if (has_precision || has_width)
+ {
+ /* We know the number of wide characters in advance. */
+ size_t remaining;
+# if HAVE_MBRTOWC
+ mbstate_t state;
+ memset (&state, '\0', sizeof (mbstate_t));
+# endif
+ ENSURE_ALLOCATION (xsum (length, characters));
+ for (remaining = characters; remaining > 0; remaining--)
+ {
+ wchar_t wc;
+ int count;
+# if HAVE_MBRTOWC
+ count = mbrtowc (&wc, arg, arg_end - arg, &state);
+# else
+ count = mbtowc (&wc, arg, arg_end - arg);
+# endif
+ if (count <= 0)
+ /* mbrtowc not consistent with mbrlen, or mbtowc
+ not consistent with mblen. */
+ abort ();
+ result[length++] = wc;
+ arg += count;
+ }
+ if (!(arg == arg_end))
+ abort ();
+ }
+ else
+ {
+# if HAVE_MBRTOWC
+ mbstate_t state;
+ memset (&state, '\0', sizeof (mbstate_t));
+# endif
+ while (arg < arg_end)
+ {
+ wchar_t wc;
+ int count;
+# if HAVE_MBRTOWC
+ count = mbrtowc (&wc, arg, arg_end - arg, &state);
+# else
+ count = mbtowc (&wc, arg, arg_end - arg);
+# endif
+ if (count <= 0)
+ /* mbrtowc not consistent with mbrlen, or mbtowc
+ not consistent with mblen. */
+ abort ();
+ ENSURE_ALLOCATION (xsum (length, 1));
+ result[length++] = wc;
+ arg += count;
+ }
+ }
+
+ if (has_width && width > characters
+ && (dp->flags & FLAG_LEFT))
+ {
+ size_t n = width - characters;
+ ENSURE_ALLOCATION (xsum (length, n));
+ DCHAR_SET (result + length, ' ', n);
+ length += n;
+ }
+ }
+# else
+ /* %ls in vasnprintf. See the specification of fprintf. */
+ {
+ const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
+ const wchar_t *arg_end;
+ size_t characters;
+# if !DCHAR_IS_TCHAR
+ /* This code assumes that TCHAR_T is 'char'. */
+ typedef int TCHAR_T_verify[2 * (sizeof (TCHAR_T) == 1) - 1];
+ TCHAR_T *tmpsrc;
+ DCHAR_T *tmpdst;
+ size_t tmpdst_len;
+# endif
+ size_t w;
+
+ if (has_precision)
+ {
+ /* Use only as many wide characters as needed to produce
+ at most PRECISION bytes, from the left. */
+# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
+ mbstate_t state;
+ memset (&state, '\0', sizeof (mbstate_t));
+# endif
+ arg_end = arg;
+ characters = 0;
+ while (precision > 0)
+ {
+ char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
+ int count;
+
+ if (*arg_end == 0)
+ /* Found the terminating null wide character. */
+ break;
+# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
+ count = wcrtomb (cbuf, *arg_end, &state);
+# else
+ count = wctomb (cbuf, *arg_end);
+# endif
+ if (count < 0)
+ {
+ /* Cannot convert. */
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ CLEANUP ();
+ errno = EILSEQ;
+ return NULL;
+ }
+ if (precision < count)
+ break;
+ arg_end++;
+ characters += count;
+ precision -= count;
+ }
+ }
+# if DCHAR_IS_TCHAR
+ else if (has_width)
+# else
+ else
+# endif
+ {
+ /* Use the entire string, and count the number of
+ bytes. */
+# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
+ mbstate_t state;
+ memset (&state, '\0', sizeof (mbstate_t));
+# endif
+ arg_end = arg;
+ characters = 0;
+ for (;;)
+ {
+ char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
+ int count;
+
+ if (*arg_end == 0)
+ /* Found the terminating null wide character. */
+ break;
+# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
+ count = wcrtomb (cbuf, *arg_end, &state);
+# else
+ count = wctomb (cbuf, *arg_end);
+# endif
+ if (count < 0)
+ {
+ /* Cannot convert. */
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ CLEANUP ();
+ errno = EILSEQ;
+ return NULL;
+ }
+ arg_end++;
+ characters += count;
+ }
+ }
+# if DCHAR_IS_TCHAR
+ else
+ {
+ /* Use the entire string. */
+ arg_end = arg + local_wcslen (arg);
+ /* The number of bytes doesn't matter. */
+ characters = 0;
+ }
+# endif
+
+# if !DCHAR_IS_TCHAR
+ /* Convert the string into a piece of temporary memory. */
+ tmpsrc = (TCHAR_T *) malloc (characters * sizeof (TCHAR_T));
+ if (tmpsrc == NULL)
+ goto out_of_memory;
+ {
+ TCHAR_T *tmpptr = tmpsrc;
+ size_t remaining;
+# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
+ mbstate_t state;
+ memset (&state, '\0', sizeof (mbstate_t));
+# endif
+ for (remaining = characters; remaining > 0; )
+ {
+ char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
+ int count;
+
+ if (*arg == 0)
+ abort ();
+# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
+ count = wcrtomb (cbuf, *arg, &state);
+# else
+ count = wctomb (cbuf, *arg);
+# endif
+ if (count <= 0)
+ /* Inconsistency. */
+ abort ();
+ memcpy (tmpptr, cbuf, count);
+ tmpptr += count;
+ arg++;
+ remaining -= count;
+ }
+ if (!(arg == arg_end))
+ abort ();
+ }
+
+ /* Convert from TCHAR_T[] to DCHAR_T[]. */
+ tmpdst =
+ DCHAR_CONV_FROM_ENCODING (locale_charset (),
+ iconveh_question_mark,
+ tmpsrc, characters,
+ NULL,
+ NULL, &tmpdst_len);
+ if (tmpdst == NULL)
+ {
+ int saved_errno = errno;
+ free (tmpsrc);
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ CLEANUP ();
+ errno = saved_errno;
+ return NULL;
+ }
+ free (tmpsrc);
+# endif
+
+ if (has_width)
+ {
+# if ENABLE_UNISTDIO
+ /* Outside POSIX, it's preferrable to compare the width
+ against the number of _characters_ of the converted
+ value. */
+ w = DCHAR_MBSNLEN (result + length, characters);
+# else
+ /* The width is compared against the number of _bytes_
+ of the converted value, says POSIX. */
+ w = characters;
+# endif
+ }
+ else
+ /* w doesn't matter. */
+ w = 0;
+
+ if (has_width && width > w
+ && !(dp->flags & FLAG_LEFT))
+ {
+ size_t n = width - w;
+ ENSURE_ALLOCATION (xsum (length, n));
+ DCHAR_SET (result + length, ' ', n);
+ length += n;
+ }
+
+# if DCHAR_IS_TCHAR
+ if (has_precision || has_width)
+ {
+ /* We know the number of bytes in advance. */
+ size_t remaining;
+# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
+ mbstate_t state;
+ memset (&state, '\0', sizeof (mbstate_t));
+# endif
+ ENSURE_ALLOCATION (xsum (length, characters));
+ for (remaining = characters; remaining > 0; )
+ {
+ char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
+ int count;
+
+ if (*arg == 0)
+ abort ();
+# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
+ count = wcrtomb (cbuf, *arg, &state);
+# else
+ count = wctomb (cbuf, *arg);
+# endif
+ if (count <= 0)
+ /* Inconsistency. */
+ abort ();
+ memcpy (result + length, cbuf, count);
+ length += count;
+ arg++;
+ remaining -= count;
+ }
+ if (!(arg == arg_end))
+ abort ();
+ }
+ else
+ {
+# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
+ mbstate_t state;
+ memset (&state, '\0', sizeof (mbstate_t));
+# endif
+ while (arg < arg_end)
+ {
+ char cbuf[64]; /* Assume MB_CUR_MAX <= 64. */
+ int count;
+
+ if (*arg == 0)
+ abort ();
+# if HAVE_WCRTOMB && !defined GNULIB_defined_mbstate_t
+ count = wcrtomb (cbuf, *arg, &state);
+# else
+ count = wctomb (cbuf, *arg);
+# endif
+ if (count <= 0)
+ {
+ /* Cannot convert. */
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ CLEANUP ();
+ errno = EILSEQ;
+ return NULL;
+ }
+ ENSURE_ALLOCATION (xsum (length, count));
+ memcpy (result + length, cbuf, count);
+ length += count;
+ arg++;
+ }
+ }
+# else
+ ENSURE_ALLOCATION (xsum (length, tmpdst_len));
+ DCHAR_CPY (result + length, tmpdst, tmpdst_len);
+ free (tmpdst);
+ length += tmpdst_len;
+# endif
+
+ if (has_width && width > w
+ && (dp->flags & FLAG_LEFT))
+ {
+ size_t n = width - w;
+ ENSURE_ALLOCATION (xsum (length, n));
+ DCHAR_SET (result + length, ' ', n);
+ length += n;
+ }
+ }
+# endif
+ }
+#endif
+#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
+ else if ((dp->conversion == 'a' || dp->conversion == 'A')
+# if !(NEED_PRINTF_DIRECTIVE_A || (NEED_PRINTF_LONG_DOUBLE && NEED_PRINTF_DOUBLE))
+ && (0
+# if NEED_PRINTF_DOUBLE
+ || a.arg[dp->arg_index].type == TYPE_DOUBLE
+# endif
+# if NEED_PRINTF_LONG_DOUBLE
+ || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
+# endif
+ )
+# endif
+ )
+ {
+ arg_type type = a.arg[dp->arg_index].type;
+ int flags = dp->flags;
+ int has_width;
+ size_t width;
+ int has_precision;
+ size_t precision;
+ size_t tmp_length;
+ DCHAR_T tmpbuf[700];
+ DCHAR_T *tmp;
+ DCHAR_T *pad_ptr;
+ DCHAR_T *p;
+
+ has_width = 0;
+ width = 0;
+ if (dp->width_start != dp->width_end)
+ {
+ if (dp->width_arg_index != ARG_NONE)
+ {
+ int arg;
+
+ if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+ abort ();
+ arg = a.arg[dp->width_arg_index].a.a_int;
+ if (arg < 0)
+ {
+ /* "A negative field width is taken as a '-' flag
+ followed by a positive field width." */
+ flags |= FLAG_LEFT;
+ width = (unsigned int) (-arg);
+ }
+ else
+ width = arg;
+ }
+ else
+ {
+ const FCHAR_T *digitp = dp->width_start;
+
+ do
+ width = xsum (xtimes (width, 10), *digitp++ - '0');
+ while (digitp != dp->width_end);
+ }
+ has_width = 1;
+ }
+
+ has_precision = 0;
+ precision = 0;
+ if (dp->precision_start != dp->precision_end)
+ {
+ if (dp->precision_arg_index != ARG_NONE)
+ {
+ int arg;
+
+ if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+ abort ();
+ arg = a.arg[dp->precision_arg_index].a.a_int;
+ /* "A negative precision is taken as if the precision
+ were omitted." */
+ if (arg >= 0)
+ {
+ precision = arg;
+ has_precision = 1;
+ }
+ }
+ else
+ {
+ const FCHAR_T *digitp = dp->precision_start + 1;
+
+ precision = 0;
+ while (digitp != dp->precision_end)
+ precision = xsum (xtimes (precision, 10), *digitp++ - '0');
+ has_precision = 1;
+ }
+ }
+
+ /* Allocate a temporary buffer of sufficient size. */
+ if (type == TYPE_LONGDOUBLE)
+ tmp_length =
+ (unsigned int) ((LDBL_DIG + 1)
+ * 0.831 /* decimal -> hexadecimal */
+ )
+ + 1; /* turn floor into ceil */
+ else
+ tmp_length =
+ (unsigned int) ((DBL_DIG + 1)
+ * 0.831 /* decimal -> hexadecimal */
+ )
+ + 1; /* turn floor into ceil */
+ if (tmp_length < precision)
+ tmp_length = precision;
+ /* Account for sign, decimal point etc. */
+ tmp_length = xsum (tmp_length, 12);
+
+ if (tmp_length < width)
+ tmp_length = width;
+
+ tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
+
+ if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T))
+ tmp = tmpbuf;
+ else
+ {
+ size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T));
+
+ if (size_overflow_p (tmp_memsize))
+ /* Overflow, would lead to out of memory. */
+ goto out_of_memory;
+ tmp = (DCHAR_T *) malloc (tmp_memsize);
+ if (tmp == NULL)
+ /* Out of memory. */
+ goto out_of_memory;
+ }
+
+ pad_ptr = NULL;
+ p = tmp;
+ if (type == TYPE_LONGDOUBLE)
+ {
+# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE
+ long double arg = a.arg[dp->arg_index].a.a_longdouble;
+
+ if (isnanl (arg))
+ {
+ if (dp->conversion == 'A')
+ {
+ *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
+ }
+ else
+ {
+ *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
+ }
+ }
+ else
+ {
+ int sign = 0;
+ DECL_LONG_DOUBLE_ROUNDING
+
+ BEGIN_LONG_DOUBLE_ROUNDING ();
+
+ if (signbit (arg)) /* arg < 0.0L or negative zero */
+ {
+ sign = -1;
+ arg = -arg;
+ }
+
+ if (sign < 0)
+ *p++ = '-';
+ else if (flags & FLAG_SHOWSIGN)
+ *p++ = '+';
+ else if (flags & FLAG_SPACE)
+ *p++ = ' ';
+
+ if (arg > 0.0L && arg + arg == arg)
+ {
+ if (dp->conversion == 'A')
+ {
+ *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
+ }
+ else
+ {
+ *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
+ }
+ }
+ else
+ {
+ int exponent;
+ long double mantissa;
+
+ if (arg > 0.0L)
+ mantissa = printf_frexpl (arg, &exponent);
+ else
+ {
+ exponent = 0;
+ mantissa = 0.0L;
+ }
+
+ if (has_precision
+ && precision < (unsigned int) ((LDBL_DIG + 1) * 0.831) + 1)
+ {
+ /* Round the mantissa. */
+ long double tail = mantissa;
+ size_t q;
+
+ for (q = precision; ; q--)
+ {
+ int digit = (int) tail;
+ tail -= digit;
+ if (q == 0)
+ {
+ if (digit & 1 ? tail >= 0.5L : tail > 0.5L)
+ tail = 1 - tail;
+ else
+ tail = - tail;
+ break;
+ }
+ tail *= 16.0L;
+ }
+ if (tail != 0.0L)
+ for (q = precision; q > 0; q--)
+ tail *= 0.0625L;
+ mantissa += tail;
+ }
+
+ *p++ = '0';
+ *p++ = dp->conversion - 'A' + 'X';
+ pad_ptr = p;
+ {
+ int digit;
+
+ digit = (int) mantissa;
+ mantissa -= digit;
+ *p++ = '0' + digit;
+ if ((flags & FLAG_ALT)
+ || mantissa > 0.0L || precision > 0)
+ {
+ *p++ = decimal_point_char ();
+ /* This loop terminates because we assume
+ that FLT_RADIX is a power of 2. */
+ while (mantissa > 0.0L)
+ {
+ mantissa *= 16.0L;
+ digit = (int) mantissa;
+ mantissa -= digit;
+ *p++ = digit
+ + (digit < 10
+ ? '0'
+ : dp->conversion - 10);
+ if (precision > 0)
+ precision--;
+ }
+ while (precision > 0)
+ {
+ *p++ = '0';
+ precision--;
+ }
+ }
+ }
+ *p++ = dp->conversion - 'A' + 'P';
+# if WIDE_CHAR_VERSION
+ {
+ static const wchar_t decimal_format[] =
+ { '%', '+', 'd', '\0' };
+ SNPRINTF (p, 6 + 1, decimal_format, exponent);
+ }
+ while (*p != '\0')
+ p++;
+# else
+ if (sizeof (DCHAR_T) == 1)
+ {
+ sprintf ((char *) p, "%+d", exponent);
+ while (*p != '\0')
+ p++;
+ }
+ else
+ {
+ char expbuf[6 + 1];
+ const char *ep;
+ sprintf (expbuf, "%+d", exponent);
+ for (ep = expbuf; (*p = *ep) != '\0'; ep++)
+ p++;
+ }
+# endif
+ }
+
+ END_LONG_DOUBLE_ROUNDING ();
+ }
+# else
+ abort ();
+# endif
+ }
+ else
+ {
+# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE
+ double arg = a.arg[dp->arg_index].a.a_double;
+
+ if (isnand (arg))
+ {
+ if (dp->conversion == 'A')
+ {
+ *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
+ }
+ else
+ {
+ *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
+ }
+ }
+ else
+ {
+ int sign = 0;
+
+ if (signbit (arg)) /* arg < 0.0 or negative zero */
+ {
+ sign = -1;
+ arg = -arg;
+ }
+
+ if (sign < 0)
+ *p++ = '-';
+ else if (flags & FLAG_SHOWSIGN)
+ *p++ = '+';
+ else if (flags & FLAG_SPACE)
+ *p++ = ' ';
+
+ if (arg > 0.0 && arg + arg == arg)
+ {
+ if (dp->conversion == 'A')
+ {
+ *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
+ }
+ else
+ {
+ *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
+ }
+ }
+ else
+ {
+ int exponent;
+ double mantissa;
+
+ if (arg > 0.0)
+ mantissa = printf_frexp (arg, &exponent);
+ else
+ {
+ exponent = 0;
+ mantissa = 0.0;
+ }
+
+ if (has_precision
+ && precision < (unsigned int) ((DBL_DIG + 1) * 0.831) + 1)
+ {
+ /* Round the mantissa. */
+ double tail = mantissa;
+ size_t q;
+
+ for (q = precision; ; q--)
+ {
+ int digit = (int) tail;
+ tail -= digit;
+ if (q == 0)
+ {
+ if (digit & 1 ? tail >= 0.5 : tail > 0.5)
+ tail = 1 - tail;
+ else
+ tail = - tail;
+ break;
+ }
+ tail *= 16.0;
+ }
+ if (tail != 0.0)
+ for (q = precision; q > 0; q--)
+ tail *= 0.0625;
+ mantissa += tail;
+ }
+
+ *p++ = '0';
+ *p++ = dp->conversion - 'A' + 'X';
+ pad_ptr = p;
+ {
+ int digit;
+
+ digit = (int) mantissa;
+ mantissa -= digit;
+ *p++ = '0' + digit;
+ if ((flags & FLAG_ALT)
+ || mantissa > 0.0 || precision > 0)
+ {
+ *p++ = decimal_point_char ();
+ /* This loop terminates because we assume
+ that FLT_RADIX is a power of 2. */
+ while (mantissa > 0.0)
+ {
+ mantissa *= 16.0;
+ digit = (int) mantissa;
+ mantissa -= digit;
+ *p++ = digit
+ + (digit < 10
+ ? '0'
+ : dp->conversion - 10);
+ if (precision > 0)
+ precision--;
+ }
+ while (precision > 0)
+ {
+ *p++ = '0';
+ precision--;
+ }
+ }
+ }
+ *p++ = dp->conversion - 'A' + 'P';
+# if WIDE_CHAR_VERSION
+ {
+ static const wchar_t decimal_format[] =
+ { '%', '+', 'd', '\0' };
+ SNPRINTF (p, 6 + 1, decimal_format, exponent);
+ }
+ while (*p != '\0')
+ p++;
+# else
+ if (sizeof (DCHAR_T) == 1)
+ {
+ sprintf ((char *) p, "%+d", exponent);
+ while (*p != '\0')
+ p++;
+ }
+ else
+ {
+ char expbuf[6 + 1];
+ const char *ep;
+ sprintf (expbuf, "%+d", exponent);
+ for (ep = expbuf; (*p = *ep) != '\0'; ep++)
+ p++;
+ }
+# endif
+ }
+ }
+# else
+ abort ();
+# endif
+ }
+ /* The generated string now extends from tmp to p, with the
+ zero padding insertion point being at pad_ptr. */
+ if (has_width && p - tmp < width)
+ {
+ size_t pad = width - (p - tmp);
+ DCHAR_T *end = p + pad;
+
+ if (flags & FLAG_LEFT)
+ {
+ /* Pad with spaces on the right. */
+ for (; pad > 0; pad--)
+ *p++ = ' ';
+ }
+ else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
+ {
+ /* Pad with zeroes. */
+ DCHAR_T *q = end;
+
+ while (p > pad_ptr)
+ *--q = *--p;
+ for (; pad > 0; pad--)
+ *p++ = '0';
+ }
+ else
+ {
+ /* Pad with spaces on the left. */
+ DCHAR_T *q = end;
+
+ while (p > tmp)
+ *--q = *--p;
+ for (; pad > 0; pad--)
+ *p++ = ' ';
+ }
+
+ p = end;
+ }
+
+ {
+ size_t count = p - tmp;
+
+ if (count >= tmp_length)
+ /* tmp_length was incorrectly calculated - fix the
+ code above! */
+ abort ();
+
+ /* Make room for the result. */
+ if (count >= allocated - length)
+ {
+ size_t n = xsum (length, count);
+
+ ENSURE_ALLOCATION (n);
+ }
+
+ /* Append the result. */
+ memcpy (result + length, tmp, count * sizeof (DCHAR_T));
+ if (tmp != tmpbuf)
+ free (tmp);
+ length += count;
+ }
+ }
+#endif
+#if (NEED_PRINTF_INFINITE_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
+ else if ((dp->conversion == 'f' || dp->conversion == 'F'
+ || dp->conversion == 'e' || dp->conversion == 'E'
+ || dp->conversion == 'g' || dp->conversion == 'G'
+ || dp->conversion == 'a' || dp->conversion == 'A')
+ && (0
+# if NEED_PRINTF_DOUBLE
+ || a.arg[dp->arg_index].type == TYPE_DOUBLE
+# elif NEED_PRINTF_INFINITE_DOUBLE
+ || (a.arg[dp->arg_index].type == TYPE_DOUBLE
+ /* The systems (mingw) which produce wrong output
+ for Inf, -Inf, and NaN also do so for -0.0.
+ Therefore we treat this case here as well. */
+ && is_infinite_or_zero (a.arg[dp->arg_index].a.a_double))
+# endif
+# if NEED_PRINTF_LONG_DOUBLE
+ || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
+# elif NEED_PRINTF_INFINITE_LONG_DOUBLE
+ || (a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
+ /* Some systems produce wrong output for Inf,
+ -Inf, and NaN. Some systems in this category
+ (IRIX 5.3) also do so for -0.0. Therefore we
+ treat this case here as well. */
+ && is_infinite_or_zerol (a.arg[dp->arg_index].a.a_longdouble))
+# endif
+ ))
+ {
+# if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE)
+ arg_type type = a.arg[dp->arg_index].type;
+# endif
+ int flags = dp->flags;
+ int has_width;
+ size_t width;
+ int has_precision;
+ size_t precision;
+ size_t tmp_length;
+ DCHAR_T tmpbuf[700];
+ DCHAR_T *tmp;
+ DCHAR_T *pad_ptr;
+ DCHAR_T *p;
+
+ has_width = 0;
+ width = 0;
+ if (dp->width_start != dp->width_end)
+ {
+ if (dp->width_arg_index != ARG_NONE)
+ {
+ int arg;
+
+ if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+ abort ();
+ arg = a.arg[dp->width_arg_index].a.a_int;
+ if (arg < 0)
+ {
+ /* "A negative field width is taken as a '-' flag
+ followed by a positive field width." */
+ flags |= FLAG_LEFT;
+ width = (unsigned int) (-arg);
+ }
+ else
+ width = arg;
+ }
+ else
+ {
+ const FCHAR_T *digitp = dp->width_start;
+
+ do
+ width = xsum (xtimes (width, 10), *digitp++ - '0');
+ while (digitp != dp->width_end);
+ }
+ has_width = 1;
+ }
+
+ has_precision = 0;
+ precision = 0;
+ if (dp->precision_start != dp->precision_end)
+ {
+ if (dp->precision_arg_index != ARG_NONE)
+ {
+ int arg;
+
+ if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+ abort ();
+ arg = a.arg[dp->precision_arg_index].a.a_int;
+ /* "A negative precision is taken as if the precision
+ were omitted." */
+ if (arg >= 0)
+ {
+ precision = arg;
+ has_precision = 1;
+ }
+ }
+ else
+ {
+ const FCHAR_T *digitp = dp->precision_start + 1;
+
+ precision = 0;
+ while (digitp != dp->precision_end)
+ precision = xsum (xtimes (precision, 10), *digitp++ - '0');
+ has_precision = 1;
+ }
+ }
+
+ /* POSIX specifies the default precision to be 6 for %f, %F,
+ %e, %E, but not for %g, %G. Implementations appear to use
+ the same default precision also for %g, %G. But for %a, %A,
+ the default precision is 0. */
+ if (!has_precision)
+ if (!(dp->conversion == 'a' || dp->conversion == 'A'))
+ precision = 6;
+
+ /* Allocate a temporary buffer of sufficient size. */
+# if NEED_PRINTF_DOUBLE && NEED_PRINTF_LONG_DOUBLE
+ tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : DBL_DIG + 1);
+# elif NEED_PRINTF_INFINITE_DOUBLE && NEED_PRINTF_LONG_DOUBLE
+ tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : 0);
+# elif NEED_PRINTF_LONG_DOUBLE
+ tmp_length = LDBL_DIG + 1;
+# elif NEED_PRINTF_DOUBLE
+ tmp_length = DBL_DIG + 1;
+# else
+ tmp_length = 0;
+# endif
+ if (tmp_length < precision)
+ tmp_length = precision;
+# if NEED_PRINTF_LONG_DOUBLE
+# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
+ if (type == TYPE_LONGDOUBLE)
+# endif
+ if (dp->conversion == 'f' || dp->conversion == 'F')
+ {
+ long double arg = a.arg[dp->arg_index].a.a_longdouble;
+ if (!(isnanl (arg) || arg + arg == arg))
+ {
+ /* arg is finite and nonzero. */
+ int exponent = floorlog10l (arg < 0 ? -arg : arg);
+ if (exponent >= 0 && tmp_length < exponent + precision)
+ tmp_length = exponent + precision;
+ }
+ }
+# endif
+# if NEED_PRINTF_DOUBLE
+# if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE
+ if (type == TYPE_DOUBLE)
+# endif
+ if (dp->conversion == 'f' || dp->conversion == 'F')
+ {
+ double arg = a.arg[dp->arg_index].a.a_double;
+ if (!(isnand (arg) || arg + arg == arg))
+ {
+ /* arg is finite and nonzero. */
+ int exponent = floorlog10 (arg < 0 ? -arg : arg);
+ if (exponent >= 0 && tmp_length < exponent + precision)
+ tmp_length = exponent + precision;
+ }
+ }
+# endif
+ /* Account for sign, decimal point etc. */
+ tmp_length = xsum (tmp_length, 12);
+
+ if (tmp_length < width)
+ tmp_length = width;
+
+ tmp_length = xsum (tmp_length, 1); /* account for trailing NUL */
+
+ if (tmp_length <= sizeof (tmpbuf) / sizeof (DCHAR_T))
+ tmp = tmpbuf;
+ else
+ {
+ size_t tmp_memsize = xtimes (tmp_length, sizeof (DCHAR_T));
+
+ if (size_overflow_p (tmp_memsize))
+ /* Overflow, would lead to out of memory. */
+ goto out_of_memory;
+ tmp = (DCHAR_T *) malloc (tmp_memsize);
+ if (tmp == NULL)
+ /* Out of memory. */
+ goto out_of_memory;
+ }
+
+ pad_ptr = NULL;
+ p = tmp;
+
+# if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE
+# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
+ if (type == TYPE_LONGDOUBLE)
+# endif
+ {
+ long double arg = a.arg[dp->arg_index].a.a_longdouble;
+
+ if (isnanl (arg))
+ {
+ if (dp->conversion >= 'A' && dp->conversion <= 'Z')
+ {
+ *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
+ }
+ else
+ {
+ *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
+ }
+ }
+ else
+ {
+ int sign = 0;
+ DECL_LONG_DOUBLE_ROUNDING
+
+ BEGIN_LONG_DOUBLE_ROUNDING ();
+
+ if (signbit (arg)) /* arg < 0.0L or negative zero */
+ {
+ sign = -1;
+ arg = -arg;
+ }
+
+ if (sign < 0)
+ *p++ = '-';
+ else if (flags & FLAG_SHOWSIGN)
+ *p++ = '+';
+ else if (flags & FLAG_SPACE)
+ *p++ = ' ';
+
+ if (arg > 0.0L && arg + arg == arg)
+ {
+ if (dp->conversion >= 'A' && dp->conversion <= 'Z')
+ {
+ *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
+ }
+ else
+ {
+ *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
+ }
+ }
+ else
+ {
+# if NEED_PRINTF_LONG_DOUBLE
+ pad_ptr = p;
+
+ if (dp->conversion == 'f' || dp->conversion == 'F')
+ {
+ char *digits;
+ size_t ndigits;
+
+ digits =
+ scale10_round_decimal_long_double (arg, precision);
+ if (digits == NULL)
+ {
+ END_LONG_DOUBLE_ROUNDING ();
+ goto out_of_memory;
+ }
+ ndigits = strlen (digits);
+
+ if (ndigits > precision)
+ do
+ {
+ --ndigits;
+ *p++ = digits[ndigits];
+ }
+ while (ndigits > precision);
+ else
+ *p++ = '0';
+ /* Here ndigits <= precision. */
+ if ((flags & FLAG_ALT) || precision > 0)
+ {
+ *p++ = decimal_point_char ();
+ for (; precision > ndigits; precision--)
+ *p++ = '0';
+ while (ndigits > 0)
+ {
+ --ndigits;
+ *p++ = digits[ndigits];
+ }
+ }
+
+ free (digits);
+ }
+ else if (dp->conversion == 'e' || dp->conversion == 'E')
+ {
+ int exponent;
+
+ if (arg == 0.0L)
+ {
+ exponent = 0;
+ *p++ = '0';
+ if ((flags & FLAG_ALT) || precision > 0)
+ {
+ *p++ = decimal_point_char ();
+ for (; precision > 0; precision--)
+ *p++ = '0';
+ }
+ }
+ else
+ {
+ /* arg > 0.0L. */
+ int adjusted;
+ char *digits;
+ size_t ndigits;
+
+ exponent = floorlog10l (arg);
+ adjusted = 0;
+ for (;;)
+ {
+ digits =
+ scale10_round_decimal_long_double (arg,
+ (int)precision - exponent);
+ if (digits == NULL)
+ {
+ END_LONG_DOUBLE_ROUNDING ();
+ goto out_of_memory;
+ }
+ ndigits = strlen (digits);
+
+ if (ndigits == precision + 1)
+ break;
+ if (ndigits < precision
+ || ndigits > precision + 2)
+ /* The exponent was not guessed
+ precisely enough. */
+ abort ();
+ if (adjusted)
+ /* None of two values of exponent is
+ the right one. Prevent an endless
+ loop. */
+ abort ();
+ free (digits);
+ if (ndigits == precision)
+ exponent -= 1;
+ else
+ exponent += 1;
+ adjusted = 1;
+ }
+ /* Here ndigits = precision+1. */
+ if (is_borderline (digits, precision))
+ {
+ /* Maybe the exponent guess was too high
+ and a smaller exponent can be reached
+ by turning a 10...0 into 9...9x. */
+ char *digits2 =
+ scale10_round_decimal_long_double (arg,
+ (int)precision - exponent + 1);
+ if (digits2 == NULL)
+ {
+ free (digits);
+ END_LONG_DOUBLE_ROUNDING ();
+ goto out_of_memory;
+ }
+ if (strlen (digits2) == precision + 1)
+ {
+ free (digits);
+ digits = digits2;
+ exponent -= 1;
+ }
+ else
+ free (digits2);
+ }
+ /* Here ndigits = precision+1. */
+
+ *p++ = digits[--ndigits];
+ if ((flags & FLAG_ALT) || precision > 0)
+ {
+ *p++ = decimal_point_char ();
+ while (ndigits > 0)
+ {
+ --ndigits;
+ *p++ = digits[ndigits];
+ }
+ }
+
+ free (digits);
+ }
+
+ *p++ = dp->conversion; /* 'e' or 'E' */
+# if WIDE_CHAR_VERSION
+ {
+ static const wchar_t decimal_format[] =
+ { '%', '+', '.', '2', 'd', '\0' };
+ SNPRINTF (p, 6 + 1, decimal_format, exponent);
+ }
+ while (*p != '\0')
+ p++;
+# else
+ if (sizeof (DCHAR_T) == 1)
+ {
+ sprintf ((char *) p, "%+.2d", exponent);
+ while (*p != '\0')
+ p++;
+ }
+ else
+ {
+ char expbuf[6 + 1];
+ const char *ep;
+ sprintf (expbuf, "%+.2d", exponent);
+ for (ep = expbuf; (*p = *ep) != '\0'; ep++)
+ p++;
+ }
+# endif
+ }
+ else if (dp->conversion == 'g' || dp->conversion == 'G')
+ {
+ if (precision == 0)
+ precision = 1;
+ /* precision >= 1. */
+
+ if (arg == 0.0L)
+ /* The exponent is 0, >= -4, < precision.
+ Use fixed-point notation. */
+ {
+ size_t ndigits = precision;
+ /* Number of trailing zeroes that have to be
+ dropped. */
+ size_t nzeroes =
+ (flags & FLAG_ALT ? 0 : precision - 1);
+
+ --ndigits;
+ *p++ = '0';
+ if ((flags & FLAG_ALT) || ndigits > nzeroes)
+ {
+ *p++ = decimal_point_char ();
+ while (ndigits > nzeroes)
+ {
+ --ndigits;
+ *p++ = '0';
+ }
+ }
+ }
+ else
+ {
+ /* arg > 0.0L. */
+ int exponent;
+ int adjusted;
+ char *digits;
+ size_t ndigits;
+ size_t nzeroes;
+
+ exponent = floorlog10l (arg);
+ adjusted = 0;
+ for (;;)
+ {
+ digits =
+ scale10_round_decimal_long_double (arg,
+ (int)(precision - 1) - exponent);
+ if (digits == NULL)
+ {
+ END_LONG_DOUBLE_ROUNDING ();
+ goto out_of_memory;
+ }
+ ndigits = strlen (digits);
+
+ if (ndigits == precision)
+ break;
+ if (ndigits < precision - 1
+ || ndigits > precision + 1)
+ /* The exponent was not guessed
+ precisely enough. */
+ abort ();
+ if (adjusted)
+ /* None of two values of exponent is
+ the right one. Prevent an endless
+ loop. */
+ abort ();
+ free (digits);
+ if (ndigits < precision)
+ exponent -= 1;
+ else
+ exponent += 1;
+ adjusted = 1;
+ }
+ /* Here ndigits = precision. */
+ if (is_borderline (digits, precision - 1))
+ {
+ /* Maybe the exponent guess was too high
+ and a smaller exponent can be reached
+ by turning a 10...0 into 9...9x. */
+ char *digits2 =
+ scale10_round_decimal_long_double (arg,
+ (int)(precision - 1) - exponent + 1);
+ if (digits2 == NULL)
+ {
+ free (digits);
+ END_LONG_DOUBLE_ROUNDING ();
+ goto out_of_memory;
+ }
+ if (strlen (digits2) == precision)
+ {
+ free (digits);
+ digits = digits2;
+ exponent -= 1;
+ }
+ else
+ free (digits2);
+ }
+ /* Here ndigits = precision. */
+
+ /* Determine the number of trailing zeroes
+ that have to be dropped. */
+ nzeroes = 0;
+ if ((flags & FLAG_ALT) == 0)
+ while (nzeroes < ndigits
+ && digits[nzeroes] == '0')
+ nzeroes++;
+
+ /* The exponent is now determined. */
+ if (exponent >= -4
+ && exponent < (long)precision)
+ {
+ /* Fixed-point notation:
+ max(exponent,0)+1 digits, then the
+ decimal point, then the remaining
+ digits without trailing zeroes. */
+ if (exponent >= 0)
+ {
+ size_t count = exponent + 1;
+ /* Note: count <= precision = ndigits. */
+ for (; count > 0; count--)
+ *p++ = digits[--ndigits];
+ if ((flags & FLAG_ALT) || ndigits > nzeroes)
+ {
+ *p++ = decimal_point_char ();
+ while (ndigits > nzeroes)
+ {
+ --ndigits;
+ *p++ = digits[ndigits];
+ }
+ }
+ }
+ else
+ {
+ size_t count = -exponent - 1;
+ *p++ = '0';
+ *p++ = decimal_point_char ();
+ for (; count > 0; count--)
+ *p++ = '0';
+ while (ndigits > nzeroes)
+ {
+ --ndigits;
+ *p++ = digits[ndigits];
+ }
+ }
+ }
+ else
+ {
+ /* Exponential notation. */
+ *p++ = digits[--ndigits];
+ if ((flags & FLAG_ALT) || ndigits > nzeroes)
+ {
+ *p++ = decimal_point_char ();
+ while (ndigits > nzeroes)
+ {
+ --ndigits;
+ *p++ = digits[ndigits];
+ }
+ }
+ *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */
+# if WIDE_CHAR_VERSION
+ {
+ static const wchar_t decimal_format[] =
+ { '%', '+', '.', '2', 'd', '\0' };
+ SNPRINTF (p, 6 + 1, decimal_format, exponent);
+ }
+ while (*p != '\0')
+ p++;
+# else
+ if (sizeof (DCHAR_T) == 1)
+ {
+ sprintf ((char *) p, "%+.2d", exponent);
+ while (*p != '\0')
+ p++;
+ }
+ else
+ {
+ char expbuf[6 + 1];
+ const char *ep;
+ sprintf (expbuf, "%+.2d", exponent);
+ for (ep = expbuf; (*p = *ep) != '\0'; ep++)
+ p++;
+ }
+# endif
+ }
+
+ free (digits);
+ }
+ }
+ else
+ abort ();
+# else
+ /* arg is finite. */
+ if (!(arg == 0.0L))
+ abort ();
+
+ pad_ptr = p;
+
+ if (dp->conversion == 'f' || dp->conversion == 'F')
+ {
+ *p++ = '0';
+ if ((flags & FLAG_ALT) || precision > 0)
+ {
+ *p++ = decimal_point_char ();
+ for (; precision > 0; precision--)
+ *p++ = '0';
+ }
+ }
+ else if (dp->conversion == 'e' || dp->conversion == 'E')
+ {
+ *p++ = '0';
+ if ((flags & FLAG_ALT) || precision > 0)
+ {
+ *p++ = decimal_point_char ();
+ for (; precision > 0; precision--)
+ *p++ = '0';
+ }
+ *p++ = dp->conversion; /* 'e' or 'E' */
+ *p++ = '+';
+ *p++ = '0';
+ *p++ = '0';
+ }
+ else if (dp->conversion == 'g' || dp->conversion == 'G')
+ {
+ *p++ = '0';
+ if (flags & FLAG_ALT)
+ {
+ size_t ndigits =
+ (precision > 0 ? precision - 1 : 0);
+ *p++ = decimal_point_char ();
+ for (; ndigits > 0; --ndigits)
+ *p++ = '0';
+ }
+ }
+ else if (dp->conversion == 'a' || dp->conversion == 'A')
+ {
+ *p++ = '0';
+ *p++ = dp->conversion - 'A' + 'X';
+ pad_ptr = p;
+ *p++ = '0';
+ if ((flags & FLAG_ALT) || precision > 0)
+ {
+ *p++ = decimal_point_char ();
+ for (; precision > 0; precision--)
+ *p++ = '0';
+ }
+ *p++ = dp->conversion - 'A' + 'P';
+ *p++ = '+';
+ *p++ = '0';
+ }
+ else
+ abort ();
+# endif
+ }
+
+ END_LONG_DOUBLE_ROUNDING ();
+ }
+ }
+# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
+ else
+# endif
+# endif
+# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
+ {
+ double arg = a.arg[dp->arg_index].a.a_double;
+
+ if (isnand (arg))
+ {
+ if (dp->conversion >= 'A' && dp->conversion <= 'Z')
+ {
+ *p++ = 'N'; *p++ = 'A'; *p++ = 'N';
+ }
+ else
+ {
+ *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
+ }
+ }
+ else
+ {
+ int sign = 0;
+
+ if (signbit (arg)) /* arg < 0.0 or negative zero */
+ {
+ sign = -1;
+ arg = -arg;
+ }
+
+ if (sign < 0)
+ *p++ = '-';
+ else if (flags & FLAG_SHOWSIGN)
+ *p++ = '+';
+ else if (flags & FLAG_SPACE)
+ *p++ = ' ';
+
+ if (arg > 0.0 && arg + arg == arg)
+ {
+ if (dp->conversion >= 'A' && dp->conversion <= 'Z')
+ {
+ *p++ = 'I'; *p++ = 'N'; *p++ = 'F';
+ }
+ else
+ {
+ *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
+ }
+ }
+ else
+ {
+# if NEED_PRINTF_DOUBLE
+ pad_ptr = p;
+
+ if (dp->conversion == 'f' || dp->conversion == 'F')
+ {
+ char *digits;
+ size_t ndigits;
+
+ digits =
+ scale10_round_decimal_double (arg, precision);
+ if (digits == NULL)
+ goto out_of_memory;
+ ndigits = strlen (digits);
+
+ if (ndigits > precision)
+ do
+ {
+ --ndigits;
+ *p++ = digits[ndigits];
+ }
+ while (ndigits > precision);
+ else
+ *p++ = '0';
+ /* Here ndigits <= precision. */
+ if ((flags & FLAG_ALT) || precision > 0)
+ {
+ *p++ = decimal_point_char ();
+ for (; precision > ndigits; precision--)
+ *p++ = '0';
+ while (ndigits > 0)
+ {
+ --ndigits;
+ *p++ = digits[ndigits];
+ }
+ }
+
+ free (digits);
+ }
+ else if (dp->conversion == 'e' || dp->conversion == 'E')
+ {
+ int exponent;
+
+ if (arg == 0.0)
+ {
+ exponent = 0;
+ *p++ = '0';
+ if ((flags & FLAG_ALT) || precision > 0)
+ {
+ *p++ = decimal_point_char ();
+ for (; precision > 0; precision--)
+ *p++ = '0';
+ }
+ }
+ else
+ {
+ /* arg > 0.0. */
+ int adjusted;
+ char *digits;
+ size_t ndigits;
+
+ exponent = floorlog10 (arg);
+ adjusted = 0;
+ for (;;)
+ {
+ digits =
+ scale10_round_decimal_double (arg,
+ (int)precision - exponent);
+ if (digits == NULL)
+ goto out_of_memory;
+ ndigits = strlen (digits);
+
+ if (ndigits == precision + 1)
+ break;
+ if (ndigits < precision
+ || ndigits > precision + 2)
+ /* The exponent was not guessed
+ precisely enough. */
+ abort ();
+ if (adjusted)
+ /* None of two values of exponent is
+ the right one. Prevent an endless
+ loop. */
+ abort ();
+ free (digits);
+ if (ndigits == precision)
+ exponent -= 1;
+ else
+ exponent += 1;
+ adjusted = 1;
+ }
+ /* Here ndigits = precision+1. */
+ if (is_borderline (digits, precision))
+ {
+ /* Maybe the exponent guess was too high
+ and a smaller exponent can be reached
+ by turning a 10...0 into 9...9x. */
+ char *digits2 =
+ scale10_round_decimal_double (arg,
+ (int)precision - exponent + 1);
+ if (digits2 == NULL)
+ {
+ free (digits);
+ goto out_of_memory;
+ }
+ if (strlen (digits2) == precision + 1)
+ {
+ free (digits);
+ digits = digits2;
+ exponent -= 1;
+ }
+ else
+ free (digits2);
+ }
+ /* Here ndigits = precision+1. */
+
+ *p++ = digits[--ndigits];
+ if ((flags & FLAG_ALT) || precision > 0)
+ {
+ *p++ = decimal_point_char ();
+ while (ndigits > 0)
+ {
+ --ndigits;
+ *p++ = digits[ndigits];
+ }
+ }
+
+ free (digits);
+ }
+
+ *p++ = dp->conversion; /* 'e' or 'E' */
+# if WIDE_CHAR_VERSION
+ {
+ static const wchar_t decimal_format[] =
+ /* Produce the same number of exponent digits
+ as the native printf implementation. */
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+ { '%', '+', '.', '3', 'd', '\0' };
+# else
+ { '%', '+', '.', '2', 'd', '\0' };
+# endif
+ SNPRINTF (p, 6 + 1, decimal_format, exponent);
+ }
+ while (*p != '\0')
+ p++;
+# else
+ {
+ static const char decimal_format[] =
+ /* Produce the same number of exponent digits
+ as the native printf implementation. */
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+ "%+.3d";
+# else
+ "%+.2d";
+# endif
+ if (sizeof (DCHAR_T) == 1)
+ {
+ sprintf ((char *) p, decimal_format, exponent);
+ while (*p != '\0')
+ p++;
+ }
+ else
+ {
+ char expbuf[6 + 1];
+ const char *ep;
+ sprintf (expbuf, decimal_format, exponent);
+ for (ep = expbuf; (*p = *ep) != '\0'; ep++)
+ p++;
+ }
+ }
+# endif
+ }
+ else if (dp->conversion == 'g' || dp->conversion == 'G')
+ {
+ if (precision == 0)
+ precision = 1;
+ /* precision >= 1. */
+
+ if (arg == 0.0)
+ /* The exponent is 0, >= -4, < precision.
+ Use fixed-point notation. */
+ {
+ size_t ndigits = precision;
+ /* Number of trailing zeroes that have to be
+ dropped. */
+ size_t nzeroes =
+ (flags & FLAG_ALT ? 0 : precision - 1);
+
+ --ndigits;
+ *p++ = '0';
+ if ((flags & FLAG_ALT) || ndigits > nzeroes)
+ {
+ *p++ = decimal_point_char ();
+ while (ndigits > nzeroes)
+ {
+ --ndigits;
+ *p++ = '0';
+ }
+ }
+ }
+ else
+ {
+ /* arg > 0.0. */
+ int exponent;
+ int adjusted;
+ char *digits;
+ size_t ndigits;
+ size_t nzeroes;
+
+ exponent = floorlog10 (arg);
+ adjusted = 0;
+ for (;;)
+ {
+ digits =
+ scale10_round_decimal_double (arg,
+ (int)(precision - 1) - exponent);
+ if (digits == NULL)
+ goto out_of_memory;
+ ndigits = strlen (digits);
+
+ if (ndigits == precision)
+ break;
+ if (ndigits < precision - 1
+ || ndigits > precision + 1)
+ /* The exponent was not guessed
+ precisely enough. */
+ abort ();
+ if (adjusted)
+ /* None of two values of exponent is
+ the right one. Prevent an endless
+ loop. */
+ abort ();
+ free (digits);
+ if (ndigits < precision)
+ exponent -= 1;
+ else
+ exponent += 1;
+ adjusted = 1;
+ }
+ /* Here ndigits = precision. */
+ if (is_borderline (digits, precision - 1))
+ {
+ /* Maybe the exponent guess was too high
+ and a smaller exponent can be reached
+ by turning a 10...0 into 9...9x. */
+ char *digits2 =
+ scale10_round_decimal_double (arg,
+ (int)(precision - 1) - exponent + 1);
+ if (digits2 == NULL)
+ {
+ free (digits);
+ goto out_of_memory;
+ }
+ if (strlen (digits2) == precision)
+ {
+ free (digits);
+ digits = digits2;
+ exponent -= 1;
+ }
+ else
+ free (digits2);
+ }
+ /* Here ndigits = precision. */
+
+ /* Determine the number of trailing zeroes
+ that have to be dropped. */
+ nzeroes = 0;
+ if ((flags & FLAG_ALT) == 0)
+ while (nzeroes < ndigits
+ && digits[nzeroes] == '0')
+ nzeroes++;
+
+ /* The exponent is now determined. */
+ if (exponent >= -4
+ && exponent < (long)precision)
+ {
+ /* Fixed-point notation:
+ max(exponent,0)+1 digits, then the
+ decimal point, then the remaining
+ digits without trailing zeroes. */
+ if (exponent >= 0)
+ {
+ size_t count = exponent + 1;
+ /* Note: count <= precision = ndigits. */
+ for (; count > 0; count--)
+ *p++ = digits[--ndigits];
+ if ((flags & FLAG_ALT) || ndigits > nzeroes)
+ {
+ *p++ = decimal_point_char ();
+ while (ndigits > nzeroes)
+ {
+ --ndigits;
+ *p++ = digits[ndigits];
+ }
+ }
+ }
+ else
+ {
+ size_t count = -exponent - 1;
+ *p++ = '0';
+ *p++ = decimal_point_char ();
+ for (; count > 0; count--)
+ *p++ = '0';
+ while (ndigits > nzeroes)
+ {
+ --ndigits;
+ *p++ = digits[ndigits];
+ }
+ }
+ }
+ else
+ {
+ /* Exponential notation. */
+ *p++ = digits[--ndigits];
+ if ((flags & FLAG_ALT) || ndigits > nzeroes)
+ {
+ *p++ = decimal_point_char ();
+ while (ndigits > nzeroes)
+ {
+ --ndigits;
+ *p++ = digits[ndigits];
+ }
+ }
+ *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */
+# if WIDE_CHAR_VERSION
+ {
+ static const wchar_t decimal_format[] =
+ /* Produce the same number of exponent digits
+ as the native printf implementation. */
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+ { '%', '+', '.', '3', 'd', '\0' };
+# else
+ { '%', '+', '.', '2', 'd', '\0' };
+# endif
+ SNPRINTF (p, 6 + 1, decimal_format, exponent);
+ }
+ while (*p != '\0')
+ p++;
+# else
+ {
+ static const char decimal_format[] =
+ /* Produce the same number of exponent digits
+ as the native printf implementation. */
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+ "%+.3d";
+# else
+ "%+.2d";
+# endif
+ if (sizeof (DCHAR_T) == 1)
+ {
+ sprintf ((char *) p, decimal_format, exponent);
+ while (*p != '\0')
+ p++;
+ }
+ else
+ {
+ char expbuf[6 + 1];
+ const char *ep;
+ sprintf (expbuf, decimal_format, exponent);
+ for (ep = expbuf; (*p = *ep) != '\0'; ep++)
+ p++;
+ }
+ }
+# endif
+ }
+
+ free (digits);
+ }
+ }
+ else
+ abort ();
+# else
+ /* arg is finite. */
+ if (!(arg == 0.0))
+ abort ();
+
+ pad_ptr = p;
+
+ if (dp->conversion == 'f' || dp->conversion == 'F')
+ {
+ *p++ = '0';
+ if ((flags & FLAG_ALT) || precision > 0)
+ {
+ *p++ = decimal_point_char ();
+ for (; precision > 0; precision--)
+ *p++ = '0';
+ }
+ }
+ else if (dp->conversion == 'e' || dp->conversion == 'E')
+ {
+ *p++ = '0';
+ if ((flags & FLAG_ALT) || precision > 0)
+ {
+ *p++ = decimal_point_char ();
+ for (; precision > 0; precision--)
+ *p++ = '0';
+ }
+ *p++ = dp->conversion; /* 'e' or 'E' */
+ *p++ = '+';
+ /* Produce the same number of exponent digits as
+ the native printf implementation. */
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+ *p++ = '0';
+# endif
+ *p++ = '0';
+ *p++ = '0';
+ }
+ else if (dp->conversion == 'g' || dp->conversion == 'G')
+ {
+ *p++ = '0';
+ if (flags & FLAG_ALT)
+ {
+ size_t ndigits =
+ (precision > 0 ? precision - 1 : 0);
+ *p++ = decimal_point_char ();
+ for (; ndigits > 0; --ndigits)
+ *p++ = '0';
+ }
+ }
+ else
+ abort ();
+# endif
+ }
+ }
+ }
+# endif
+
+ /* The generated string now extends from tmp to p, with the
+ zero padding insertion point being at pad_ptr. */
+ if (has_width && p - tmp < width)
+ {
+ size_t pad = width - (p - tmp);
+ DCHAR_T *end = p + pad;
+
+ if (flags & FLAG_LEFT)
+ {
+ /* Pad with spaces on the right. */
+ for (; pad > 0; pad--)
+ *p++ = ' ';
+ }
+ else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
+ {
+ /* Pad with zeroes. */
+ DCHAR_T *q = end;
+
+ while (p > pad_ptr)
+ *--q = *--p;
+ for (; pad > 0; pad--)
+ *p++ = '0';
+ }
+ else
+ {
+ /* Pad with spaces on the left. */
+ DCHAR_T *q = end;
+
+ while (p > tmp)
+ *--q = *--p;
+ for (; pad > 0; pad--)
+ *p++ = ' ';
+ }
+
+ p = end;
+ }
+
+ {
+ size_t count = p - tmp;
+
+ if (count >= tmp_length)
+ /* tmp_length was incorrectly calculated - fix the
+ code above! */
+ abort ();
+
+ /* Make room for the result. */
+ if (count >= allocated - length)
+ {
+ size_t n = xsum (length, count);
+
+ ENSURE_ALLOCATION (n);
+ }
+
+ /* Append the result. */
+ memcpy (result + length, tmp, count * sizeof (DCHAR_T));
+ if (tmp != tmpbuf)
+ free (tmp);
+ length += count;
+ }
+ }
+#endif
+ else
+ {
+ arg_type type = a.arg[dp->arg_index].type;
+ int flags = dp->flags;
+#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
+ int has_width;
+ size_t width;
+#endif
+#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION
+ int has_precision;
+ size_t precision;
+#endif
+#if NEED_PRINTF_UNBOUNDED_PRECISION
+ int prec_ourselves;
+#else
+# define prec_ourselves 0
+#endif
+#if NEED_PRINTF_FLAG_LEFTADJUST
+# define pad_ourselves 1
+#elif !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
+ int pad_ourselves;
+#else
+# define pad_ourselves 0
+#endif
+ TCHAR_T *fbp;
+ unsigned int prefix_count;
+ int prefixes[2] IF_LINT (= { 0 });
+#if !USE_SNPRINTF
+ size_t tmp_length;
+ TCHAR_T tmpbuf[700];
+ TCHAR_T *tmp;
+#endif
+
+#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
+ has_width = 0;
+ width = 0;
+ if (dp->width_start != dp->width_end)
+ {
+ if (dp->width_arg_index != ARG_NONE)
+ {
+ int arg;
+
+ if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+ abort ();
+ arg = a.arg[dp->width_arg_index].a.a_int;
+ if (arg < 0)
+ {
+ /* "A negative field width is taken as a '-' flag
+ followed by a positive field width." */
+ flags |= FLAG_LEFT;
+ width = (unsigned int) (-arg);
+ }
+ else
+ width = arg;
+ }
+ else
+ {
+ const FCHAR_T *digitp = dp->width_start;
+
+ do
+ width = xsum (xtimes (width, 10), *digitp++ - '0');
+ while (digitp != dp->width_end);
+ }
+ has_width = 1;
+ }
+#endif
+
+#if !USE_SNPRINTF || !HAVE_SNPRINTF_RETVAL_C99 || NEED_PRINTF_UNBOUNDED_PRECISION
+ has_precision = 0;
+ precision = 6;
+ if (dp->precision_start != dp->precision_end)
+ {
+ if (dp->precision_arg_index != ARG_NONE)
+ {
+ int arg;
+
+ if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+ abort ();
+ arg = a.arg[dp->precision_arg_index].a.a_int;
+ /* "A negative precision is taken as if the precision
+ were omitted." */
+ if (arg >= 0)
+ {
+ precision = arg;
+ has_precision = 1;
+ }
+ }
+ else
+ {
+ const FCHAR_T *digitp = dp->precision_start + 1;
+
+ precision = 0;
+ while (digitp != dp->precision_end)
+ precision = xsum (xtimes (precision, 10), *digitp++ - '0');
+ has_precision = 1;
+ }
+ }
+#endif
+
+ /* Decide whether to handle the precision ourselves. */
+#if NEED_PRINTF_UNBOUNDED_PRECISION
+ switch (dp->conversion)
+ {
+ case 'd': case 'i': case 'u':
+ case 'o':
+ case 'x': case 'X': case 'p':
+ prec_ourselves = has_precision && (precision > 0);
+ break;
+ default:
+ prec_ourselves = 0;
+ break;
+ }
+#endif
+
+ /* Decide whether to perform the padding ourselves. */
+#if !NEED_PRINTF_FLAG_LEFTADJUST && (!DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION)
+ switch (dp->conversion)
+ {
+# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO
+ /* If we need conversion from TCHAR_T[] to DCHAR_T[], we need
+ to perform the padding after this conversion. Functions
+ with unistdio extensions perform the padding based on
+ character count rather than element count. */
+ case 'c': case 's':
+# endif
+# if NEED_PRINTF_FLAG_ZERO
+ case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
+ case 'a': case 'A':
+# endif
+ pad_ourselves = 1;
+ break;
+ default:
+ pad_ourselves = prec_ourselves;
+ break;
+ }
+#endif
+
+#if !USE_SNPRINTF
+ /* Allocate a temporary buffer of sufficient size for calling
+ sprintf. */
+ tmp_length =
+ MAX_ROOM_NEEDED (&a, dp->arg_index, dp->conversion, type,
+ flags, width, has_precision, precision,
+ pad_ourselves);
+
+ if (tmp_length <= sizeof (tmpbuf) / sizeof (TCHAR_T))
+ tmp = tmpbuf;
+ else
+ {
+ size_t tmp_memsize = xtimes (tmp_length, sizeof (TCHAR_T));
+
+ if (size_overflow_p (tmp_memsize))
+ /* Overflow, would lead to out of memory. */
+ goto out_of_memory;
+ tmp = (TCHAR_T *) malloc (tmp_memsize);
+ if (tmp == NULL)
+ /* Out of memory. */
+ goto out_of_memory;
+ }
+#endif
+
+ /* Construct the format string for calling snprintf or
+ sprintf. */
+ fbp = buf;
+ *fbp++ = '%';
+#if NEED_PRINTF_FLAG_GROUPING
+ /* The underlying implementation doesn't support the ' flag.
+ Produce no grouping characters in this case; this is
+ acceptable because the grouping is locale dependent. */
+#else
+ if (flags & FLAG_GROUP)
+ *fbp++ = '\'';
+#endif
+ if (flags & FLAG_LEFT)
+ *fbp++ = '-';
+ if (flags & FLAG_SHOWSIGN)
+ *fbp++ = '+';
+ if (flags & FLAG_SPACE)
+ *fbp++ = ' ';
+ if (flags & FLAG_ALT)
+ *fbp++ = '#';
+ if (!pad_ourselves)
+ {
+ if (flags & FLAG_ZERO)
+ *fbp++ = '0';
+ if (dp->width_start != dp->width_end)
+ {
+ size_t n = dp->width_end - dp->width_start;
+ /* The width specification is known to consist only
+ of standard ASCII characters. */
+ if (sizeof (FCHAR_T) == sizeof (TCHAR_T))
+ {
+ memcpy (fbp, dp->width_start, n * sizeof (TCHAR_T));
+ fbp += n;
+ }
+ else
+ {
+ const FCHAR_T *mp = dp->width_start;
+ do
+ *fbp++ = (unsigned char) *mp++;
+ while (--n > 0);
+ }
+ }
+ }
+ if (!prec_ourselves)
+ {
+ if (dp->precision_start != dp->precision_end)
+ {
+ size_t n = dp->precision_end - dp->precision_start;
+ /* The precision specification is known to consist only
+ of standard ASCII characters. */
+ if (sizeof (FCHAR_T) == sizeof (TCHAR_T))
+ {
+ memcpy (fbp, dp->precision_start, n * sizeof (TCHAR_T));
+ fbp += n;
+ }
+ else
+ {
+ const FCHAR_T *mp = dp->precision_start;
+ do
+ *fbp++ = (unsigned char) *mp++;
+ while (--n > 0);
+ }
+ }
+ }
+
+ switch (type)
+ {
+#if HAVE_LONG_LONG_INT
+ case TYPE_LONGLONGINT:
+ case TYPE_ULONGLONGINT:
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+ *fbp++ = 'I';
+ *fbp++ = '6';
+ *fbp++ = '4';
+ break;
+# else
+ *fbp++ = 'l';
+ /*FALLTHROUGH*/
+# endif
+#endif
+ case TYPE_LONGINT:
+ case TYPE_ULONGINT:
+#if HAVE_WINT_T
+ case TYPE_WIDE_CHAR:
+#endif
+#if HAVE_WCHAR_T
+ case TYPE_WIDE_STRING:
+#endif
+ *fbp++ = 'l';
+ break;
+ case TYPE_LONGDOUBLE:
+ *fbp++ = 'L';
+ break;
+ default:
+ break;
+ }
+#if NEED_PRINTF_DIRECTIVE_F
+ if (dp->conversion == 'F')
+ *fbp = 'f';
+ else
+#endif
+ *fbp = dp->conversion;
+#if USE_SNPRINTF
+# if !(__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3) || ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__))
+ fbp[1] = '%';
+ fbp[2] = 'n';
+ fbp[3] = '\0';
+# else
+ /* On glibc2 systems from glibc >= 2.3 - probably also older
+ ones - we know that snprintf's returns value conforms to
+ ISO C 99: the gl_SNPRINTF_DIRECTIVE_N test passes.
+ Therefore we can avoid using %n in this situation.
+ On glibc2 systems from 2004-10-18 or newer, the use of %n
+ in format strings in writable memory may crash the program
+ (if compiled with _FORTIFY_SOURCE=2), so we should avoid it
+ in this situation. */
+ /* On native Win32 systems (such as mingw), we can avoid using
+ %n because:
+ - Although the gl_SNPRINTF_TRUNCATION_C99 test fails,
+ snprintf does not write more than the specified number
+ of bytes. (snprintf (buf, 3, "%d %d", 4567, 89) writes
+ '4', '5', '6' into buf, not '4', '5', '\0'.)
+ - Although the gl_SNPRINTF_RETVAL_C99 test fails, snprintf
+ allows us to recognize the case of an insufficient
+ buffer size: it returns -1 in this case.
+ On native Win32 systems (such as mingw) where the OS is
+ Windows Vista, the use of %n in format strings by default
+ crashes the program. See
+ <http://gcc.gnu.org/ml/gcc/2007-06/msg00122.html> and
+ <http://msdn2.microsoft.com/en-us/library/ms175782(VS.80).aspx>
+ So we should avoid %n in this situation. */
+ fbp[1] = '\0';
+# endif
+#else
+ fbp[1] = '\0';
+#endif
+
+ /* Construct the arguments for calling snprintf or sprintf. */
+ prefix_count = 0;
+ if (!pad_ourselves && dp->width_arg_index != ARG_NONE)
+ {
+ if (!(a.arg[dp->width_arg_index].type == TYPE_INT))
+ abort ();
+ prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
+ }
+ if (!prec_ourselves && dp->precision_arg_index != ARG_NONE)
+ {
+ if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
+ abort ();
+ prefixes[prefix_count++] = a.arg[dp->precision_arg_index].a.a_int;
+ }
+
+#if USE_SNPRINTF
+ /* The SNPRINTF result is appended after result[0..length].
+ The latter is an array of DCHAR_T; SNPRINTF appends an
+ array of TCHAR_T to it. This is possible because
+ sizeof (TCHAR_T) divides sizeof (DCHAR_T) and
+ alignof (TCHAR_T) <= alignof (DCHAR_T). */
+# define TCHARS_PER_DCHAR (sizeof (DCHAR_T) / sizeof (TCHAR_T))
+ /* Ensure that maxlen below will be >= 2. Needed on BeOS,
+ where an snprintf() with maxlen==1 acts like sprintf(). */
+ ENSURE_ALLOCATION (xsum (length,
+ (2 + TCHARS_PER_DCHAR - 1)
+ / TCHARS_PER_DCHAR));
+ /* Prepare checking whether snprintf returns the count
+ via %n. */
+ *(TCHAR_T *) (result + length) = '\0';
+#endif
+
+ for (;;)
+ {
+ int count = -1;
+
+#if USE_SNPRINTF
+ int retcount = 0;
+ size_t maxlen = allocated - length;
+ /* SNPRINTF can fail if its second argument is
+ > INT_MAX. */
+ if (maxlen > INT_MAX / TCHARS_PER_DCHAR)
+ maxlen = INT_MAX / TCHARS_PER_DCHAR;
+ maxlen = maxlen * TCHARS_PER_DCHAR;
+# define SNPRINTF_BUF(arg) \
+ switch (prefix_count) \
+ { \
+ case 0: \
+ retcount = SNPRINTF ((TCHAR_T *) (result + length), \
+ maxlen, buf, \
+ arg, &count); \
+ break; \
+ case 1: \
+ retcount = SNPRINTF ((TCHAR_T *) (result + length), \
+ maxlen, buf, \
+ prefixes[0], arg, &count); \
+ break; \
+ case 2: \
+ retcount = SNPRINTF ((TCHAR_T *) (result + length), \
+ maxlen, buf, \
+ prefixes[0], prefixes[1], arg, \
+ &count); \
+ break; \
+ default: \
+ abort (); \
+ }
+#else
+# define SNPRINTF_BUF(arg) \
+ switch (prefix_count) \
+ { \
+ case 0: \
+ count = sprintf (tmp, buf, arg); \
+ break; \
+ case 1: \
+ count = sprintf (tmp, buf, prefixes[0], arg); \
+ break; \
+ case 2: \
+ count = sprintf (tmp, buf, prefixes[0], prefixes[1],\
+ arg); \
+ break; \
+ default: \
+ abort (); \
+ }
+#endif
+
+ errno = 0;
+ switch (type)
+ {
+ case TYPE_SCHAR:
+ {
+ int arg = a.arg[dp->arg_index].a.a_schar;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_UCHAR:
+ {
+ unsigned int arg = a.arg[dp->arg_index].a.a_uchar;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_SHORT:
+ {
+ int arg = a.arg[dp->arg_index].a.a_short;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_USHORT:
+ {
+ unsigned int arg = a.arg[dp->arg_index].a.a_ushort;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_INT:
+ {
+ int arg = a.arg[dp->arg_index].a.a_int;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_UINT:
+ {
+ unsigned int arg = a.arg[dp->arg_index].a.a_uint;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_LONGINT:
+ {
+ long int arg = a.arg[dp->arg_index].a.a_longint;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_ULONGINT:
+ {
+ unsigned long int arg = a.arg[dp->arg_index].a.a_ulongint;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#if HAVE_LONG_LONG_INT
+ case TYPE_LONGLONGINT:
+ {
+ long long int arg = a.arg[dp->arg_index].a.a_longlongint;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_ULONGLONGINT:
+ {
+ unsigned long long int arg = a.arg[dp->arg_index].a.a_ulonglongint;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#endif
+ case TYPE_DOUBLE:
+ {
+ double arg = a.arg[dp->arg_index].a.a_double;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_LONGDOUBLE:
+ {
+ long double arg = a.arg[dp->arg_index].a.a_longdouble;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ case TYPE_CHAR:
+ {
+ int arg = a.arg[dp->arg_index].a.a_char;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#if HAVE_WINT_T
+ case TYPE_WIDE_CHAR:
+ {
+ wint_t arg = a.arg[dp->arg_index].a.a_wide_char;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#endif
+ case TYPE_STRING:
+ {
+ const char *arg = a.arg[dp->arg_index].a.a_string;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#if HAVE_WCHAR_T
+ case TYPE_WIDE_STRING:
+ {
+ const wchar_t *arg = a.arg[dp->arg_index].a.a_wide_string;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+#endif
+ case TYPE_POINTER:
+ {
+ void *arg = a.arg[dp->arg_index].a.a_pointer;
+ SNPRINTF_BUF (arg);
+ }
+ break;
+ default:
+ abort ();
+ }
+
+#if USE_SNPRINTF
+ /* Portability: Not all implementations of snprintf()
+ are ISO C 99 compliant. Determine the number of
+ bytes that snprintf() has produced or would have
+ produced. */
+ if (count >= 0)
+ {
+ /* Verify that snprintf() has NUL-terminated its
+ result. */
+ if (count < maxlen
+ && ((TCHAR_T *) (result + length)) [count] != '\0')
+ abort ();
+ /* Portability hack. */
+ if (retcount > count)
+ count = retcount;
+ }
+ else
+ {
+ /* snprintf() doesn't understand the '%n'
+ directive. */
+ if (fbp[1] != '\0')
+ {
+ /* Don't use the '%n' directive; instead, look
+ at the snprintf() return value. */
+ fbp[1] = '\0';
+ continue;
+ }
+ else
+ {
+ /* Look at the snprintf() return value. */
+ if (retcount < 0)
+ {
+# if !HAVE_SNPRINTF_RETVAL_C99
+ /* HP-UX 10.20 snprintf() is doubly deficient:
+ It doesn't understand the '%n' directive,
+ *and* it returns -1 (rather than the length
+ that would have been required) when the
+ buffer is too small.
+ But a failure at this point can also come
+ from other reasons than a too small buffer,
+ such as an invalid wide string argument to
+ the %ls directive, or possibly an invalid
+ floating-point argument. */
+ size_t tmp_length =
+ MAX_ROOM_NEEDED (&a, dp->arg_index,
+ dp->conversion, type, flags,
+ width, has_precision,
+ precision, pad_ourselves);
+
+ if (maxlen < tmp_length)
+ {
+ /* Make more room. But try to do through
+ this reallocation only once. */
+ size_t bigger_need =
+ xsum (length,
+ xsum (tmp_length,
+ TCHARS_PER_DCHAR - 1)
+ / TCHARS_PER_DCHAR);
+ /* And always grow proportionally.
+ (There may be several arguments, each
+ needing a little more room than the
+ previous one.) */
+ size_t bigger_need2 =
+ xsum (xtimes (allocated, 2), 12);
+ if (bigger_need < bigger_need2)
+ bigger_need = bigger_need2;
+ ENSURE_ALLOCATION (bigger_need);
+ continue;
+ }
+# endif
+ }
+ else
+ count = retcount;
+ }
+ }
+#endif
+
+ /* Attempt to handle failure. */
+ if (count < 0)
+ {
+ /* SNPRINTF or sprintf failed. Save and use the errno
+ that it has set, if any. */
+ int saved_errno = errno;
+
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ CLEANUP ();
+ errno =
+ (saved_errno != 0
+ ? saved_errno
+ : (dp->conversion == 'c' || dp->conversion == 's'
+ ? EILSEQ
+ : EINVAL));
+ return NULL;
+ }
+
+#if USE_SNPRINTF
+ /* Handle overflow of the allocated buffer.
+ If such an overflow occurs, a C99 compliant snprintf()
+ returns a count >= maxlen. However, a non-compliant
+ snprintf() function returns only count = maxlen - 1. To
+ cover both cases, test whether count >= maxlen - 1. */
+ if ((unsigned int) count + 1 >= maxlen)
+ {
+ /* If maxlen already has attained its allowed maximum,
+ allocating more memory will not increase maxlen.
+ Instead of looping, bail out. */
+ if (maxlen == INT_MAX / TCHARS_PER_DCHAR)
+ goto overflow;
+ else
+ {
+ /* Need at least (count + 1) * sizeof (TCHAR_T)
+ bytes. (The +1 is for the trailing NUL.)
+ But ask for (count + 2) * sizeof (TCHAR_T)
+ bytes, so that in the next round, we likely get
+ maxlen > (unsigned int) count + 1
+ and so we don't get here again.
+ And allocate proportionally, to avoid looping
+ eternally if snprintf() reports a too small
+ count. */
+ size_t n =
+ xmax (xsum (length,
+ ((unsigned int) count + 2
+ + TCHARS_PER_DCHAR - 1)
+ / TCHARS_PER_DCHAR),
+ xtimes (allocated, 2));
+
+ ENSURE_ALLOCATION (n);
+ continue;
+ }
+ }
+#endif
+
+#if NEED_PRINTF_UNBOUNDED_PRECISION
+ if (prec_ourselves)
+ {
+ /* Handle the precision. */
+ TCHAR_T *prec_ptr =
+# if USE_SNPRINTF
+ (TCHAR_T *) (result + length);
+# else
+ tmp;
+# endif
+ size_t prefix_count;
+ size_t move;
+
+ prefix_count = 0;
+ /* Put the additional zeroes after the sign. */
+ if (count >= 1
+ && (*prec_ptr == '-' || *prec_ptr == '+'
+ || *prec_ptr == ' '))
+ prefix_count = 1;
+ /* Put the additional zeroes after the 0x prefix if
+ (flags & FLAG_ALT) || (dp->conversion == 'p'). */
+ else if (count >= 2
+ && prec_ptr[0] == '0'
+ && (prec_ptr[1] == 'x' || prec_ptr[1] == 'X'))
+ prefix_count = 2;
+
+ move = count - prefix_count;
+ if (precision > move)
+ {
+ /* Insert zeroes. */
+ size_t insert = precision - move;
+ TCHAR_T *prec_end;
+
+# if USE_SNPRINTF
+ size_t n =
+ xsum (length,
+ (count + insert + TCHARS_PER_DCHAR - 1)
+ / TCHARS_PER_DCHAR);
+ length += (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR;
+ ENSURE_ALLOCATION (n);
+ length -= (count + TCHARS_PER_DCHAR - 1) / TCHARS_PER_DCHAR;
+ prec_ptr = (TCHAR_T *) (result + length);
+# endif
+
+ prec_end = prec_ptr + count;
+ prec_ptr += prefix_count;
+
+ while (prec_end > prec_ptr)
+ {
+ prec_end--;
+ prec_end[insert] = prec_end[0];
+ }
+
+ prec_end += insert;
+ do
+ *--prec_end = '0';
+ while (prec_end > prec_ptr);
+
+ count += insert;
+ }
+ }
+#endif
+
+#if !USE_SNPRINTF
+ if (count >= tmp_length)
+ /* tmp_length was incorrectly calculated - fix the
+ code above! */
+ abort ();
+#endif
+
+#if !DCHAR_IS_TCHAR
+ /* Convert from TCHAR_T[] to DCHAR_T[]. */
+ if (dp->conversion == 'c' || dp->conversion == 's')
+ {
+ /* type = TYPE_CHAR or TYPE_WIDE_CHAR or TYPE_STRING
+ TYPE_WIDE_STRING.
+ The result string is not certainly ASCII. */
+ const TCHAR_T *tmpsrc;
+ DCHAR_T *tmpdst;
+ size_t tmpdst_len;
+ /* This code assumes that TCHAR_T is 'char'. */
+ typedef int TCHAR_T_verify
+ [2 * (sizeof (TCHAR_T) == 1) - 1];
+# if USE_SNPRINTF
+ tmpsrc = (TCHAR_T *) (result + length);
+# else
+ tmpsrc = tmp;
+# endif
+ tmpdst =
+ DCHAR_CONV_FROM_ENCODING (locale_charset (),
+ iconveh_question_mark,
+ tmpsrc, count,
+ NULL,
+ NULL, &tmpdst_len);
+ if (tmpdst == NULL)
+ {
+ int saved_errno = errno;
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ CLEANUP ();
+ errno = saved_errno;
+ return NULL;
+ }
+ ENSURE_ALLOCATION (xsum (length, tmpdst_len));
+ DCHAR_CPY (result + length, tmpdst, tmpdst_len);
+ free (tmpdst);
+ count = tmpdst_len;
+ }
+ else
+ {
+ /* The result string is ASCII.
+ Simple 1:1 conversion. */
+# if USE_SNPRINTF
+ /* If sizeof (DCHAR_T) == sizeof (TCHAR_T), it's a
+ no-op conversion, in-place on the array starting
+ at (result + length). */
+ if (sizeof (DCHAR_T) != sizeof (TCHAR_T))
+# endif
+ {
+ const TCHAR_T *tmpsrc;
+ DCHAR_T *tmpdst;
+ size_t n;
+
+# if USE_SNPRINTF
+ if (result == resultbuf)
+ {
+ tmpsrc = (TCHAR_T *) (result + length);
+ /* ENSURE_ALLOCATION will not move tmpsrc
+ (because it's part of resultbuf). */
+ ENSURE_ALLOCATION (xsum (length, count));
+ }
+ else
+ {
+ /* ENSURE_ALLOCATION will move the array
+ (because it uses realloc(). */
+ ENSURE_ALLOCATION (xsum (length, count));
+ tmpsrc = (TCHAR_T *) (result + length);
+ }
+# else
+ tmpsrc = tmp;
+ ENSURE_ALLOCATION (xsum (length, count));
+# endif
+ tmpdst = result + length;
+ /* Copy backwards, because of overlapping. */
+ tmpsrc += count;
+ tmpdst += count;
+ for (n = count; n > 0; n--)
+ *--tmpdst = (unsigned char) *--tmpsrc;
+ }
+ }
+#endif
+
+#if DCHAR_IS_TCHAR && !USE_SNPRINTF
+ /* Make room for the result. */
+ if (count > allocated - length)
+ {
+ /* Need at least count elements. But allocate
+ proportionally. */
+ size_t n =
+ xmax (xsum (length, count), xtimes (allocated, 2));
+
+ ENSURE_ALLOCATION (n);
+ }
+#endif
+
+ /* Here count <= allocated - length. */
+
+ /* Perform padding. */
+#if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_LEFTADJUST || NEED_PRINTF_FLAG_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION
+ if (pad_ourselves && has_width)
+ {
+ size_t w;
+# if ENABLE_UNISTDIO
+ /* Outside POSIX, it's preferrable to compare the width
+ against the number of _characters_ of the converted
+ value. */
+ w = DCHAR_MBSNLEN (result + length, count);
+# else
+ /* The width is compared against the number of _bytes_
+ of the converted value, says POSIX. */
+ w = count;
+# endif
+ if (w < width)
+ {
+ size_t pad = width - w;
+
+ /* Make room for the result. */
+ if (xsum (count, pad) > allocated - length)
+ {
+ /* Need at least count + pad elements. But
+ allocate proportionally. */
+ size_t n =
+ xmax (xsum3 (length, count, pad),
+ xtimes (allocated, 2));
+
+# if USE_SNPRINTF
+ length += count;
+ ENSURE_ALLOCATION (n);
+ length -= count;
+# else
+ ENSURE_ALLOCATION (n);
+# endif
+ }
+ /* Here count + pad <= allocated - length. */
+
+ {
+# if !DCHAR_IS_TCHAR || USE_SNPRINTF
+ DCHAR_T * const rp = result + length;
+# else
+ DCHAR_T * const rp = tmp;
+# endif
+ DCHAR_T *p = rp + count;
+ DCHAR_T *end = p + pad;
+ DCHAR_T *pad_ptr;
+# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO
+ if (dp->conversion == 'c'
+ || dp->conversion == 's')
+ /* No zero-padding for string directives. */
+ pad_ptr = NULL;
+ else
+# endif
+ {
+ pad_ptr = (*rp == '-' ? rp + 1 : rp);
+ /* No zero-padding of "inf" and "nan". */
+ if ((*pad_ptr >= 'A' && *pad_ptr <= 'Z')
+ || (*pad_ptr >= 'a' && *pad_ptr <= 'z'))
+ pad_ptr = NULL;
+ }
+ /* The generated string now extends from rp to p,
+ with the zero padding insertion point being at
+ pad_ptr. */
+
+ count = count + pad; /* = end - rp */
+
+ if (flags & FLAG_LEFT)
+ {
+ /* Pad with spaces on the right. */
+ for (; pad > 0; pad--)
+ *p++ = ' ';
+ }
+ else if ((flags & FLAG_ZERO) && pad_ptr != NULL)
+ {
+ /* Pad with zeroes. */
+ DCHAR_T *q = end;
+
+ while (p > pad_ptr)
+ *--q = *--p;
+ for (; pad > 0; pad--)
+ *p++ = '0';
+ }
+ else
+ {
+ /* Pad with spaces on the left. */
+ DCHAR_T *q = end;
+
+ while (p > rp)
+ *--q = *--p;
+ for (; pad > 0; pad--)
+ *p++ = ' ';
+ }
+ }
+ }
+ }
+#endif
+
+ /* Here still count <= allocated - length. */
+
+#if !DCHAR_IS_TCHAR || USE_SNPRINTF
+ /* The snprintf() result did fit. */
+#else
+ /* Append the sprintf() result. */
+ memcpy (result + length, tmp, count * sizeof (DCHAR_T));
+#endif
+#if !USE_SNPRINTF
+ if (tmp != tmpbuf)
+ free (tmp);
+#endif
+
+#if NEED_PRINTF_DIRECTIVE_F
+ if (dp->conversion == 'F')
+ {
+ /* Convert the %f result to upper case for %F. */
+ DCHAR_T *rp = result + length;
+ size_t rc;
+ for (rc = count; rc > 0; rc--, rp++)
+ if (*rp >= 'a' && *rp <= 'z')
+ *rp = *rp - 'a' + 'A';
+ }
+#endif
+
+ length += count;
+ break;
+ }
+#undef pad_ourselves
+#undef prec_ourselves
+ }
+ }
+ }
+
+ /* Add the final NUL. */
+ ENSURE_ALLOCATION (xsum (length, 1));
+ result[length] = '\0';
+
+ if (result != resultbuf && length + 1 < allocated)
+ {
+ /* Shrink the allocated memory if possible. */
+ DCHAR_T *memory;
+
+ memory = (DCHAR_T *) realloc (result, (length + 1) * sizeof (DCHAR_T));
+ if (memory != NULL)
+ result = memory;
+ }
+
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ CLEANUP ();
+ *lengthp = length;
+ /* Note that we can produce a big string of a length > INT_MAX. POSIX
+ says that snprintf() fails with errno = EOVERFLOW in this case, but
+ that's only because snprintf() returns an 'int'. This function does
+ not have this limitation. */
+ return result;
+
+#if USE_SNPRINTF
+ overflow:
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ CLEANUP ();
+ errno = EOVERFLOW;
+ return NULL;
+#endif
+
+ out_of_memory:
+ if (!(result == resultbuf || result == NULL))
+ free (result);
+ if (buf_malloced != NULL)
+ free (buf_malloced);
+ out_of_memory_1:
+ CLEANUP ();
+ errno = ENOMEM;
+ return NULL;
+ }
+}
+
+#undef MAX_ROOM_NEEDED
+#undef TCHARS_PER_DCHAR
+#undef SNPRINTF
+#undef USE_SNPRINTF
+#undef DCHAR_SET
+#undef DCHAR_CPY
+#undef PRINTF_PARSE
+#undef DIRECTIVES
+#undef DIRECTIVE
+#undef DCHAR_IS_TCHAR
+#undef TCHAR_T
+#undef DCHAR_T
+#undef FCHAR_T
+#undef VASNPRINTF
diff --git a/intl/vasnprintf.h b/intl/vasnprintf.h
new file mode 100644
index 00000000..ff1d183b
--- /dev/null
+++ b/intl/vasnprintf.h
@@ -0,0 +1,78 @@
+/* vsprintf with automatic memory allocation.
+ Copyright (C) 2002-2004 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifndef _VASNPRINTF_H
+#define _VASNPRINTF_H
+
+/* Get va_list. */
+#include <stdarg.h>
+
+/* Get size_t. */
+#include <stddef.h>
+
+#ifndef __attribute__
+/* This feature is available in gcc versions 2.5 and later. */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) || __STRICT_ANSI__
+# define __attribute__(Spec) /* empty */
+# endif
+/* The __-protected variants of `format' and `printf' attributes
+ are accepted by gcc versions 2.6.4 (effectively 2.7) and later. */
+# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
+# define __format__ format
+# define __printf__ printf
+# endif
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Write formatted output to a string dynamically allocated with malloc().
+ You can pass a preallocated buffer for the result in RESULTBUF and its
+ size in *LENGTHP; otherwise you pass RESULTBUF = NULL.
+ If successful, return the address of the string (this may be = RESULTBUF
+ if no dynamic memory allocation was necessary) and set *LENGTHP to the
+ number of resulting bytes, excluding the trailing NUL. Upon error, set
+ errno and return NULL.
+
+ When dynamic memory allocation occurs, the preallocated buffer is left
+ alone (with possibly modified contents). This makes it possible to use
+ a statically allocated or stack-allocated buffer, like this:
+
+ char buf[100];
+ size_t len = sizeof (buf);
+ char *output = vasnprintf (buf, &len, format, args);
+ if (output == NULL)
+ ... error handling ...;
+ else
+ {
+ ... use the output string ...;
+ if (output != buf)
+ free (output);
+ }
+ */
+extern char * asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...)
+ __attribute__ ((__format__ (__printf__, 3, 4)));
+extern char * vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
+ __attribute__ ((__format__ (__printf__, 3, 0)));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VASNPRINTF_H */
diff --git a/intl/vasnwprintf.h b/intl/vasnwprintf.h
new file mode 100644
index 00000000..a01745bd
--- /dev/null
+++ b/intl/vasnwprintf.h
@@ -0,0 +1,46 @@
+/* vswprintf with automatic memory allocation.
+ Copyright (C) 2002-2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifndef _VASNWPRINTF_H
+#define _VASNWPRINTF_H
+
+/* Get va_list. */
+#include <stdarg.h>
+
+/* Get wchar_t, size_t. */
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Write formatted output to a string dynamically allocated with malloc().
+ You can pass a preallocated buffer for the result in RESULTBUF and its
+ size in *LENGTHP; otherwise you pass RESULTBUF = NULL.
+ If successful, return the address of the string (this may be = RESULTBUF
+ if no dynamic memory allocation was necessary) and set *LENGTHP to the
+ number of resulting bytes, excluding the trailing NUL. Upon error, set
+ errno and return NULL. */
+extern wchar_t * asnwprintf (wchar_t *resultbuf, size_t *lengthp, const wchar_t *format, ...);
+extern wchar_t * vasnwprintf (wchar_t *resultbuf, size_t *lengthp, const wchar_t *format, va_list args);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VASNWPRINTF_H */
diff --git a/intl/version.c b/intl/version.c
new file mode 100644
index 00000000..a968cf74
--- /dev/null
+++ b/intl/version.c
@@ -0,0 +1,26 @@
+/* libintl library version.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libgnuintl.h"
+
+/* Version number: (major<<16) + (minor<<8) + subminor */
+int libintl_version = LIBINTL_VERSION;
diff --git a/intl/wprintf-parse.h b/intl/wprintf-parse.h
new file mode 100644
index 00000000..a08356ed
--- /dev/null
+++ b/intl/wprintf-parse.h
@@ -0,0 +1,75 @@
+/* Parse printf format string.
+ Copyright (C) 1999, 2002-2003 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifndef _WPRINTF_PARSE_H
+#define _WPRINTF_PARSE_H
+
+#include "printf-args.h"
+
+
+/* Flags */
+#define FLAG_GROUP 1 /* ' flag */
+#define FLAG_LEFT 2 /* - flag */
+#define FLAG_SHOWSIGN 4 /* + flag */
+#define FLAG_SPACE 8 /* space flag */
+#define FLAG_ALT 16 /* # flag */
+#define FLAG_ZERO 32
+
+/* arg_index value indicating that no argument is consumed. */
+#define ARG_NONE (~(size_t)0)
+
+/* A parsed directive. */
+typedef struct
+{
+ const wchar_t* dir_start;
+ const wchar_t* dir_end;
+ int flags;
+ const wchar_t* width_start;
+ const wchar_t* width_end;
+ size_t width_arg_index;
+ const wchar_t* precision_start;
+ const wchar_t* precision_end;
+ size_t precision_arg_index;
+ wchar_t conversion; /* d i o u x X f e E g G c s p n U % but not C S */
+ size_t arg_index;
+}
+wchar_t_directive;
+
+/* A parsed format string. */
+typedef struct
+{
+ size_t count;
+ wchar_t_directive *dir;
+ size_t max_width_length;
+ size_t max_precision_length;
+}
+wchar_t_directives;
+
+
+/* Parses the format string. Fills in the number N of directives, and fills
+ in directives[0], ..., directives[N-1], and sets directives[N].dir_start
+ to the end of the format string. Also fills in the arg_type fields of the
+ arguments and the needed count of arguments. */
+#ifdef STATIC
+STATIC
+#else
+extern
+#endif
+int wprintf_parse (const wchar_t *format, wchar_t_directives *d, arguments *a);
+
+#endif /* _WPRINTF_PARSE_H */
diff --git a/intl/xsize.h b/intl/xsize.h
new file mode 100644
index 00000000..0b0cef8e
--- /dev/null
+++ b/intl/xsize.h
@@ -0,0 +1,109 @@
+/* xsize.h -- Checked size_t computations.
+
+ Copyright (C) 2003, 2008 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ USA. */
+
+#ifndef _XSIZE_H
+#define _XSIZE_H
+
+/* Get size_t. */
+#include <stddef.h>
+
+/* Get SIZE_MAX. */
+#include <limits.h>
+#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+
+/* The size of memory objects is often computed through expressions of
+ type size_t. Example:
+ void* p = malloc (header_size + n * element_size).
+ These computations can lead to overflow. When this happens, malloc()
+ returns a piece of memory that is way too small, and the program then
+ crashes while attempting to fill the memory.
+ To avoid this, the functions and macros in this file check for overflow.
+ The convention is that SIZE_MAX represents overflow.
+ malloc (SIZE_MAX) is not guaranteed to fail -- think of a malloc
+ implementation that uses mmap --, it's recommended to use size_overflow_p()
+ or size_in_bounds_p() before invoking malloc().
+ The example thus becomes:
+ size_t size = xsum (header_size, xtimes (n, element_size));
+ void *p = (size_in_bounds_p (size) ? malloc (size) : NULL);
+*/
+
+/* Convert an arbitrary value >= 0 to type size_t. */
+#define xcast_size_t(N) \
+ ((N) <= SIZE_MAX ? (size_t) (N) : SIZE_MAX)
+
+/* Sum of two sizes, with overflow check. */
+static inline size_t
+#if __GNUC__ >= 3
+__attribute__ ((__pure__))
+#endif
+xsum (size_t size1, size_t size2)
+{
+ size_t sum = size1 + size2;
+ return (sum >= size1 ? sum : SIZE_MAX);
+}
+
+/* Sum of three sizes, with overflow check. */
+static inline size_t
+#if __GNUC__ >= 3
+__attribute__ ((__pure__))
+#endif
+xsum3 (size_t size1, size_t size2, size_t size3)
+{
+ return xsum (xsum (size1, size2), size3);
+}
+
+/* Sum of four sizes, with overflow check. */
+static inline size_t
+#if __GNUC__ >= 3
+__attribute__ ((__pure__))
+#endif
+xsum4 (size_t size1, size_t size2, size_t size3, size_t size4)
+{
+ return xsum (xsum (xsum (size1, size2), size3), size4);
+}
+
+/* Maximum of two sizes, with overflow check. */
+static inline size_t
+#if __GNUC__ >= 3
+__attribute__ ((__pure__))
+#endif
+xmax (size_t size1, size_t size2)
+{
+ /* No explicit check is needed here, because for any n:
+ max (SIZE_MAX, n) == SIZE_MAX and max (n, SIZE_MAX) == SIZE_MAX. */
+ return (size1 >= size2 ? size1 : size2);
+}
+
+/* Multiplication of a count with an element size, with overflow check.
+ The count must be >= 0 and the element size must be > 0.
+ This is a macro, not an inline function, so that it works correctly even
+ when N is of a wider type and N > SIZE_MAX. */
+#define xtimes(N, ELSIZE) \
+ ((N) <= SIZE_MAX / (ELSIZE) ? (size_t) (N) * (ELSIZE) : SIZE_MAX)
+
+/* Check for overflow. */
+#define size_overflow_p(SIZE) \
+ ((SIZE) == SIZE_MAX)
+/* Check against overflow. */
+#define size_in_bounds_p(SIZE) \
+ ((SIZE) != SIZE_MAX)
+
+#endif /* _XSIZE_H */
diff --git a/intltool-extract.in b/intltool-extract.in
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/intltool-extract.in
diff --git a/intltool-merge.in b/intltool-merge.in
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/intltool-merge.in
diff --git a/intltool-update.in b/intltool-update.in
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/intltool-update.in
diff --git a/main.c b/main.c
index 50644574..0cae38ba 100644
--- a/main.c
+++ b/main.c
@@ -42,6 +42,7 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
+#include "gettext.h"
#include "playlist.h"
#include "playback.h"
#include "unistd.h"
@@ -80,23 +81,23 @@ client_exec_command_line (const char *cmdline, int len) {
// if (filter == 1) {
// help, version and nowplaying are executed with any filter
if (!strcmp (parg, "--help") || !strcmp (parg, "-h")) {
- fprintf (stdout, "Usage: deadbeef [options] [file(s)]\n");
- fprintf (stdout, "Options:\n");
- fprintf (stdout, " --help or -h Print help (this message) and exit\n");
- fprintf (stdout, " --quit Quit player\n");
- fprintf (stdout, " --version Print version info and exit\n");
- fprintf (stdout, " --play Start playback\n");
- fprintf (stdout, " --stop Stop playback\n");
- fprintf (stdout, " --pause Pause playback\n");
- fprintf (stdout, " --next Next song in playlist\n");
- fprintf (stdout, " --prev Previous song in playlist\n");
- fprintf (stdout, " --random Random song in playlist\n");
- fprintf (stdout, " --queue Append file(s) to existing playlist\n");
- fprintf (stdout, " --nowplaying FMT Print formatted track name to stdout\n");
- fprintf (stdout, " FMT %%-syntax: [a]rtist, [t]itle, al[b]um,\n"
+ fprintf (stdout, _("Usage: deadbeef [options] [file(s)]\n"));
+ fprintf (stdout, _("Options:\n"));
+ fprintf (stdout, _(" --help or -h Print help (this message) and exit\n"));
+ fprintf (stdout, _(" --quit Quit player\n"));
+ fprintf (stdout, _(" --version Print version info and exit\n"));
+ fprintf (stdout, _(" --play Start playback\n"));
+ fprintf (stdout, _(" --stop Stop playback\n"));
+ fprintf (stdout, _(" --pause Pause playback\n"));
+ fprintf (stdout, _(" --next Next song in playlist\n"));
+ fprintf (stdout, _(" --prev Previous song in playlist\n"));
+ fprintf (stdout, _(" --random Random song in playlist\n"));
+ fprintf (stdout, _(" --queue Append file(s) to existing playlist\n"));
+ fprintf (stdout, _(" --nowplaying FMT Print formatted track name to stdout\n"));
+ fprintf (stdout, _(" FMT %%-syntax: [a]rtist, [t]itle, al[b]um,\n"
" [l]ength, track[n]umber, [y]ear, [c]omment,\n"
- " copy[r]ight, [e]lapsed\n");
- fprintf (stdout, " e.g.: --nowplaying \"%%a - %%t\" should print \"artist - title\"\n");
+ " copy[r]ight, [e]lapsed\n"));
+ fprintf (stdout, _(" e.g.: --nowplaying \"%%a - %%t\" should print \"artist - title\"\n"));
return 1;
}
else if (!strcmp (parg, "--version")) {
@@ -463,6 +464,12 @@ main (int argc, char *argv[]) {
signal (SIGSEGV, sigsegv_handler);
setlocale (LC_ALL, "");
setlocale (LC_NUMERIC, "C");
+#ifdef ENABLE_NLS
+// fprintf (stderr, "enabling gettext support: package=" PACKAGE ", dir=" LOCALEDIR "...\n");
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ bind_textdomain_codeset (PACKAGE, "UTF-8");
+ textdomain (PACKAGE);
+#endif
fprintf (stderr, "starting deadbeef " VERSION "\n");
srand (time (NULL));
#ifdef __linux__
diff --git a/playlist.c b/playlist.c
index 51470a29..f2d07dd1 100644
--- a/playlist.c
+++ b/playlist.c
@@ -15,6 +15,9 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
@@ -32,6 +35,7 @@
#endif
#include <limits.h>
#include <errno.h>
+#include "gettext.h"
#include "playlist.h"
#include "streamer.h"
#include "messagepump.h"
@@ -355,7 +359,7 @@ plt_remove (int plt) {
trace ("warning: deleting last playlist\n");
pl_clear ();
free (playlist->title);
- playlist->title = strdup ("Default");
+ playlist->title = strdup (_("Default"));
PLT_UNLOCK;
plt_gen_conf ();
plug_trigger_event (DB_EV_PLAYLISTSWITCH, 0);
@@ -2220,7 +2224,7 @@ pl_load_all (void) {
fprintf (stderr, "error: cannot make string with default playlist path\n");
return -1;
}
- if (plt_add (plt_get_count (), "Default") < 0) {
+ if (plt_add (plt_get_count (), _("Default")) < 0) {
return -1;
}
return pl_load (defpl);
diff --git a/plugins.c b/plugins.c
index b0517fab..4fcfde34 100644
--- a/plugins.c
+++ b/plugins.c
@@ -30,6 +30,7 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
+#include "gettext.h"
#include "plugins.h"
#include "md5/md5.h"
#include "messagepump.h"
@@ -829,7 +830,7 @@ plug_get_output (void) {
int
plug_select_output (void) {
- const char *outplugname = conf_get_str ("output_plugin", "ALSA output plugin");
+ const char *outplugname = conf_get_str ("output_plugin", _("ALSA output plugin"));
for (int i = 0; g_output_plugins[i]; i++) {
DB_output_t *p = g_output_plugins[i];
if (!strcmp (p->plugin.name, outplugname)) {
diff --git a/plugins/gtkui/callbacks.c b/plugins/gtkui/callbacks.c
index 6160eae2..81183a66 100644
--- a/plugins/gtkui/callbacks.c
+++ b/plugins/gtkui/callbacks.c
@@ -27,6 +27,7 @@
#include <assert.h>
#include <ctype.h>
#include <gdk/gdkkeysyms.h>
+#include "../../gettext.h"
#include "callbacks.h"
#include "interface.h"
@@ -93,7 +94,7 @@ file_filter_func (const GtkFileFilterInfo *filter_info, gpointer data) {
static GtkFileFilter *
set_file_filter (GtkWidget *dlg, const char *name) {
if (!name) {
- name = "Supported sound formats";
+ name = _("Supported sound formats");
}
GtkFileFilter* flt;
@@ -104,7 +105,7 @@ set_file_filter (GtkWidget *dlg, const char *name) {
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dlg), flt);
gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (dlg), flt);
flt = gtk_file_filter_new ();
- gtk_file_filter_set_name (flt, "Other files (*)");
+ gtk_file_filter_set_name (flt, _("Other files (*)"));
gtk_file_filter_add_pattern (flt, "*");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dlg), flt);
}
@@ -113,7 +114,7 @@ void
on_open_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
- GtkWidget *dlg = gtk_file_chooser_dialog_new ("Open file(s)...", GTK_WINDOW (mainwin), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
+ GtkWidget *dlg = gtk_file_chooser_dialog_new (_("Open file(s)..."), GTK_WINDOW (mainwin), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
set_file_filter (dlg, NULL);
@@ -146,7 +147,7 @@ void
on_add_files_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
- GtkWidget *dlg = gtk_file_chooser_dialog_new ("Add file(s) to playlist...", GTK_WINDOW (mainwin), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
+ GtkWidget *dlg = gtk_file_chooser_dialog_new (_("Add file(s) to playlist..."), GTK_WINDOW (mainwin), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
set_file_filter (dlg, NULL);
@@ -178,7 +179,7 @@ void
on_add_folders_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
- GtkWidget *dlg = gtk_file_chooser_dialog_new ("Add folder(s) to playlist...", GTK_WINDOW (mainwin), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
+ GtkWidget *dlg = gtk_file_chooser_dialog_new (_("Add folder(s) to playlist..."), GTK_WINDOW (mainwin), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
set_file_filter (dlg, NULL);
@@ -636,7 +637,7 @@ show_info_window (const char *fname, const char *title, GtkWidget **pwindow) {
char buf[s+1];
if (fread (buf, 1, s, fp) != s) {
fprintf (stderr, "error reading help file contents\n");
- const char *error = "Failed while reading help file";
+ const char *error = _("Failed while reading help file");
gtk_text_buffer_set_text (buffer, error, strlen (error));
}
else {
@@ -646,7 +647,7 @@ show_info_window (const char *fname, const char *title, GtkWidget **pwindow) {
fclose (fp);
}
else {
- const char *error = "Failed to load help file";
+ const char *error = _("Failed to load help file");
gtk_text_buffer_set_text (buffer, error, strlen (error));
}
gtk_text_view_set_buffer (GTK_TEXT_VIEW (txt), buffer);
@@ -660,7 +661,7 @@ void
on_help1_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
- show_info_window (DOCDIR "/help.txt", "Help", &helpwindow);
+ show_info_window (DOCDIR "/help.txt", _("Help"), &helpwindow);
}
static GtkWidget *aboutwindow;
@@ -669,7 +670,9 @@ void
on_about1_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
- show_info_window (DOCDIR "/about.txt", "About DeaDBeeF " VERSION, &aboutwindow);
+ char s[200];
+ snprintf (s, sizeof (s), _("About DeaDBeeF %s"), VERSION);
+ show_info_window (DOCDIR "/about.txt", s, &aboutwindow);
}
static GtkWidget *changelogwindow;
@@ -678,7 +681,9 @@ void
on_changelog1_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
- show_info_window (DOCDIR "/ChangeLog", "DeaDBeeF " VERSION " ChangeLog", &changelogwindow);
+ char s[200];
+ snprintf (s, sizeof (s), _("DeaDBeeF %s ChangeLog"), VERSION);
+ show_info_window (DOCDIR "/ChangeLog", s, &changelogwindow);
}
static GtkWidget *gplwindow;
diff --git a/plugins/gtkui/ddbtabstrip.c b/plugins/gtkui/ddbtabstrip.c
index e5cba53a..82b11003 100644
--- a/plugins/gtkui/ddbtabstrip.c
+++ b/plugins/gtkui/ddbtabstrip.c
@@ -524,7 +524,7 @@ on_rename_playlist1_activate (GtkMenuItem *menuitem,
{
GtkWidget *dlg = create_editplaylistdlg ();
gtk_dialog_set_default_response (GTK_DIALOG (dlg), GTK_RESPONSE_OK);
- gtk_window_set_title (GTK_WINDOW (dlg), "Edit playlist");
+ gtk_window_set_title (GTK_WINDOW (dlg), _("Edit playlist"));
GtkWidget *e = lookup_widget (dlg, "title");
char t[100];
plt_get_title_wrapper (tab_clicked, t, sizeof (t));
@@ -601,15 +601,15 @@ create_plmenu (void)
plmenu = gtk_menu_new ();
- rename_playlist1 = gtk_menu_item_new_with_mnemonic ("Rename Playlist");
+ rename_playlist1 = gtk_menu_item_new_with_mnemonic (_("Rename Playlist"));
gtk_widget_show (rename_playlist1);
gtk_container_add (GTK_CONTAINER (plmenu), rename_playlist1);
- remove_playlist1 = gtk_menu_item_new_with_mnemonic ("Remove Playlist");
+ remove_playlist1 = gtk_menu_item_new_with_mnemonic (_("Remove Playlist"));
gtk_widget_show (remove_playlist1);
gtk_container_add (GTK_CONTAINER (plmenu), remove_playlist1);
- add_new_playlist1 = gtk_menu_item_new_with_mnemonic ("Add New Playlist");
+ add_new_playlist1 = gtk_menu_item_new_with_mnemonic (_("Add New Playlist"));
gtk_widget_show (add_new_playlist1);
gtk_container_add (GTK_CONTAINER (plmenu), add_new_playlist1);
diff --git a/plugins/gtkui/deadbeef.glade b/plugins/gtkui/deadbeef.glade
index 4e43799b..ded6befc 100644
--- a/plugins/gtkui/deadbeef.glade
+++ b/plugins/gtkui/deadbeef.glade
@@ -6,7 +6,7 @@
<widget class="GtkWindow" id="mainwin">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK</property>
- <property name="title" translatable="yes">DeaDBeeF</property>
+ <property name="title">DeaDBeeF</property>
<property name="type">GTK_WINDOW_TOPLEVEL</property>
<property name="window_position">GTK_WIN_POS_NONE</property>
<property name="modal">False</property>
@@ -594,7 +594,7 @@
<child>
<widget class="GtkMenuItem" id="gpl1">
<property name="visible">True</property>
- <property name="label" translatable="yes">_GPLv2</property>
+ <property name="label">_GPLv2</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_gpl1_activate" last_modification_time="Wed, 06 Jan 2010 20:30:20 GMT"/>
</widget>
@@ -603,7 +603,7 @@
<child>
<widget class="GtkMenuItem" id="lgpl1">
<property name="visible">True</property>
- <property name="label" translatable="yes">_LGPLv2.1</property>
+ <property name="label">_LGPLv2.1</property>
<property name="use_underline">True</property>
<signal name="activate" handler="on_lgpl1_activate" last_modification_time="Wed, 06 Jan 2010 20:30:20 GMT"/>
</widget>
@@ -1893,7 +1893,7 @@
<child>
<widget class="GtkLabel" id="label86">
<property name="visible">True</property>
- <property name="label">_Cancel</property>
+ <property name="label" translatable="yes">_Cancel</property>
<property name="use_underline">True</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
@@ -1968,7 +1968,7 @@
<child>
<widget class="GtkLabel" id="label85">
<property name="visible">True</property>
- <property name="label">_OK</property>
+ <property name="label" translatable="yes">_OK</property>
<property name="use_underline">True</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
@@ -2361,7 +2361,7 @@ Example: %a - %t [%l]</property>
<child>
<widget class="GtkLabel" id="label91">
<property name="visible">True</property>
- <property name="label">_Close</property>
+ <property name="label" translatable="yes">_Close</property>
<property name="use_underline">True</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
@@ -2606,7 +2606,7 @@ Example: %a - %t [%l]</property>
<child>
<widget class="GtkComboBox" id="pref_src_quality">
<property name="visible">True</property>
- <property name="items" translatable="yes">sinc_best_quality
+ <property name="items">sinc_best_quality
sinc_medium_quality
sinc_fastest
zero_order_hold
@@ -3772,7 +3772,7 @@ Album</property>
<child>
<widget class="GtkComboBox" id="pref_network_proxytype">
<property name="visible">True</property>
- <property name="items" translatable="yes">HTTP
+ <property name="items">HTTP
HTTP_1_0
SOCKS4
SOCKS5
@@ -4239,7 +4239,7 @@ SOCKS5_HOSTNAME</property>
<child>
<widget class="GtkLabel" id="label68">
<property name="visible">True</property>
- <property name="label" translatable="yes">&lt;b&gt;MP3&lt;/b&gt;</property>
+ <property name="label">&lt;b&gt;MP3&lt;/b&gt;</property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
@@ -4411,7 +4411,7 @@ SOCKS5_HOSTNAME</property>
<child>
<widget class="GtkLabel" id="label70">
<property name="visible">True</property>
- <property name="label" translatable="yes">&lt;b&gt;APE&lt;/b&gt;</property>
+ <property name="label">&lt;b&gt;APE&lt;/b&gt;</property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
@@ -4577,7 +4577,7 @@ SOCKS5_HOSTNAME</property>
<child>
<widget class="GtkLabel" id="label79">
<property name="visible">True</property>
- <property name="label" translatable="yes">&lt;b&gt;WavPack&lt;/b&gt;</property>
+ <property name="label">&lt;b&gt;WavPack&lt;/b&gt;</property>
<property name="use_underline">False</property>
<property name="use_markup">True</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
@@ -5126,7 +5126,7 @@ SOCKS5_HOSTNAME</property>
<child>
<widget class="GtkLabel" id="label94">
<property name="visible">True</property>
- <property name="label">_Cancel</property>
+ <property name="label" translatable="yes">_Cancel</property>
<property name="use_underline">True</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
@@ -5201,7 +5201,7 @@ SOCKS5_HOSTNAME</property>
<child>
<widget class="GtkLabel" id="label93">
<property name="visible">True</property>
- <property name="label">_OK</property>
+ <property name="label" translatable="yes">_OK</property>
<property name="use_underline">True</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
@@ -5387,7 +5387,7 @@ SOCKS5_HOSTNAME</property>
<child>
<widget class="GtkLabel" id="label95">
<property name="visible">True</property>
- <property name="label">_Cancel</property>
+ <property name="label" translatable="yes">_Cancel</property>
<property name="use_underline">True</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
@@ -5462,7 +5462,7 @@ SOCKS5_HOSTNAME</property>
<child>
<widget class="GtkLabel" id="label96">
<property name="visible">True</property>
- <property name="label">_OK</property>
+ <property name="label" translatable="yes">_OK</property>
<property name="use_underline">True</property>
<property name="use_markup">False</property>
<property name="justify">GTK_JUSTIFY_LEFT</property>
diff --git a/plugins/gtkui/deadbeef.gladep b/plugins/gtkui/deadbeef.gladep
index 6cfb1d88..88874320 100644
--- a/plugins/gtkui/deadbeef.gladep
+++ b/plugins/gtkui/deadbeef.gladep
@@ -6,7 +6,6 @@
<program_name>deadbeef</program_name>
<source_directory></source_directory>
<gnome_support>FALSE</gnome_support>
- <gettext_support>FALSE</gettext_support>
<output_main_file>FALSE</output_main_file>
<output_build_files>FALSE</output_build_files>
</glade-project>
diff --git a/plugins/gtkui/eq.c b/plugins/gtkui/eq.c
index 01b5195d..cb62a303 100644
--- a/plugins/gtkui/eq.c
+++ b/plugins/gtkui/eq.c
@@ -110,14 +110,14 @@ on_zero_bands_clicked (GtkButton *button,
void
on_save_preset_clicked (GtkButton *button,
gpointer user_data) {
- GtkWidget *dlg = gtk_file_chooser_dialog_new ("Save DeaDBeeF EQ Preset", GTK_WINDOW (mainwin), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_OK, NULL);
+ GtkWidget *dlg = gtk_file_chooser_dialog_new (_("Save DeaDBeeF EQ Preset"), GTK_WINDOW (mainwin), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_OK, NULL);
gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dlg), TRUE);
gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dlg), "untitled.ddbeq");
GtkFileFilter* flt;
flt = gtk_file_filter_new ();
- gtk_file_filter_set_name (flt, "DeaDBeeF preset files (*.ddbeq)");
+ gtk_file_filter_set_name (flt, _("DeaDBeeF EQ preset files (*.ddbeq)"));
gtk_file_filter_add_pattern (flt, "*.ddbeq");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dlg), flt);
@@ -148,11 +148,11 @@ on_save_preset_clicked (GtkButton *button,
void
on_load_preset_clicked (GtkButton *button,
gpointer user_data) {
- GtkWidget *dlg = gtk_file_chooser_dialog_new ("Load DeaDBeeF EQ Preset...", GTK_WINDOW (mainwin), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
+ GtkWidget *dlg = gtk_file_chooser_dialog_new (_("Load DeaDBeeF EQ Preset..."), GTK_WINDOW (mainwin), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
GtkFileFilter* flt;
flt = gtk_file_filter_new ();
- gtk_file_filter_set_name (flt, "DeaDBeeF EQ presets (*.ddbeq)");
+ gtk_file_filter_set_name (flt, _("DeaDBeeF EQ presets (*.ddbeq)"));
gtk_file_filter_add_pattern (flt, "*.ddbeq");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dlg), flt);
@@ -211,11 +211,11 @@ on_load_preset_clicked (GtkButton *button,
void
on_import_fb2k_preset_clicked (GtkButton *button,
gpointer user_data) {
- GtkWidget *dlg = gtk_file_chooser_dialog_new ("Import Foobar2000 EQ Preset...", GTK_WINDOW (mainwin), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
+ GtkWidget *dlg = gtk_file_chooser_dialog_new (_("Import Foobar2000 EQ Preset..."), GTK_WINDOW (mainwin), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
GtkFileFilter* flt;
flt = gtk_file_filter_new ();
- gtk_file_filter_set_name (flt, "Foobar2000 EQ presets (*.feq)");
+ gtk_file_filter_set_name (flt, _("Foobar2000 EQ presets (*.feq)"));
gtk_file_filter_add_pattern (flt, "*.feq");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dlg), flt);
@@ -289,49 +289,49 @@ eq_window_show (void) {
GtkWidget *button;
- eqenablebtn = button = gtk_check_button_new_with_label ("Enable");
+ eqenablebtn = button = gtk_check_button_new_with_label (_("Enable"));
gtk_widget_show (button);
gtk_box_pack_start (GTK_BOX (buttons), button, FALSE, FALSE, 0);
g_signal_connect ((gpointer) button, "toggled",
G_CALLBACK (on_enable_toggled),
NULL);
- button = gtk_button_new_with_label ("Zero All");
+ button = gtk_button_new_with_label (_("Zero All"));
gtk_widget_show (button);
gtk_box_pack_start (GTK_BOX (buttons), button, FALSE, FALSE, 0);
g_signal_connect ((gpointer) button, "clicked",
G_CALLBACK (on_zero_all_clicked),
NULL);
- button = gtk_button_new_with_label ("Zero Preamp");
+ button = gtk_button_new_with_label (_("Zero Preamp"));
gtk_widget_show (button);
gtk_box_pack_start (GTK_BOX (buttons), button, FALSE, FALSE, 0);
g_signal_connect ((gpointer) button, "clicked",
G_CALLBACK (on_zero_preamp_clicked),
NULL);
- button = gtk_button_new_with_label ("Zero Bands");
+ button = gtk_button_new_with_label (_("Zero Bands"));
gtk_widget_show (button);
gtk_box_pack_start (GTK_BOX (buttons), button, FALSE, FALSE, 0);
g_signal_connect ((gpointer) button, "clicked",
G_CALLBACK (on_zero_bands_clicked),
NULL);
- button = gtk_button_new_with_label ("Save Preset");
+ button = gtk_button_new_with_label (_("Save Preset"));
gtk_widget_show (button);
gtk_box_pack_start (GTK_BOX (buttons), button, FALSE, FALSE, 0);
g_signal_connect ((gpointer) button, "clicked",
G_CALLBACK (on_save_preset_clicked),
NULL);
- button = gtk_button_new_with_label ("Load Preset");
+ button = gtk_button_new_with_label (_("Load Preset"));
gtk_widget_show (button);
gtk_box_pack_start (GTK_BOX (buttons), button, FALSE, FALSE, 0);
g_signal_connect ((gpointer) button, "clicked",
G_CALLBACK (on_load_preset_clicked),
NULL);
- button = gtk_button_new_with_label ("Import Foobar2000 Preset");
+ button = gtk_button_new_with_label (_("Import Foobar2000 Preset"));
gtk_widget_show (button);
gtk_box_pack_start (GTK_BOX (buttons), button, FALSE, FALSE, 0);
g_signal_connect ((gpointer) button, "clicked",
diff --git a/plugins/gtkui/gtkui.c b/plugins/gtkui/gtkui.c
index c6493b11..a7f41cbb 100644
--- a/plugins/gtkui/gtkui.c
+++ b/plugins/gtkui/gtkui.c
@@ -26,6 +26,7 @@
#include <math.h>
#include <sys/time.h>
#include <unistd.h>
+#include "../../gettext.h"
#include "gtkui.h"
#include "ddblistview.h"
#include "mainplaylist.h"
@@ -124,10 +125,10 @@ update_songinfo (gpointer ctx) {
snprintf (totaltime_str, sizeof (totaltime_str), "%d:%02d:%02d", hourtotal, mintotal, sectotal);
}
else if (daystotal == 1) {
- snprintf (totaltime_str, sizeof (totaltime_str), "1 day %d:%02d:%02d", hourtotal, mintotal, sectotal);
+ snprintf (totaltime_str, sizeof (totaltime_str), _("1 day %d:%02d:%02d"), hourtotal, mintotal, sectotal);
}
else {
- snprintf (totaltime_str, sizeof (totaltime_str), "%d days %d:%02d:%02d", daystotal, hourtotal, mintotal, sectotal);
+ snprintf (totaltime_str, sizeof (totaltime_str), _("%d days %d:%02d:%02d"), daystotal, hourtotal, mintotal, sectotal);
}
DB_playItem_t *track = deadbeef->streamer_get_playing_track ();
@@ -136,7 +137,7 @@ update_songinfo (gpointer ctx) {
float duration = track ? deadbeef->pl_get_item_duration (track) : -1;
if (deadbeef->get_output ()->state () == OUTPUT_STATE_STOPPED || !track || !c) {
- snprintf (sbtext_new, sizeof (sbtext_new), "Stopped | %d tracks | %s total playtime", deadbeef->pl_getcount (PL_MAIN), totaltime_str);
+ snprintf (sbtext_new, sizeof (sbtext_new), _("Stopped | %d tracks | %s total playtime"), deadbeef->pl_getcount (PL_MAIN), totaltime_str);
songpos = 0;
}
else {
@@ -146,7 +147,7 @@ update_songinfo (gpointer ctx) {
int mindur = duration / 60;
int secdur = duration - mindur * 60;
- const char *mode = c->channels == 1 ? "Mono" : "Stereo";
+ const char *mode = c->channels == 1 ? _("Mono") : _("Stereo");
int samplerate = c->samplerate;
int bitspersample = c->bps;
songpos = playpos;
@@ -166,14 +167,14 @@ update_songinfo (gpointer ctx) {
memcpy (&last_br_update, &tm, sizeof (tm));
int bitrate = deadbeef->streamer_get_apx_bitrate ();
if (bitrate > 0) {
- snprintf (sbitrate, sizeof (sbitrate), "| %4d kbps ", bitrate);
+ snprintf (sbitrate, sizeof (sbitrate), _("| %4d kbps "), bitrate);
}
else {
sbitrate[0] = 0;
}
}
- const char *spaused = deadbeef->get_output ()->state () == OUTPUT_STATE_PAUSED ? "Paused | " : "";
- snprintf (sbtext_new, sizeof (sbtext_new), "%s%s %s| %dHz | %d bit | %s | %d:%02d / %s | %d tracks | %s total playtime", spaused, track->filetype ? track->filetype:"-", sbitrate, samplerate, bitspersample, mode, minpos, secpos, t, deadbeef->pl_getcount (PL_MAIN), totaltime_str);
+ const char *spaused = deadbeef->get_output ()->state () == OUTPUT_STATE_PAUSED ? _("Paused | ") : "";
+ snprintf (sbtext_new, sizeof (sbtext_new), _("%s%s %s| %dHz | %d bit | %s | %d:%02d / %s | %d tracks | %s total playtime"), spaused, track->filetype ? track->filetype:"-", sbitrate, samplerate, bitspersample, mode, minpos, secpos, t, deadbeef->pl_getcount (PL_MAIN), totaltime_str);
}
if (strcmp (sbtext_new, sb_text)) {
@@ -529,7 +530,7 @@ char last_playlist_save_name[1024] = "";
void
save_playlist_as (void) {
- GtkWidget *dlg = gtk_file_chooser_dialog_new ("Save Playlist As", GTK_WINDOW (mainwin), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_OK, NULL);
+ GtkWidget *dlg = gtk_file_chooser_dialog_new (_("Save Playlist As"), GTK_WINDOW (mainwin), GTK_FILE_CHOOSER_ACTION_SAVE, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_SAVE, GTK_RESPONSE_OK, NULL);
gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dlg), TRUE);
gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dlg), "untitled.dbpl");
@@ -538,7 +539,7 @@ save_playlist_as (void) {
GtkFileFilter* flt;
flt = gtk_file_filter_new ();
- gtk_file_filter_set_name (flt, "DeaDBeeF playlist files (*.dbpl)");
+ gtk_file_filter_set_name (flt, _("DeaDBeeF playlist files (*.dbpl)"));
gtk_file_filter_add_pattern (flt, "*.dbpl");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dlg), flt);
@@ -592,14 +593,14 @@ void
on_playlist_load_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
- GtkWidget *dlg = gtk_file_chooser_dialog_new ("Load Playlist", GTK_WINDOW (mainwin), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
+ GtkWidget *dlg = gtk_file_chooser_dialog_new (_("Load Playlist"), GTK_WINDOW (mainwin), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
// restore folder
gtk_file_chooser_set_current_folder_uri (GTK_FILE_CHOOSER (dlg), deadbeef->conf_get_str ("filechooser.playlist.lastdir", ""));
GtkFileFilter* flt;
flt = gtk_file_filter_new ();
- gtk_file_filter_set_name (flt, "DeaDBeeF playlist files (*.dbpl)");
+ gtk_file_filter_set_name (flt, _("DeaDBeeF playlist files (*.dbpl)"));
gtk_file_filter_add_pattern (flt, "*.dbpl");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dlg), flt);
@@ -737,10 +738,10 @@ gtkui_add_new_playlist (void) {
for (;;) {
char name[100];
if (!idx) {
- strcpy (name, "New Playlist");
+ strcpy (name, _("New Playlist"));
}
else {
- snprintf (name, sizeof (name), "New Playlist (%d)", idx);
+ snprintf (name, sizeof (name), _("New Playlist (%d)"), idx);
}
for (i = 0; i < cnt; i++) {
char t[100];
diff --git a/plugins/gtkui/interface.c b/plugins/gtkui/interface.c
index ce410de5..29105a69 100644
--- a/plugins/gtkui/interface.c
+++ b/plugins/gtkui/interface.c
@@ -137,14 +137,14 @@ create_mainwin (void)
gtk_widget_show (menubar1);
gtk_box_pack_start (GTK_BOX (vbox1), menubar1, FALSE, FALSE, 0);
- menuitem1 = gtk_menu_item_new_with_mnemonic ("_File");
+ menuitem1 = gtk_menu_item_new_with_mnemonic (_("_File"));
gtk_widget_show (menuitem1);
gtk_container_add (GTK_CONTAINER (menubar1), menuitem1);
menuitem1_menu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem1), menuitem1_menu);
- open = gtk_image_menu_item_new_with_mnemonic ("_Open file(s)");
+ open = gtk_image_menu_item_new_with_mnemonic (_("_Open file(s)"));
gtk_widget_show (open);
gtk_container_add (GTK_CONTAINER (menuitem1_menu), open);
gtk_widget_add_accelerator (open, "activate", accel_group,
@@ -160,7 +160,7 @@ create_mainwin (void)
gtk_container_add (GTK_CONTAINER (menuitem1_menu), separator2);
gtk_widget_set_sensitive (separator2, FALSE);
- add_files = gtk_image_menu_item_new_with_mnemonic ("Add file(s)");
+ add_files = gtk_image_menu_item_new_with_mnemonic (_("Add file(s)"));
gtk_widget_show (add_files);
gtk_container_add (GTK_CONTAINER (menuitem1_menu), add_files);
@@ -168,7 +168,7 @@ create_mainwin (void)
gtk_widget_show (image377);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (add_files), image377);
- add_folders = gtk_image_menu_item_new_with_mnemonic ("Add folder(s)");
+ add_folders = gtk_image_menu_item_new_with_mnemonic (_("Add folder(s)"));
gtk_widget_show (add_folders);
gtk_container_add (GTK_CONTAINER (menuitem1_menu), add_folders);
@@ -176,7 +176,7 @@ create_mainwin (void)
gtk_widget_show (image378);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (add_folders), image378);
- add_audio_cd = gtk_image_menu_item_new_with_mnemonic ("Add Audio CD");
+ add_audio_cd = gtk_image_menu_item_new_with_mnemonic (_("Add Audio CD"));
gtk_widget_show (add_audio_cd);
gtk_container_add (GTK_CONTAINER (menuitem1_menu), add_audio_cd);
@@ -184,7 +184,7 @@ create_mainwin (void)
gtk_widget_show (image379);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (add_audio_cd), image379);
- add_location1 = gtk_menu_item_new_with_mnemonic ("Add location");
+ add_location1 = gtk_menu_item_new_with_mnemonic (_("Add location"));
gtk_widget_show (add_location1);
gtk_container_add (GTK_CONTAINER (menuitem1_menu), add_location1);
@@ -193,22 +193,22 @@ create_mainwin (void)
gtk_container_add (GTK_CONTAINER (menuitem1_menu), separatormenuitem1);
gtk_widget_set_sensitive (separatormenuitem1, FALSE);
- new_playlist1 = gtk_menu_item_new_with_mnemonic ("New playlist");
+ new_playlist1 = gtk_menu_item_new_with_mnemonic (_("New playlist"));
gtk_widget_show (new_playlist1);
gtk_container_add (GTK_CONTAINER (menuitem1_menu), new_playlist1);
gtk_widget_add_accelerator (new_playlist1, "activate", accel_group,
GDK_n, (GdkModifierType) GDK_CONTROL_MASK,
GTK_ACCEL_VISIBLE);
- playlist_load = gtk_menu_item_new_with_mnemonic ("Load playlist");
+ playlist_load = gtk_menu_item_new_with_mnemonic (_("Load playlist"));
gtk_widget_show (playlist_load);
gtk_container_add (GTK_CONTAINER (menuitem1_menu), playlist_load);
- playlist_save = gtk_menu_item_new_with_mnemonic ("Save playlist");
+ playlist_save = gtk_menu_item_new_with_mnemonic (_("Save playlist"));
gtk_widget_show (playlist_save);
gtk_container_add (GTK_CONTAINER (menuitem1_menu), playlist_save);
- playlist_save_as = gtk_menu_item_new_with_mnemonic ("Save playlist as");
+ playlist_save_as = gtk_menu_item_new_with_mnemonic (_("Save playlist as"));
gtk_widget_show (playlist_save_as);
gtk_container_add (GTK_CONTAINER (menuitem1_menu), playlist_save_as);
@@ -217,7 +217,7 @@ create_mainwin (void)
gtk_container_add (GTK_CONTAINER (menuitem1_menu), separator8);
gtk_widget_set_sensitive (separator8, FALSE);
- quit = gtk_image_menu_item_new_with_mnemonic ("_Quit");
+ quit = gtk_image_menu_item_new_with_mnemonic (_("_Quit"));
gtk_widget_show (quit);
gtk_container_add (GTK_CONTAINER (menuitem1_menu), quit);
gtk_widget_add_accelerator (quit, "activate", accel_group,
@@ -228,14 +228,14 @@ create_mainwin (void)
gtk_widget_show (image380);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (quit), image380);
- edit1 = gtk_menu_item_new_with_mnemonic ("_Edit");
+ edit1 = gtk_menu_item_new_with_mnemonic (_("_Edit"));
gtk_widget_show (edit1);
gtk_container_add (GTK_CONTAINER (menubar1), edit1);
edit1_menu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (edit1), edit1_menu);
- clear1 = gtk_image_menu_item_new_with_mnemonic ("_Clear");
+ clear1 = gtk_image_menu_item_new_with_mnemonic (_("_Clear"));
gtk_widget_show (clear1);
gtk_container_add (GTK_CONTAINER (edit1_menu), clear1);
@@ -243,32 +243,32 @@ create_mainwin (void)
gtk_widget_show (image381);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (clear1), image381);
- select_all1 = gtk_menu_item_new_with_mnemonic ("Select all");
+ select_all1 = gtk_menu_item_new_with_mnemonic (_("Select all"));
gtk_widget_show (select_all1);
gtk_container_add (GTK_CONTAINER (edit1_menu), select_all1);
gtk_widget_add_accelerator (select_all1, "activate", accel_group,
GDK_A, (GdkModifierType) GDK_CONTROL_MASK,
GTK_ACCEL_VISIBLE);
- deselect_all1 = gtk_menu_item_new_with_mnemonic ("Deselect all");
+ deselect_all1 = gtk_menu_item_new_with_mnemonic (_("Deselect all"));
gtk_widget_show (deselect_all1);
gtk_container_add (GTK_CONTAINER (edit1_menu), deselect_all1);
gtk_widget_add_accelerator (deselect_all1, "activate", accel_group,
GDK_Escape, (GdkModifierType) 0,
GTK_ACCEL_VISIBLE);
- invert_selection1 = gtk_menu_item_new_with_mnemonic ("Invert selection");
+ invert_selection1 = gtk_menu_item_new_with_mnemonic (_("Invert selection"));
gtk_widget_show (invert_selection1);
gtk_container_add (GTK_CONTAINER (edit1_menu), invert_selection1);
- selection1 = gtk_menu_item_new_with_mnemonic ("Selection");
+ selection1 = gtk_menu_item_new_with_mnemonic (_("Selection"));
gtk_widget_show (selection1);
gtk_container_add (GTK_CONTAINER (edit1_menu), selection1);
selection1_menu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (selection1), selection1_menu);
- remove1 = gtk_image_menu_item_new_with_mnemonic ("Remove");
+ remove1 = gtk_image_menu_item_new_with_mnemonic (_("Remove"));
gtk_widget_show (remove1);
gtk_container_add (GTK_CONTAINER (selection1_menu), remove1);
@@ -276,11 +276,11 @@ create_mainwin (void)
gtk_widget_show (image382);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (remove1), image382);
- crop1 = gtk_menu_item_new_with_mnemonic ("Crop");
+ crop1 = gtk_menu_item_new_with_mnemonic (_("Crop"));
gtk_widget_show (crop1);
gtk_container_add (GTK_CONTAINER (selection1_menu), crop1);
- find1 = gtk_menu_item_new_with_mnemonic ("_Find");
+ find1 = gtk_menu_item_new_with_mnemonic (_("_Find"));
gtk_widget_show (find1);
gtk_container_add (GTK_CONTAINER (edit1_menu), find1);
gtk_widget_add_accelerator (find1, "activate", accel_group,
@@ -292,114 +292,114 @@ create_mainwin (void)
gtk_container_add (GTK_CONTAINER (edit1_menu), separator5);
gtk_widget_set_sensitive (separator5, FALSE);
- preferences = gtk_menu_item_new_with_mnemonic ("Preferences");
+ preferences = gtk_menu_item_new_with_mnemonic (_("Preferences"));
gtk_widget_show (preferences);
gtk_container_add (GTK_CONTAINER (edit1_menu), preferences);
- view1 = gtk_menu_item_new_with_mnemonic ("_View");
+ view1 = gtk_menu_item_new_with_mnemonic (_("_View"));
gtk_widget_show (view1);
gtk_container_add (GTK_CONTAINER (menubar1), view1);
view1_menu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (view1), view1_menu);
- view_status_bar = gtk_check_menu_item_new_with_mnemonic ("Status bar");
+ view_status_bar = gtk_check_menu_item_new_with_mnemonic (_("Status bar"));
gtk_widget_show (view_status_bar);
gtk_container_add (GTK_CONTAINER (view1_menu), view_status_bar);
- view_headers = gtk_check_menu_item_new_with_mnemonic ("Column headers");
+ view_headers = gtk_check_menu_item_new_with_mnemonic (_("Column headers"));
gtk_widget_show (view_headers);
gtk_container_add (GTK_CONTAINER (view1_menu), view_headers);
- view_tabs = gtk_check_menu_item_new_with_mnemonic ("Tabs");
+ view_tabs = gtk_check_menu_item_new_with_mnemonic (_("Tabs"));
gtk_widget_show (view_tabs);
gtk_container_add (GTK_CONTAINER (view1_menu), view_tabs);
- view_eq = gtk_check_menu_item_new_with_mnemonic ("Equalizer");
+ view_eq = gtk_check_menu_item_new_with_mnemonic (_("Equalizer"));
gtk_widget_show (view_eq);
gtk_container_add (GTK_CONTAINER (view1_menu), view_eq);
- playback1 = gtk_menu_item_new_with_mnemonic ("_Playback");
+ playback1 = gtk_menu_item_new_with_mnemonic (_("_Playback"));
gtk_widget_show (playback1);
gtk_container_add (GTK_CONTAINER (menubar1), playback1);
playback1_menu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (playback1), playback1_menu);
- order1 = gtk_menu_item_new_with_mnemonic ("Order");
+ order1 = gtk_menu_item_new_with_mnemonic (_("Order"));
gtk_widget_show (order1);
gtk_container_add (GTK_CONTAINER (playback1_menu), order1);
order1_menu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (order1), order1_menu);
- order_linear = gtk_radio_menu_item_new_with_mnemonic (order_linear_group, "Linear");
+ order_linear = gtk_radio_menu_item_new_with_mnemonic (order_linear_group, _("Linear"));
order_linear_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (order_linear));
gtk_widget_show (order_linear);
gtk_container_add (GTK_CONTAINER (order1_menu), order_linear);
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (order_linear), TRUE);
- order_shuffle = gtk_radio_menu_item_new_with_mnemonic (order_linear_group, "Shuffle");
+ order_shuffle = gtk_radio_menu_item_new_with_mnemonic (order_linear_group, _("Shuffle"));
order_linear_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (order_shuffle));
gtk_widget_show (order_shuffle);
gtk_container_add (GTK_CONTAINER (order1_menu), order_shuffle);
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (order_shuffle), TRUE);
- order_random = gtk_radio_menu_item_new_with_mnemonic (order_linear_group, "Random");
+ order_random = gtk_radio_menu_item_new_with_mnemonic (order_linear_group, _("Random"));
order_linear_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (order_random));
gtk_widget_show (order_random);
gtk_container_add (GTK_CONTAINER (order1_menu), order_random);
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (order_random), TRUE);
- looping1 = gtk_menu_item_new_with_mnemonic ("Looping");
+ looping1 = gtk_menu_item_new_with_mnemonic (_("Looping"));
gtk_widget_show (looping1);
gtk_container_add (GTK_CONTAINER (playback1_menu), looping1);
looping1_menu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (looping1), looping1_menu);
- loop_all = gtk_radio_menu_item_new_with_mnemonic (loop_all_group, "Loop All");
+ loop_all = gtk_radio_menu_item_new_with_mnemonic (loop_all_group, _("Loop All"));
loop_all_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (loop_all));
gtk_widget_show (loop_all);
gtk_container_add (GTK_CONTAINER (looping1_menu), loop_all);
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (loop_all), TRUE);
- loop_single = gtk_radio_menu_item_new_with_mnemonic (loop_all_group, "Loop Single Song");
+ loop_single = gtk_radio_menu_item_new_with_mnemonic (loop_all_group, _("Loop Single Song"));
loop_all_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (loop_single));
gtk_widget_show (loop_single);
gtk_container_add (GTK_CONTAINER (looping1_menu), loop_single);
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (loop_single), TRUE);
- loop_disable = gtk_radio_menu_item_new_with_mnemonic (loop_all_group, "Don't Loop");
+ loop_disable = gtk_radio_menu_item_new_with_mnemonic (loop_all_group, _("Don't Loop"));
loop_all_group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (loop_disable));
gtk_widget_show (loop_disable);
gtk_container_add (GTK_CONTAINER (looping1_menu), loop_disable);
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (loop_disable), TRUE);
- scroll_follows_playback = gtk_check_menu_item_new_with_mnemonic ("Scroll follows playback");
+ scroll_follows_playback = gtk_check_menu_item_new_with_mnemonic (_("Scroll follows playback"));
gtk_widget_show (scroll_follows_playback);
gtk_container_add (GTK_CONTAINER (playback1_menu), scroll_follows_playback);
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (scroll_follows_playback), TRUE);
- cursor_follows_playback = gtk_check_menu_item_new_with_mnemonic ("Cursor follows playback");
+ cursor_follows_playback = gtk_check_menu_item_new_with_mnemonic (_("Cursor follows playback"));
gtk_widget_show (cursor_follows_playback);
gtk_container_add (GTK_CONTAINER (playback1_menu), cursor_follows_playback);
- stop_after_current = gtk_check_menu_item_new_with_mnemonic ("Stop after current");
+ stop_after_current = gtk_check_menu_item_new_with_mnemonic (_("Stop after current"));
gtk_widget_show (stop_after_current);
gtk_container_add (GTK_CONTAINER (playback1_menu), stop_after_current);
gtk_widget_add_accelerator (stop_after_current, "activate", accel_group,
GDK_M, (GdkModifierType) GDK_CONTROL_MASK,
GTK_ACCEL_VISIBLE);
- menuitem4 = gtk_menu_item_new_with_mnemonic ("_Help");
+ menuitem4 = gtk_menu_item_new_with_mnemonic (_("_Help"));
gtk_widget_show (menuitem4);
gtk_container_add (GTK_CONTAINER (menubar1), menuitem4);
menuitem4_menu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem4), menuitem4_menu);
- help1 = gtk_image_menu_item_new_with_mnemonic ("_Help");
+ help1 = gtk_image_menu_item_new_with_mnemonic (_("_Help"));
gtk_widget_show (help1);
gtk_container_add (GTK_CONTAINER (menuitem4_menu), help1);
@@ -407,7 +407,7 @@ create_mainwin (void)
gtk_widget_show (image383);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (help1), image383);
- changelog1 = gtk_menu_item_new_with_mnemonic ("_ChangeLog");
+ changelog1 = gtk_menu_item_new_with_mnemonic (_("_ChangeLog"));
gtk_widget_show (changelog1);
gtk_container_add (GTK_CONTAINER (menuitem4_menu), changelog1);
@@ -429,7 +429,7 @@ create_mainwin (void)
gtk_container_add (GTK_CONTAINER (menuitem4_menu), separator9);
gtk_widget_set_sensitive (separator9, FALSE);
- about1 = gtk_image_menu_item_new_with_mnemonic ("_About");
+ about1 = gtk_image_menu_item_new_with_mnemonic (_("_About"));
gtk_widget_show (about1);
gtk_container_add (GTK_CONTAINER (menuitem4_menu), about1);
@@ -813,7 +813,7 @@ create_searchwin (void)
searchwin = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_set_events (searchwin, GDK_KEY_PRESS_MASK);
- gtk_window_set_title (GTK_WINDOW (searchwin), "Search");
+ gtk_window_set_title (GTK_WINDOW (searchwin), _("Search"));
gtk_window_set_skip_taskbar_hint (GTK_WINDOW (searchwin), TRUE);
gtk_window_set_skip_pager_hint (GTK_WINDOW (searchwin), TRUE);
@@ -888,7 +888,7 @@ create_traymenu (void)
traymenu = gtk_menu_new ();
- stop2 = gtk_image_menu_item_new_with_mnemonic ("Stop");
+ stop2 = gtk_image_menu_item_new_with_mnemonic (_("Stop"));
gtk_widget_show (stop2);
gtk_container_add (GTK_CONTAINER (traymenu), stop2);
@@ -896,7 +896,7 @@ create_traymenu (void)
gtk_widget_show (image59);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (stop2), image59);
- play2 = gtk_image_menu_item_new_with_mnemonic ("Play");
+ play2 = gtk_image_menu_item_new_with_mnemonic (_("Play"));
gtk_widget_show (play2);
gtk_container_add (GTK_CONTAINER (traymenu), play2);
@@ -904,7 +904,7 @@ create_traymenu (void)
gtk_widget_show (image60);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (play2), image60);
- pause2 = gtk_image_menu_item_new_with_mnemonic ("Pause");
+ pause2 = gtk_image_menu_item_new_with_mnemonic (_("Pause"));
gtk_widget_show (pause2);
gtk_container_add (GTK_CONTAINER (traymenu), pause2);
@@ -912,7 +912,7 @@ create_traymenu (void)
gtk_widget_show (image61);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (pause2), image61);
- previous2 = gtk_image_menu_item_new_with_mnemonic ("Previous");
+ previous2 = gtk_image_menu_item_new_with_mnemonic (_("Previous"));
gtk_widget_show (previous2);
gtk_container_add (GTK_CONTAINER (traymenu), previous2);
@@ -920,7 +920,7 @@ create_traymenu (void)
gtk_widget_show (image62);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (previous2), image62);
- next2 = gtk_image_menu_item_new_with_mnemonic ("Next");
+ next2 = gtk_image_menu_item_new_with_mnemonic (_("Next"));
gtk_widget_show (next2);
gtk_container_add (GTK_CONTAINER (traymenu), next2);
@@ -928,7 +928,7 @@ create_traymenu (void)
gtk_widget_show (image63);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (next2), image63);
- play_random1 = gtk_menu_item_new_with_mnemonic ("Play Random");
+ play_random1 = gtk_menu_item_new_with_mnemonic (_("Play Random"));
gtk_widget_show (play_random1);
gtk_container_add (GTK_CONTAINER (traymenu), play_random1);
@@ -937,7 +937,7 @@ create_traymenu (void)
gtk_container_add (GTK_CONTAINER (traymenu), separator4);
gtk_widget_set_sensitive (separator4, FALSE);
- about3 = gtk_image_menu_item_new_with_mnemonic ("About");
+ about3 = gtk_image_menu_item_new_with_mnemonic (_("About"));
gtk_widget_show (about3);
gtk_container_add (GTK_CONTAINER (traymenu), about3);
@@ -950,7 +950,7 @@ create_traymenu (void)
gtk_container_add (GTK_CONTAINER (traymenu), separator3);
gtk_widget_set_sensitive (separator3, FALSE);
- quit = gtk_image_menu_item_new_with_mnemonic ("Quit");
+ quit = gtk_image_menu_item_new_with_mnemonic (_("Quit"));
gtk_widget_show (quit);
gtk_container_add (GTK_CONTAINER (traymenu), quit);
@@ -1022,7 +1022,7 @@ create_addprogress (void)
addprogress = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_container_set_border_width (GTK_CONTAINER (addprogress), 12);
- gtk_window_set_title (GTK_WINDOW (addprogress), "Adding files...");
+ gtk_window_set_title (GTK_WINDOW (addprogress), _("Adding files..."));
gtk_window_set_position (GTK_WINDOW (addprogress), GTK_WIN_POS_CENTER_ON_PARENT);
gtk_window_set_modal (GTK_WINDOW (addprogress), TRUE);
gtk_window_set_skip_taskbar_hint (GTK_WINDOW (addprogress), TRUE);
@@ -1066,7 +1066,7 @@ create_addprogress (void)
gtk_widget_show (image389);
gtk_box_pack_start (GTK_BOX (hbox51), image389, FALSE, FALSE, 0);
- label87 = gtk_label_new_with_mnemonic ("_Abort");
+ label87 = gtk_label_new_with_mnemonic (_("_Abort"));
gtk_widget_show (label87);
gtk_box_pack_start (GTK_BOX (hbox51), label87, FALSE, FALSE, 0);
@@ -1102,7 +1102,7 @@ create_helpwindow (void)
helpwindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_set_size_request (helpwindow, 600, 400);
gtk_widget_set_events (helpwindow, GDK_KEY_PRESS_MASK);
- gtk_window_set_title (GTK_WINDOW (helpwindow), "Help");
+ gtk_window_set_title (GTK_WINDOW (helpwindow), _("Help"));
gtk_window_set_modal (GTK_WINDOW (helpwindow), TRUE);
gtk_window_set_destroy_with_parent (GTK_WINDOW (helpwindow), TRUE);
gtk_window_set_skip_taskbar_hint (GTK_WINDOW (helpwindow), TRUE);
@@ -1167,7 +1167,7 @@ create_trackproperties (void)
trackproperties = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_set_size_request (trackproperties, 400, 400);
- gtk_window_set_title (GTK_WINDOW (trackproperties), "Track Properties");
+ gtk_window_set_title (GTK_WINDOW (trackproperties), _("Track Properties"));
gtk_window_set_skip_taskbar_hint (GTK_WINDOW (trackproperties), TRUE);
gtk_window_set_skip_pager_hint (GTK_WINDOW (trackproperties), TRUE);
@@ -1191,7 +1191,7 @@ create_trackproperties (void)
gtk_container_add (GTK_CONTAINER (scrolledwindow5), metalist);
gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (metalist), TRUE);
- label99 = gtk_label_new ("<b>WARNING</b>: tag writing feature is still in development.\n<b>Make backup copies</b> before using.");
+ label99 = gtk_label_new (_("<b>WARNING</b>: tag writing feature is still in development.\n<b>Make backup copies</b> before using."));
gtk_widget_show (label99);
gtk_box_pack_start (GTK_BOX (vbox16), label99, FALSE, FALSE, 0);
gtk_label_set_use_markup (GTK_LABEL (label99), TRUE);
@@ -1218,7 +1218,7 @@ create_trackproperties (void)
gtk_widget_show (image390);
gtk_box_pack_start (GTK_BOX (hbox52), image390, FALSE, FALSE, 0);
- label88 = gtk_label_new_with_mnemonic ("_Apply");
+ label88 = gtk_label_new_with_mnemonic (_("_Apply"));
gtk_widget_show (label88);
gtk_box_pack_start (GTK_BOX (hbox52), label88, FALSE, FALSE, 0);
@@ -1239,11 +1239,11 @@ create_trackproperties (void)
gtk_widget_show (image391);
gtk_box_pack_start (GTK_BOX (hbox53), image391, FALSE, FALSE, 0);
- label89 = gtk_label_new_with_mnemonic ("_Close");
+ label89 = gtk_label_new_with_mnemonic (_("_Close"));
gtk_widget_show (label89);
gtk_box_pack_start (GTK_BOX (hbox53), label89, FALSE, FALSE, 0);
- label64 = gtk_label_new ("Metadata");
+ label64 = gtk_label_new (_("Metadata"));
gtk_widget_show (label64);
gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook3), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook3), 0), label64);
@@ -1285,11 +1285,11 @@ create_trackproperties (void)
gtk_widget_show (image392);
gtk_box_pack_start (GTK_BOX (hbox54), image392, FALSE, FALSE, 0);
- label90 = gtk_label_new_with_mnemonic ("_Close");
+ label90 = gtk_label_new_with_mnemonic (_("_Close"));
gtk_widget_show (label90);
gtk_box_pack_start (GTK_BOX (hbox54), label90, FALSE, FALSE, 0);
- label80 = gtk_label_new ("Properties");
+ label80 = gtk_label_new (_("Properties"));
gtk_widget_show (label80);
gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook3), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook3), 1), label80);
@@ -1375,7 +1375,7 @@ create_editcolumndlg (void)
editcolumndlg = gtk_dialog_new ();
gtk_container_set_border_width (GTK_CONTAINER (editcolumndlg), 12);
- gtk_window_set_title (GTK_WINDOW (editcolumndlg), "editcolumndlg");
+ gtk_window_set_title (GTK_WINDOW (editcolumndlg), _("editcolumndlg"));
gtk_window_set_modal (GTK_WINDOW (editcolumndlg), TRUE);
gtk_window_set_type_hint (GTK_WINDOW (editcolumndlg), GDK_WINDOW_TYPE_HINT_DIALOG);
@@ -1390,7 +1390,7 @@ create_editcolumndlg (void)
gtk_widget_show (hbox29);
gtk_box_pack_start (GTK_BOX (vbox14), hbox29, FALSE, FALSE, 0);
- label26 = gtk_label_new ("Title:");
+ label26 = gtk_label_new (_("Title:"));
gtk_widget_show (label26);
gtk_box_pack_start (GTK_BOX (hbox29), label26, FALSE, FALSE, 0);
gtk_misc_set_alignment (GTK_MISC (label26), 0, 0.5);
@@ -1398,7 +1398,7 @@ create_editcolumndlg (void)
title = gtk_entry_new ();
gtk_widget_show (title);
gtk_box_pack_start (GTK_BOX (hbox29), title, TRUE, TRUE, 0);
- gtk_entry_set_text (GTK_ENTRY (title), "Enter new column title here");
+ gtk_entry_set_text (GTK_ENTRY (title), _("Enter new column title here"));
gtk_entry_set_invisible_char (GTK_ENTRY (title), 9679);
gtk_entry_set_activates_default (GTK_ENTRY (title), TRUE);
@@ -1406,7 +1406,7 @@ create_editcolumndlg (void)
gtk_widget_show (hbox30);
gtk_box_pack_start (GTK_BOX (vbox14), hbox30, FALSE, FALSE, 0);
- label37 = gtk_label_new ("Type:");
+ label37 = gtk_label_new (_("Type:"));
gtk_widget_show (label37);
gtk_box_pack_start (GTK_BOX (hbox30), label37, FALSE, FALSE, 0);
gtk_misc_set_alignment (GTK_MISC (label37), 0, 0.5);
@@ -1414,23 +1414,23 @@ create_editcolumndlg (void)
id = gtk_combo_box_new_text ();
gtk_widget_show (id);
gtk_box_pack_start (GTK_BOX (hbox30), id, TRUE, TRUE, 0);
- gtk_combo_box_append_text (GTK_COMBO_BOX (id), "File number");
- gtk_combo_box_append_text (GTK_COMBO_BOX (id), "Playing");
- gtk_combo_box_append_text (GTK_COMBO_BOX (id), "Album Art");
- gtk_combo_box_append_text (GTK_COMBO_BOX (id), "Artist - Album");
- gtk_combo_box_append_text (GTK_COMBO_BOX (id), "Artist");
- gtk_combo_box_append_text (GTK_COMBO_BOX (id), "Album");
- gtk_combo_box_append_text (GTK_COMBO_BOX (id), "Title");
- gtk_combo_box_append_text (GTK_COMBO_BOX (id), "Length");
- gtk_combo_box_append_text (GTK_COMBO_BOX (id), "Track");
- gtk_combo_box_append_text (GTK_COMBO_BOX (id), "Band / Album Artist");
- gtk_combo_box_append_text (GTK_COMBO_BOX (id), "Custom");
+ gtk_combo_box_append_text (GTK_COMBO_BOX (id), _("File number"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (id), _("Playing"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (id), _("Album Art"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (id), _("Artist - Album"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (id), _("Artist"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (id), _("Album"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (id), _("Title"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (id), _("Length"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (id), _("Track"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (id), _("Band / Album Artist"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (id), _("Custom"));
hbox31 = gtk_hbox_new (FALSE, 8);
gtk_widget_show (hbox31);
gtk_box_pack_start (GTK_BOX (vbox14), hbox31, FALSE, FALSE, 0);
- fmtlabel = gtk_label_new ("Format:");
+ fmtlabel = gtk_label_new (_("Format:"));
gtk_widget_show (fmtlabel);
gtk_box_pack_start (GTK_BOX (hbox31), fmtlabel, FALSE, FALSE, 0);
gtk_misc_set_alignment (GTK_MISC (fmtlabel), 0, 0.5);
@@ -1445,7 +1445,7 @@ create_editcolumndlg (void)
gtk_widget_show (hbox32);
gtk_box_pack_start (GTK_BOX (vbox14), hbox32, FALSE, FALSE, 0);
- label38 = gtk_label_new ("Alignment:");
+ label38 = gtk_label_new (_("Alignment:"));
gtk_widget_show (label38);
gtk_box_pack_start (GTK_BOX (hbox32), label38, FALSE, FALSE, 0);
gtk_misc_set_alignment (GTK_MISC (label38), 0, 0.5);
@@ -1453,10 +1453,10 @@ create_editcolumndlg (void)
align = gtk_combo_box_new_text ();
gtk_widget_show (align);
gtk_box_pack_start (GTK_BOX (hbox32), align, TRUE, TRUE, 0);
- gtk_combo_box_append_text (GTK_COMBO_BOX (align), "Left");
- gtk_combo_box_append_text (GTK_COMBO_BOX (align), "Right");
+ gtk_combo_box_append_text (GTK_COMBO_BOX (align), _("Left"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (align), _("Right"));
- label25 = gtk_label_new ("Format conversions (start with %):\n [a]rtist, [t]itle, al[b]um, [B]and, [C]omposer\n track[n]umber, [N]totaltracks,\n [l]ength, [y]ear, [g]enre, [c]omment,\n copy[r]ight, [f]ilename, [T]ags\nExample: %a - %t [%l]");
+ label25 = gtk_label_new (_("Format conversions (start with %):\n [a]rtist, [t]itle, al[b]um, [B]and, [C]omposer\n track[n]umber, [N]totaltracks,\n [l]ength, [y]ear, [g]enre, [c]omment,\n copy[r]ight, [f]ilename, [T]ags\nExample: %a - %t [%l]"));
gtk_widget_show (label25);
gtk_box_pack_start (GTK_BOX (vbox14), label25, TRUE, TRUE, 0);
GTK_WIDGET_SET_FLAGS (label25, GTK_CAN_FOCUS);
@@ -1485,7 +1485,7 @@ create_editcolumndlg (void)
gtk_widget_show (image388);
gtk_box_pack_start (GTK_BOX (hbox50), image388, FALSE, FALSE, 0);
- label86 = gtk_label_new_with_mnemonic ("_Cancel");
+ label86 = gtk_label_new_with_mnemonic (_("_Cancel"));
gtk_widget_show (label86);
gtk_box_pack_start (GTK_BOX (hbox50), label86, FALSE, FALSE, 0);
@@ -1506,7 +1506,7 @@ create_editcolumndlg (void)
gtk_widget_show (image387);
gtk_box_pack_start (GTK_BOX (hbox49), image387, FALSE, FALSE, 0);
- label85 = gtk_label_new_with_mnemonic ("_OK");
+ label85 = gtk_label_new_with_mnemonic (_("_OK"));
gtk_widget_show (label85);
gtk_box_pack_start (GTK_BOX (hbox49), label85, FALSE, FALSE, 0);
@@ -1703,7 +1703,7 @@ create_prefwin (void)
prefwin = gtk_dialog_new ();
gtk_widget_set_size_request (prefwin, 630, 400);
gtk_container_set_border_width (GTK_CONTAINER (prefwin), 12);
- gtk_window_set_title (GTK_WINDOW (prefwin), "Preferences");
+ gtk_window_set_title (GTK_WINDOW (prefwin), _("Preferences"));
gtk_window_set_default_size (GTK_WINDOW (prefwin), 630, 400);
gtk_window_set_type_hint (GTK_WINDOW (prefwin), GDK_WINDOW_TYPE_HINT_DIALOG);
@@ -1723,7 +1723,7 @@ create_prefwin (void)
gtk_widget_show (hbox11);
gtk_box_pack_start (GTK_BOX (vbox10), hbox11, FALSE, FALSE, 0);
- label23 = gtk_label_new ("Output plugin:");
+ label23 = gtk_label_new (_("Output plugin:"));
gtk_widget_show (label23);
gtk_box_pack_start (GTK_BOX (hbox11), label23, FALSE, FALSE, 0);
gtk_misc_set_alignment (GTK_MISC (label23), 0, 0.5);
@@ -1736,7 +1736,7 @@ create_prefwin (void)
gtk_widget_show (hbox12);
gtk_box_pack_start (GTK_BOX (vbox10), hbox12, FALSE, FALSE, 0);
- label4 = gtk_label_new ("Output device:");
+ label4 = gtk_label_new (_("Output device:"));
gtk_widget_show (label4);
gtk_box_pack_start (GTK_BOX (hbox12), label4, FALSE, FALSE, 0);
gtk_misc_set_alignment (GTK_MISC (label4), 0, 0.5);
@@ -1745,7 +1745,7 @@ create_prefwin (void)
gtk_widget_show (pref_soundcard);
gtk_box_pack_start (GTK_BOX (hbox12), pref_soundcard, TRUE, TRUE, 0);
- Sound = gtk_label_new ("Sound");
+ Sound = gtk_label_new (_("Sound"));
gtk_widget_show (Sound);
gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 0), Sound);
@@ -1754,7 +1754,7 @@ create_prefwin (void)
gtk_container_add (GTK_CONTAINER (notebook), vbox8);
gtk_container_set_border_width (GTK_CONTAINER (vbox8), 12);
- pref_dynsamplerate = gtk_check_button_new_with_mnemonic ("Allow dynamic samplerate switching");
+ pref_dynsamplerate = gtk_check_button_new_with_mnemonic (_("Allow dynamic samplerate switching"));
gtk_widget_show (pref_dynsamplerate);
gtk_box_pack_start (GTK_BOX (vbox8), pref_dynsamplerate, FALSE, FALSE, 0);
@@ -1762,7 +1762,7 @@ create_prefwin (void)
gtk_widget_show (hbox9);
gtk_box_pack_start (GTK_BOX (vbox8), hbox9, FALSE, FALSE, 0);
- label6 = gtk_label_new ("Samplerate conversion quality:");
+ label6 = gtk_label_new (_("Samplerate conversion quality:"));
gtk_widget_show (label6);
gtk_box_pack_start (GTK_BOX (hbox9), label6, FALSE, FALSE, 0);
gtk_label_set_justify (GTK_LABEL (label6), GTK_JUSTIFY_RIGHT);
@@ -1781,7 +1781,7 @@ create_prefwin (void)
gtk_widget_show (hbox10);
gtk_box_pack_start (GTK_BOX (vbox8), hbox10, FALSE, FALSE, 0);
- label8 = gtk_label_new ("Replaygain mode:");
+ label8 = gtk_label_new (_("Replaygain mode:"));
gtk_widget_show (label8);
gtk_box_pack_start (GTK_BOX (hbox10), label8, FALSE, FALSE, 0);
gtk_misc_set_alignment (GTK_MISC (label8), 0, 0.5);
@@ -1790,15 +1790,15 @@ create_prefwin (void)
gtk_widget_show (pref_replaygain_mode);
gtk_box_pack_start (GTK_BOX (hbox10), pref_replaygain_mode, TRUE, TRUE, 0);
gtk_widget_set_size_request (pref_replaygain_mode, 337, -1);
- gtk_combo_box_append_text (GTK_COMBO_BOX (pref_replaygain_mode), "Disable");
- gtk_combo_box_append_text (GTK_COMBO_BOX (pref_replaygain_mode), "Track");
- gtk_combo_box_append_text (GTK_COMBO_BOX (pref_replaygain_mode), "Album");
+ gtk_combo_box_append_text (GTK_COMBO_BOX (pref_replaygain_mode), _("Disable"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (pref_replaygain_mode), _("Track"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (pref_replaygain_mode), _("Album"));
- pref_replaygain_scale = gtk_check_button_new_with_mnemonic ("Replaygain peak scale");
+ pref_replaygain_scale = gtk_check_button_new_with_mnemonic (_("Replaygain peak scale"));
gtk_widget_show (pref_replaygain_scale);
gtk_box_pack_start (GTK_BOX (vbox8), pref_replaygain_scale, FALSE, FALSE, 0);
- label39 = gtk_label_new ("Sound (adv.)");
+ label39 = gtk_label_new (_("Sound (adv.)"));
gtk_widget_show (label39);
gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 1), label39);
@@ -1807,11 +1807,11 @@ create_prefwin (void)
gtk_container_add (GTK_CONTAINER (notebook), vbox9);
gtk_container_set_border_width (GTK_CONTAINER (vbox9), 12);
- pref_close_send_to_tray = gtk_check_button_new_with_mnemonic ("Close minimizes to tray");
+ pref_close_send_to_tray = gtk_check_button_new_with_mnemonic (_("Close minimizes to tray"));
gtk_widget_show (pref_close_send_to_tray);
gtk_box_pack_start (GTK_BOX (vbox9), pref_close_send_to_tray, FALSE, FALSE, 0);
- mmb_delete_playlist = gtk_check_button_new_with_mnemonic ("Middle mouse button closes playlist");
+ mmb_delete_playlist = gtk_check_button_new_with_mnemonic (_("Middle mouse button closes playlist"));
gtk_widget_show (mmb_delete_playlist);
gtk_box_pack_start (GTK_BOX (vbox9), mmb_delete_playlist, FALSE, FALSE, 0);
@@ -1824,7 +1824,7 @@ create_prefwin (void)
gtk_container_add (GTK_CONTAINER (notebook4), vbox21);
gtk_container_set_border_width (GTK_CONTAINER (vbox21), 12);
- override_bar_colors = gtk_check_button_new_with_mnemonic ("Override");
+ override_bar_colors = gtk_check_button_new_with_mnemonic (_("Override"));
gtk_widget_show (override_bar_colors);
gtk_box_pack_start (GTK_BOX (vbox21), override_bar_colors, FALSE, FALSE, 0);
@@ -1833,14 +1833,14 @@ create_prefwin (void)
gtk_box_pack_start (GTK_BOX (vbox21), bar_colors_group, TRUE, TRUE, 0);
gtk_table_set_col_spacings (GTK_TABLE (bar_colors_group), 8);
- label43 = gtk_label_new ("Foreground");
+ label43 = gtk_label_new (_("Foreground"));
gtk_widget_show (label43);
gtk_table_attach (GTK_TABLE (bar_colors_group), label43, 0, 1, 0, 1,
(GtkAttachOptions) (GTK_EXPAND),
(GtkAttachOptions) (0), 0, 0);
gtk_misc_set_alignment (GTK_MISC (label43), 0, 0.5);
- label47 = gtk_label_new ("Background");
+ label47 = gtk_label_new (_("Background"));
gtk_widget_show (label47);
gtk_table_attach (GTK_TABLE (bar_colors_group), label47, 1, 2, 0, 1,
(GtkAttachOptions) (GTK_EXPAND),
@@ -1859,7 +1859,7 @@ create_prefwin (void)
(GtkAttachOptions) (GTK_EXPAND),
(GtkAttachOptions) (0), 0, 0);
- label73 = gtk_label_new ("Seekbar/Volumebar colors");
+ label73 = gtk_label_new (_("Seekbar/Volumebar colors"));
gtk_widget_show (label73);
gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook4), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook4), 0), label73);
@@ -1868,7 +1868,7 @@ create_prefwin (void)
gtk_container_add (GTK_CONTAINER (notebook4), vbox22);
gtk_container_set_border_width (GTK_CONTAINER (vbox22), 12);
- override_tabstrip_colors = gtk_check_button_new_with_mnemonic ("Override");
+ override_tabstrip_colors = gtk_check_button_new_with_mnemonic (_("Override"));
gtk_widget_show (override_tabstrip_colors);
gtk_box_pack_start (GTK_BOX (vbox22), override_tabstrip_colors, FALSE, FALSE, 0);
@@ -1877,21 +1877,21 @@ create_prefwin (void)
gtk_box_pack_start (GTK_BOX (vbox22), tabstrip_colors_group, TRUE, TRUE, 0);
gtk_table_set_col_spacings (GTK_TABLE (tabstrip_colors_group), 8);
- label45 = gtk_label_new ("Middle");
+ label45 = gtk_label_new (_("Middle"));
gtk_widget_show (label45);
gtk_table_attach (GTK_TABLE (tabstrip_colors_group), label45, 0, 1, 0, 1,
(GtkAttachOptions) (GTK_EXPAND),
(GtkAttachOptions) (0), 0, 0);
gtk_misc_set_alignment (GTK_MISC (label45), 0, 0.5);
- label46 = gtk_label_new ("Light");
+ label46 = gtk_label_new (_("Light"));
gtk_widget_show (label46);
gtk_table_attach (GTK_TABLE (tabstrip_colors_group), label46, 1, 2, 0, 1,
(GtkAttachOptions) (GTK_EXPAND),
(GtkAttachOptions) (0), 0, 0);
gtk_misc_set_alignment (GTK_MISC (label46), 0, 0.5);
- label44 = gtk_label_new ("Dark");
+ label44 = gtk_label_new (_("Dark"));
gtk_widget_show (label44);
gtk_table_attach (GTK_TABLE (tabstrip_colors_group), label44, 2, 3, 0, 1,
(GtkAttachOptions) (GTK_EXPAND),
@@ -1922,14 +1922,14 @@ create_prefwin (void)
(GtkAttachOptions) (GTK_EXPAND),
(GtkAttachOptions) (0), 0, 0);
- label76 = gtk_label_new ("Base");
+ label76 = gtk_label_new (_("Base"));
gtk_widget_show (label76);
gtk_table_attach (GTK_TABLE (tabstrip_colors_group), label76, 3, 4, 0, 1,
(GtkAttachOptions) (GTK_EXPAND),
(GtkAttachOptions) (0), 0, 0);
gtk_misc_set_alignment (GTK_MISC (label76), 0, 0.5);
- label74 = gtk_label_new ("Tab strip colors");
+ label74 = gtk_label_new (_("Tab strip colors"));
gtk_widget_show (label74);
gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook4), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook4), 1), label74);
@@ -1938,7 +1938,7 @@ create_prefwin (void)
gtk_container_add (GTK_CONTAINER (notebook4), vbox23);
gtk_container_set_border_width (GTK_CONTAINER (vbox23), 12);
- override_listview_colors = gtk_check_button_new_with_mnemonic ("Override (looses GTK treeview theming, but speeds up rendering)");
+ override_listview_colors = gtk_check_button_new_with_mnemonic (_("Override (looses GTK treeview theming, but speeds up rendering)"));
gtk_widget_show (override_listview_colors);
gtk_box_pack_start (GTK_BOX (vbox23), override_listview_colors, FALSE, FALSE, 0);
@@ -1947,14 +1947,14 @@ create_prefwin (void)
gtk_box_pack_start (GTK_BOX (vbox23), listview_colors_group, TRUE, TRUE, 0);
gtk_table_set_col_spacings (GTK_TABLE (listview_colors_group), 8);
- label58 = gtk_label_new ("Even row");
+ label58 = gtk_label_new (_("Even row"));
gtk_widget_show (label58);
gtk_table_attach (GTK_TABLE (listview_colors_group), label58, 0, 1, 0, 1,
(GtkAttachOptions) (GTK_EXPAND),
(GtkAttachOptions) (0), 0, 0);
gtk_misc_set_alignment (GTK_MISC (label58), 0, 0.5);
- label59 = gtk_label_new ("Odd row");
+ label59 = gtk_label_new (_("Odd row"));
gtk_widget_show (label59);
gtk_table_attach (GTK_TABLE (listview_colors_group), label59, 1, 2, 0, 1,
(GtkAttachOptions) (GTK_EXPAND),
@@ -1973,14 +1973,14 @@ create_prefwin (void)
(GtkAttachOptions) (GTK_EXPAND),
(GtkAttachOptions) (0), 0, 0);
- label77 = gtk_label_new ("Text");
+ label77 = gtk_label_new (_("Text"));
gtk_widget_show (label77);
gtk_table_attach (GTK_TABLE (listview_colors_group), label77, 3, 4, 0, 1,
(GtkAttachOptions) (GTK_EXPAND),
(GtkAttachOptions) (0), 0, 0);
gtk_misc_set_alignment (GTK_MISC (label77), 0, 0.5);
- label78 = gtk_label_new ("Selected row");
+ label78 = gtk_label_new (_("Selected row"));
gtk_widget_show (label78);
gtk_table_attach (GTK_TABLE (listview_colors_group), label78, 2, 3, 0, 1,
(GtkAttachOptions) (GTK_EXPAND),
@@ -1999,7 +1999,7 @@ create_prefwin (void)
(GtkAttachOptions) (GTK_EXPAND),
(GtkAttachOptions) (0), 0, 0);
- label61 = gtk_label_new ("Selected text");
+ label61 = gtk_label_new (_("Selected text"));
gtk_widget_show (label61);
gtk_table_attach (GTK_TABLE (listview_colors_group), label61, 4, 5, 0, 1,
(GtkAttachOptions) (GTK_EXPAND),
@@ -2012,7 +2012,7 @@ create_prefwin (void)
(GtkAttachOptions) (GTK_EXPAND),
(GtkAttachOptions) (0), 0, 0);
- label62 = gtk_label_new ("Cursor");
+ label62 = gtk_label_new (_("Cursor"));
gtk_widget_show (label62);
gtk_table_attach (GTK_TABLE (listview_colors_group), label62, 5, 6, 0, 1,
(GtkAttachOptions) (GTK_EXPAND),
@@ -2025,11 +2025,11 @@ create_prefwin (void)
(GtkAttachOptions) (GTK_EXPAND),
(GtkAttachOptions) (0), 0, 0);
- label75 = gtk_label_new ("Playlist colors");
+ label75 = gtk_label_new (_("Playlist colors"));
gtk_widget_show (label75);
gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook4), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook4), 2), label75);
- label2 = gtk_label_new ("GUI");
+ label2 = gtk_label_new (_("GUI"));
gtk_widget_show (label2);
gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 2), label2);
@@ -2038,7 +2038,7 @@ create_prefwin (void)
gtk_container_add (GTK_CONTAINER (notebook), vbox11);
gtk_container_set_border_width (GTK_CONTAINER (vbox11), 12);
- pref_network_enableproxy = gtk_check_button_new_with_mnemonic ("Enable Proxy Server");
+ pref_network_enableproxy = gtk_check_button_new_with_mnemonic (_("Enable Proxy Server"));
gtk_widget_show (pref_network_enableproxy);
gtk_box_pack_start (GTK_BOX (vbox11), pref_network_enableproxy, FALSE, FALSE, 0);
@@ -2046,7 +2046,7 @@ create_prefwin (void)
gtk_widget_show (hbox13);
gtk_box_pack_start (GTK_BOX (vbox11), hbox13, FALSE, FALSE, 0);
- label18 = gtk_label_new ("Proxy Server Address:");
+ label18 = gtk_label_new (_("Proxy Server Address:"));
gtk_widget_show (label18);
gtk_box_pack_start (GTK_BOX (hbox13), label18, FALSE, FALSE, 0);
gtk_misc_set_alignment (GTK_MISC (label18), 0, 0.5);
@@ -2060,7 +2060,7 @@ create_prefwin (void)
gtk_widget_show (hbox14);
gtk_box_pack_start (GTK_BOX (vbox11), hbox14, FALSE, FALSE, 0);
- label19 = gtk_label_new ("Proxy Server Port:");
+ label19 = gtk_label_new (_("Proxy Server Port:"));
gtk_widget_show (label19);
gtk_box_pack_start (GTK_BOX (hbox14), label19, FALSE, FALSE, 0);
gtk_misc_set_alignment (GTK_MISC (label19), 0, 0.5);
@@ -2074,7 +2074,7 @@ create_prefwin (void)
gtk_widget_show (hbox15);
gtk_box_pack_start (GTK_BOX (vbox11), hbox15, FALSE, FALSE, 0);
- label20 = gtk_label_new ("Proxy Type:");
+ label20 = gtk_label_new (_("Proxy Type:"));
gtk_widget_show (label20);
gtk_box_pack_start (GTK_BOX (hbox15), label20, FALSE, FALSE, 0);
gtk_misc_set_alignment (GTK_MISC (label20), 0, 0.5);
@@ -2093,7 +2093,7 @@ create_prefwin (void)
gtk_widget_show (hbox61);
gtk_box_pack_start (GTK_BOX (vbox11), hbox61, FALSE, FALSE, 0);
- label97 = gtk_label_new ("Proxy Username:");
+ label97 = gtk_label_new (_("Proxy Username:"));
gtk_widget_show (label97);
gtk_box_pack_start (GTK_BOX (hbox61), label97, FALSE, FALSE, 0);
@@ -2106,7 +2106,7 @@ create_prefwin (void)
gtk_widget_show (hbox62);
gtk_box_pack_start (GTK_BOX (vbox11), hbox62, FALSE, FALSE, 0);
- label98 = gtk_label_new ("Proxy Password:");
+ label98 = gtk_label_new (_("Proxy Password:"));
gtk_widget_show (label98);
gtk_box_pack_start (GTK_BOX (hbox62), label98, FALSE, FALSE, 0);
@@ -2116,7 +2116,7 @@ create_prefwin (void)
gtk_entry_set_visibility (GTK_ENTRY (proxypassword), FALSE);
gtk_entry_set_invisible_char (GTK_ENTRY (proxypassword), 9679);
- label16 = gtk_label_new ("Network");
+ label16 = gtk_label_new (_("Network"));
gtk_widget_show (label16);
gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 3), label16);
@@ -2144,15 +2144,15 @@ create_prefwin (void)
gtk_widget_show (hbox38);
gtk_box_pack_start (GTK_BOX (vbox19), hbox38, FALSE, FALSE, 0);
- write_id3v2 = gtk_check_button_new_with_mnemonic ("Write ID3v2");
+ write_id3v2 = gtk_check_button_new_with_mnemonic (_("Write ID3v2"));
gtk_widget_show (write_id3v2);
gtk_box_pack_start (GTK_BOX (hbox38), write_id3v2, FALSE, FALSE, 0);
- write_id3v1 = gtk_check_button_new_with_mnemonic ("Write ID3v1");
+ write_id3v1 = gtk_check_button_new_with_mnemonic (_("Write ID3v1"));
gtk_widget_show (write_id3v1);
gtk_box_pack_start (GTK_BOX (hbox38), write_id3v1, FALSE, FALSE, 0);
- write_apev2 = gtk_check_button_new_with_mnemonic ("Write APEv2");
+ write_apev2 = gtk_check_button_new_with_mnemonic (_("Write APEv2"));
gtk_widget_show (write_apev2);
gtk_box_pack_start (GTK_BOX (hbox38), write_apev2, FALSE, FALSE, 0);
@@ -2160,15 +2160,15 @@ create_prefwin (void)
gtk_widget_show (hbox40);
gtk_box_pack_start (GTK_BOX (vbox19), hbox40, FALSE, FALSE, 0);
- strip_id3v2 = gtk_check_button_new_with_mnemonic ("Strip ID3v2");
+ strip_id3v2 = gtk_check_button_new_with_mnemonic (_("Strip ID3v2"));
gtk_widget_show (strip_id3v2);
gtk_box_pack_start (GTK_BOX (hbox40), strip_id3v2, FALSE, FALSE, 0);
- strip_id3v1 = gtk_check_button_new_with_mnemonic ("Strip ID3v1");
+ strip_id3v1 = gtk_check_button_new_with_mnemonic (_("Strip ID3v1"));
gtk_widget_show (strip_id3v1);
gtk_box_pack_start (GTK_BOX (hbox40), strip_id3v1, FALSE, FALSE, 0);
- strip_apev2 = gtk_check_button_new_with_mnemonic ("Strip APEv2");
+ strip_apev2 = gtk_check_button_new_with_mnemonic (_("Strip APEv2"));
gtk_widget_show (strip_apev2);
gtk_box_pack_start (GTK_BOX (hbox40), strip_apev2, FALSE, FALSE, 0);
@@ -2176,21 +2176,21 @@ create_prefwin (void)
gtk_widget_show (hbox36);
gtk_box_pack_start (GTK_BOX (vbox19), hbox36, TRUE, TRUE, 0);
- label69 = gtk_label_new ("ID3v2 version");
+ label69 = gtk_label_new (_("ID3v2 version"));
gtk_widget_show (label69);
gtk_box_pack_start (GTK_BOX (hbox36), label69, FALSE, FALSE, 0);
id3v2_version = gtk_combo_box_new_text ();
gtk_widget_show (id3v2_version);
gtk_box_pack_start (GTK_BOX (hbox36), id3v2_version, TRUE, TRUE, 0);
- gtk_combo_box_append_text (GTK_COMBO_BOX (id3v2_version), "2.3 (Recommended)");
- gtk_combo_box_append_text (GTK_COMBO_BOX (id3v2_version), "2.4");
+ gtk_combo_box_append_text (GTK_COMBO_BOX (id3v2_version), _("2.3 (Recommended)"));
+ gtk_combo_box_append_text (GTK_COMBO_BOX (id3v2_version), _("2.4"));
hbox39 = gtk_hbox_new (FALSE, 8);
gtk_widget_show (hbox39);
gtk_box_pack_start (GTK_BOX (vbox19), hbox39, TRUE, TRUE, 0);
- label71 = gtk_label_new ("ID3v1 character encoding (default is iso8859-1)");
+ label71 = gtk_label_new (_("ID3v1 character encoding (default is iso8859-1)"));
gtk_widget_show (label71);
gtk_box_pack_start (GTK_BOX (hbox39), label71, FALSE, FALSE, 0);
@@ -2227,11 +2227,11 @@ create_prefwin (void)
gtk_widget_show (hbox37);
gtk_box_pack_start (GTK_BOX (vbox20), hbox37, TRUE, TRUE, 0);
- ape_write_id3v2 = gtk_check_button_new_with_mnemonic ("Write ID3v2.4");
+ ape_write_id3v2 = gtk_check_button_new_with_mnemonic (_("Write ID3v2.4"));
gtk_widget_show (ape_write_id3v2);
gtk_box_pack_start (GTK_BOX (hbox37), ape_write_id3v2, FALSE, FALSE, 0);
- ape_write_apev2 = gtk_check_button_new_with_mnemonic ("Write APEv2");
+ ape_write_apev2 = gtk_check_button_new_with_mnemonic (_("Write APEv2"));
gtk_widget_show (ape_write_apev2);
gtk_box_pack_start (GTK_BOX (hbox37), ape_write_apev2, FALSE, FALSE, 0);
@@ -2239,11 +2239,11 @@ create_prefwin (void)
gtk_widget_show (hbox45);
gtk_box_pack_start (GTK_BOX (vbox20), hbox45, TRUE, TRUE, 0);
- ape_strip_id3v2 = gtk_check_button_new_with_mnemonic ("Strip ID3v2");
+ ape_strip_id3v2 = gtk_check_button_new_with_mnemonic (_("Strip ID3v2"));
gtk_widget_show (ape_strip_id3v2);
gtk_box_pack_start (GTK_BOX (hbox45), ape_strip_id3v2, FALSE, FALSE, 0);
- ape_strip_apev2 = gtk_check_button_new_with_mnemonic ("Strip APEv2");
+ ape_strip_apev2 = gtk_check_button_new_with_mnemonic (_("Strip APEv2"));
gtk_widget_show (ape_strip_apev2);
gtk_box_pack_start (GTK_BOX (hbox45), ape_strip_apev2, FALSE, FALSE, 0);
@@ -2271,11 +2271,11 @@ create_prefwin (void)
gtk_widget_show (hbox44);
gtk_box_pack_start (GTK_BOX (vbox_wv), hbox44, FALSE, FALSE, 0);
- wv_write_apev2 = gtk_check_button_new_with_mnemonic ("Write APEv2");
+ wv_write_apev2 = gtk_check_button_new_with_mnemonic (_("Write APEv2"));
gtk_widget_show (wv_write_apev2);
gtk_box_pack_start (GTK_BOX (hbox44), wv_write_apev2, FALSE, FALSE, 0);
- wv_write_id3v1 = gtk_check_button_new_with_mnemonic ("Write ID3v1");
+ wv_write_id3v1 = gtk_check_button_new_with_mnemonic (_("Write ID3v1"));
gtk_widget_show (wv_write_id3v1);
gtk_box_pack_start (GTK_BOX (hbox44), wv_write_id3v1, FALSE, FALSE, 0);
@@ -2283,11 +2283,11 @@ create_prefwin (void)
gtk_widget_show (hbox43);
gtk_box_pack_start (GTK_BOX (vbox_wv), hbox43, FALSE, FALSE, 0);
- wv_strip_apev2 = gtk_check_button_new_with_mnemonic ("Strip APEv2");
+ wv_strip_apev2 = gtk_check_button_new_with_mnemonic (_("Strip APEv2"));
gtk_widget_show (wv_strip_apev2);
gtk_box_pack_start (GTK_BOX (hbox43), wv_strip_apev2, FALSE, FALSE, 0);
- wv_strip_id3v1 = gtk_check_button_new_with_mnemonic ("Strip ID3v1");
+ wv_strip_id3v1 = gtk_check_button_new_with_mnemonic (_("Strip ID3v1"));
gtk_widget_show (wv_strip_id3v1);
gtk_box_pack_start (GTK_BOX (hbox43), wv_strip_id3v1, FALSE, FALSE, 0);
@@ -2296,7 +2296,7 @@ create_prefwin (void)
gtk_frame_set_label_widget (GTK_FRAME (frame7), label79);
gtk_label_set_use_markup (GTK_LABEL (label79), TRUE);
- label67 = gtk_label_new ("Tag writer");
+ label67 = gtk_label_new (_("Tag writer"));
gtk_widget_show (label67);
gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 4), label67);
@@ -2327,7 +2327,7 @@ create_prefwin (void)
gtk_widget_show (hbox16);
gtk_box_pack_start (GTK_BOX (vbox12), hbox16, FALSE, FALSE, 0);
- label11 = gtk_label_new ("Description:");
+ label11 = gtk_label_new (_("Description:"));
gtk_widget_show (label11);
gtk_box_pack_start (GTK_BOX (hbox16), label11, FALSE, FALSE, 0);
gtk_misc_set_alignment (GTK_MISC (label11), 0, 0.5);
@@ -2342,7 +2342,7 @@ create_prefwin (void)
gtk_widget_show (hbox17);
gtk_box_pack_start (GTK_BOX (vbox12), hbox17, FALSE, FALSE, 0);
- label12 = gtk_label_new ("Author(s):");
+ label12 = gtk_label_new (_("Author(s):"));
gtk_widget_show (label12);
gtk_box_pack_start (GTK_BOX (hbox17), label12, FALSE, FALSE, 0);
gtk_misc_set_alignment (GTK_MISC (label12), 0, 0.5);
@@ -2357,7 +2357,7 @@ create_prefwin (void)
gtk_widget_show (hbox18);
gtk_box_pack_start (GTK_BOX (vbox12), hbox18, FALSE, FALSE, 0);
- label13 = gtk_label_new ("Email:");
+ label13 = gtk_label_new (_("Email:"));
gtk_widget_show (label13);
gtk_box_pack_start (GTK_BOX (hbox18), label13, FALSE, FALSE, 0);
gtk_misc_set_alignment (GTK_MISC (label13), 0, 0.5);
@@ -2372,7 +2372,7 @@ create_prefwin (void)
gtk_widget_show (hbox19);
gtk_box_pack_start (GTK_BOX (vbox12), hbox19, FALSE, FALSE, 0);
- label14 = gtk_label_new ("Website:");
+ label14 = gtk_label_new (_("Website:"));
gtk_widget_show (label14);
gtk_box_pack_start (GTK_BOX (hbox19), label14, FALSE, FALSE, 0);
gtk_misc_set_alignment (GTK_MISC (label14), 0, 0.5);
@@ -2403,11 +2403,11 @@ create_prefwin (void)
gtk_widget_show (image394);
gtk_box_pack_start (GTK_BOX (hbox56), image394, FALSE, FALSE, 0);
- label92 = gtk_label_new_with_mnemonic ("Configure");
+ label92 = gtk_label_new_with_mnemonic (_("Configure"));
gtk_widget_show (label92);
gtk_box_pack_start (GTK_BOX (hbox56), label92, FALSE, FALSE, 0);
- label3 = gtk_label_new ("Plugins");
+ label3 = gtk_label_new (_("Plugins"));
gtk_widget_show (label3);
gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 5), label3);
gtk_misc_set_alignment (GTK_MISC (label3), 0.48, 0.5);
@@ -2433,7 +2433,7 @@ create_prefwin (void)
gtk_widget_show (image393);
gtk_box_pack_start (GTK_BOX (hbox55), image393, FALSE, FALSE, 0);
- label91 = gtk_label_new_with_mnemonic ("_Close");
+ label91 = gtk_label_new_with_mnemonic (_("_Close"));
gtk_widget_show (label91);
gtk_box_pack_start (GTK_BOX (hbox55), label91, FALSE, FALSE, 0);
@@ -2751,7 +2751,7 @@ create_editplaylistdlg (void)
editplaylistdlg = gtk_dialog_new ();
gtk_container_set_border_width (GTK_CONTAINER (editplaylistdlg), 8);
- gtk_window_set_title (GTK_WINDOW (editplaylistdlg), "editplaylistdlg");
+ gtk_window_set_title (GTK_WINDOW (editplaylistdlg), _("editplaylistdlg"));
gtk_window_set_destroy_with_parent (GTK_WINDOW (editplaylistdlg), TRUE);
gtk_window_set_type_hint (GTK_WINDOW (editplaylistdlg), GDK_WINDOW_TYPE_HINT_DIALOG);
@@ -2767,7 +2767,7 @@ create_editplaylistdlg (void)
gtk_widget_show (hbox33);
gtk_box_pack_start (GTK_BOX (vbox15), hbox33, TRUE, TRUE, 0);
- label40 = gtk_label_new ("Title:");
+ label40 = gtk_label_new (_("Title:"));
gtk_widget_show (label40);
gtk_box_pack_start (GTK_BOX (hbox33), label40, FALSE, FALSE, 0);
@@ -2798,7 +2798,7 @@ create_editplaylistdlg (void)
gtk_widget_show (image396);
gtk_box_pack_start (GTK_BOX (hbox58), image396, FALSE, FALSE, 0);
- label94 = gtk_label_new_with_mnemonic ("_Cancel");
+ label94 = gtk_label_new_with_mnemonic (_("_Cancel"));
gtk_widget_show (label94);
gtk_box_pack_start (GTK_BOX (hbox58), label94, FALSE, FALSE, 0);
@@ -2819,7 +2819,7 @@ create_editplaylistdlg (void)
gtk_widget_show (image395);
gtk_box_pack_start (GTK_BOX (hbox57), image395, FALSE, FALSE, 0);
- label93 = gtk_label_new_with_mnemonic ("_OK");
+ label93 = gtk_label_new_with_mnemonic (_("_OK"));
gtk_widget_show (label93);
gtk_box_pack_start (GTK_BOX (hbox57), label93, FALSE, FALSE, 0);
@@ -2867,7 +2867,7 @@ create_addlocationdlg (void)
addlocationdlg = gtk_dialog_new ();
gtk_container_set_border_width (GTK_CONTAINER (addlocationdlg), 8);
- gtk_window_set_title (GTK_WINDOW (addlocationdlg), "Add location");
+ gtk_window_set_title (GTK_WINDOW (addlocationdlg), _("Add location"));
gtk_window_set_type_hint (GTK_WINDOW (addlocationdlg), GDK_WINDOW_TYPE_HINT_DIALOG);
dialog_vbox4 = GTK_DIALOG (addlocationdlg)->vbox;
@@ -2878,7 +2878,7 @@ create_addlocationdlg (void)
gtk_box_pack_start (GTK_BOX (dialog_vbox4), hbox34, TRUE, TRUE, 0);
gtk_container_set_border_width (GTK_CONTAINER (hbox34), 4);
- label41 = gtk_label_new ("URL:");
+ label41 = gtk_label_new (_("URL:"));
gtk_widget_show (label41);
gtk_box_pack_start (GTK_BOX (hbox34), label41, FALSE, FALSE, 0);
@@ -2910,7 +2910,7 @@ create_addlocationdlg (void)
gtk_widget_show (image397);
gtk_box_pack_start (GTK_BOX (hbox59), image397, FALSE, FALSE, 0);
- label95 = gtk_label_new_with_mnemonic ("_Cancel");
+ label95 = gtk_label_new_with_mnemonic (_("_Cancel"));
gtk_widget_show (label95);
gtk_box_pack_start (GTK_BOX (hbox59), label95, FALSE, FALSE, 0);
@@ -2931,7 +2931,7 @@ create_addlocationdlg (void)
gtk_widget_show (image398);
gtk_box_pack_start (GTK_BOX (hbox60), image398, FALSE, FALSE, 0);
- label96 = gtk_label_new_with_mnemonic ("_OK");
+ label96 = gtk_label_new_with_mnemonic (_("_OK"));
gtk_widget_show (label96);
gtk_box_pack_start (GTK_BOX (hbox60), label96, FALSE, FALSE, 0);
@@ -2979,7 +2979,7 @@ create_groupbydlg (void)
GtkWidget *label83;
groupbydlg = gtk_dialog_new ();
- gtk_window_set_title (GTK_WINDOW (groupbydlg), "Group By");
+ gtk_window_set_title (GTK_WINDOW (groupbydlg), _("Group By"));
gtk_window_set_type_hint (GTK_WINDOW (groupbydlg), GDK_WINDOW_TYPE_HINT_DIALOG);
dialog_vbox5 = GTK_DIALOG (groupbydlg)->vbox;
@@ -2994,7 +2994,7 @@ create_groupbydlg (void)
gtk_widget_show (hbox46);
gtk_box_pack_start (GTK_BOX (vbox25), hbox46, FALSE, FALSE, 0);
- label81 = gtk_label_new ("Format:");
+ label81 = gtk_label_new (_("Format:"));
gtk_widget_show (label81);
gtk_box_pack_start (GTK_BOX (hbox46), label81, FALSE, FALSE, 0);
@@ -3004,7 +3004,7 @@ create_groupbydlg (void)
gtk_entry_set_invisible_char (GTK_ENTRY (format), 9679);
gtk_entry_set_activates_default (GTK_ENTRY (format), TRUE);
- label82 = gtk_label_new ("Format conversions (start with %):\n [a]rtist, [t]itle, al[b]um, [B]and, [C]omposer\n track[n]umber, [N]totaltracks,\n [l]ength, [y]ear, [g]enre, [c]omment,\n copy[r]ight, [f]ilename, [T]ags\nExample: %a - %t [%l]");
+ label82 = gtk_label_new (_("Format conversions (start with %):\n [a]rtist, [t]itle, al[b]um, [B]and, [C]omposer\n track[n]umber, [N]totaltracks,\n [l]ength, [y]ear, [g]enre, [c]omment,\n copy[r]ight, [f]ilename, [T]ags\nExample: %a - %t [%l]"));
gtk_widget_show (label82);
gtk_box_pack_start (GTK_BOX (vbox25), label82, FALSE, FALSE, 0);
GTK_WIDGET_SET_FLAGS (label82, GTK_CAN_FOCUS);
@@ -3033,7 +3033,7 @@ create_groupbydlg (void)
gtk_widget_show (image386);
gtk_box_pack_start (GTK_BOX (hbox48), image386, FALSE, FALSE, 0);
- label84 = gtk_label_new_with_mnemonic ("_Cancel");
+ label84 = gtk_label_new_with_mnemonic (_("_Cancel"));
gtk_widget_show (label84);
gtk_box_pack_start (GTK_BOX (hbox48), label84, FALSE, FALSE, 0);
@@ -3054,7 +3054,7 @@ create_groupbydlg (void)
gtk_widget_show (image385);
gtk_box_pack_start (GTK_BOX (hbox47), image385, FALSE, FALSE, 0);
- label83 = gtk_label_new_with_mnemonic ("_OK");
+ label83 = gtk_label_new_with_mnemonic (_("_OK"));
gtk_widget_show (label83);
gtk_box_pack_start (GTK_BOX (hbox47), label83, FALSE, FALSE, 0);
diff --git a/plugins/gtkui/mainplaylist.c b/plugins/gtkui/mainplaylist.c
index 4c3b5d9e..7ad6e0ad 100644
--- a/plugins/gtkui/mainplaylist.c
+++ b/plugins/gtkui/mainplaylist.c
@@ -16,8 +16,12 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
#include <stdlib.h>
#include <string.h>
+#include "../../gettext.h"
#include "parser.h"
#include "gtkui.h"
#include "ddblistview.h"
@@ -290,11 +294,11 @@ main_playlist_init (GtkWidget *widget) {
DB_conf_item_t *col = deadbeef->conf_find ("playlist.column.", NULL);
if (!col) {
// create default set of columns
- add_column_helper (listview, "Playing", 50, DB_COLUMN_PLAYING, NULL, 0);
- add_column_helper (listview, "Artist / Album", 150, -1, "%a - %b", 0);
- add_column_helper (listview, "Track No", 50, -1, "%n", 1);
- add_column_helper (listview, "Title / Track Artist", 150, -1, "%t", 0);
- add_column_helper (listview, "Duration", 50, -1, "%l", 0);
+ add_column_helper (listview, _("Playing"), 50, DB_COLUMN_PLAYING, NULL, 0);
+ add_column_helper (listview, _("Artist / Album"), 150, -1, "%a - %b", 0);
+ add_column_helper (listview, _("Track No"), 50, -1, "%n", 1);
+ add_column_helper (listview, _("Title / Track Artist"), 150, -1, "%t", 0);
+ add_column_helper (listview, _("Duration"), 50, -1, "%l", 0);
}
else {
while (col) {
diff --git a/plugins/gtkui/plcommon.c b/plugins/gtkui/plcommon.c
index 96ddff69..741658d6 100644
--- a/plugins/gtkui/plcommon.c
+++ b/plugins/gtkui/plcommon.c
@@ -313,9 +313,9 @@ on_remove_from_disk_activate (GtkMenuItem *menuitem,
GtkWidget *widget = GTK_WIDGET (menuitem);
if (deadbeef->conf_get_int ("gtkui.delete_files_ask", 1)) {
- GtkWidget *dlg = gtk_message_dialog_new (GTK_WINDOW (mainwin), GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, "Delete files from disk");
- gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dlg), "Files will be lost. Proceed?\n(This dialog can be turned off in GTKUI plugin settings)");
- gtk_window_set_title (GTK_WINDOW (dlg), "Warning");
+ GtkWidget *dlg = gtk_message_dialog_new (GTK_WINDOW (mainwin), GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, _("Delete files from disk"));
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dlg), _("Files will be lost. Proceed?\n(This dialog can be turned off in GTKUI plugin settings)"));
+ gtk_window_set_title (GTK_WINDOW (dlg), _("Warning"));
int response = gtk_dialog_run (GTK_DIALOG (dlg));
gtk_widget_destroy (dlg);
@@ -360,12 +360,12 @@ list_context_menu (DdbListview *listview, DdbListviewIter it, int idx) {
GtkWidget *reload_metadata;
playlist_menu = gtk_menu_new ();
- add_to_playback_queue1 = gtk_menu_item_new_with_mnemonic ("Add to playback queue");
+ add_to_playback_queue1 = gtk_menu_item_new_with_mnemonic (_("Add to playback queue"));
gtk_widget_show (add_to_playback_queue1);
gtk_container_add (GTK_CONTAINER (playlist_menu), add_to_playback_queue1);
g_object_set_data (G_OBJECT (add_to_playback_queue1), "ps", listview);
- remove_from_playback_queue1 = gtk_menu_item_new_with_mnemonic ("Remove from playback queue");
+ remove_from_playback_queue1 = gtk_menu_item_new_with_mnemonic (_("Remove from playback queue"));
if (inqueue == -1) {
gtk_widget_set_sensitive (remove_from_playback_queue1, FALSE);
}
@@ -373,7 +373,7 @@ list_context_menu (DdbListview *listview, DdbListviewIter it, int idx) {
gtk_container_add (GTK_CONTAINER (playlist_menu), remove_from_playback_queue1);
g_object_set_data (G_OBJECT (remove_from_playback_queue1), "ps", listview);
- reload_metadata = gtk_menu_item_new_with_mnemonic ("Reload metadata");
+ reload_metadata = gtk_menu_item_new_with_mnemonic (_("Reload metadata"));
gtk_widget_show (reload_metadata);
gtk_container_add (GTK_CONTAINER (playlist_menu), reload_metadata);
g_object_set_data (G_OBJECT (reload_metadata), "ps", listview);
@@ -384,12 +384,12 @@ list_context_menu (DdbListview *listview, DdbListviewIter it, int idx) {
gtk_container_add (GTK_CONTAINER (playlist_menu), separator9);
gtk_widget_set_sensitive (separator9, FALSE);
- remove2 = gtk_menu_item_new_with_mnemonic ("Remove");
+ remove2 = gtk_menu_item_new_with_mnemonic (_("Remove"));
gtk_widget_show (remove2);
gtk_container_add (GTK_CONTAINER (playlist_menu), remove2);
g_object_set_data (G_OBJECT (remove2), "ps", listview);
- remove_from_disk = gtk_menu_item_new_with_mnemonic ("Remove from disk");
+ remove_from_disk = gtk_menu_item_new_with_mnemonic (_("Remove from disk"));
gtk_widget_show (remove_from_disk);
gtk_container_add (GTK_CONTAINER (playlist_menu), remove_from_disk);
g_object_set_data (G_OBJECT (remove_from_disk), "ps", listview);
@@ -399,7 +399,7 @@ list_context_menu (DdbListview *listview, DdbListviewIter it, int idx) {
gtk_container_add (GTK_CONTAINER (playlist_menu), separator8);
gtk_widget_set_sensitive (separator8, FALSE);
- properties1 = gtk_menu_item_new_with_mnemonic ("Properties");
+ properties1 = gtk_menu_item_new_with_mnemonic (_("Properties"));
gtk_widget_show (properties1);
gtk_container_add (GTK_CONTAINER (playlist_menu), properties1);
g_object_set_data (G_OBJECT (properties1), "ps", listview);
@@ -613,7 +613,7 @@ on_add_column_activate (GtkMenuItem *menuitem,
{
GtkWidget *dlg = create_editcolumndlg ();
gtk_dialog_set_default_response (GTK_DIALOG (dlg), GTK_RESPONSE_OK);
- gtk_window_set_title (GTK_WINDOW (dlg), "Add column");
+ gtk_window_set_title (GTK_WINDOW (dlg), _("Add column"));
gtk_combo_box_set_active (GTK_COMBO_BOX (lookup_widget (dlg, "id")), 0);
gtk_combo_box_set_active (GTK_COMBO_BOX (lookup_widget (dlg, "align")), 0);
gint response = gtk_dialog_run (GTK_DIALOG (dlg));
@@ -643,7 +643,7 @@ on_edit_column_activate (GtkMenuItem *menuitem,
return;
GtkWidget *dlg = create_editcolumndlg ();
gtk_dialog_set_default_response (GTK_DIALOG (dlg), GTK_RESPONSE_OK);
- gtk_window_set_title (GTK_WINDOW (dlg), "Edit column");
+ gtk_window_set_title (GTK_WINDOW (dlg), _("Edit column"));
const char *title;
int width;
@@ -738,15 +738,15 @@ create_headermenu (int groupby)
headermenu = gtk_menu_new ();
- add_column = gtk_menu_item_new_with_mnemonic ("Add column");
+ add_column = gtk_menu_item_new_with_mnemonic (_("Add column"));
gtk_widget_show (add_column);
gtk_container_add (GTK_CONTAINER (headermenu), add_column);
- edit_column = gtk_menu_item_new_with_mnemonic ("Edit column");
+ edit_column = gtk_menu_item_new_with_mnemonic (_("Edit column"));
gtk_widget_show (edit_column);
gtk_container_add (GTK_CONTAINER (headermenu), edit_column);
- remove_column = gtk_menu_item_new_with_mnemonic ("Remove column");
+ remove_column = gtk_menu_item_new_with_mnemonic (_("Remove column"));
gtk_widget_show (remove_column);
gtk_container_add (GTK_CONTAINER (headermenu), remove_column);
@@ -756,26 +756,26 @@ create_headermenu (int groupby)
gtk_container_add (GTK_CONTAINER (headermenu), separator);
gtk_widget_set_sensitive (separator, FALSE);
- group_by = gtk_menu_item_new_with_mnemonic ("Group by");
+ group_by = gtk_menu_item_new_with_mnemonic (_("Group by"));
gtk_widget_show (group_by);
gtk_container_add (GTK_CONTAINER (headermenu), group_by);
group_by_menu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (group_by), group_by_menu);
- none = gtk_menu_item_new_with_mnemonic ("None");
+ none = gtk_menu_item_new_with_mnemonic (_("None"));
gtk_widget_show (none);
gtk_container_add (GTK_CONTAINER (group_by_menu), none);
- artist_date_album = gtk_menu_item_new_with_mnemonic ("Artist/Date/Album");
+ artist_date_album = gtk_menu_item_new_with_mnemonic (_("Artist/Date/Album"));
gtk_widget_show (artist_date_album);
gtk_container_add (GTK_CONTAINER (group_by_menu), artist_date_album);
- artist = gtk_menu_item_new_with_mnemonic ("Artist");
+ artist = gtk_menu_item_new_with_mnemonic (_("Artist"));
gtk_widget_show (artist);
gtk_container_add (GTK_CONTAINER (group_by_menu), artist);
- custom = gtk_menu_item_new_with_mnemonic ("Custom");
+ custom = gtk_menu_item_new_with_mnemonic (_("Custom"));
gtk_widget_show (custom);
gtk_container_add (GTK_CONTAINER (group_by_menu), custom);
diff --git a/plugins/gtkui/pluginconf.c b/plugins/gtkui/pluginconf.c
index acae34d4..72ad0aae 100644
--- a/plugins/gtkui/pluginconf.c
+++ b/plugins/gtkui/pluginconf.c
@@ -25,6 +25,7 @@
#include <stdlib.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
+#include "../../gettext.h"
#include "../../deadbeef.h"
#include "gtkui.h"
#include "parser.h"
@@ -37,7 +38,7 @@ extern GtkWidget *mainwin;
void
on_prop_browse_file (GtkButton *button, gpointer user_data) {
- GtkWidget *dlg = gtk_file_chooser_dialog_new ("Open file...", GTK_WINDOW (mainwin), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
+ GtkWidget *dlg = gtk_file_chooser_dialog_new (_("Open file..."), GTK_WINDOW (mainwin), GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (dlg), FALSE);
// restore folder
@@ -135,7 +136,7 @@ void
plugin_configure (GtkWidget *parentwin, DB_plugin_t *p) {
// create window
char title[200];
- snprintf (title, sizeof (title), "Setup %s", p->name);
+ snprintf (title, sizeof (title), _("Setup %s"), p->name);
GtkWidget *win = gtk_dialog_new_with_buttons (title, GTK_WINDOW (parentwin), GTK_DIALOG_MODAL, GTK_STOCK_APPLY, GTK_RESPONSE_APPLY, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
gtk_dialog_set_default_response (GTK_DIALOG (win), GTK_RESPONSE_OK);
gtk_window_set_type_hint (GTK_WINDOW (win), GDK_WINDOW_TYPE_HINT_DIALOG);
diff --git a/plugins/gtkui/prefwin.c b/plugins/gtkui/prefwin.c
index 2d6face5..fc8649e8 100644
--- a/plugins/gtkui/prefwin.c
+++ b/plugins/gtkui/prefwin.c
@@ -16,11 +16,15 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
#include <gtk/gtk.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <gdk/gdkkeysyms.h>
+#include "../../gettext.h"
#include "gtkui.h"
#include "support.h"
#include "interface.h"
@@ -91,7 +95,7 @@ preferences_fill_soundcards (void) {
GtkTreeModel *mdl = gtk_combo_box_get_model (combobox);
gtk_list_store_clear (GTK_LIST_STORE (mdl));
- gtk_combo_box_append_text (combobox, "Default Audio Device");
+ gtk_combo_box_append_text (combobox, _("Default Audio Device"));
if (!strcmp (s, "default")) {
gtk_combo_box_set_active (combobox, 0);
}
@@ -260,17 +264,17 @@ prefwin_add_hotkeys_tab (GtkWidget *prefwin) {
gtk_box_pack_start (GTK_BOX (vbox17), hbuttonbox3, FALSE, FALSE, 0);
gtk_button_box_set_layout (GTK_BUTTON_BOX (hbuttonbox3), GTK_BUTTONBOX_END);
- addhotkey = gtk_button_new_with_mnemonic ("Add");
+ addhotkey = gtk_button_new_with_mnemonic (_("Add"));
gtk_widget_show (addhotkey);
gtk_container_add (GTK_CONTAINER (hbuttonbox3), addhotkey);
GTK_WIDGET_SET_FLAGS (addhotkey, GTK_CAN_DEFAULT);
- removehotkey = gtk_button_new_with_mnemonic ("Remove");
+ removehotkey = gtk_button_new_with_mnemonic (_("Remove"));
gtk_widget_show (removehotkey);
gtk_container_add (GTK_CONTAINER (hbuttonbox3), removehotkey);
GTK_WIDGET_SET_FLAGS (removehotkey, GTK_CAN_DEFAULT);
- label66 = gtk_label_new ("Global Hotkeys");
+ label66 = gtk_label_new (_("Global Hotkeys"));
gtk_widget_show (label66);
int npages = gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook2));
gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook2), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook2), npages-1), label66);
@@ -325,8 +329,8 @@ prefwin_add_hotkeys_tab (GtkWidget *prefwin) {
hkstore);
- GtkTreeViewColumn *hk_col1 = gtk_tree_view_column_new_with_attributes ("Slot", rend_hk_slot, "text", 0, NULL);
- GtkTreeViewColumn *hk_col2 = gtk_tree_view_column_new_with_attributes ("Key combination", rend_hk_binding, "text", 1, NULL);
+ GtkTreeViewColumn *hk_col1 = gtk_tree_view_column_new_with_attributes (_("Slot"), rend_hk_slot, "text", 0, NULL);
+ GtkTreeViewColumn *hk_col2 = gtk_tree_view_column_new_with_attributes (_("Key combination"), rend_hk_binding, "text", 1, NULL);
gtk_tree_view_append_column (hktree, hk_col1);
gtk_tree_view_append_column (hktree, hk_col2);
@@ -372,7 +376,7 @@ on_preferences_activate (GtkMenuItem *menuitem,
GtkComboBox *combobox = NULL;
// output plugin selection
- const char *outplugname = deadbeef->conf_get_str ("output_plugin", "ALSA output plugin");
+ const char *outplugname = deadbeef->conf_get_str ("output_plugin", _("ALSA output plugin"));
combobox = GTK_COMBO_BOX (lookup_widget (w, "pref_output_plugin"));
DB_output_t **out_plugs = deadbeef->plug_get_output_list ();
@@ -481,7 +485,7 @@ on_preferences_activate (GtkMenuItem *menuitem,
}
#else
GtkListStore *store = gtk_list_store_new (1, G_TYPE_STRING);
- GtkTreeViewColumn *col2 = gtk_tree_view_column_new_with_attributes ("Title", rend_text, "text", 0, NULL);
+ GtkTreeViewColumn *col2 = gtk_tree_view_column_new_with_attributes (_("Title"), rend_text, "text", 0, NULL);
gtk_tree_view_append_column (tree, col2);
DB_plugin_t **plugins = deadbeef->plug_get_list ();
int i;
@@ -562,7 +566,7 @@ void
on_pref_output_plugin_changed (GtkComboBox *combobox,
gpointer user_data)
{
- const char *outplugname = deadbeef->conf_get_str ("output_plugin", "ALSA output plugin");
+ const char *outplugname = deadbeef->conf_get_str ("output_plugin", _("ALSA output plugin"));
int active = gtk_combo_box_get_active (combobox);
DB_output_t **out_plugs = deadbeef->plug_get_output_list ();
diff --git a/plugins/gtkui/progress.c b/plugins/gtkui/progress.c
index 89ce4bb4..d986a162 100644
--- a/plugins/gtkui/progress.c
+++ b/plugins/gtkui/progress.c
@@ -15,11 +15,15 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
#include <gtk/gtk.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
+#include "../../gettext.h"
#include "interface.h"
#include "callbacks.h"
#include "support.h"
@@ -57,7 +61,7 @@ progress_show (void) {
if (playlist) {
gtk_widget_set_sensitive (playlist, FALSE);
}
- progress_settext ("Initializing...");
+ progress_settext (_("Initializing..."));
gtk_widget_show_all (progressdlg);
gtk_window_present (GTK_WINDOW (progressdlg));
gtk_window_set_transient_for (GTK_WINDOW (progressdlg), GTK_WINDOW (mainwin));
diff --git a/plugins/gtkui/search.c b/plugins/gtkui/search.c
index ef34cd24..36818f9f 100644
--- a/plugins/gtkui/search.c
+++ b/plugins/gtkui/search.c
@@ -24,6 +24,7 @@
#include <math.h>
#include <stdlib.h>
#include <string.h>
+#include "../../gettext.h"
#include "callbacks.h"
#include "interface.h"
@@ -429,10 +430,10 @@ search_playlist_init (GtkWidget *widget) {
// create default set of columns
DB_conf_item_t *col = deadbeef->conf_find ("search.column.", NULL);
if (!col) {
- add_column_helper (listview, "Artist / Album", 150, -1, "%a - %b", 0);
- add_column_helper (listview, "Track No", 50, -1, "%n", 1);
- add_column_helper (listview, "Title / Track Artist", 150, -1, "%t", 0);
- add_column_helper (listview, "Duration", 50, -1, "%l", 0);
+ add_column_helper (listview, _("Artist / Album"), 150, -1, "%a - %b", 0);
+ add_column_helper (listview, _("Track No"), 50, -1, "%n", 1);
+ add_column_helper (listview, _("Title / Track Artist"), 150, -1, "%t", 0);
+ add_column_helper (listview, _("Duration"), 50, -1, "%l", 0);
}
else {
while (col) {
diff --git a/plugins/gtkui/support.c b/plugins/gtkui/support.c
index 7dc3c78c..00aff298 100644
--- a/plugins/gtkui/support.c
+++ b/plugins/gtkui/support.c
@@ -87,7 +87,7 @@ create_pixmap (GtkWidget *widget,
if (!pathname)
{
- g_warning ("Couldn't find pixmap file: %s", filename);
+ g_warning (_("Couldn't find pixmap file: %s"), filename);
return gtk_image_new ();
}
@@ -111,7 +111,7 @@ create_pixbuf (const gchar *filename)
if (!pathname)
{
- g_warning ("Couldn't find pixmap file: %s", filename);
+ g_warning (_("Couldn't find pixmap file: %s"), filename);
return NULL;
}
diff --git a/plugins/gtkui/support.h b/plugins/gtkui/support.h
index 2dea079c..a32649e5 100644
--- a/plugins/gtkui/support.h
+++ b/plugins/gtkui/support.h
@@ -9,6 +9,31 @@
#include <gtk/gtk.h>
/*
+ * Standard gettext macros.
+ */
+#ifdef ENABLE_NLS
+# include <libintl.h>
+# undef _
+# define _(String) dgettext (PACKAGE, String)
+# define Q_(String) g_strip_context ((String), gettext (String))
+# ifdef gettext_noop
+# define N_(String) gettext_noop (String)
+# else
+# define N_(String) (String)
+# endif
+#else
+# define textdomain(String) (String)
+# define gettext(String) (String)
+# define dgettext(Domain,Message) (Message)
+# define dcgettext(Domain,Message,Type) (Message)
+# define bindtextdomain(Domain,Directory) (Domain)
+# define _(String) (String)
+# define Q_(String) g_strip_context ((String), (String))
+# define N_(String) (String)
+#endif
+
+
+/*
* Public Functions.
*/
diff --git a/plugins/gtkui/trkproperties.c b/plugins/gtkui/trkproperties.c
index 3dca1718..cea21d6f 100644
--- a/plugins/gtkui/trkproperties.c
+++ b/plugins/gtkui/trkproperties.c
@@ -16,10 +16,14 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include <string.h>
#include <math.h>
+#include "../../gettext.h"
#include "ddblistview.h"
#include "trkproperties.h"
#include "interface.h"
@@ -46,10 +50,10 @@ on_trackproperties_delete_event (GtkWidget *widget,
gpointer user_data)
{
if (trkproperties_modified) {
- GtkWidget *dlg = gtk_message_dialog_new (GTK_WINDOW (mainwin), GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, "You've modified data for this track.");
+ GtkWidget *dlg = gtk_message_dialog_new (GTK_WINDOW (mainwin), GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, _("You've modified data for this track."));
gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (trackproperties));
- gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dlg), "Really close the window?");
- gtk_window_set_title (GTK_WINDOW (dlg), "Warning");
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dlg), _("Really close the window?"));
+ gtk_window_set_title (GTK_WINDOW (dlg), _("Warning"));
int response = gtk_dialog_run (GTK_DIALOG (dlg));
gtk_widget_destroy (dlg);
@@ -168,12 +172,12 @@ trkproperties_fill_metadata (void) {
gtk_list_store_set (propstore, &iter, 0, "Subtrack Index", 1, temp, -1);
gtk_list_store_append (propstore, &iter);
deadbeef->pl_format_time (deadbeef->pl_get_item_duration (track), temp, sizeof (temp));
- gtk_list_store_set (propstore, &iter, 0, "Duration", 1, temp, -1);
+ gtk_list_store_set (propstore, &iter, 0, _("Duration"), 1, temp, -1);
gtk_list_store_append (propstore, &iter);
deadbeef->pl_format_title (track, -1, temp, sizeof (temp), -1, "%T");
- gtk_list_store_set (propstore, &iter, 0, "Tag Type(s)", 1, temp, -1);
+ gtk_list_store_set (propstore, &iter, 0, _("Tag Type(s)"), 1, temp, -1);
gtk_list_store_append (propstore, &iter);
- gtk_list_store_set (propstore, &iter, 0, "Embedded Cuesheet", 1, (deadbeef->pl_get_item_flags (track) & DDB_HAS_EMBEDDED_CUESHEET) ? "Yes" : "No", -1);
+ gtk_list_store_set (propstore, &iter, 0, _("Embedded Cuesheet"), 1, (deadbeef->pl_get_item_flags (track) & DDB_HAS_EMBEDDED_CUESHEET) ? _("Yes") : _("No"), -1);
gtk_list_store_append (propstore, &iter);
snprintf (temp, sizeof (temp), "%0.2f dB", track->replaygain_album_gain);
@@ -241,8 +245,8 @@ show_track_properties_dlg (DB_playItem_t *it) {
G_CALLBACK (on_metadata_edited),
store);
}
- GtkTreeViewColumn *col1 = gtk_tree_view_column_new_with_attributes ("Key", rend_text, "text", 0, NULL);
- GtkTreeViewColumn *col2 = gtk_tree_view_column_new_with_attributes ("Value", rend_text2, "text", 1, NULL);
+ GtkTreeViewColumn *col1 = gtk_tree_view_column_new_with_attributes (_("Key"), rend_text, "text", 0, NULL);
+ GtkTreeViewColumn *col2 = gtk_tree_view_column_new_with_attributes (_("Value"), rend_text2, "text", 1, NULL);
gtk_tree_view_append_column (tree, col1);
gtk_tree_view_append_column (tree, col2);
@@ -253,8 +257,8 @@ show_track_properties_dlg (DB_playItem_t *it) {
GtkCellRenderer *rend_propkey = gtk_cell_renderer_text_new ();
GtkCellRenderer *rend_propvalue = gtk_cell_renderer_text_new ();
g_object_set (G_OBJECT (rend_propvalue), "editable", TRUE, NULL);
- col1 = gtk_tree_view_column_new_with_attributes ("Key", rend_propkey, "text", 0, NULL);
- col2 = gtk_tree_view_column_new_with_attributes ("Value", rend_propvalue, "text", 1, NULL);
+ col1 = gtk_tree_view_column_new_with_attributes (_("Key"), rend_propkey, "text", 0, NULL);
+ col2 = gtk_tree_view_column_new_with_attributes (_("Value"), rend_propvalue, "text", 1, NULL);
gtk_tree_view_append_column (proptree, col1);
gtk_tree_view_append_column (proptree, col2);
}
diff --git a/plugins/notify/notify.c b/plugins/notify/notify.c
index 1f1bc194..7d81c6d8 100644
--- a/plugins/notify/notify.c
+++ b/plugins/notify/notify.c
@@ -21,6 +21,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "../../gettext.h"
#define E_NOTIFICATION_BUS_NAME "org.freedesktop.Notifications"
#define E_NOTIFICATION_INTERFACE "org.freedesktop.Notifications"
@@ -134,7 +135,7 @@ on_songchanged (DB_event_trackchange_t *ev, uintptr_t data) {
const char *v_appname = "DeaDBeeF";
dbus_uint32_t v_id = 0;
const char *v_iconname = PREFIX "/share/deadbeef/pixmaps/play_24.png";
- const char *v_summary = "DeaDBeeF now playing";
+ const char *v_summary = _("DeaDBeeF now playing");
const char *v_body = esc;
dbus_int32_t v_timeout = -1;
diff --git a/po/ChangeLog b/po/ChangeLog
new file mode 100644
index 00000000..2ee0657e
--- /dev/null
+++ b/po/ChangeLog
@@ -0,0 +1,5 @@
+2010-05-19 gettextize <bug-gnu-gettext@gnu.org>
+
+ * Makefile.in.in: Upgrade to gettext-0.18.
+ * Rules-quot: Upgrade to gettext-0.18.
+
diff --git a/po/LINGUAS b/po/LINGUAS
new file mode 100644
index 00000000..2a98264a
--- /dev/null
+++ b/po/LINGUAS
@@ -0,0 +1,8 @@
+el
+es
+he
+hr
+nl
+ru
+sv
+uk
diff --git a/po/Makefile.in.in b/po/Makefile.in.in
new file mode 100644
index 00000000..cc8a2227
--- /dev/null
+++ b/po/Makefile.in.in
@@ -0,0 +1,217 @@
+# Makefile for program source directory in GNU NLS utilities package.
+# Copyright (C) 1995, 1996, 1997 by Ulrich Drepper <drepper@gnu.ai.mit.edu>
+# Copyright (C) 2004-2008 Rodney Dawes <dobey.pwns@gmail.com>
+#
+# This file may be copied and used freely without restrictions. It may
+# be used in projects which are not available under a GNU Public License,
+# but which still want to provide support for the GNU gettext functionality.
+#
+# - Modified by Owen Taylor <otaylor@redhat.com> to use GETTEXT_PACKAGE
+# instead of PACKAGE and to look for po2tbl in ./ not in intl/
+#
+# - Modified by jacob berkman <jacob@ximian.com> to install
+# Makefile.in.in and po2tbl.sed.in for use with glib-gettextize
+#
+# - Modified by Rodney Dawes <dobey.pwns@gmail.com> for use with intltool
+#
+# We have the following line for use by intltoolize:
+# INTLTOOL_MAKEFILE
+
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+PACKAGE = @PACKAGE@
+VERSION = @VERSION@
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+top_builddir = @top_builddir@
+VPATH = @srcdir@
+
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+datadir = @datadir@
+datarootdir = @datarootdir@
+libdir = @libdir@
+DATADIRNAME = @DATADIRNAME@
+itlocaledir = $(prefix)/$(DATADIRNAME)/locale
+subdir = po
+install_sh = @install_sh@
+# Automake >= 1.8 provides @mkdir_p@.
+# Until it can be supposed, use the safe fallback:
+mkdir_p = $(install_sh) -d
+
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+
+GMSGFMT = @GMSGFMT@
+MSGFMT = @MSGFMT@
+XGETTEXT = @XGETTEXT@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+MSGMERGE = INTLTOOL_EXTRACT=$(INTLTOOL_EXTRACT) srcdir=$(srcdir) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --dist
+GENPOT = INTLTOOL_EXTRACT=$(INTLTOOL_EXTRACT) srcdir=$(srcdir) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --pot
+
+ALL_LINGUAS = @ALL_LINGUAS@
+
+PO_LINGUAS=$(shell if test -r $(srcdir)/LINGUAS; then grep -v "^\#" $(srcdir)/LINGUAS; else echo "$(ALL_LINGUAS)"; fi)
+
+USER_LINGUAS=$(shell if test -n "$(LINGUAS)"; then LLINGUAS="$(LINGUAS)"; ALINGUAS="$(ALL_LINGUAS)"; for lang in $$LLINGUAS; do if test -n "`grep \^$$lang$$ $(srcdir)/LINGUAS 2>/dev/null`" -o -n "`echo $$ALINGUAS|tr ' ' '\n'|grep \^$$lang$$`"; then printf "$$lang "; fi; done; fi)
+
+USE_LINGUAS=$(shell if test -n "$(USER_LINGUAS)" -o -n "$(LINGUAS)"; then LLINGUAS="$(USER_LINGUAS)"; else if test -n "$(PO_LINGUAS)"; then LLINGUAS="$(PO_LINGUAS)"; else LLINGUAS="$(ALL_LINGUAS)"; fi; fi; for lang in $$LLINGUAS; do printf "$$lang "; done)
+
+POFILES=$(shell LINGUAS="$(PO_LINGUAS)"; for lang in $$LINGUAS; do printf "$$lang.po "; done)
+
+DISTFILES = Makefile.in.in POTFILES.in $(POFILES)
+EXTRA_DISTFILES = ChangeLog POTFILES.skip Makevars LINGUAS
+
+POTFILES = \
+# This comment gets stripped out
+
+CATALOGS=$(shell LINGUAS="$(USE_LINGUAS)"; for lang in $$LINGUAS; do printf "$$lang.gmo "; done)
+
+.SUFFIXES:
+.SUFFIXES: .po .pox .gmo .mo .msg .cat
+
+.po.pox:
+ $(MAKE) $(GETTEXT_PACKAGE).pot
+ $(MSGMERGE) $< $(GETTEXT_PACKAGE).pot -o $*.pox
+
+.po.mo:
+ $(MSGFMT) -o $@ $<
+
+.po.gmo:
+ file=`echo $* | sed 's,.*/,,'`.gmo \
+ && rm -f $$file && $(GMSGFMT) -o $$file $<
+
+.po.cat:
+ sed -f ../intl/po2msg.sed < $< > $*.msg \
+ && rm -f $@ && gencat $@ $*.msg
+
+
+all: all-@USE_NLS@
+
+all-yes: $(CATALOGS)
+all-no:
+
+$(GETTEXT_PACKAGE).pot: $(POTFILES)
+ $(GENPOT)
+
+install: install-data
+install-data: install-data-@USE_NLS@
+install-data-no: all
+install-data-yes: all
+ linguas="$(USE_LINGUAS)"; \
+ for lang in $$linguas; do \
+ dir=$(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES; \
+ $(mkdir_p) $$dir; \
+ if test -r $$lang.gmo; then \
+ $(INSTALL_DATA) $$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \
+ echo "installing $$lang.gmo as $$dir/$(GETTEXT_PACKAGE).mo"; \
+ else \
+ $(INSTALL_DATA) $(srcdir)/$$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \
+ echo "installing $(srcdir)/$$lang.gmo as" \
+ "$$dir/$(GETTEXT_PACKAGE).mo"; \
+ fi; \
+ if test -r $$lang.gmo.m; then \
+ $(INSTALL_DATA) $$lang.gmo.m $$dir/$(GETTEXT_PACKAGE).mo.m; \
+ echo "installing $$lang.gmo.m as $$dir/$(GETTEXT_PACKAGE).mo.m"; \
+ else \
+ if test -r $(srcdir)/$$lang.gmo.m ; then \
+ $(INSTALL_DATA) $(srcdir)/$$lang.gmo.m \
+ $$dir/$(GETTEXT_PACKAGE).mo.m; \
+ echo "installing $(srcdir)/$$lang.gmo.m as" \
+ "$$dir/$(GETTEXT_PACKAGE).mo.m"; \
+ else \
+ true; \
+ fi; \
+ fi; \
+ done
+
+# Empty stubs to satisfy archaic automake needs
+dvi info ctags tags CTAGS TAGS ID:
+
+# Define this as empty until I found a useful application.
+install-exec installcheck:
+
+uninstall:
+ linguas="$(USE_LINGUAS)"; \
+ for lang in $$linguas; do \
+ rm -f $(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo; \
+ rm -f $(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo.m; \
+ done
+
+check: all $(GETTEXT_PACKAGE).pot
+ rm -f missing notexist
+ srcdir=$(srcdir) $(INTLTOOL_UPDATE) -m
+ if [ -r missing -o -r notexist ]; then \
+ exit 1; \
+ fi
+
+mostlyclean:
+ rm -f *.pox $(GETTEXT_PACKAGE).pot *.old.po cat-id-tbl.tmp
+ rm -f .intltool-merge-cache
+
+clean: mostlyclean
+
+distclean: clean
+ rm -f Makefile Makefile.in POTFILES stamp-it
+ rm -f *.mo *.msg *.cat *.cat.m *.gmo
+
+maintainer-clean: distclean
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+ rm -f Makefile.in.in
+
+distdir = ../$(PACKAGE)-$(VERSION)/$(subdir)
+dist distdir: $(DISTFILES)
+ dists="$(DISTFILES)"; \
+ extra_dists="$(EXTRA_DISTFILES)"; \
+ for file in $$extra_dists; do \
+ test -f $(srcdir)/$$file && dists="$$dists $(srcdir)/$$file"; \
+ done; \
+ for file in $$dists; do \
+ test -f $$file || file="$(srcdir)/$$file"; \
+ ln $$file $(distdir) 2> /dev/null \
+ || cp -p $$file $(distdir); \
+ done
+
+update-po: Makefile
+ $(MAKE) $(GETTEXT_PACKAGE).pot
+ tmpdir=`pwd`; \
+ linguas="$(USE_LINGUAS)"; \
+ for lang in $$linguas; do \
+ echo "$$lang:"; \
+ result="`$(MSGMERGE) -o $$tmpdir/$$lang.new.po $$lang`"; \
+ if $$result; then \
+ if cmp $(srcdir)/$$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
+ rm -f $$tmpdir/$$lang.new.po; \
+ else \
+ if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
+ :; \
+ else \
+ echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
+ rm -f $$tmpdir/$$lang.new.po; \
+ exit 1; \
+ fi; \
+ fi; \
+ else \
+ echo "msgmerge for $$lang.gmo failed!"; \
+ rm -f $$tmpdir/$$lang.new.po; \
+ fi; \
+ done
+
+Makefile POTFILES: stamp-it
+ @if test ! -f $@; then \
+ rm -f stamp-it; \
+ $(MAKE) stamp-it; \
+ fi
+
+stamp-it: Makefile.in.in $(top_builddir)/config.status POTFILES.in
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/Makefile.in CONFIG_HEADERS= CONFIG_LINKS= \
+ $(SHELL) ./config.status
+
+# Tell versions [3.59,3.63) of GNU make not to export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/po/POTFILES.in b/po/POTFILES.in
new file mode 100644
index 00000000..25ecd072
--- /dev/null
+++ b/po/POTFILES.in
@@ -0,0 +1,21 @@
+plugins/gtkui/callbacks.c
+plugins/gtkui/ddbtabstrip.c
+plugins/gtkui/eq.c
+plugins/gtkui/gtkui.c
+plugins/gtkui/interface.c
+plugins/gtkui/mainplaylist.c
+plugins/gtkui/plcommon.c
+plugins/gtkui/pluginconf.c
+plugins/gtkui/prefwin.c
+plugins/gtkui/progress.c
+plugins/gtkui/search.c
+plugins/gtkui/trkproperties.c
+plugins/notify/notify.c
+main.c
+playlist.c
+plugins.c
+deadbeef.desktop.in
+intl/plural.c
+plugins/gtkui/deadbeef.glade
+plugins/gtkui/support.c
+plugins/vorbis/vcedit.c
diff --git a/po/deadbeef.pot b/po/deadbeef.pot
new file mode 100644
index 00000000..15b635d2
--- /dev/null
+++ b/po/deadbeef.pot
@@ -0,0 +1,1086 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-05-27 16:47+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../plugins/gtkui/callbacks.c:97
+msgid "Supported sound formats"
+msgstr ""
+
+#: ../plugins/gtkui/callbacks.c:108
+msgid "Other files (*)"
+msgstr ""
+
+#: ../plugins/gtkui/callbacks.c:117
+msgid "Open file(s)..."
+msgstr ""
+
+#: ../plugins/gtkui/callbacks.c:150
+msgid "Add file(s) to playlist..."
+msgstr ""
+
+#: ../plugins/gtkui/callbacks.c:182
+msgid "Add folder(s) to playlist..."
+msgstr ""
+
+#: ../plugins/gtkui/callbacks.c:640
+msgid "Failed while reading help file"
+msgstr ""
+
+#: ../plugins/gtkui/callbacks.c:650
+msgid "Failed to load help file"
+msgstr ""
+
+#: ../plugins/gtkui/callbacks.c:664 ../plugins/gtkui/interface.c:1105
+#: ../plugins/gtkui/deadbeef.glade.h:56
+msgid "Help"
+msgstr ""
+
+#: ../plugins/gtkui/callbacks.c:674
+#, c-format
+msgid "About DeaDBeeF %s"
+msgstr ""
+
+#: ../plugins/gtkui/callbacks.c:685
+#, c-format
+msgid "DeaDBeeF %s ChangeLog"
+msgstr ""
+
+#: ../plugins/gtkui/ddbtabstrip.c:527
+msgid "Edit playlist"
+msgstr ""
+
+#: ../plugins/gtkui/ddbtabstrip.c:604
+msgid "Rename Playlist"
+msgstr ""
+
+#: ../plugins/gtkui/ddbtabstrip.c:608
+msgid "Remove Playlist"
+msgstr ""
+
+#: ../plugins/gtkui/ddbtabstrip.c:612
+msgid "Add New Playlist"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:113
+msgid "Save DeaDBeeF EQ Preset"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:120
+msgid "DeaDBeeF EQ preset files (*.ddbeq)"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:151
+msgid "Load DeaDBeeF EQ Preset..."
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:155
+msgid "DeaDBeeF EQ presets (*.ddbeq)"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:214
+msgid "Import Foobar2000 EQ Preset..."
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:218
+msgid "Foobar2000 EQ presets (*.feq)"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:292
+msgid "Enable"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:299
+msgid "Zero All"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:306
+msgid "Zero Preamp"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:313
+msgid "Zero Bands"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:320
+msgid "Save Preset"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:327
+msgid "Load Preset"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:334
+msgid "Import Foobar2000 Preset"
+msgstr ""
+
+#: ../plugins/gtkui/gtkui.c:128
+#, c-format
+msgid "1 day %d:%02d:%02d"
+msgstr ""
+
+#: ../plugins/gtkui/gtkui.c:131
+#, c-format
+msgid "%d days %d:%02d:%02d"
+msgstr ""
+
+#: ../plugins/gtkui/gtkui.c:140
+#, c-format
+msgid "Stopped | %d tracks | %s total playtime"
+msgstr ""
+
+#: ../plugins/gtkui/gtkui.c:150
+msgid "Mono"
+msgstr ""
+
+#: ../plugins/gtkui/gtkui.c:150
+msgid "Stereo"
+msgstr ""
+
+#: ../plugins/gtkui/gtkui.c:170
+#, c-format
+msgid "| %4d kbps "
+msgstr ""
+
+#: ../plugins/gtkui/gtkui.c:176
+msgid "Paused | "
+msgstr ""
+
+#: ../plugins/gtkui/gtkui.c:177
+#, c-format
+msgid ""
+"%s%s %s| %dHz | %d bit | %s | %d:%02d / %s | %d tracks | %s total playtime"
+msgstr ""
+
+#: ../plugins/gtkui/gtkui.c:533
+msgid "Save Playlist As"
+msgstr ""
+
+#: ../plugins/gtkui/gtkui.c:542 ../plugins/gtkui/gtkui.c:603
+msgid "DeaDBeeF playlist files (*.dbpl)"
+msgstr ""
+
+#: ../plugins/gtkui/gtkui.c:596
+msgid "Load Playlist"
+msgstr ""
+
+#: ../plugins/gtkui/gtkui.c:741
+msgid "New Playlist"
+msgstr ""
+
+#: ../plugins/gtkui/gtkui.c:744
+#, c-format
+msgid "New Playlist (%d)"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:140 ../plugins/gtkui/deadbeef.glade.h:138
+msgid "_File"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:147 ../plugins/gtkui/deadbeef.glade.h:142
+msgid "_Open file(s)"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:163 ../plugins/gtkui/deadbeef.glade.h:7
+msgid "Add file(s)"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:171 ../plugins/gtkui/deadbeef.glade.h:8
+msgid "Add folder(s)"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:179 ../plugins/gtkui/deadbeef.glade.h:6
+msgid "Add Audio CD"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:187 ../plugins/gtkui/interface.c:2870
+#: ../plugins/gtkui/deadbeef.glade.h:9
+msgid "Add location"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:196 ../plugins/gtkui/deadbeef.glade.h:72
+msgid "New playlist"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:203 ../plugins/gtkui/deadbeef.glade.h:64
+msgid "Load playlist"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:207 ../plugins/gtkui/deadbeef.glade.h:99
+msgid "Save playlist"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:211 ../plugins/gtkui/deadbeef.glade.h:100
+msgid "Save playlist as"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:220 ../plugins/gtkui/deadbeef.glade.h:144
+msgid "_Quit"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:231 ../plugins/gtkui/deadbeef.glade.h:137
+msgid "_Edit"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:238 ../plugins/gtkui/deadbeef.glade.h:135
+msgid "_Clear"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:246 ../plugins/gtkui/deadbeef.glade.h:104
+msgid "Select all"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:253 ../plugins/gtkui/deadbeef.glade.h:24
+msgid "Deselect all"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:260 ../plugins/gtkui/deadbeef.glade.h:59
+msgid "Invert selection"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:264 ../plugins/gtkui/deadbeef.glade.h:107
+msgid "Selection"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:271 ../plugins/gtkui/plcommon.c:387
+#: ../plugins/gtkui/prefwin.c:272 ../plugins/gtkui/deadbeef.glade.h:95
+msgid "Remove"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:279 ../plugins/gtkui/deadbeef.glade.h:19
+msgid "Crop"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:283 ../plugins/gtkui/deadbeef.glade.h:139
+msgid "_Find"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:295 ../plugins/gtkui/interface.c:1706
+#: ../plugins/gtkui/deadbeef.glade.h:85
+msgid "Preferences"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:299 ../plugins/gtkui/deadbeef.glade.h:145
+msgid "_View"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:306 ../plugins/gtkui/deadbeef.glade.h:111
+msgid "Status bar"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:310 ../plugins/gtkui/deadbeef.glade.h:17
+msgid "Column headers"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:314 ../plugins/gtkui/deadbeef.glade.h:118
+msgid "Tabs"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:318 ../plugins/gtkui/deadbeef.glade.h:32
+msgid "Equalizer"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:322 ../plugins/gtkui/deadbeef.glade.h:143
+msgid "_Playback"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:329 ../plugins/gtkui/deadbeef.glade.h:75
+msgid "Order"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:336 ../plugins/gtkui/deadbeef.glade.h:63
+msgid "Linear"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:342 ../plugins/gtkui/deadbeef.glade.h:108
+msgid "Shuffle"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:348 ../plugins/gtkui/deadbeef.glade.h:94
+msgid "Random"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:354 ../plugins/gtkui/deadbeef.glade.h:67
+msgid "Looping"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:361 ../plugins/gtkui/deadbeef.glade.h:65
+msgid "Loop All"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:367 ../plugins/gtkui/deadbeef.glade.h:66
+msgid "Loop Single Song"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:373 ../plugins/gtkui/deadbeef.glade.h:28
+msgid "Don't Loop"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:379 ../plugins/gtkui/deadbeef.glade.h:101
+msgid "Scroll follows playback"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:384 ../plugins/gtkui/deadbeef.glade.h:21
+msgid "Cursor follows playback"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:388 ../plugins/gtkui/deadbeef.glade.h:113
+msgid "Stop after current"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:395 ../plugins/gtkui/interface.c:402
+#: ../plugins/gtkui/deadbeef.glade.h:140
+msgid "_Help"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:410 ../plugins/gtkui/deadbeef.glade.h:134
+msgid "_ChangeLog"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:432 ../plugins/gtkui/deadbeef.glade.h:131
+msgid "_About"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:816 ../plugins/gtkui/deadbeef.glade.h:102
+msgid "Search"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:891 ../plugins/gtkui/deadbeef.glade.h:112
+msgid "Stop"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:899 ../plugins/gtkui/deadbeef.glade.h:81
+msgid "Play"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:907 ../plugins/gtkui/deadbeef.glade.h:80
+msgid "Pause"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:915 ../plugins/gtkui/deadbeef.glade.h:86
+msgid "Previous"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:923 ../plugins/gtkui/deadbeef.glade.h:73
+msgid "Next"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:931 ../plugins/gtkui/deadbeef.glade.h:82
+msgid "Play Random"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:940 ../plugins/gtkui/deadbeef.glade.h:5
+msgid "About"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:953 ../plugins/gtkui/deadbeef.glade.h:93
+msgid "Quit"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1025 ../plugins/gtkui/deadbeef.glade.h:10
+msgid "Adding files..."
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1069 ../plugins/gtkui/deadbeef.glade.h:130
+msgid "_Abort"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1170 ../plugins/gtkui/deadbeef.glade.h:122
+msgid "Track Properties"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1194 ../plugins/gtkui/deadbeef.glade.h:3
+msgid ""
+"<b>WARNING</b>: tag writing feature is still in development.\n"
+"<b>Make backup copies</b> before using."
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1221 ../plugins/gtkui/deadbeef.glade.h:132
+msgid "_Apply"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1242 ../plugins/gtkui/interface.c:1288
+#: ../plugins/gtkui/interface.c:2436 ../plugins/gtkui/deadbeef.glade.h:136
+msgid "_Close"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1246 ../plugins/gtkui/deadbeef.glade.h:68
+msgid "Metadata"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1292 ../plugins/gtkui/plcommon.c:402
+#: ../plugins/gtkui/deadbeef.glade.h:87
+msgid "Properties"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1378 ../plugins/gtkui/deadbeef.glade.h:146
+msgid "editcolumndlg"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1393 ../plugins/gtkui/interface.c:2770
+#: ../plugins/gtkui/deadbeef.glade.h:121
+msgid "Title:"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1401 ../plugins/gtkui/deadbeef.glade.h:31
+msgid "Enter new column title here"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1409 ../plugins/gtkui/deadbeef.glade.h:123
+msgid "Type:"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1417
+msgid "File number"
+msgstr ""
+
+#. create default set of columns
+#: ../plugins/gtkui/interface.c:1418 ../plugins/gtkui/mainplaylist.c:297
+msgid "Playing"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1419
+msgid "Album Art"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1420
+msgid "Artist - Album"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1421 ../plugins/gtkui/plcommon.c:774
+msgid "Artist"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1422 ../plugins/gtkui/interface.c:1795
+msgid "Album"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1423 ../plugins/gtkui/prefwin.c:488
+msgid "Title"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1424
+msgid "Length"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1425 ../plugins/gtkui/interface.c:1794
+msgid "Track"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1426
+msgid "Band / Album Artist"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1427 ../plugins/gtkui/plcommon.c:778
+msgid "Custom"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1433 ../plugins/gtkui/interface.c:2997
+#: ../plugins/gtkui/deadbeef.glade.h:53
+msgid "Format:"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1448 ../plugins/gtkui/deadbeef.glade.h:11
+msgid "Alignment:"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1456
+msgid "Left"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1457
+msgid "Right"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1459 ../plugins/gtkui/interface.c:3007
+#: ../plugins/gtkui/deadbeef.glade.h:47
+#, no-c-format
+msgid ""
+"Format conversions (start with %):\n"
+" [a]rtist, [t]itle, al[b]um, [B]and, [C]omposer\n"
+" track[n]umber, [N]totaltracks,\n"
+" [l]ength, [y]ear, [g]enre, [c]omment,\n"
+" copy[r]ight, [f]ilename, [T]ags\n"
+"Example: %a - %t [%l]"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1488 ../plugins/gtkui/interface.c:2801
+#: ../plugins/gtkui/interface.c:2913 ../plugins/gtkui/interface.c:3036
+#: ../plugins/gtkui/deadbeef.glade.h:133
+msgid "_Cancel"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1509 ../plugins/gtkui/interface.c:2822
+#: ../plugins/gtkui/interface.c:2934 ../plugins/gtkui/interface.c:3057
+#: ../plugins/gtkui/deadbeef.glade.h:141
+msgid "_OK"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1726 ../plugins/gtkui/deadbeef.glade.h:77
+msgid "Output plugin:"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1739 ../plugins/gtkui/deadbeef.glade.h:76
+msgid "Output device:"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1748 ../plugins/gtkui/deadbeef.glade.h:109
+msgid "Sound"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1757 ../plugins/gtkui/deadbeef.glade.h:12
+msgid "Allow dynamic samplerate switching"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1765 ../plugins/gtkui/deadbeef.glade.h:98
+msgid "Samplerate conversion quality:"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1784 ../plugins/gtkui/deadbeef.glade.h:96
+msgid "Replaygain mode:"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1793
+msgid "Disable"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1797 ../plugins/gtkui/deadbeef.glade.h:97
+msgid "Replaygain peak scale"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1801 ../plugins/gtkui/deadbeef.glade.h:110
+msgid "Sound (adv.)"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1810 ../plugins/gtkui/deadbeef.glade.h:16
+msgid "Close minimizes to tray"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1814 ../plugins/gtkui/deadbeef.glade.h:70
+msgid "Middle mouse button closes playlist"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1827 ../plugins/gtkui/interface.c:1871
+#: ../plugins/gtkui/deadbeef.glade.h:78
+msgid "Override"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1836 ../plugins/gtkui/deadbeef.glade.h:45
+msgid "Foreground"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1843 ../plugins/gtkui/deadbeef.glade.h:14
+msgid "Background"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1862 ../plugins/gtkui/deadbeef.glade.h:103
+msgid "Seekbar/Volumebar colors"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1880 ../plugins/gtkui/deadbeef.glade.h:69
+msgid "Middle"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1887 ../plugins/gtkui/deadbeef.glade.h:62
+msgid "Light"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1894 ../plugins/gtkui/deadbeef.glade.h:22
+msgid "Dark"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1925 ../plugins/gtkui/deadbeef.glade.h:15
+msgid "Base"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1932 ../plugins/gtkui/deadbeef.glade.h:117
+msgid "Tab strip colors"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1941 ../plugins/gtkui/deadbeef.glade.h:79
+msgid "Override (looses GTK treeview theming, but speeds up rendering)"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1950 ../plugins/gtkui/deadbeef.glade.h:33
+msgid "Even row"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1957 ../plugins/gtkui/deadbeef.glade.h:74
+msgid "Odd row"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1976 ../plugins/gtkui/deadbeef.glade.h:120
+msgid "Text"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1983 ../plugins/gtkui/deadbeef.glade.h:105
+msgid "Selected row"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2002 ../plugins/gtkui/deadbeef.glade.h:106
+msgid "Selected text"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2015 ../plugins/gtkui/deadbeef.glade.h:20
+msgid "Cursor"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2028 ../plugins/gtkui/deadbeef.glade.h:83
+msgid "Playlist colors"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2032 ../plugins/gtkui/deadbeef.glade.h:54
+msgid "GUI"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2041 ../plugins/gtkui/deadbeef.glade.h:30
+msgid "Enable Proxy Server"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2049 ../plugins/gtkui/deadbeef.glade.h:89
+msgid "Proxy Server Address:"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2063 ../plugins/gtkui/deadbeef.glade.h:90
+msgid "Proxy Server Port:"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2077 ../plugins/gtkui/deadbeef.glade.h:91
+msgid "Proxy Type:"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2096 ../plugins/gtkui/deadbeef.glade.h:92
+msgid "Proxy Username:"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2109 ../plugins/gtkui/deadbeef.glade.h:88
+msgid "Proxy Password:"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2119 ../plugins/gtkui/deadbeef.glade.h:71
+msgid "Network"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2147 ../plugins/gtkui/deadbeef.glade.h:128
+msgid "Write ID3v2"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2151 ../plugins/gtkui/interface.c:2278
+#: ../plugins/gtkui/deadbeef.glade.h:127
+msgid "Write ID3v1"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2155 ../plugins/gtkui/interface.c:2234
+#: ../plugins/gtkui/interface.c:2274 ../plugins/gtkui/deadbeef.glade.h:126
+msgid "Write APEv2"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2163 ../plugins/gtkui/interface.c:2242
+#: ../plugins/gtkui/deadbeef.glade.h:116
+msgid "Strip ID3v2"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2167 ../plugins/gtkui/interface.c:2290
+#: ../plugins/gtkui/deadbeef.glade.h:115
+msgid "Strip ID3v1"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2171 ../plugins/gtkui/interface.c:2246
+#: ../plugins/gtkui/interface.c:2286 ../plugins/gtkui/deadbeef.glade.h:114
+msgid "Strip APEv2"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2179 ../plugins/gtkui/deadbeef.glade.h:58
+msgid "ID3v2 version"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2186
+msgid "2.3 (Recommended)"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2187
+msgid "2.4"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2193 ../plugins/gtkui/deadbeef.glade.h:57
+msgid "ID3v1 character encoding (default is iso8859-1)"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2230 ../plugins/gtkui/deadbeef.glade.h:129
+msgid "Write ID3v2.4"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2299 ../plugins/gtkui/deadbeef.glade.h:119
+msgid "Tag writer"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2330 ../plugins/gtkui/deadbeef.glade.h:23
+msgid "Description:"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2345 ../plugins/gtkui/deadbeef.glade.h:13
+msgid "Author(s):"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2360 ../plugins/gtkui/deadbeef.glade.h:29
+msgid "Email:"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2375 ../plugins/gtkui/deadbeef.glade.h:125
+msgid "Website:"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2406 ../plugins/gtkui/deadbeef.glade.h:18
+msgid "Configure"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2410 ../plugins/gtkui/deadbeef.glade.h:84
+msgid "Plugins"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2754 ../plugins/gtkui/deadbeef.glade.h:147
+msgid "editplaylistdlg"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2881 ../plugins/gtkui/deadbeef.glade.h:124
+msgid "URL:"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2982 ../plugins/gtkui/deadbeef.glade.h:55
+msgid "Group By"
+msgstr ""
+
+#: ../plugins/gtkui/mainplaylist.c:298 ../plugins/gtkui/search.c:433
+msgid "Artist / Album"
+msgstr ""
+
+#: ../plugins/gtkui/mainplaylist.c:299 ../plugins/gtkui/search.c:434
+msgid "Track No"
+msgstr ""
+
+#: ../plugins/gtkui/mainplaylist.c:300 ../plugins/gtkui/search.c:435
+msgid "Title / Track Artist"
+msgstr ""
+
+#: ../plugins/gtkui/mainplaylist.c:301 ../plugins/gtkui/search.c:436
+#: ../plugins/gtkui/trkproperties.c:175
+msgid "Duration"
+msgstr ""
+
+#: ../plugins/gtkui/plcommon.c:316
+msgid "Delete files from disk"
+msgstr ""
+
+#: ../plugins/gtkui/plcommon.c:317
+msgid ""
+"Files will be lost. Proceed?\n"
+"(This dialog can be turned off in GTKUI plugin settings)"
+msgstr ""
+
+#: ../plugins/gtkui/plcommon.c:318 ../plugins/gtkui/trkproperties.c:56
+msgid "Warning"
+msgstr ""
+
+#: ../plugins/gtkui/plcommon.c:363
+msgid "Add to playback queue"
+msgstr ""
+
+#: ../plugins/gtkui/plcommon.c:368
+msgid "Remove from playback queue"
+msgstr ""
+
+#: ../plugins/gtkui/plcommon.c:376
+msgid "Reload metadata"
+msgstr ""
+
+#: ../plugins/gtkui/plcommon.c:392
+msgid "Remove from disk"
+msgstr ""
+
+#: ../plugins/gtkui/plcommon.c:616 ../plugins/gtkui/plcommon.c:741
+msgid "Add column"
+msgstr ""
+
+#: ../plugins/gtkui/plcommon.c:646 ../plugins/gtkui/plcommon.c:745
+msgid "Edit column"
+msgstr ""
+
+#: ../plugins/gtkui/plcommon.c:749
+msgid "Remove column"
+msgstr ""
+
+#: ../plugins/gtkui/plcommon.c:759
+msgid "Group by"
+msgstr ""
+
+#: ../plugins/gtkui/plcommon.c:766
+msgid "None"
+msgstr ""
+
+#: ../plugins/gtkui/plcommon.c:770
+msgid "Artist/Date/Album"
+msgstr ""
+
+#: ../plugins/gtkui/pluginconf.c:41
+msgid "Open file..."
+msgstr ""
+
+#: ../plugins/gtkui/pluginconf.c:139
+#, c-format
+msgid "Setup %s"
+msgstr ""
+
+#: ../plugins/gtkui/prefwin.c:98
+msgid "Default Audio Device"
+msgstr ""
+
+#: ../plugins/gtkui/prefwin.c:267
+msgid "Add"
+msgstr ""
+
+#: ../plugins/gtkui/prefwin.c:277
+msgid "Global Hotkeys"
+msgstr ""
+
+#: ../plugins/gtkui/prefwin.c:332
+msgid "Slot"
+msgstr ""
+
+#: ../plugins/gtkui/prefwin.c:333
+msgid "Key combination"
+msgstr ""
+
+#. output plugin selection
+#: ../plugins/gtkui/prefwin.c:379 ../plugins/gtkui/prefwin.c:569
+#: ../plugins.c:833
+msgid "ALSA output plugin"
+msgstr ""
+
+#: ../plugins/gtkui/progress.c:64
+msgid "Initializing..."
+msgstr ""
+
+#: ../plugins/gtkui/trkproperties.c:53
+msgid "You've modified data for this track."
+msgstr ""
+
+#: ../plugins/gtkui/trkproperties.c:55
+msgid "Really close the window?"
+msgstr ""
+
+#: ../plugins/gtkui/trkproperties.c:178
+msgid "Tag Type(s)"
+msgstr ""
+
+#: ../plugins/gtkui/trkproperties.c:180
+msgid "Embedded Cuesheet"
+msgstr ""
+
+#: ../plugins/gtkui/trkproperties.c:180
+msgid "Yes"
+msgstr ""
+
+#: ../plugins/gtkui/trkproperties.c:180
+msgid "No"
+msgstr ""
+
+#: ../plugins/gtkui/trkproperties.c:248 ../plugins/gtkui/trkproperties.c:260
+msgid "Key"
+msgstr ""
+
+#: ../plugins/gtkui/trkproperties.c:249 ../plugins/gtkui/trkproperties.c:261
+msgid "Value"
+msgstr ""
+
+#: ../plugins/notify/notify.c:138
+msgid "DeaDBeeF now playing"
+msgstr ""
+
+#: ../main.c:84
+#, c-format
+msgid "Usage: deadbeef [options] [file(s)]\n"
+msgstr ""
+
+#: ../main.c:85
+#, c-format
+msgid "Options:\n"
+msgstr ""
+
+#: ../main.c:86
+#, c-format
+msgid " --help or -h Print help (this message) and exit\n"
+msgstr ""
+
+#: ../main.c:87
+#, c-format
+msgid " --quit Quit player\n"
+msgstr ""
+
+#: ../main.c:88
+#, c-format
+msgid " --version Print version info and exit\n"
+msgstr ""
+
+#: ../main.c:89
+#, c-format
+msgid " --play Start playback\n"
+msgstr ""
+
+#: ../main.c:90
+#, c-format
+msgid " --stop Stop playback\n"
+msgstr ""
+
+#: ../main.c:91
+#, c-format
+msgid " --pause Pause playback\n"
+msgstr ""
+
+#: ../main.c:92
+#, c-format
+msgid " --next Next song in playlist\n"
+msgstr ""
+
+#: ../main.c:93
+#, c-format
+msgid " --prev Previous song in playlist\n"
+msgstr ""
+
+#: ../main.c:94
+#, c-format
+msgid " --random Random song in playlist\n"
+msgstr ""
+
+#: ../main.c:95
+#, c-format
+msgid " --queue Append file(s) to existing playlist\n"
+msgstr ""
+
+#: ../main.c:96
+#, c-format
+msgid " --nowplaying FMT Print formatted track name to stdout\n"
+msgstr ""
+
+#: ../main.c:97
+#, c-format
+msgid ""
+" FMT %%-syntax: [a]rtist, [t]itle, al[b]um,\n"
+" [l]ength, track[n]umber, [y]ear, [c]omment,\n"
+" copy[r]ight, [e]lapsed\n"
+msgstr ""
+
+#: ../main.c:100
+#, c-format
+msgid ""
+" e.g.: --nowplaying \"%%a - %%t\" should print \"artist "
+"- title\"\n"
+msgstr ""
+
+#: ../playlist.c:369 ../playlist.c:2212
+msgid "Default"
+msgstr ""
+
+#: ../plugins/gtkui/deadbeef.glade.h:1
+msgid ""
+"2.3 (Recommended)\n"
+"2.4"
+msgstr ""
+
+#: ../plugins/gtkui/deadbeef.glade.h:25
+msgid ""
+"Disable\n"
+"Track\n"
+"Album"
+msgstr ""
+
+#: ../plugins/gtkui/deadbeef.glade.h:34
+msgid ""
+"File number\n"
+"Playing\n"
+"Album Art\n"
+"Artist - Album\n"
+"Artist\n"
+"Album\n"
+"Title\n"
+"Length\n"
+"Track\n"
+"Band / Album Artist\n"
+"Custom"
+msgstr ""
+
+#: ../plugins/gtkui/deadbeef.glade.h:60
+msgid ""
+"Left\n"
+"Right"
+msgstr ""
+
+#: ../plugins/gtkui/support.c:90 ../plugins/gtkui/support.c:114
+#, c-format
+msgid "Couldn't find pixmap file: %s"
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:129 ../plugins/vorbis/vcedit.c:155
+msgid "Couldn't get enough memory for input buffering."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:179 ../plugins/vorbis/vcedit.c:550
+msgid "Error reading first page of Ogg bitstream."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:185 ../plugins/vorbis/vcedit.c:557
+msgid "Error reading initial header packet."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:237
+msgid "Couldn't get enough memory to register new stream serial number."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:505
+msgid "Input truncated or empty."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:507
+msgid "Input is not an Ogg bitstream."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:565
+msgid "Ogg bitstream does not contain Vorbis data."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:578
+msgid "EOF before recognised stream."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:594
+msgid "Ogg bitstream does not contain a supported data-type."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:638
+msgid "Corrupt secondary header."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:659
+msgid "EOF before end of Vorbis headers."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:834
+msgid "Corrupt or missing data, continuing..."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:874
+msgid ""
+"Error writing stream to output. Output stream may be corrupted or truncated."
+msgstr ""
diff --git a/po/el.po b/po/el.po
new file mode 100644
index 00000000..49b3bc35
--- /dev/null
+++ b/po/el.po
@@ -0,0 +1,1103 @@
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-05-27 16:47+0200\n"
+"PO-Revision-Date: \n"
+"Last-Translator: George Vasilakos <forfolias@linuxteam.cs.teilar.gr>\n"
+"Language-Team: Greek\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: el\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Greek\n"
+"X-Poedit-Country: GREECE\n"
+
+#: ../plugins/gtkui/callbacks.c:97
+msgid "Supported sound formats"
+msgstr "Υποστηριζόμενοι τύποι ήχου"
+
+#: ../plugins/gtkui/callbacks.c:108
+msgid "Other files (*)"
+msgstr "Άλλα αρχεία (*)"
+
+#: ../plugins/gtkui/callbacks.c:117
+msgid "Open file(s)..."
+msgstr "Άνοιγμα αρχείου..."
+
+#: ../plugins/gtkui/callbacks.c:150
+msgid "Add file(s) to playlist..."
+msgstr "Προσθήκη αρχείου στη λίστα αναπαραγωγής"
+
+#: ../plugins/gtkui/callbacks.c:182
+msgid "Add folder(s) to playlist..."
+msgstr "Προσθήκη φακέλου στη λίστα αναπαραγωγής"
+
+#: ../plugins/gtkui/callbacks.c:640
+msgid "Failed while reading help file"
+msgstr "Αποτυχία κατά την ανάγνωση του αρχείου βοήθειας"
+
+#: ../plugins/gtkui/callbacks.c:650
+msgid "Failed to load help file"
+msgstr "Αποτυχία κατά τη φόρτωση του αρχείου βοήθειας"
+
+#: ../plugins/gtkui/callbacks.c:664 ../plugins/gtkui/interface.c:1105
+#: ../plugins/gtkui/deadbeef.glade.h:56
+msgid "Help"
+msgstr "Βοήθεια"
+
+#: ../plugins/gtkui/callbacks.c:674
+#, c-format
+msgid "About DeaDBeeF %s"
+msgstr "Περί DeaDBeeF %s"
+
+#: ../plugins/gtkui/callbacks.c:685
+#, c-format
+msgid "DeaDBeeF %s ChangeLog"
+msgstr "DeaDBeeF %s ChangeLog"
+
+#: ../plugins/gtkui/ddbtabstrip.c:527
+msgid "Edit playlist"
+msgstr "Επεξεργασία λίστας αναπαραγωγής"
+
+#: ../plugins/gtkui/ddbtabstrip.c:604
+msgid "Rename Playlist"
+msgstr "Μετονομασία λίστας αναπαραγωγής"
+
+#: ../plugins/gtkui/ddbtabstrip.c:608
+msgid "Remove Playlist"
+msgstr "Αφαίρεση λίστας αναπαραγωγής"
+
+#: ../plugins/gtkui/ddbtabstrip.c:612
+msgid "Add New Playlist"
+msgstr "Προσθήκη νέας λίστας αναπαραγωγής"
+
+#: ../plugins/gtkui/eq.c:113
+msgid "Save DeaDBeeF EQ Preset"
+msgstr "Αποθήκευση ρύθμισης DeaDBeeF EQ"
+
+#: ../plugins/gtkui/eq.c:120
+msgid "DeaDBeeF EQ preset files (*.ddbeq)"
+msgstr "Αρχεία ρύθμισης DeaDBeeF EQ (*.ddbeq)"
+
+#: ../plugins/gtkui/eq.c:151
+msgid "Load DeaDBeeF EQ Preset..."
+msgstr "Φόρτωση ρύθμισης DeaDBeeF EQ"
+
+#: ../plugins/gtkui/eq.c:155
+msgid "DeaDBeeF EQ presets (*.ddbeq)"
+msgstr "Ρυθμίσεις DeaDBeeF EQ (*.ddbeq)"
+
+#: ../plugins/gtkui/eq.c:214
+msgid "Import Foobar2000 EQ Preset..."
+msgstr "Εισαγωγή ρυθμίσεων Foobar2000 EQ..."
+
+#: ../plugins/gtkui/eq.c:218
+msgid "Foobar2000 EQ presets (*.feq)"
+msgstr "Ρυθμίσεις Foobar2000 EQ (*.feq)"
+
+#: ../plugins/gtkui/eq.c:292
+msgid "Enable"
+msgstr "Ενεργό"
+
+#: ../plugins/gtkui/eq.c:299
+msgid "Zero All"
+msgstr "Όλα μηδέν"
+
+#: ../plugins/gtkui/eq.c:306
+msgid "Zero Preamp"
+msgstr "Μηδέν προενίσχυση"
+
+#: ../plugins/gtkui/eq.c:313
+msgid "Zero Bands"
+msgstr "Μηδέν ζώνες"
+
+#: ../plugins/gtkui/eq.c:320
+msgid "Save Preset"
+msgstr "Αποθήκευση ρύθμισης"
+
+#: ../plugins/gtkui/eq.c:327
+msgid "Load Preset"
+msgstr "Φόρτωση ρύθμισης"
+
+#: ../plugins/gtkui/eq.c:334
+msgid "Import Foobar2000 Preset"
+msgstr "Εισαγωγή ρύθμισης Foobar2000"
+
+#: ../plugins/gtkui/gtkui.c:128
+#, c-format
+msgid "1 day %d:%02d:%02d"
+msgstr "1 μέρα %d:%02d:%02d"
+
+#: ../plugins/gtkui/gtkui.c:131
+#, c-format
+msgid "%d days %d:%02d:%02d"
+msgstr "%d μέρες %d:%02d:%02d"
+
+#: ../plugins/gtkui/gtkui.c:140
+#, c-format
+msgid "Stopped | %d tracks | %s total playtime"
+msgstr "Διακοπή | %d κομμάτια | %s συνολικός χρόνος αναπαραγωγής"
+
+#: ../plugins/gtkui/gtkui.c:150
+msgid "Mono"
+msgstr "Μονοφωνικό"
+
+#: ../plugins/gtkui/gtkui.c:150
+msgid "Stereo"
+msgstr "Στερεοφωνικό"
+
+#: ../plugins/gtkui/gtkui.c:170
+#, c-format
+msgid "| %4d kbps "
+msgstr "| %4d kbps "
+
+#: ../plugins/gtkui/gtkui.c:176
+msgid "Paused | "
+msgstr "Παύση |"
+
+#: ../plugins/gtkui/gtkui.c:177
+#, c-format
+msgid ""
+"%s%s %s| %dHz | %d bit | %s | %d:%02d / %s | %d tracks | %s total playtime"
+msgstr ""
+"%s%s %s| %dHz | %d bit | %s | %d:%02d / %s | %d κομμάτια | %s συνολικός "
+"χρόνος αναπαραγωγής"
+
+#: ../plugins/gtkui/gtkui.c:533
+msgid "Save Playlist As"
+msgstr "Αποθήκευση λίστας αναπαραγωγής ως"
+
+#: ../plugins/gtkui/gtkui.c:542 ../plugins/gtkui/gtkui.c:603
+msgid "DeaDBeeF playlist files (*.dbpl)"
+msgstr "Αρχεία λίστας αναπαραγωγής DeaDBeeF (*.dbpl)"
+
+#: ../plugins/gtkui/gtkui.c:596
+msgid "Load Playlist"
+msgstr "Φόρτωση λίστας αναπαραγωγής"
+
+#: ../plugins/gtkui/gtkui.c:741
+msgid "New Playlist"
+msgstr "Νέα λίστα αναπαραγωγής"
+
+#: ../plugins/gtkui/gtkui.c:744
+#, c-format
+msgid "New Playlist (%d)"
+msgstr "Νέα λίστα αναπαραγωγής (%d)"
+
+#: ../plugins/gtkui/interface.c:140 ../plugins/gtkui/deadbeef.glade.h:138
+msgid "_File"
+msgstr "_Αρχείο"
+
+#: ../plugins/gtkui/interface.c:147 ../plugins/gtkui/deadbeef.glade.h:142
+msgid "_Open file(s)"
+msgstr "_Άνοιγμα αρχείου"
+
+#: ../plugins/gtkui/interface.c:163 ../plugins/gtkui/deadbeef.glade.h:7
+msgid "Add file(s)"
+msgstr "Προσθήκη αρχείου"
+
+#: ../plugins/gtkui/interface.c:171 ../plugins/gtkui/deadbeef.glade.h:8
+msgid "Add folder(s)"
+msgstr "Προσθήκη φακέλου"
+
+#: ../plugins/gtkui/interface.c:179 ../plugins/gtkui/deadbeef.glade.h:6
+msgid "Add Audio CD"
+msgstr "Προσθήκη CD ήχου"
+
+#: ../plugins/gtkui/interface.c:187 ../plugins/gtkui/interface.c:2870
+#: ../plugins/gtkui/deadbeef.glade.h:9
+msgid "Add location"
+msgstr "Προσθήκη τοποθεσίας"
+
+#: ../plugins/gtkui/interface.c:196 ../plugins/gtkui/deadbeef.glade.h:72
+msgid "New playlist"
+msgstr "Νέα λίστα αναπαραγωγής"
+
+#: ../plugins/gtkui/interface.c:203 ../plugins/gtkui/deadbeef.glade.h:64
+msgid "Load playlist"
+msgstr "Φόρτωση λίστας αναπαραγωγής"
+
+#: ../plugins/gtkui/interface.c:207 ../plugins/gtkui/deadbeef.glade.h:99
+msgid "Save playlist"
+msgstr "Αποθήκευση λίστας αναπαραγωγής"
+
+#: ../plugins/gtkui/interface.c:211 ../plugins/gtkui/deadbeef.glade.h:100
+msgid "Save playlist as"
+msgstr "Αποθήκευση λίστας αναπαραγωγής ως"
+
+#: ../plugins/gtkui/interface.c:220 ../plugins/gtkui/deadbeef.glade.h:144
+msgid "_Quit"
+msgstr "_Έξοδος"
+
+#: ../plugins/gtkui/interface.c:231 ../plugins/gtkui/deadbeef.glade.h:137
+msgid "_Edit"
+msgstr "_Επεξεργασία"
+
+#: ../plugins/gtkui/interface.c:238 ../plugins/gtkui/deadbeef.glade.h:135
+msgid "_Clear"
+msgstr "_Καθαρισμός"
+
+#: ../plugins/gtkui/interface.c:246 ../plugins/gtkui/deadbeef.glade.h:104
+msgid "Select all"
+msgstr "Επιλογή όλων"
+
+#: ../plugins/gtkui/interface.c:253 ../plugins/gtkui/deadbeef.glade.h:24
+msgid "Deselect all"
+msgstr "Αποεπιλογή όλων"
+
+#: ../plugins/gtkui/interface.c:260 ../plugins/gtkui/deadbeef.glade.h:59
+msgid "Invert selection"
+msgstr "Αναστροφή επιλογής"
+
+#: ../plugins/gtkui/interface.c:264 ../plugins/gtkui/deadbeef.glade.h:107
+msgid "Selection"
+msgstr "Επιλογμένο"
+
+#: ../plugins/gtkui/interface.c:271 ../plugins/gtkui/plcommon.c:387
+#: ../plugins/gtkui/prefwin.c:272 ../plugins/gtkui/deadbeef.glade.h:95
+msgid "Remove"
+msgstr "Αφαίρεση"
+
+#: ../plugins/gtkui/interface.c:279 ../plugins/gtkui/deadbeef.glade.h:19
+msgid "Crop"
+msgstr "Περικοπή"
+
+#: ../plugins/gtkui/interface.c:283 ../plugins/gtkui/deadbeef.glade.h:139
+msgid "_Find"
+msgstr "_Αναζήτηση"
+
+#: ../plugins/gtkui/interface.c:295 ../plugins/gtkui/interface.c:1706
+#: ../plugins/gtkui/deadbeef.glade.h:85
+msgid "Preferences"
+msgstr "Ρυθμίσεις"
+
+#: ../plugins/gtkui/interface.c:299 ../plugins/gtkui/deadbeef.glade.h:145
+msgid "_View"
+msgstr "_Προβολή"
+
+#: ../plugins/gtkui/interface.c:306 ../plugins/gtkui/deadbeef.glade.h:111
+msgid "Status bar"
+msgstr "Μπάρα κατάστασης"
+
+#: ../plugins/gtkui/interface.c:310 ../plugins/gtkui/deadbeef.glade.h:17
+msgid "Column headers"
+msgstr "Τίτλοι στύλων"
+
+#: ../plugins/gtkui/interface.c:314 ../plugins/gtkui/deadbeef.glade.h:118
+msgid "Tabs"
+msgstr "Καρτέλες"
+
+#: ../plugins/gtkui/interface.c:318 ../plugins/gtkui/deadbeef.glade.h:32
+msgid "Equalizer"
+msgstr "Ισοσταθμιστής"
+
+#: ../plugins/gtkui/interface.c:322 ../plugins/gtkui/deadbeef.glade.h:143
+msgid "_Playback"
+msgstr "Αναπαραγωγή"
+
+#: ../plugins/gtkui/interface.c:329 ../plugins/gtkui/deadbeef.glade.h:75
+msgid "Order"
+msgstr "Σειρά"
+
+#: ../plugins/gtkui/interface.c:336 ../plugins/gtkui/deadbeef.glade.h:63
+msgid "Linear"
+msgstr "Γραμμικά"
+
+#: ../plugins/gtkui/interface.c:342 ../plugins/gtkui/deadbeef.glade.h:108
+msgid "Shuffle"
+msgstr "Ανακατεμένα"
+
+#: ../plugins/gtkui/interface.c:348 ../plugins/gtkui/deadbeef.glade.h:94
+msgid "Random"
+msgstr "Τυχαία"
+
+#: ../plugins/gtkui/interface.c:354 ../plugins/gtkui/deadbeef.glade.h:67
+msgid "Looping"
+msgstr "Επανάληψη"
+
+#: ../plugins/gtkui/interface.c:361 ../plugins/gtkui/deadbeef.glade.h:65
+msgid "Loop All"
+msgstr "Επανάληψη όλων"
+
+#: ../plugins/gtkui/interface.c:367 ../plugins/gtkui/deadbeef.glade.h:66
+msgid "Loop Single Song"
+msgstr "Επανάληψη κομματιού"
+
+#: ../plugins/gtkui/interface.c:373 ../plugins/gtkui/deadbeef.glade.h:28
+msgid "Don't Loop"
+msgstr "Χωρίς επανάληψη"
+
+#: ../plugins/gtkui/interface.c:379 ../plugins/gtkui/deadbeef.glade.h:101
+msgid "Scroll follows playback"
+msgstr "Η κύληση ακολουθεί την αναπαραγωγή"
+
+#: ../plugins/gtkui/interface.c:384 ../plugins/gtkui/deadbeef.glade.h:21
+msgid "Cursor follows playback"
+msgstr "Ο δείκτης ποντικιού ακολουθεί την αναπαραγωγή"
+
+#: ../plugins/gtkui/interface.c:388 ../plugins/gtkui/deadbeef.glade.h:113
+msgid "Stop after current"
+msgstr "Διακοπή μετά το τρέχον"
+
+#: ../plugins/gtkui/interface.c:395 ../plugins/gtkui/interface.c:402
+#: ../plugins/gtkui/deadbeef.glade.h:140
+msgid "_Help"
+msgstr "_Βοήθεια"
+
+#: ../plugins/gtkui/interface.c:410 ../plugins/gtkui/deadbeef.glade.h:134
+msgid "_ChangeLog"
+msgstr "_ChangeLog"
+
+#: ../plugins/gtkui/interface.c:432 ../plugins/gtkui/deadbeef.glade.h:131
+msgid "_About"
+msgstr "_Περί"
+
+#: ../plugins/gtkui/interface.c:816 ../plugins/gtkui/deadbeef.glade.h:102
+msgid "Search"
+msgstr "Αναζήτηση"
+
+#: ../plugins/gtkui/interface.c:891 ../plugins/gtkui/deadbeef.glade.h:112
+msgid "Stop"
+msgstr "Διακοπή"
+
+#: ../plugins/gtkui/interface.c:899 ../plugins/gtkui/deadbeef.glade.h:81
+msgid "Play"
+msgstr "Αναπαραγωγή"
+
+#: ../plugins/gtkui/interface.c:907 ../plugins/gtkui/deadbeef.glade.h:80
+msgid "Pause"
+msgstr "Παύση"
+
+#: ../plugins/gtkui/interface.c:915 ../plugins/gtkui/deadbeef.glade.h:86
+msgid "Previous"
+msgstr "Προηγούμενο"
+
+#: ../plugins/gtkui/interface.c:923 ../plugins/gtkui/deadbeef.glade.h:73
+msgid "Next"
+msgstr "Επόμενο"
+
+#: ../plugins/gtkui/interface.c:931 ../plugins/gtkui/deadbeef.glade.h:82
+msgid "Play Random"
+msgstr "Αναπαραγωγή τυχαίου"
+
+#: ../plugins/gtkui/interface.c:940 ../plugins/gtkui/deadbeef.glade.h:5
+msgid "About"
+msgstr "Περί"
+
+#: ../plugins/gtkui/interface.c:953 ../plugins/gtkui/deadbeef.glade.h:93
+msgid "Quit"
+msgstr "Έξοδος"
+
+#: ../plugins/gtkui/interface.c:1025 ../plugins/gtkui/deadbeef.glade.h:10
+msgid "Adding files..."
+msgstr "Προσθήκη αρχείων"
+
+#: ../plugins/gtkui/interface.c:1069 ../plugins/gtkui/deadbeef.glade.h:130
+msgid "_Abort"
+msgstr "_Ακύρωση"
+
+#: ../plugins/gtkui/interface.c:1170 ../plugins/gtkui/deadbeef.glade.h:122
+msgid "Track Properties"
+msgstr "Ιδιότητες κομματιού"
+
+#: ../plugins/gtkui/interface.c:1194 ../plugins/gtkui/deadbeef.glade.h:3
+msgid ""
+"<b>WARNING</b>: tag writing feature is still in development.\n"
+"<b>Make backup copies</b> before using."
+msgstr ""
+"<b>ΠΡΟΕΙΔΟΠΟΙΗΣΉ</b>: η εγγραφή ετικετών είναι ακόμα υπό ανάπτυξη.\n"
+"<b>Κρατήστε αντίγραφα ασφαλείας</b> πριν τη χρήση."
+
+#: ../plugins/gtkui/interface.c:1221 ../plugins/gtkui/deadbeef.glade.h:132
+msgid "_Apply"
+msgstr "_Εφαρμογή"
+
+#: ../plugins/gtkui/interface.c:1242 ../plugins/gtkui/interface.c:1288
+#: ../plugins/gtkui/interface.c:2436 ../plugins/gtkui/deadbeef.glade.h:136
+msgid "_Close"
+msgstr "_Κλείσιμο"
+
+#: ../plugins/gtkui/interface.c:1246 ../plugins/gtkui/deadbeef.glade.h:68
+msgid "Metadata"
+msgstr "Μεταδεδομένα"
+
+#: ../plugins/gtkui/interface.c:1292 ../plugins/gtkui/plcommon.c:402
+#: ../plugins/gtkui/deadbeef.glade.h:87
+msgid "Properties"
+msgstr "Ιδιότητες"
+
+#: ../plugins/gtkui/interface.c:1378 ../plugins/gtkui/deadbeef.glade.h:146
+msgid "editcolumndlg"
+msgstr "Διάλογος επεξεργασίας στύλης"
+
+#: ../plugins/gtkui/interface.c:1393 ../plugins/gtkui/interface.c:2770
+#: ../plugins/gtkui/deadbeef.glade.h:121
+msgid "Title:"
+msgstr "Τίτλος:"
+
+#: ../plugins/gtkui/interface.c:1401 ../plugins/gtkui/deadbeef.glade.h:31
+msgid "Enter new column title here"
+msgstr "Εισαγωγή νέου τίτλου για τη στήλη"
+
+#: ../plugins/gtkui/interface.c:1409 ../plugins/gtkui/deadbeef.glade.h:123
+msgid "Type:"
+msgstr "Τύπος"
+
+#: ../plugins/gtkui/interface.c:1417
+msgid "File number"
+msgstr "Αριθμός αρχείου"
+
+#. create default set of columns
+#: ../plugins/gtkui/interface.c:1418 ../plugins/gtkui/mainplaylist.c:297
+msgid "Playing"
+msgstr "Αναπαραγωγή"
+
+#: ../plugins/gtkui/interface.c:1419
+msgid "Album Art"
+msgstr "Σχέδιο άλπουμ"
+
+#: ../plugins/gtkui/interface.c:1420
+msgid "Artist - Album"
+msgstr "Καλλιτέχνης - Άλμπουμ"
+
+#: ../plugins/gtkui/interface.c:1421 ../plugins/gtkui/plcommon.c:774
+msgid "Artist"
+msgstr "Καλλιτέχνης"
+
+#: ../plugins/gtkui/interface.c:1422 ../plugins/gtkui/interface.c:1795
+msgid "Album"
+msgstr "Άλμπουμ"
+
+#: ../plugins/gtkui/interface.c:1423 ../plugins/gtkui/prefwin.c:488
+msgid "Title"
+msgstr "Τίτλος"
+
+#: ../plugins/gtkui/interface.c:1424
+msgid "Length"
+msgstr "Διάρκεια"
+
+#: ../plugins/gtkui/interface.c:1425 ../plugins/gtkui/interface.c:1794
+msgid "Track"
+msgstr "Κομμάτι"
+
+#: ../plugins/gtkui/interface.c:1426
+msgid "Band / Album Artist"
+msgstr "Συγκρότημα / Καλλιτέχνης άλμπουμ"
+
+#: ../plugins/gtkui/interface.c:1427 ../plugins/gtkui/plcommon.c:778
+msgid "Custom"
+msgstr "Αυτοσχέδιο"
+
+#: ../plugins/gtkui/interface.c:1433 ../plugins/gtkui/interface.c:2997
+#: ../plugins/gtkui/deadbeef.glade.h:53
+msgid "Format:"
+msgstr "Μορφή:"
+
+#: ../plugins/gtkui/interface.c:1448 ../plugins/gtkui/deadbeef.glade.h:11
+msgid "Alignment:"
+msgstr "Στοίχιση:"
+
+#: ../plugins/gtkui/interface.c:1456
+msgid "Left"
+msgstr "Αριστερά"
+
+#: ../plugins/gtkui/interface.c:1457
+msgid "Right"
+msgstr "Δεξιά"
+
+#: ../plugins/gtkui/interface.c:1459 ../plugins/gtkui/interface.c:3007
+#: ../plugins/gtkui/deadbeef.glade.h:47
+#, fuzzy, no-c-format
+msgid ""
+"Format conversions (start with %):\n"
+" [a]rtist, [t]itle, al[b]um, [B]and, [C]omposer\n"
+" track[n]umber, [N]totaltracks,\n"
+" [l]ength, [y]ear, [g]enre, [c]omment,\n"
+" copy[r]ight, [f]ilename, [T]ags\n"
+"Example: %a - %t [%l]"
+msgstr ""
+"Μορφές μετατροπής (ξεκινούν με %):\n"
+" [a]rtist, [t]itle, al[b]um, [B]and,\n"
+" track[n]umber, [N]totaltracks,\n"
+" [l]ength, [y]ear, [g]enre, [c]omment,\n"
+" copy[r]ight, [f]ilename, [T]ags\n"
+"Παράδειγμα: %a - %t [%l]"
+
+#: ../plugins/gtkui/interface.c:1488 ../plugins/gtkui/interface.c:2801
+#: ../plugins/gtkui/interface.c:2913 ../plugins/gtkui/interface.c:3036
+#: ../plugins/gtkui/deadbeef.glade.h:133
+msgid "_Cancel"
+msgstr "_Άκυρο"
+
+#: ../plugins/gtkui/interface.c:1509 ../plugins/gtkui/interface.c:2822
+#: ../plugins/gtkui/interface.c:2934 ../plugins/gtkui/interface.c:3057
+#: ../plugins/gtkui/deadbeef.glade.h:141
+msgid "_OK"
+msgstr "_Εντάξει"
+
+#: ../plugins/gtkui/interface.c:1726 ../plugins/gtkui/deadbeef.glade.h:77
+msgid "Output plugin:"
+msgstr "Plugin εξόδου:"
+
+#: ../plugins/gtkui/interface.c:1739 ../plugins/gtkui/deadbeef.glade.h:76
+msgid "Output device:"
+msgstr "Συσκευή εξόδου:"
+
+#: ../plugins/gtkui/interface.c:1748 ../plugins/gtkui/deadbeef.glade.h:109
+msgid "Sound"
+msgstr "Ήχος"
+
+#: ../plugins/gtkui/interface.c:1757 ../plugins/gtkui/deadbeef.glade.h:12
+msgid "Allow dynamic samplerate switching"
+msgstr "Να επιτρέπεται η δυναμική ρύθμιση samplerate"
+
+#: ../plugins/gtkui/interface.c:1765 ../plugins/gtkui/deadbeef.glade.h:98
+msgid "Samplerate conversion quality:"
+msgstr "Ποιότητα μετατροπής samplerate:"
+
+#: ../plugins/gtkui/interface.c:1784 ../plugins/gtkui/deadbeef.glade.h:96
+msgid "Replaygain mode:"
+msgstr "Λειτουργία Replaygain:"
+
+#: ../plugins/gtkui/interface.c:1793
+msgid "Disable"
+msgstr "Ανενεργό"
+
+#: ../plugins/gtkui/interface.c:1797 ../plugins/gtkui/deadbeef.glade.h:97
+msgid "Replaygain peak scale"
+msgstr "Κορυφή κλίμακας Replaygain"
+
+#: ../plugins/gtkui/interface.c:1801 ../plugins/gtkui/deadbeef.glade.h:110
+msgid "Sound (adv.)"
+msgstr "Ήχος (προχ.)"
+
+#: ../plugins/gtkui/interface.c:1810 ../plugins/gtkui/deadbeef.glade.h:16
+msgid "Close minimizes to tray"
+msgstr "Το κλείσιμο να ελαχιστοποιεί στο tray"
+
+#: ../plugins/gtkui/interface.c:1814 ../plugins/gtkui/deadbeef.glade.h:70
+msgid "Middle mouse button closes playlist"
+msgstr "Το μεσαίο πλήκτρο του ποντικιού να κλείνει τη λίστα αναπαραγωγής"
+
+#: ../plugins/gtkui/interface.c:1827 ../plugins/gtkui/interface.c:1871
+#: ../plugins/gtkui/deadbeef.glade.h:78
+msgid "Override"
+msgstr "Παράκαμψη"
+
+#: ../plugins/gtkui/interface.c:1836 ../plugins/gtkui/deadbeef.glade.h:45
+msgid "Foreground"
+msgstr "Προσκήνιο"
+
+#: ../plugins/gtkui/interface.c:1843 ../plugins/gtkui/deadbeef.glade.h:14
+msgid "Background"
+msgstr "Παρασκήνιο"
+
+#: ../plugins/gtkui/interface.c:1862 ../plugins/gtkui/deadbeef.glade.h:103
+msgid "Seekbar/Volumebar colors"
+msgstr "Χρώματα μπάρας μετατόπισης/ήχου"
+
+#: ../plugins/gtkui/interface.c:1880 ../plugins/gtkui/deadbeef.glade.h:69
+msgid "Middle"
+msgstr "Μέση"
+
+#: ../plugins/gtkui/interface.c:1887 ../plugins/gtkui/deadbeef.glade.h:62
+msgid "Light"
+msgstr "Φωτεινό"
+
+#: ../plugins/gtkui/interface.c:1894 ../plugins/gtkui/deadbeef.glade.h:22
+msgid "Dark"
+msgstr "Σκοτεινό"
+
+#: ../plugins/gtkui/interface.c:1925 ../plugins/gtkui/deadbeef.glade.h:15
+msgid "Base"
+msgstr "Βάση"
+
+#: ../plugins/gtkui/interface.c:1932 ../plugins/gtkui/deadbeef.glade.h:117
+msgid "Tab strip colors"
+msgstr "Χρώματα στο χώρο καρτελών"
+
+#: ../plugins/gtkui/interface.c:1941 ../plugins/gtkui/deadbeef.glade.h:79
+msgid "Override (looses GTK treeview theming, but speeds up rendering)"
+msgstr "Παράκαμψη (χάνει το GTK treeview θέμα, αλλά επιταχύνει την απόδοση)"
+
+#: ../plugins/gtkui/interface.c:1950 ../plugins/gtkui/deadbeef.glade.h:33
+msgid "Even row"
+msgstr "Ζυγή σειρά "
+
+#: ../plugins/gtkui/interface.c:1957 ../plugins/gtkui/deadbeef.glade.h:74
+msgid "Odd row"
+msgstr "Μονή σειρά"
+
+#: ../plugins/gtkui/interface.c:1976 ../plugins/gtkui/deadbeef.glade.h:120
+msgid "Text"
+msgstr "Κείμενο"
+
+#: ../plugins/gtkui/interface.c:1983 ../plugins/gtkui/deadbeef.glade.h:105
+msgid "Selected row"
+msgstr "Επιλεγμένη σειρά"
+
+#: ../plugins/gtkui/interface.c:2002 ../plugins/gtkui/deadbeef.glade.h:106
+msgid "Selected text"
+msgstr "Επιλεγμένο κείμενο"
+
+#: ../plugins/gtkui/interface.c:2015 ../plugins/gtkui/deadbeef.glade.h:20
+msgid "Cursor"
+msgstr "Δείκτης ποντικιού"
+
+#: ../plugins/gtkui/interface.c:2028 ../plugins/gtkui/deadbeef.glade.h:83
+msgid "Playlist colors"
+msgstr "Χρώματα λίστας αναπαραγωγής"
+
+#: ../plugins/gtkui/interface.c:2032 ../plugins/gtkui/deadbeef.glade.h:54
+msgid "GUI"
+msgstr "Γραφική Διεπαφή"
+
+#: ../plugins/gtkui/interface.c:2041 ../plugins/gtkui/deadbeef.glade.h:30
+msgid "Enable Proxy Server"
+msgstr "Ενεργοποίηση Proxy Server"
+
+#: ../plugins/gtkui/interface.c:2049 ../plugins/gtkui/deadbeef.glade.h:89
+msgid "Proxy Server Address:"
+msgstr "Διεύθυνση Proxy Server:"
+
+#: ../plugins/gtkui/interface.c:2063 ../plugins/gtkui/deadbeef.glade.h:90
+msgid "Proxy Server Port:"
+msgstr "Πόρτα Proxy Server:"
+
+#: ../plugins/gtkui/interface.c:2077 ../plugins/gtkui/deadbeef.glade.h:91
+msgid "Proxy Type:"
+msgstr "Τύπος Proxy:"
+
+#: ../plugins/gtkui/interface.c:2096 ../plugins/gtkui/deadbeef.glade.h:92
+msgid "Proxy Username:"
+msgstr "Όνομα χρήστη Proxy:"
+
+#: ../plugins/gtkui/interface.c:2109 ../plugins/gtkui/deadbeef.glade.h:88
+msgid "Proxy Password:"
+msgstr "Κωδικός Proxy:"
+
+#: ../plugins/gtkui/interface.c:2119 ../plugins/gtkui/deadbeef.glade.h:71
+msgid "Network"
+msgstr "Δίκτυο"
+
+#: ../plugins/gtkui/interface.c:2147 ../plugins/gtkui/deadbeef.glade.h:128
+msgid "Write ID3v2"
+msgstr "Εγγραφή ID3v2"
+
+#: ../plugins/gtkui/interface.c:2151 ../plugins/gtkui/interface.c:2278
+#: ../plugins/gtkui/deadbeef.glade.h:127
+msgid "Write ID3v1"
+msgstr "Εγγραφή ID3v1"
+
+#: ../plugins/gtkui/interface.c:2155 ../plugins/gtkui/interface.c:2234
+#: ../plugins/gtkui/interface.c:2274 ../plugins/gtkui/deadbeef.glade.h:126
+msgid "Write APEv2"
+msgstr "Εγγραφή APEv2"
+
+#: ../plugins/gtkui/interface.c:2163 ../plugins/gtkui/interface.c:2242
+#: ../plugins/gtkui/deadbeef.glade.h:116
+msgid "Strip ID3v2"
+msgstr "Αφαίρεση ID3v2"
+
+#: ../plugins/gtkui/interface.c:2167 ../plugins/gtkui/interface.c:2290
+#: ../plugins/gtkui/deadbeef.glade.h:115
+msgid "Strip ID3v1"
+msgstr "Αφαίρεση ID3v1"
+
+#: ../plugins/gtkui/interface.c:2171 ../plugins/gtkui/interface.c:2246
+#: ../plugins/gtkui/interface.c:2286 ../plugins/gtkui/deadbeef.glade.h:114
+msgid "Strip APEv2"
+msgstr "Αφαίρεση APEv2"
+
+#: ../plugins/gtkui/interface.c:2179 ../plugins/gtkui/deadbeef.glade.h:58
+msgid "ID3v2 version"
+msgstr "Έκδοση ID3v2"
+
+#: ../plugins/gtkui/interface.c:2186
+msgid "2.3 (Recommended)"
+msgstr "2.3 (Προτείνεται)"
+
+#: ../plugins/gtkui/interface.c:2187
+msgid "2.4"
+msgstr "2.4"
+
+#: ../plugins/gtkui/interface.c:2193 ../plugins/gtkui/deadbeef.glade.h:57
+msgid "ID3v1 character encoding (default is iso8859-1)"
+msgstr "ID3v1 κωδικοποίηση χαρακτήρων (προεπιλογή είναι iso8859-1)"
+
+#: ../plugins/gtkui/interface.c:2230 ../plugins/gtkui/deadbeef.glade.h:129
+msgid "Write ID3v2.4"
+msgstr "Εγγραφή ID3v2.4"
+
+#: ../plugins/gtkui/interface.c:2299 ../plugins/gtkui/deadbeef.glade.h:119
+msgid "Tag writer"
+msgstr "Συγγραφέας ετικετών"
+
+#: ../plugins/gtkui/interface.c:2330 ../plugins/gtkui/deadbeef.glade.h:23
+msgid "Description:"
+msgstr "Περιγραφή:"
+
+#: ../plugins/gtkui/interface.c:2345 ../plugins/gtkui/deadbeef.glade.h:13
+msgid "Author(s):"
+msgstr "Συγγραφέας:"
+
+#: ../plugins/gtkui/interface.c:2360 ../plugins/gtkui/deadbeef.glade.h:29
+msgid "Email:"
+msgstr "Email:"
+
+#: ../plugins/gtkui/interface.c:2375 ../plugins/gtkui/deadbeef.glade.h:125
+msgid "Website:"
+msgstr "Ιστοσελίδα:"
+
+#: ../plugins/gtkui/interface.c:2406 ../plugins/gtkui/deadbeef.glade.h:18
+msgid "Configure"
+msgstr "Ρύθμιση"
+
+#: ../plugins/gtkui/interface.c:2410 ../plugins/gtkui/deadbeef.glade.h:84
+msgid "Plugins"
+msgstr "Plugins"
+
+#: ../plugins/gtkui/interface.c:2754 ../plugins/gtkui/deadbeef.glade.h:147
+msgid "editplaylistdlg"
+msgstr "Διάλογος επεξεργασίας λίστας αναπαραγωγής"
+
+#: ../plugins/gtkui/interface.c:2881 ../plugins/gtkui/deadbeef.glade.h:124
+msgid "URL:"
+msgstr "URL:"
+
+#: ../plugins/gtkui/interface.c:2982 ../plugins/gtkui/deadbeef.glade.h:55
+msgid "Group By"
+msgstr "Ομαδοποίηση κατά"
+
+#: ../plugins/gtkui/mainplaylist.c:298 ../plugins/gtkui/search.c:433
+msgid "Artist / Album"
+msgstr "Καλλιτέχνης / Άλμπουμ"
+
+#: ../plugins/gtkui/mainplaylist.c:299 ../plugins/gtkui/search.c:434
+msgid "Track No"
+msgstr "Αριθμός κομματιού"
+
+#: ../plugins/gtkui/mainplaylist.c:300 ../plugins/gtkui/search.c:435
+msgid "Title / Track Artist"
+msgstr "Τίτλος / Καλλιτέχνης κομματιού"
+
+#: ../plugins/gtkui/mainplaylist.c:301 ../plugins/gtkui/search.c:436
+#: ../plugins/gtkui/trkproperties.c:175
+msgid "Duration"
+msgstr "Διάρκεια"
+
+#: ../plugins/gtkui/plcommon.c:316
+msgid "Delete files from disk"
+msgstr "Διαγραφή αρχείων από το δίσκο"
+
+#: ../plugins/gtkui/plcommon.c:317
+msgid ""
+"Files will be lost. Proceed?\n"
+"(This dialog can be turned off in GTKUI plugin settings)"
+msgstr ""
+"τα αρχεία θα χαθούν. Να προχωρήσω; \\ n (Αυτό το παράθυρο μπορεί να "
+"απενεργοποιηθεί από τις ρυθμίσεις του GTKUI plugin)"
+
+#: ../plugins/gtkui/plcommon.c:318 ../plugins/gtkui/trkproperties.c:56
+msgid "Warning"
+msgstr "Προειδοποίηση"
+
+#: ../plugins/gtkui/plcommon.c:363
+msgid "Add to playback queue"
+msgstr "Προσθήκη στην ουρά αναπαραγωγής"
+
+#: ../plugins/gtkui/plcommon.c:368
+msgid "Remove from playback queue"
+msgstr "Αφαίρεση από την ουρά αναπαραγωγής"
+
+#: ../plugins/gtkui/plcommon.c:376
+msgid "Reload metadata"
+msgstr "Επαναφόρτωση μεταδεδομένων"
+
+#: ../plugins/gtkui/plcommon.c:392
+msgid "Remove from disk"
+msgstr "Αφαίρεση από τον δίσκο"
+
+#: ../plugins/gtkui/plcommon.c:616 ../plugins/gtkui/plcommon.c:741
+msgid "Add column"
+msgstr "Προσθήκη στήλης"
+
+#: ../plugins/gtkui/plcommon.c:646 ../plugins/gtkui/plcommon.c:745
+msgid "Edit column"
+msgstr "Επεξεργασία στήλη"
+
+#: ../plugins/gtkui/plcommon.c:749
+msgid "Remove column"
+msgstr "Αφαίρεση στήλης"
+
+#: ../plugins/gtkui/plcommon.c:759
+msgid "Group by"
+msgstr "Ομαδοποίηση κατά"
+
+#: ../plugins/gtkui/plcommon.c:766
+msgid "None"
+msgstr "Κανένα"
+
+#: ../plugins/gtkui/plcommon.c:770
+msgid "Artist/Date/Album"
+msgstr "Καλλιτέχνης/Ημερομηνία/Άλμπουμ"
+
+#: ../plugins/gtkui/pluginconf.c:41
+msgid "Open file..."
+msgstr "Άνοιγμα αρχείου..."
+
+#: ../plugins/gtkui/pluginconf.c:139
+#, c-format
+msgid "Setup %s"
+msgstr "Εγκατάσταση %s"
+
+#: ../plugins/gtkui/prefwin.c:98
+msgid "Default Audio Device"
+msgstr "Προεπιλεγμένη συσκευή ήχου"
+
+#: ../plugins/gtkui/prefwin.c:267
+msgid "Add"
+msgstr "Προσθήκη"
+
+#: ../plugins/gtkui/prefwin.c:277
+msgid "Global Hotkeys"
+msgstr "Συντομεύσεις πληκτρολογίου"
+
+#: ../plugins/gtkui/prefwin.c:332
+msgid "Slot"
+msgstr "Θέση"
+
+#: ../plugins/gtkui/prefwin.c:333
+msgid "Key combination"
+msgstr "Συνδυασμός πλήκτρων"
+
+#. output plugin selection
+#: ../plugins/gtkui/prefwin.c:379 ../plugins/gtkui/prefwin.c:569
+#: ../plugins.c:833
+msgid "ALSA output plugin"
+msgstr "Plugin εξόδου ALSA"
+
+#: ../plugins/gtkui/progress.c:64
+msgid "Initializing..."
+msgstr "Αρχικοποίηση..."
+
+#: ../plugins/gtkui/trkproperties.c:53
+msgid "You've modified data for this track."
+msgstr "Έχετε τροποποιήσει στοιχεία του κομματιού."
+
+#: ../plugins/gtkui/trkproperties.c:55
+msgid "Really close the window?"
+msgstr "Είστε σίγουροι πως θέλετε να κλείσετε το παράθυρο;"
+
+#: ../plugins/gtkui/trkproperties.c:178
+msgid "Tag Type(s)"
+msgstr "Τύπος ετικέτας"
+
+#: ../plugins/gtkui/trkproperties.c:180
+msgid "Embedded Cuesheet"
+msgstr "Ενσωματωμένα Cuesheet"
+
+#: ../plugins/gtkui/trkproperties.c:180
+msgid "Yes"
+msgstr "Ναί"
+
+#: ../plugins/gtkui/trkproperties.c:180
+msgid "No"
+msgstr "Όχι"
+
+#: ../plugins/gtkui/trkproperties.c:248 ../plugins/gtkui/trkproperties.c:260
+msgid "Key"
+msgstr "Πλήκτρο"
+
+#: ../plugins/gtkui/trkproperties.c:249 ../plugins/gtkui/trkproperties.c:261
+msgid "Value"
+msgstr "Τιμή"
+
+#: ../plugins/notify/notify.c:138
+#, fuzzy
+msgid "DeaDBeeF now playing"
+msgstr "DeaDBeeF %s ChangeLog"
+
+#: ../main.c:84
+#, c-format
+msgid "Usage: deadbeef [options] [file(s)]\n"
+msgstr "Χρήση: deadbeef [επιλογές] [αρχεία]\n"
+
+#: ../main.c:85
+#, c-format
+msgid "Options:\n"
+msgstr "Επιλογές:\n"
+
+#: ../main.c:86
+#, c-format
+msgid " --help or -h Print help (this message) and exit\n"
+msgstr " --help ή -h Εμφάνιση κειμένου βοήθειας και έξοδος\n"
+
+#: ../main.c:87
+#, c-format
+msgid " --quit Quit player\n"
+msgstr "--quit Έξοδος\n"
+
+#: ../main.c:88
+#, c-format
+msgid " --version Print version info and exit\n"
+msgstr "--version Εμφάνιση πληροφοριών έκδοσης και έξοδος\n"
+
+#: ../main.c:89
+#, c-format
+msgid " --play Start playback\n"
+msgstr "--play Εκκίνηση αναπαραγωγής\n"
+
+#: ../main.c:90
+#, c-format
+msgid " --stop Stop playback\n"
+msgstr "--stop Διακοπή αναπαραγωγής\n"
+
+#: ../main.c:91
+#, c-format
+msgid " --pause Pause playback\n"
+msgstr "--pause Παύση αναπαραγωγής\n"
+
+#: ../main.c:92
+#, c-format
+msgid " --next Next song in playlist\n"
+msgstr "--next Επόμενο τραγούδι στη λίστα αναπαραγωγής\n"
+
+#: ../main.c:93
+#, c-format
+msgid " --prev Previous song in playlist\n"
+msgstr "--prev Προηγούμενο τραγούδι στη λίστα αναπαραγωγής\n"
+
+#: ../main.c:94
+#, c-format
+msgid " --random Random song in playlist\n"
+msgstr "--random Τυχαίο κομμάτι στη λίστα αναπαραγωγής\n"
+
+#: ../main.c:95
+#, c-format
+msgid " --queue Append file(s) to existing playlist\n"
+msgstr "--queue Προσάρτηση αρχείου στην υπάρχουσα λίστα αναπαραγωγής\n"
+
+#: ../main.c:96
+#, c-format
+msgid " --nowplaying FMT Print formatted track name to stdout\n"
+msgstr "--nowplaying FMT Εμφάνιση μορφοποιημένου ονόματος κομματιού\n"
+
+#: ../main.c:97
+#, c-format
+msgid ""
+" FMT %%-syntax: [a]rtist, [t]itle, al[b]um,\n"
+" [l]ength, track[n]umber, [y]ear, [c]omment,\n"
+" copy[r]ight, [e]lapsed\n"
+msgstr ""
+"FMT %%-syntax: [a]rtist, [t]itle, al[b]um,\n"
+" [l]ength, track[n]umber, [y]ear, [c]omment,\n"
+" copy[r]ight, [e]lapsed\n"
+
+#: ../main.c:100
+#, c-format
+msgid ""
+" e.g.: --nowplaying \"%%a - %%t\" should print \"artist "
+"- title\"\n"
+msgstr "π.χ.: --nowplaying \"%%a - %%t\" θα εμφανίσει \"artist - title\"\n"
+
+#: ../playlist.c:369 ../playlist.c:2212
+msgid "Default"
+msgstr "Προεπιλογή"
+
+#: ../plugins/gtkui/deadbeef.glade.h:1
+#, fuzzy
+msgid ""
+"2.3 (Recommended)\n"
+"2.4"
+msgstr "2.3 (Προτείνεται)"
+
+#: ../plugins/gtkui/deadbeef.glade.h:25
+msgid ""
+"Disable\n"
+"Track\n"
+"Album"
+msgstr ""
+
+#: ../plugins/gtkui/deadbeef.glade.h:34
+msgid ""
+"File number\n"
+"Playing\n"
+"Album Art\n"
+"Artist - Album\n"
+"Artist\n"
+"Album\n"
+"Title\n"
+"Length\n"
+"Track\n"
+"Band / Album Artist\n"
+"Custom"
+msgstr ""
+
+#: ../plugins/gtkui/deadbeef.glade.h:60
+#, fuzzy
+msgid ""
+"Left\n"
+"Right"
+msgstr "Δεξιά"
+
+#: ../plugins/gtkui/support.c:90 ../plugins/gtkui/support.c:114
+#, c-format
+msgid "Couldn't find pixmap file: %s"
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:129 ../plugins/vorbis/vcedit.c:155
+msgid "Couldn't get enough memory for input buffering."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:179 ../plugins/vorbis/vcedit.c:550
+msgid "Error reading first page of Ogg bitstream."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:185 ../plugins/vorbis/vcedit.c:557
+msgid "Error reading initial header packet."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:237
+msgid "Couldn't get enough memory to register new stream serial number."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:505
+msgid "Input truncated or empty."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:507
+msgid "Input is not an Ogg bitstream."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:565
+msgid "Ogg bitstream does not contain Vorbis data."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:578
+msgid "EOF before recognised stream."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:594
+msgid "Ogg bitstream does not contain a supported data-type."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:638
+msgid "Corrupt secondary header."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:659
+msgid "EOF before end of Vorbis headers."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:834
+msgid "Corrupt or missing data, continuing..."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:874
+msgid ""
+"Error writing stream to output. Output stream may be corrupted or truncated."
+msgstr ""
diff --git a/po/es.po b/po/es.po
new file mode 100644
index 00000000..e20eaf26
--- /dev/null
+++ b/po/es.po
@@ -0,0 +1,1106 @@
+# Deadbeef Audio Player
+# Copyright (C) 2009-2001 Alexey Yakovenko <waker@users.sourceforge.net>
+# This file is distributed under the same license as the Deadbeef package.
+# depaz <depazzz@gmail.com>, 2010.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-05-27 16:47+0200\n"
+"PO-Revision-Date: 2010-05-21 18:34+0300\n"
+"Last-Translator: F.J. de Pablos <depazzz@gmail.com>\n"
+"Language-Team: Spanish\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../plugins/gtkui/callbacks.c:97
+msgid "Supported sound formats"
+msgstr "Formatos de audio soportados"
+
+#: ../plugins/gtkui/callbacks.c:108
+msgid "Other files (*)"
+msgstr "Otros archivos (*)"
+
+#: ../plugins/gtkui/callbacks.c:117
+msgid "Open file(s)..."
+msgstr "Abrir archivo(s)..."
+
+#: ../plugins/gtkui/callbacks.c:150
+msgid "Add file(s) to playlist..."
+msgstr "Añadir archivo(s) a la lista de reproducción..."
+
+#: ../plugins/gtkui/callbacks.c:182
+msgid "Add folder(s) to playlist..."
+msgstr "Añadir carpeta(s) a la lista de reproducción"
+
+#: ../plugins/gtkui/callbacks.c:640
+msgid "Failed while reading help file"
+msgstr "Error al leer el archivo de ayuda"
+
+#: ../plugins/gtkui/callbacks.c:650
+msgid "Failed to load help file"
+msgstr "Error al cargar el archivo de ayuda"
+
+#: ../plugins/gtkui/callbacks.c:664 ../plugins/gtkui/interface.c:1105
+#: ../plugins/gtkui/deadbeef.glade.h:56
+msgid "Help"
+msgstr "Ayuda"
+
+#: ../plugins/gtkui/callbacks.c:674
+#, c-format
+msgid "About DeaDBeeF %s"
+msgstr "Acerca de DeaDBeeF %s"
+
+#: ../plugins/gtkui/callbacks.c:685
+#, c-format
+msgid "DeaDBeeF %s ChangeLog"
+msgstr "Cambios en DeaDBeeF %s"
+
+#: ../plugins/gtkui/ddbtabstrip.c:527
+msgid "Edit playlist"
+msgstr "Editar Lista de Reproducción"
+
+#: ../plugins/gtkui/ddbtabstrip.c:604
+msgid "Rename Playlist"
+msgstr "Renombrar Lista de Reproducción"
+
+#: ../plugins/gtkui/ddbtabstrip.c:608
+msgid "Remove Playlist"
+msgstr "Quitar Lista de Reproducción"
+
+#: ../plugins/gtkui/ddbtabstrip.c:612
+msgid "Add New Playlist"
+msgstr "Nueva Lista de Reproducción"
+
+#: ../plugins/gtkui/eq.c:113
+msgid "Save DeaDBeeF EQ Preset"
+msgstr "Guardar Ajustes del Ec de DeaDBeeF"
+
+#: ../plugins/gtkui/eq.c:120
+msgid "DeaDBeeF EQ preset files (*.ddbeq)"
+msgstr "Ajustes del Ec de DeaDBeeF (*.ddbeq)"
+
+#: ../plugins/gtkui/eq.c:151
+msgid "Load DeaDBeeF EQ Preset..."
+msgstr "Cargar Ajustes del Ec"
+
+#: ../plugins/gtkui/eq.c:155
+msgid "DeaDBeeF EQ presets (*.ddbeq)"
+msgstr "Ajustes del Ec de DeaDBeeF (*.ddbeq)"
+
+#: ../plugins/gtkui/eq.c:214
+msgid "Import Foobar2000 EQ Preset..."
+msgstr "Importar Ajustes del Ec de Foobar2000"
+
+#: ../plugins/gtkui/eq.c:218
+msgid "Foobar2000 EQ presets (*.feq)"
+msgstr "Ajustes de Ec de Foobar2000"
+
+#: ../plugins/gtkui/eq.c:292
+msgid "Enable"
+msgstr "Activar"
+
+#: ../plugins/gtkui/eq.c:299
+msgid "Zero All"
+msgstr "Resetear Todo"
+
+#: ../plugins/gtkui/eq.c:306
+msgid "Zero Preamp"
+msgstr "Resetear Preamp"
+
+#: ../plugins/gtkui/eq.c:313
+msgid "Zero Bands"
+msgstr "Resetear Bandas"
+
+#: ../plugins/gtkui/eq.c:320
+msgid "Save Preset"
+msgstr "Guardar Ajustes"
+
+#: ../plugins/gtkui/eq.c:327
+msgid "Load Preset"
+msgstr "Cargar Ajustes"
+
+#: ../plugins/gtkui/eq.c:334
+msgid "Import Foobar2000 Preset"
+msgstr "Importar de Foobar2000"
+
+#: ../plugins/gtkui/gtkui.c:128
+#, c-format
+msgid "1 day %d:%02d:%02d"
+msgstr "1 día y %d:%02d:%02d"
+
+#: ../plugins/gtkui/gtkui.c:131
+#, c-format
+msgid "%d days %d:%02d:%02d"
+msgstr "%d días y %d:%02d:%02d"
+
+#: ../plugins/gtkui/gtkui.c:140
+#, c-format
+msgid "Stopped | %d tracks | %s total playtime"
+msgstr "Parado | %d pistas | Tiempo total: %s "
+
+#: ../plugins/gtkui/gtkui.c:150
+msgid "Mono"
+msgstr "Mono"
+
+#: ../plugins/gtkui/gtkui.c:150
+msgid "Stereo"
+msgstr "Estéreo"
+
+#: ../plugins/gtkui/gtkui.c:170
+#, c-format
+msgid "| %4d kbps "
+msgstr "| %4d kbps "
+
+#: ../plugins/gtkui/gtkui.c:176
+msgid "Paused | "
+msgstr "Pausado | "
+
+#: ../plugins/gtkui/gtkui.c:177
+#, c-format
+msgid ""
+"%s%s %s| %dHz | %d bit | %s | %d:%02d / %s | %d tracks | %s total playtime"
+msgstr ""
+"%s%s %s| %dHz | %d bit | %s | %d:%02d / %s | %d pistas | Tiempo total: %s"
+
+#: ../plugins/gtkui/gtkui.c:533
+msgid "Save Playlist As"
+msgstr "Guardar Lista de Reproducción Como..."
+
+#: ../plugins/gtkui/gtkui.c:542 ../plugins/gtkui/gtkui.c:603
+msgid "DeaDBeeF playlist files (*.dbpl)"
+msgstr "Listas de reproducción de DeaDBeeF (*.dbpl)"
+
+#: ../plugins/gtkui/gtkui.c:596
+msgid "Load Playlist"
+msgstr "Cargar Lista de Reproducción"
+
+#: ../plugins/gtkui/gtkui.c:741
+msgid "New Playlist"
+msgstr "Lista de Reproducción"
+
+#: ../plugins/gtkui/gtkui.c:744
+#, c-format
+msgid "New Playlist (%d)"
+msgstr "Lista de Reproducción (%d)"
+
+#: ../plugins/gtkui/interface.c:140 ../plugins/gtkui/deadbeef.glade.h:138
+msgid "_File"
+msgstr "_Archivo"
+
+#: ../plugins/gtkui/interface.c:147 ../plugins/gtkui/deadbeef.glade.h:142
+msgid "_Open file(s)"
+msgstr "_Abrir archivo(s)"
+
+#: ../plugins/gtkui/interface.c:163 ../plugins/gtkui/deadbeef.glade.h:7
+msgid "Add file(s)"
+msgstr "Añadir archivo(s)"
+
+#: ../plugins/gtkui/interface.c:171 ../plugins/gtkui/deadbeef.glade.h:8
+msgid "Add folder(s)"
+msgstr "Añadir carpeta(s)"
+
+#: ../plugins/gtkui/interface.c:179 ../plugins/gtkui/deadbeef.glade.h:6
+msgid "Add Audio CD"
+msgstr "Añadir CD de audio"
+
+#: ../plugins/gtkui/interface.c:187 ../plugins/gtkui/interface.c:2870
+#: ../plugins/gtkui/deadbeef.glade.h:9
+msgid "Add location"
+msgstr "Añadir dirección"
+
+#: ../plugins/gtkui/interface.c:196 ../plugins/gtkui/deadbeef.glade.h:72
+msgid "New playlist"
+msgstr "Nueva lista de reproducción"
+
+#: ../plugins/gtkui/interface.c:203 ../plugins/gtkui/deadbeef.glade.h:64
+msgid "Load playlist"
+msgstr "Cargar lista de reproducción"
+
+#: ../plugins/gtkui/interface.c:207 ../plugins/gtkui/deadbeef.glade.h:99
+msgid "Save playlist"
+msgstr "Guardar lista de reproducción"
+
+#: ../plugins/gtkui/interface.c:211 ../plugins/gtkui/deadbeef.glade.h:100
+msgid "Save playlist as"
+msgstr "Guardar lista de reproducción como..."
+
+#: ../plugins/gtkui/interface.c:220 ../plugins/gtkui/deadbeef.glade.h:144
+msgid "_Quit"
+msgstr "_Salir"
+
+#: ../plugins/gtkui/interface.c:231 ../plugins/gtkui/deadbeef.glade.h:137
+msgid "_Edit"
+msgstr "_Editar"
+
+#: ../plugins/gtkui/interface.c:238 ../plugins/gtkui/deadbeef.glade.h:135
+msgid "_Clear"
+msgstr "_Limpiar"
+
+#: ../plugins/gtkui/interface.c:246 ../plugins/gtkui/deadbeef.glade.h:104
+msgid "Select all"
+msgstr "Seleccionar todo"
+
+#: ../plugins/gtkui/interface.c:253 ../plugins/gtkui/deadbeef.glade.h:24
+msgid "Deselect all"
+msgstr "Deseleccionar todo"
+
+#: ../plugins/gtkui/interface.c:260 ../plugins/gtkui/deadbeef.glade.h:59
+msgid "Invert selection"
+msgstr "Invertir selección"
+
+#: ../plugins/gtkui/interface.c:264 ../plugins/gtkui/deadbeef.glade.h:107
+msgid "Selection"
+msgstr "Selección"
+
+#: ../plugins/gtkui/interface.c:271 ../plugins/gtkui/plcommon.c:387
+#: ../plugins/gtkui/prefwin.c:272 ../plugins/gtkui/deadbeef.glade.h:95
+msgid "Remove"
+msgstr "Quitar"
+
+#: ../plugins/gtkui/interface.c:279 ../plugins/gtkui/deadbeef.glade.h:19
+msgid "Crop"
+msgstr "Cortar"
+
+#: ../plugins/gtkui/interface.c:283 ../plugins/gtkui/deadbeef.glade.h:139
+msgid "_Find"
+msgstr "_Buscar"
+
+#: ../plugins/gtkui/interface.c:295 ../plugins/gtkui/interface.c:1706
+#: ../plugins/gtkui/deadbeef.glade.h:85
+msgid "Preferences"
+msgstr "Preferencias"
+
+#: ../plugins/gtkui/interface.c:299 ../plugins/gtkui/deadbeef.glade.h:145
+msgid "_View"
+msgstr "_Ver"
+
+#: ../plugins/gtkui/interface.c:306 ../plugins/gtkui/deadbeef.glade.h:111
+msgid "Status bar"
+msgstr "Barra de estado"
+
+#: ../plugins/gtkui/interface.c:310 ../plugins/gtkui/deadbeef.glade.h:17
+msgid "Column headers"
+msgstr "Cabeceras de columnas"
+
+#: ../plugins/gtkui/interface.c:314 ../plugins/gtkui/deadbeef.glade.h:118
+msgid "Tabs"
+msgstr "Pestañas"
+
+#: ../plugins/gtkui/interface.c:318 ../plugins/gtkui/deadbeef.glade.h:32
+msgid "Equalizer"
+msgstr "Ecualizador"
+
+#: ../plugins/gtkui/interface.c:322 ../plugins/gtkui/deadbeef.glade.h:143
+msgid "_Playback"
+msgstr "_Reproducción"
+
+#: ../plugins/gtkui/interface.c:329 ../plugins/gtkui/deadbeef.glade.h:75
+msgid "Order"
+msgstr "Orden"
+
+#: ../plugins/gtkui/interface.c:336 ../plugins/gtkui/deadbeef.glade.h:63
+msgid "Linear"
+msgstr "Lineal"
+
+#: ../plugins/gtkui/interface.c:342 ../plugins/gtkui/deadbeef.glade.h:108
+msgid "Shuffle"
+msgstr "Barajar"
+
+#: ../plugins/gtkui/interface.c:348 ../plugins/gtkui/deadbeef.glade.h:94
+msgid "Random"
+msgstr "Aleatorio"
+
+#: ../plugins/gtkui/interface.c:354 ../plugins/gtkui/deadbeef.glade.h:67
+msgid "Looping"
+msgstr "Repetir"
+
+#: ../plugins/gtkui/interface.c:361 ../plugins/gtkui/deadbeef.glade.h:65
+msgid "Loop All"
+msgstr "Repetir Todo"
+
+#: ../plugins/gtkui/interface.c:367 ../plugins/gtkui/deadbeef.glade.h:66
+msgid "Loop Single Song"
+msgstr "Repetir Una Canción"
+
+#: ../plugins/gtkui/interface.c:373 ../plugins/gtkui/deadbeef.glade.h:28
+msgid "Don't Loop"
+msgstr "No Repetir"
+
+#: ../plugins/gtkui/interface.c:379 ../plugins/gtkui/deadbeef.glade.h:101
+msgid "Scroll follows playback"
+msgstr "Desplazar al cambiar de pista"
+
+#: ../plugins/gtkui/interface.c:384 ../plugins/gtkui/deadbeef.glade.h:21
+msgid "Cursor follows playback"
+msgstr "Seleccionar al cambiar de pista"
+
+#: ../plugins/gtkui/interface.c:388 ../plugins/gtkui/deadbeef.glade.h:113
+msgid "Stop after current"
+msgstr "Parar al terminar la pista actual"
+
+#: ../plugins/gtkui/interface.c:395 ../plugins/gtkui/interface.c:402
+#: ../plugins/gtkui/deadbeef.glade.h:140
+msgid "_Help"
+msgstr "_Ayuda"
+
+#: ../plugins/gtkui/interface.c:410 ../plugins/gtkui/deadbeef.glade.h:134
+msgid "_ChangeLog"
+msgstr "_Cambios"
+
+#: ../plugins/gtkui/interface.c:432 ../plugins/gtkui/deadbeef.glade.h:131
+msgid "_About"
+msgstr "_Acerca de"
+
+#: ../plugins/gtkui/interface.c:816 ../plugins/gtkui/deadbeef.glade.h:102
+msgid "Search"
+msgstr "Buscar"
+
+#: ../plugins/gtkui/interface.c:891 ../plugins/gtkui/deadbeef.glade.h:112
+msgid "Stop"
+msgstr "Parar"
+
+#: ../plugins/gtkui/interface.c:899 ../plugins/gtkui/deadbeef.glade.h:81
+msgid "Play"
+msgstr "Reproducir"
+
+#: ../plugins/gtkui/interface.c:907 ../plugins/gtkui/deadbeef.glade.h:80
+msgid "Pause"
+msgstr "Pausar"
+
+#: ../plugins/gtkui/interface.c:915 ../plugins/gtkui/deadbeef.glade.h:86
+msgid "Previous"
+msgstr "Anterior"
+
+#: ../plugins/gtkui/interface.c:923 ../plugins/gtkui/deadbeef.glade.h:73
+msgid "Next"
+msgstr "Siguiente"
+
+#: ../plugins/gtkui/interface.c:931 ../plugins/gtkui/deadbeef.glade.h:82
+msgid "Play Random"
+msgstr "Aleatorio"
+
+#: ../plugins/gtkui/interface.c:940 ../plugins/gtkui/deadbeef.glade.h:5
+msgid "About"
+msgstr "Acerca de"
+
+#: ../plugins/gtkui/interface.c:953 ../plugins/gtkui/deadbeef.glade.h:93
+msgid "Quit"
+msgstr "Salir"
+
+#: ../plugins/gtkui/interface.c:1025 ../plugins/gtkui/deadbeef.glade.h:10
+msgid "Adding files..."
+msgstr "Añadiendo archivos..."
+
+#: ../plugins/gtkui/interface.c:1069 ../plugins/gtkui/deadbeef.glade.h:130
+msgid "_Abort"
+msgstr "_Abortar"
+
+#: ../plugins/gtkui/interface.c:1170 ../plugins/gtkui/deadbeef.glade.h:122
+msgid "Track Properties"
+msgstr "Propiedades de la Pista"
+
+#: ../plugins/gtkui/interface.c:1194 ../plugins/gtkui/deadbeef.glade.h:3
+msgid ""
+"<b>WARNING</b>: tag writing feature is still in development.\n"
+"<b>Make backup copies</b> before using."
+msgstr ""
+"<b>AVISO</b>: la edición de etiquetas está aún en desarrollo.\n"
+"<b>Haz copias de seguridad</b> antes de intentarlo."
+
+#: ../plugins/gtkui/interface.c:1221 ../plugins/gtkui/deadbeef.glade.h:132
+msgid "_Apply"
+msgstr "_Aplicar"
+
+#: ../plugins/gtkui/interface.c:1242 ../plugins/gtkui/interface.c:1288
+#: ../plugins/gtkui/interface.c:2436 ../plugins/gtkui/deadbeef.glade.h:136
+msgid "_Close"
+msgstr "_Cerrar"
+
+#: ../plugins/gtkui/interface.c:1246 ../plugins/gtkui/deadbeef.glade.h:68
+msgid "Metadata"
+msgstr "Metadatos"
+
+#: ../plugins/gtkui/interface.c:1292 ../plugins/gtkui/plcommon.c:402
+#: ../plugins/gtkui/deadbeef.glade.h:87
+msgid "Properties"
+msgstr "Propiedades"
+
+#: ../plugins/gtkui/interface.c:1378 ../plugins/gtkui/deadbeef.glade.h:146
+msgid "editcolumndlg"
+msgstr "editcolumndlg"
+
+#: ../plugins/gtkui/interface.c:1393 ../plugins/gtkui/interface.c:2770
+#: ../plugins/gtkui/deadbeef.glade.h:121
+msgid "Title:"
+msgstr "Título:"
+
+#: ../plugins/gtkui/interface.c:1401 ../plugins/gtkui/deadbeef.glade.h:31
+msgid "Enter new column title here"
+msgstr "Introduce el título de la columna"
+
+#: ../plugins/gtkui/interface.c:1409 ../plugins/gtkui/deadbeef.glade.h:123
+msgid "Type:"
+msgstr "Tipo:"
+
+#: ../plugins/gtkui/interface.c:1417
+msgid "File number"
+msgstr "Número de archivo"
+
+#. create default set of columns
+#: ../plugins/gtkui/interface.c:1418 ../plugins/gtkui/mainplaylist.c:297
+msgid "Playing"
+msgstr "Reproduciendo"
+
+#: ../plugins/gtkui/interface.c:1419
+msgid "Album Art"
+msgstr "Portada"
+
+#: ../plugins/gtkui/interface.c:1420
+msgid "Artist - Album"
+msgstr "Artista - Álbum"
+
+#: ../plugins/gtkui/interface.c:1421 ../plugins/gtkui/plcommon.c:774
+msgid "Artist"
+msgstr "Artista"
+
+#: ../plugins/gtkui/interface.c:1422 ../plugins/gtkui/interface.c:1795
+msgid "Album"
+msgstr "Álbum"
+
+#: ../plugins/gtkui/interface.c:1423 ../plugins/gtkui/prefwin.c:488
+msgid "Title"
+msgstr "Título"
+
+#: ../plugins/gtkui/interface.c:1424
+msgid "Length"
+msgstr "Duración"
+
+#: ../plugins/gtkui/interface.c:1425 ../plugins/gtkui/interface.c:1794
+msgid "Track"
+msgstr "Pista"
+
+#: ../plugins/gtkui/interface.c:1426
+msgid "Band / Album Artist"
+msgstr "Grupo / Artista"
+
+#: ../plugins/gtkui/interface.c:1427 ../plugins/gtkui/plcommon.c:778
+msgid "Custom"
+msgstr "Personalizado"
+
+#: ../plugins/gtkui/interface.c:1433 ../plugins/gtkui/interface.c:2997
+#: ../plugins/gtkui/deadbeef.glade.h:53
+msgid "Format:"
+msgstr "Formato:"
+
+#: ../plugins/gtkui/interface.c:1448 ../plugins/gtkui/deadbeef.glade.h:11
+msgid "Alignment:"
+msgstr "Alineación:"
+
+#: ../plugins/gtkui/interface.c:1456
+msgid "Left"
+msgstr "Izquierda"
+
+#: ../plugins/gtkui/interface.c:1457
+msgid "Right"
+msgstr "Derecha"
+
+#: ../plugins/gtkui/interface.c:1459 ../plugins/gtkui/interface.c:3007
+#: ../plugins/gtkui/deadbeef.glade.h:47
+#, fuzzy, no-c-format
+msgid ""
+"Format conversions (start with %):\n"
+" [a]rtist, [t]itle, al[b]um, [B]and, [C]omposer\n"
+" track[n]umber, [N]totaltracks,\n"
+" [l]ength, [y]ear, [g]enre, [c]omment,\n"
+" copy[r]ight, [f]ilename, [T]ags\n"
+"Example: %a - %t [%l]"
+msgstr ""
+"Formato (empezar con %):\n"
+" a: Artista, t: Título, b: Álbum, B: Grupo,\n"
+" n: Número de pista, N: Pistas totales,\n"
+" l: Duración, y: Año, g: Género, c: Comentario,\n"
+" r: Copyright, f: Archivo, T: Etiquetas\n"
+"Ejemplo: %a - %t [%l]"
+
+#: ../plugins/gtkui/interface.c:1488 ../plugins/gtkui/interface.c:2801
+#: ../plugins/gtkui/interface.c:2913 ../plugins/gtkui/interface.c:3036
+#: ../plugins/gtkui/deadbeef.glade.h:133
+msgid "_Cancel"
+msgstr "_Cancelar"
+
+#: ../plugins/gtkui/interface.c:1509 ../plugins/gtkui/interface.c:2822
+#: ../plugins/gtkui/interface.c:2934 ../plugins/gtkui/interface.c:3057
+#: ../plugins/gtkui/deadbeef.glade.h:141
+msgid "_OK"
+msgstr "_Aceptar"
+
+#: ../plugins/gtkui/interface.c:1726 ../plugins/gtkui/deadbeef.glade.h:77
+msgid "Output plugin:"
+msgstr "Plugin de salida:"
+
+#: ../plugins/gtkui/interface.c:1739 ../plugins/gtkui/deadbeef.glade.h:76
+msgid "Output device:"
+msgstr "Dispositivo de salida:"
+
+#: ../plugins/gtkui/interface.c:1748 ../plugins/gtkui/deadbeef.glade.h:109
+msgid "Sound"
+msgstr "Audio"
+
+#: ../plugins/gtkui/interface.c:1757 ../plugins/gtkui/deadbeef.glade.h:12
+msgid "Allow dynamic samplerate switching"
+msgstr "Permitir cambio dinámico de frecuencia"
+
+#: ../plugins/gtkui/interface.c:1765 ../plugins/gtkui/deadbeef.glade.h:98
+msgid "Samplerate conversion quality:"
+msgstr "Calidad de conversión de frecuencia:"
+
+#: ../plugins/gtkui/interface.c:1784 ../plugins/gtkui/deadbeef.glade.h:96
+msgid "Replaygain mode:"
+msgstr "Modo replaygain"
+
+#: ../plugins/gtkui/interface.c:1793
+msgid "Disable"
+msgstr "Desactivar"
+
+#: ../plugins/gtkui/interface.c:1797 ../plugins/gtkui/deadbeef.glade.h:97
+msgid "Replaygain peak scale"
+msgstr "Normalizar con replaygain"
+
+#: ../plugins/gtkui/interface.c:1801 ../plugins/gtkui/deadbeef.glade.h:110
+msgid "Sound (adv.)"
+msgstr "Audio (avanzado)"
+
+#: ../plugins/gtkui/interface.c:1810 ../plugins/gtkui/deadbeef.glade.h:16
+msgid "Close minimizes to tray"
+msgstr "Cerrar minimiza a la bandeja"
+
+#: ../plugins/gtkui/interface.c:1814 ../plugins/gtkui/deadbeef.glade.h:70
+msgid "Middle mouse button closes playlist"
+msgstr "Botón central del ratón cierra la lista de reproducción."
+
+#: ../plugins/gtkui/interface.c:1827 ../plugins/gtkui/interface.c:1871
+#: ../plugins/gtkui/deadbeef.glade.h:78
+msgid "Override"
+msgstr "Cambiar"
+
+#: ../plugins/gtkui/interface.c:1836 ../plugins/gtkui/deadbeef.glade.h:45
+msgid "Foreground"
+msgstr "Frente"
+
+#: ../plugins/gtkui/interface.c:1843 ../plugins/gtkui/deadbeef.glade.h:14
+msgid "Background"
+msgstr "Fondo"
+
+#: ../plugins/gtkui/interface.c:1862 ../plugins/gtkui/deadbeef.glade.h:103
+msgid "Seekbar/Volumebar colors"
+msgstr "Colores de barras de tiempo/volumen"
+
+#: ../plugins/gtkui/interface.c:1880 ../plugins/gtkui/deadbeef.glade.h:69
+msgid "Middle"
+msgstr "Medio"
+
+#: ../plugins/gtkui/interface.c:1887 ../plugins/gtkui/deadbeef.glade.h:62
+msgid "Light"
+msgstr "Claro"
+
+#: ../plugins/gtkui/interface.c:1894 ../plugins/gtkui/deadbeef.glade.h:22
+msgid "Dark"
+msgstr "Oscuro"
+
+#: ../plugins/gtkui/interface.c:1925 ../plugins/gtkui/deadbeef.glade.h:15
+msgid "Base"
+msgstr "Base"
+
+#: ../plugins/gtkui/interface.c:1932 ../plugins/gtkui/deadbeef.glade.h:117
+msgid "Tab strip colors"
+msgstr "Colores de pestañas"
+
+#: ../plugins/gtkui/interface.c:1941 ../plugins/gtkui/deadbeef.glade.h:79
+msgid "Override (looses GTK treeview theming, but speeds up rendering)"
+msgstr "Cambiar (ignora el tema GTK, pero acelera el renderizado)"
+
+#: ../plugins/gtkui/interface.c:1950 ../plugins/gtkui/deadbeef.glade.h:33
+msgid "Even row"
+msgstr "Fila par"
+
+#: ../plugins/gtkui/interface.c:1957 ../plugins/gtkui/deadbeef.glade.h:74
+msgid "Odd row"
+msgstr "Fila impar"
+
+#: ../plugins/gtkui/interface.c:1976 ../plugins/gtkui/deadbeef.glade.h:120
+msgid "Text"
+msgstr "Texto"
+
+#: ../plugins/gtkui/interface.c:1983 ../plugins/gtkui/deadbeef.glade.h:105
+msgid "Selected row"
+msgstr "Fila seleccionada"
+
+#: ../plugins/gtkui/interface.c:2002 ../plugins/gtkui/deadbeef.glade.h:106
+msgid "Selected text"
+msgstr "Texto Seleccionado"
+
+#: ../plugins/gtkui/interface.c:2015 ../plugins/gtkui/deadbeef.glade.h:20
+msgid "Cursor"
+msgstr "Cursor"
+
+#: ../plugins/gtkui/interface.c:2028 ../plugins/gtkui/deadbeef.glade.h:83
+msgid "Playlist colors"
+msgstr "Colores de lista de reproducción"
+
+#: ../plugins/gtkui/interface.c:2032 ../plugins/gtkui/deadbeef.glade.h:54
+msgid "GUI"
+msgstr "Interfaz"
+
+#: ../plugins/gtkui/interface.c:2041 ../plugins/gtkui/deadbeef.glade.h:30
+msgid "Enable Proxy Server"
+msgstr "Activar Servidor Proxy"
+
+#: ../plugins/gtkui/interface.c:2049 ../plugins/gtkui/deadbeef.glade.h:89
+msgid "Proxy Server Address:"
+msgstr "Dirección:"
+
+#: ../plugins/gtkui/interface.c:2063 ../plugins/gtkui/deadbeef.glade.h:90
+msgid "Proxy Server Port:"
+msgstr "Puerto:"
+
+#: ../plugins/gtkui/interface.c:2077 ../plugins/gtkui/deadbeef.glade.h:91
+msgid "Proxy Type:"
+msgstr "Tipo:"
+
+#: ../plugins/gtkui/interface.c:2096 ../plugins/gtkui/deadbeef.glade.h:92
+msgid "Proxy Username:"
+msgstr "Usuario:"
+
+#: ../plugins/gtkui/interface.c:2109 ../plugins/gtkui/deadbeef.glade.h:88
+msgid "Proxy Password:"
+msgstr "Contraseña:"
+
+#: ../plugins/gtkui/interface.c:2119 ../plugins/gtkui/deadbeef.glade.h:71
+msgid "Network"
+msgstr "Red"
+
+#: ../plugins/gtkui/interface.c:2147 ../plugins/gtkui/deadbeef.glade.h:128
+msgid "Write ID3v2"
+msgstr "Escribir ID3v2"
+
+#: ../plugins/gtkui/interface.c:2151 ../plugins/gtkui/interface.c:2278
+#: ../plugins/gtkui/deadbeef.glade.h:127
+msgid "Write ID3v1"
+msgstr "Escribir ID3v1"
+
+#: ../plugins/gtkui/interface.c:2155 ../plugins/gtkui/interface.c:2234
+#: ../plugins/gtkui/interface.c:2274 ../plugins/gtkui/deadbeef.glade.h:126
+msgid "Write APEv2"
+msgstr "Escribir APEv2"
+
+#: ../plugins/gtkui/interface.c:2163 ../plugins/gtkui/interface.c:2242
+#: ../plugins/gtkui/deadbeef.glade.h:116
+msgid "Strip ID3v2"
+msgstr "Recortar ID3v2"
+
+#: ../plugins/gtkui/interface.c:2167 ../plugins/gtkui/interface.c:2290
+#: ../plugins/gtkui/deadbeef.glade.h:115
+msgid "Strip ID3v1"
+msgstr "Recortar ID3v1"
+
+#: ../plugins/gtkui/interface.c:2171 ../plugins/gtkui/interface.c:2246
+#: ../plugins/gtkui/interface.c:2286 ../plugins/gtkui/deadbeef.glade.h:114
+msgid "Strip APEv2"
+msgstr "Recortar APEv2"
+
+#: ../plugins/gtkui/interface.c:2179 ../plugins/gtkui/deadbeef.glade.h:58
+msgid "ID3v2 version"
+msgstr "Versión de ID3v2"
+
+#: ../plugins/gtkui/interface.c:2186
+msgid "2.3 (Recommended)"
+msgstr "2.3 (Recomendada)"
+
+#: ../plugins/gtkui/interface.c:2187
+msgid "2.4"
+msgstr "2.4"
+
+#: ../plugins/gtkui/interface.c:2193 ../plugins/gtkui/deadbeef.glade.h:57
+msgid "ID3v1 character encoding (default is iso8859-1)"
+msgstr "Codificación de ID3v1 (por defecto es iso8859-1)"
+
+#: ../plugins/gtkui/interface.c:2230 ../plugins/gtkui/deadbeef.glade.h:129
+msgid "Write ID3v2.4"
+msgstr "Escribir ID3v2.4"
+
+#: ../plugins/gtkui/interface.c:2299 ../plugins/gtkui/deadbeef.glade.h:119
+msgid "Tag writer"
+msgstr "Editor de etiquetas"
+
+#: ../plugins/gtkui/interface.c:2330 ../plugins/gtkui/deadbeef.glade.h:23
+msgid "Description:"
+msgstr "Descripción:"
+
+#: ../plugins/gtkui/interface.c:2345 ../plugins/gtkui/deadbeef.glade.h:13
+msgid "Author(s):"
+msgstr "Autor:"
+
+#: ../plugins/gtkui/interface.c:2360 ../plugins/gtkui/deadbeef.glade.h:29
+msgid "Email:"
+msgstr "Email:"
+
+#: ../plugins/gtkui/interface.c:2375 ../plugins/gtkui/deadbeef.glade.h:125
+msgid "Website:"
+msgstr "Sitio Web:"
+
+#: ../plugins/gtkui/interface.c:2406 ../plugins/gtkui/deadbeef.glade.h:18
+msgid "Configure"
+msgstr "Configurar"
+
+#: ../plugins/gtkui/interface.c:2410 ../plugins/gtkui/deadbeef.glade.h:84
+msgid "Plugins"
+msgstr "Plugins"
+
+#: ../plugins/gtkui/interface.c:2754 ../plugins/gtkui/deadbeef.glade.h:147
+msgid "editplaylistdlg"
+msgstr "editplaylistdlg"
+
+#: ../plugins/gtkui/interface.c:2881 ../plugins/gtkui/deadbeef.glade.h:124
+msgid "URL:"
+msgstr "URL:"
+
+#: ../plugins/gtkui/interface.c:2982 ../plugins/gtkui/deadbeef.glade.h:55
+msgid "Group By"
+msgstr "Agrupar Por"
+
+#: ../plugins/gtkui/mainplaylist.c:298 ../plugins/gtkui/search.c:433
+msgid "Artist / Album"
+msgstr "Artista / Álbum"
+
+#: ../plugins/gtkui/mainplaylist.c:299 ../plugins/gtkui/search.c:434
+msgid "Track No"
+msgstr "Pista"
+
+#: ../plugins/gtkui/mainplaylist.c:300 ../plugins/gtkui/search.c:435
+msgid "Title / Track Artist"
+msgstr "Título / Intérprete"
+
+#: ../plugins/gtkui/mainplaylist.c:301 ../plugins/gtkui/search.c:436
+#: ../plugins/gtkui/trkproperties.c:175
+msgid "Duration"
+msgstr "Duración"
+
+#: ../plugins/gtkui/plcommon.c:316
+msgid "Delete files from disk"
+msgstr "Eliminar archivos del disco duro"
+
+#: ../plugins/gtkui/plcommon.c:317
+msgid ""
+"Files will be lost. Proceed?\n"
+"(This dialog can be turned off in GTKUI plugin settings)"
+msgstr ""
+"Perderás los archivos. ¿Deseas continuar?\n"
+"(Éste aviso puede desactivarse en las opciones del plugin GTKUI)"
+
+#: ../plugins/gtkui/plcommon.c:318 ../plugins/gtkui/trkproperties.c:56
+msgid "Warning"
+msgstr "Aviso"
+
+#: ../plugins/gtkui/plcommon.c:363
+msgid "Add to playback queue"
+msgstr "Añadir a cola de reproducción"
+
+#: ../plugins/gtkui/plcommon.c:368
+msgid "Remove from playback queue"
+msgstr "Quitar de cola de reproducción"
+
+#: ../plugins/gtkui/plcommon.c:376
+msgid "Reload metadata"
+msgstr "Recargar metadatos"
+
+#: ../plugins/gtkui/plcommon.c:392
+msgid "Remove from disk"
+msgstr "Eliminar archivo del disco duro"
+
+#: ../plugins/gtkui/plcommon.c:616 ../plugins/gtkui/plcommon.c:741
+msgid "Add column"
+msgstr "Añadir columna"
+
+#: ../plugins/gtkui/plcommon.c:646 ../plugins/gtkui/plcommon.c:745
+msgid "Edit column"
+msgstr "Editar columna"
+
+#: ../plugins/gtkui/plcommon.c:749
+msgid "Remove column"
+msgstr "Quitar columna"
+
+#: ../plugins/gtkui/plcommon.c:759
+msgid "Group by"
+msgstr "Agrupar por"
+
+#: ../plugins/gtkui/plcommon.c:766
+msgid "None"
+msgstr "Nada"
+
+#: ../plugins/gtkui/plcommon.c:770
+msgid "Artist/Date/Album"
+msgstr "Artista/Fecha/Álbum"
+
+#: ../plugins/gtkui/pluginconf.c:41
+msgid "Open file..."
+msgstr "Abrir archivo..."
+
+#: ../plugins/gtkui/pluginconf.c:139
+#, c-format
+msgid "Setup %s"
+msgstr "Configurar %s"
+
+#: ../plugins/gtkui/prefwin.c:98
+msgid "Default Audio Device"
+msgstr "Dispositivo de Audio por Defecto"
+
+#: ../plugins/gtkui/prefwin.c:267
+msgid "Add"
+msgstr "Añadir"
+
+#: ../plugins/gtkui/prefwin.c:277
+msgid "Global Hotkeys"
+msgstr "Teclas Rápidas Globales"
+
+#: ../plugins/gtkui/prefwin.c:332
+msgid "Slot"
+msgstr "Comando"
+
+#: ../plugins/gtkui/prefwin.c:333
+msgid "Key combination"
+msgstr "Combinación de teclas"
+
+#. output plugin selection
+#: ../plugins/gtkui/prefwin.c:379 ../plugins/gtkui/prefwin.c:569
+#: ../plugins.c:833
+msgid "ALSA output plugin"
+msgstr "Plugin de salida ALSA"
+
+#: ../plugins/gtkui/progress.c:64
+msgid "Initializing..."
+msgstr "Inicializando..."
+
+#: ../plugins/gtkui/trkproperties.c:53
+msgid "You've modified data for this track."
+msgstr "Has modificado los datos de ésta pista."
+
+#: ../plugins/gtkui/trkproperties.c:55
+msgid "Really close the window?"
+msgstr "¿Deseas cerrar la ventana?"
+
+#: ../plugins/gtkui/trkproperties.c:178
+msgid "Tag Type(s)"
+msgstr "Tipo de Etiqueta(s)"
+
+#: ../plugins/gtkui/trkproperties.c:180
+msgid "Embedded Cuesheet"
+msgstr "Hoja Cue Embedida"
+
+#: ../plugins/gtkui/trkproperties.c:180
+msgid "Yes"
+msgstr "Si"
+
+#: ../plugins/gtkui/trkproperties.c:180
+msgid "No"
+msgstr "No"
+
+#: ../plugins/gtkui/trkproperties.c:248 ../plugins/gtkui/trkproperties.c:260
+msgid "Key"
+msgstr "Clave"
+
+#: ../plugins/gtkui/trkproperties.c:249 ../plugins/gtkui/trkproperties.c:261
+msgid "Value"
+msgstr "Valor"
+
+#: ../plugins/notify/notify.c:138
+msgid "DeaDBeeF now playing"
+msgstr "DeaDBeeF reproduciendo:"
+
+#: ../main.c:84
+#, c-format
+msgid "Usage: deadbeef [options] [file(s)]\n"
+msgstr "Uso: deadbeef [opciones] [archivo(s)]\n"
+
+#: ../main.c:85
+#, c-format
+msgid "Options:\n"
+msgstr "Opciones:\n"
+
+#: ../main.c:86
+#, c-format
+msgid " --help or -h Print help (this message) and exit\n"
+msgstr " --help o -h Mostrar la ayuda (éste mensaje) y salir\n"
+
+#: ../main.c:87
+#, c-format
+msgid " --quit Quit player\n"
+msgstr " --quit Cerrar reproductor\n"
+
+#: ../main.c:88
+#, c-format
+msgid " --version Print version info and exit\n"
+msgstr " --version Mostar la versión y salir\n"
+
+#: ../main.c:89
+#, c-format
+msgid " --play Start playback\n"
+msgstr " --play Iniciar reproducción\n"
+
+#: ../main.c:90
+#, c-format
+msgid " --stop Stop playback\n"
+msgstr " --stop Parar reproducción\n"
+
+#: ../main.c:91
+#, c-format
+msgid " --pause Pause playback\n"
+msgstr " --pause Pausar reproducción\n"
+
+#: ../main.c:92
+#, c-format
+msgid " --next Next song in playlist\n"
+msgstr " --next Siguiente pista de la lista de reproducción\n"
+
+#: ../main.c:93
+#, c-format
+msgid " --prev Previous song in playlist\n"
+msgstr " --prev Pista anterior de la lista de reproducción \n"
+
+#: ../main.c:94
+#, c-format
+msgid " --random Random song in playlist\n"
+msgstr " --random Canción aleatoria de la lista de reproducción\n"
+
+#: ../main.c:95
+#, c-format
+msgid " --queue Append file(s) to existing playlist\n"
+msgstr " --queue Añadir archivo(s) a la lista de reproducción\n"
+
+#: ../main.c:96
+#, c-format
+msgid " --nowplaying FMT Print formatted track name to stdout\n"
+msgstr ""
+" --nowplaying FMT Mostrar nombre de la pista formateado a través de "
+"stdout\n"
+
+#: ../main.c:97
+#, c-format
+msgid ""
+" FMT %%-syntax: [a]rtist, [t]itle, al[b]um,\n"
+" [l]ength, track[n]umber, [y]ear, [c]omment,\n"
+" copy[r]ight, [e]lapsed\n"
+msgstr ""
+" FMT %%-syntaxis: a: Artista, t: Título, b: Álbum,\n"
+" l: Duración, n: Pista, y: Año, c: Comentario,\n"
+" r: Copyright, e: Tiempo restante\n"
+
+#: ../main.c:100
+#, c-format
+msgid ""
+" e.g.: --nowplaying \"%%a - %%t\" should print \"artist "
+"- title\"\n"
+msgstr ""
+" ej.: --nowplaying \"%%a - %%t\" mostraría \"artista - "
+"título\"\n"
+
+#: ../playlist.c:369 ../playlist.c:2212
+msgid "Default"
+msgstr "Por defecto"
+
+#: ../plugins/gtkui/deadbeef.glade.h:1
+#, fuzzy
+msgid ""
+"2.3 (Recommended)\n"
+"2.4"
+msgstr "2.3 (Recomendada)"
+
+#: ../plugins/gtkui/deadbeef.glade.h:25
+msgid ""
+"Disable\n"
+"Track\n"
+"Album"
+msgstr ""
+
+#: ../plugins/gtkui/deadbeef.glade.h:34
+msgid ""
+"File number\n"
+"Playing\n"
+"Album Art\n"
+"Artist - Album\n"
+"Artist\n"
+"Album\n"
+"Title\n"
+"Length\n"
+"Track\n"
+"Band / Album Artist\n"
+"Custom"
+msgstr ""
+
+#: ../plugins/gtkui/deadbeef.glade.h:60
+#, fuzzy
+msgid ""
+"Left\n"
+"Right"
+msgstr "Derecha"
+
+#: ../plugins/gtkui/support.c:90 ../plugins/gtkui/support.c:114
+#, c-format
+msgid "Couldn't find pixmap file: %s"
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:129 ../plugins/vorbis/vcedit.c:155
+msgid "Couldn't get enough memory for input buffering."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:179 ../plugins/vorbis/vcedit.c:550
+msgid "Error reading first page of Ogg bitstream."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:185 ../plugins/vorbis/vcedit.c:557
+msgid "Error reading initial header packet."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:237
+msgid "Couldn't get enough memory to register new stream serial number."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:505
+msgid "Input truncated or empty."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:507
+msgid "Input is not an Ogg bitstream."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:565
+msgid "Ogg bitstream does not contain Vorbis data."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:578
+msgid "EOF before recognised stream."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:594
+msgid "Ogg bitstream does not contain a supported data-type."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:638
+msgid "Corrupt secondary header."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:659
+msgid "EOF before end of Vorbis headers."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:834
+msgid "Corrupt or missing data, continuing..."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:874
+msgid ""
+"Error writing stream to output. Output stream may be corrupted or truncated."
+msgstr ""
diff --git a/po/he.po b/po/he.po
new file mode 100644
index 00000000..240f49e6
--- /dev/null
+++ b/po/he.po
@@ -0,0 +1,1109 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: DeaDBeeF\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-05-27 16:47+0200\n"
+"PO-Revision-Date: 2010-05-23 04:26+0200\n"
+"Last-Translator: Yaron Shahrabani <sh.yaron@gmail.com>\n"
+"Language-Team: Gezer <sh.yaron@gmail.com>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Language: Hebrew\n"
+"X-Poedit-Country: ISRAEL\n"
+"X-Poedit-SourceCharset: UTF-8\n"
+
+#: ../plugins/gtkui/callbacks.c:97
+msgid "Supported sound formats"
+msgstr "מבני השמע הנתמכים"
+
+#: ../plugins/gtkui/callbacks.c:108
+msgid "Other files (*)"
+msgstr "קבצים אחרים (*)"
+
+#: ../plugins/gtkui/callbacks.c:117
+msgid "Open file(s)..."
+msgstr "פתיחת קובץ/ים..."
+
+#: ../plugins/gtkui/callbacks.c:150
+msgid "Add file(s) to playlist..."
+msgstr "הוספת קובץ/ים לרשימת ההשמעה..."
+
+#: ../plugins/gtkui/callbacks.c:182
+msgid "Add folder(s) to playlist..."
+msgstr "הוספת תיקייה/ות לרשימת ההשמעה..."
+
+#: ../plugins/gtkui/callbacks.c:640
+msgid "Failed while reading help file"
+msgstr "ארע כשל במהלך קריאת קובץ העזרה"
+
+#: ../plugins/gtkui/callbacks.c:650
+msgid "Failed to load help file"
+msgstr "ארע כשל בטעינת קובץ העזרה"
+
+#: ../plugins/gtkui/callbacks.c:664 ../plugins/gtkui/interface.c:1105
+#: ../plugins/gtkui/deadbeef.glade.h:56
+msgid "Help"
+msgstr "עזרה"
+
+#: ../plugins/gtkui/callbacks.c:674
+#, c-format
+msgid "About DeaDBeeF %s"
+msgstr "על אודות DeaDBeeF %s"
+
+#: ../plugins/gtkui/callbacks.c:685
+#, c-format
+msgid "DeaDBeeF %s ChangeLog"
+msgstr "יומן השינויים של DeaDBeeF %s"
+
+#: ../plugins/gtkui/ddbtabstrip.c:527
+msgid "Edit playlist"
+msgstr "עריכת רשימת ההשמעה"
+
+#: ../plugins/gtkui/ddbtabstrip.c:604
+msgid "Rename Playlist"
+msgstr "שינוי שם רשימת ההשמעה"
+
+#: ../plugins/gtkui/ddbtabstrip.c:608
+msgid "Remove Playlist"
+msgstr "הסרת רשימת ההשמעה"
+
+#: ../plugins/gtkui/ddbtabstrip.c:612
+msgid "Add New Playlist"
+msgstr "הוספת רשימת השמעה חדשה"
+
+#: ../plugins/gtkui/eq.c:113
+msgid "Save DeaDBeeF EQ Preset"
+msgstr "שמירת תצורת האקוולייזר של DeaDBeeF"
+
+#: ../plugins/gtkui/eq.c:120
+msgid "DeaDBeeF EQ preset files (*.ddbeq)"
+msgstr "קובץ תצורת אקוולייזר של DeaDBeeF ‏(*.ddbeq)"
+
+#: ../plugins/gtkui/eq.c:151
+msgid "Load DeaDBeeF EQ Preset..."
+msgstr "טעינת תצורת אקוולייזר של DeaDBeeF..."
+
+#: ../plugins/gtkui/eq.c:155
+msgid "DeaDBeeF EQ presets (*.ddbeq)"
+msgstr "תצורות אקוולייזר של DeaDBeeF"
+
+#: ../plugins/gtkui/eq.c:214
+msgid "Import Foobar2000 EQ Preset..."
+msgstr "ייבוא קובץ תצורת אקוולייזר של Foobar2000..."
+
+#: ../plugins/gtkui/eq.c:218
+msgid "Foobar2000 EQ presets (*.feq)"
+msgstr "תצורות אקוולייזר של Foobar2000‏ (*.feq)"
+
+#: ../plugins/gtkui/eq.c:292
+msgid "Enable"
+msgstr "הפעלה"
+
+#: ../plugins/gtkui/eq.c:299
+msgid "Zero All"
+msgstr "הכל אפס"
+
+#: ../plugins/gtkui/eq.c:306
+msgid "Zero Preamp"
+msgstr "איפוס מגבר קדם"
+
+#: ../plugins/gtkui/eq.c:313
+msgid "Zero Bands"
+msgstr "איפוס הערוצים"
+
+#: ../plugins/gtkui/eq.c:320
+msgid "Save Preset"
+msgstr "שמירת תצורה"
+
+#: ../plugins/gtkui/eq.c:327
+msgid "Load Preset"
+msgstr "טעינת תצורה"
+
+#: ../plugins/gtkui/eq.c:334
+msgid "Import Foobar2000 Preset"
+msgstr "ייבוא תצורה של Foobar2000"
+
+#: ../plugins/gtkui/gtkui.c:128
+#, c-format
+msgid "1 day %d:%02d:%02d"
+msgstr "יום אחד %d:%02d:%02d"
+
+#: ../plugins/gtkui/gtkui.c:131
+#, c-format
+msgid "%d days %d:%02d:%02d"
+msgstr "%d ימים %d:%02d:%02d"
+
+#: ../plugins/gtkui/gtkui.c:140
+#, c-format
+msgid "Stopped | %d tracks | %s total playtime"
+msgstr "נעצר | %d רצועות | %s סך כל זמן הנגינה"
+
+#: ../plugins/gtkui/gtkui.c:150
+msgid "Mono"
+msgstr "מונו"
+
+#: ../plugins/gtkui/gtkui.c:150
+msgid "Stereo"
+msgstr "סטריאו"
+
+#: ../plugins/gtkui/gtkui.c:170
+#, c-format
+msgid "| %4d kbps "
+msgstr "| %4d קסל\"ש "
+
+#: ../plugins/gtkui/gtkui.c:176
+msgid "Paused | "
+msgstr "מושהה |"
+
+#: ../plugins/gtkui/gtkui.c:177
+#, c-format
+msgid ""
+"%s%s %s| %dHz | %d bit | %s | %d:%02d / %s | %d tracks | %s total playtime"
+msgstr ""
+"%s%s %s| %d הרץ | %d סיביות | %s | %d:%02d / %s | %d רצועות | %s סך כל זמן "
+"הנגינה"
+
+#: ../plugins/gtkui/gtkui.c:533
+msgid "Save Playlist As"
+msgstr "שמירת רשימת ההשמעה בשם"
+
+#: ../plugins/gtkui/gtkui.c:542 ../plugins/gtkui/gtkui.c:603
+msgid "DeaDBeeF playlist files (*.dbpl)"
+msgstr "קובצי רשימת השמעה של DeaDBeeF‏ (*.dbpl)"
+
+#: ../plugins/gtkui/gtkui.c:596
+msgid "Load Playlist"
+msgstr "טעינת רשימת השמעה"
+
+#: ../plugins/gtkui/gtkui.c:741
+msgid "New Playlist"
+msgstr "רשימת השמעה חדשה"
+
+#: ../plugins/gtkui/gtkui.c:744
+#, c-format
+msgid "New Playlist (%d)"
+msgstr "רשימת השמעה חדשה (%d)"
+
+#: ../plugins/gtkui/interface.c:140 ../plugins/gtkui/deadbeef.glade.h:138
+msgid "_File"
+msgstr "_קובץ"
+
+#: ../plugins/gtkui/interface.c:147 ../plugins/gtkui/deadbeef.glade.h:142
+msgid "_Open file(s)"
+msgstr "_פתיחת קובץ/ים"
+
+#: ../plugins/gtkui/interface.c:163 ../plugins/gtkui/deadbeef.glade.h:7
+msgid "Add file(s)"
+msgstr "הוספת קובץ/ים"
+
+#: ../plugins/gtkui/interface.c:171 ../plugins/gtkui/deadbeef.glade.h:8
+msgid "Add folder(s)"
+msgstr "הוספת תיקייה/ות"
+
+#: ../plugins/gtkui/interface.c:179 ../plugins/gtkui/deadbeef.glade.h:6
+msgid "Add Audio CD"
+msgstr "הוספת תקליטור שמע"
+
+#: ../plugins/gtkui/interface.c:187 ../plugins/gtkui/interface.c:2870
+#: ../plugins/gtkui/deadbeef.glade.h:9
+msgid "Add location"
+msgstr "הוספת מיקום"
+
+#: ../plugins/gtkui/interface.c:196 ../plugins/gtkui/deadbeef.glade.h:72
+msgid "New playlist"
+msgstr "רשימת השמעה חדשה"
+
+#: ../plugins/gtkui/interface.c:203 ../plugins/gtkui/deadbeef.glade.h:64
+msgid "Load playlist"
+msgstr "טעינת רשימת השמעה"
+
+#: ../plugins/gtkui/interface.c:207 ../plugins/gtkui/deadbeef.glade.h:99
+msgid "Save playlist"
+msgstr "שמירת רשימת השמעה"
+
+#: ../plugins/gtkui/interface.c:211 ../plugins/gtkui/deadbeef.glade.h:100
+msgid "Save playlist as"
+msgstr "שמירת רשימת השמעה בשם"
+
+#: ../plugins/gtkui/interface.c:220 ../plugins/gtkui/deadbeef.glade.h:144
+msgid "_Quit"
+msgstr "י_ציאה"
+
+#: ../plugins/gtkui/interface.c:231 ../plugins/gtkui/deadbeef.glade.h:137
+msgid "_Edit"
+msgstr "ע_ריכה"
+
+#: ../plugins/gtkui/interface.c:238 ../plugins/gtkui/deadbeef.glade.h:135
+msgid "_Clear"
+msgstr "_מחיקה"
+
+#: ../plugins/gtkui/interface.c:246 ../plugins/gtkui/deadbeef.glade.h:104
+msgid "Select all"
+msgstr "בחירת הכל"
+
+#: ../plugins/gtkui/interface.c:253 ../plugins/gtkui/deadbeef.glade.h:24
+msgid "Deselect all"
+msgstr "ביטול בחירת הכול"
+
+#: ../plugins/gtkui/interface.c:260 ../plugins/gtkui/deadbeef.glade.h:59
+msgid "Invert selection"
+msgstr "הפיכת הבחירה"
+
+#: ../plugins/gtkui/interface.c:264 ../plugins/gtkui/deadbeef.glade.h:107
+msgid "Selection"
+msgstr "בחירה"
+
+#: ../plugins/gtkui/interface.c:271 ../plugins/gtkui/plcommon.c:387
+#: ../plugins/gtkui/prefwin.c:272 ../plugins/gtkui/deadbeef.glade.h:95
+msgid "Remove"
+msgstr "הסרה"
+
+#: ../plugins/gtkui/interface.c:279 ../plugins/gtkui/deadbeef.glade.h:19
+msgid "Crop"
+msgstr "חיתוך"
+
+#: ../plugins/gtkui/interface.c:283 ../plugins/gtkui/deadbeef.glade.h:139
+msgid "_Find"
+msgstr "_חיפוש"
+
+#: ../plugins/gtkui/interface.c:295 ../plugins/gtkui/interface.c:1706
+#: ../plugins/gtkui/deadbeef.glade.h:85
+msgid "Preferences"
+msgstr "העדפות"
+
+#: ../plugins/gtkui/interface.c:299 ../plugins/gtkui/deadbeef.glade.h:145
+msgid "_View"
+msgstr "_תצוגה"
+
+#: ../plugins/gtkui/interface.c:306 ../plugins/gtkui/deadbeef.glade.h:111
+msgid "Status bar"
+msgstr "שורת מצב"
+
+#: ../plugins/gtkui/interface.c:310 ../plugins/gtkui/deadbeef.glade.h:17
+msgid "Column headers"
+msgstr "כותרות העמודות"
+
+#: ../plugins/gtkui/interface.c:314 ../plugins/gtkui/deadbeef.glade.h:118
+msgid "Tabs"
+msgstr "לשוניות"
+
+#: ../plugins/gtkui/interface.c:318 ../plugins/gtkui/deadbeef.glade.h:32
+msgid "Equalizer"
+msgstr "אקוולייזר"
+
+#: ../plugins/gtkui/interface.c:322 ../plugins/gtkui/deadbeef.glade.h:143
+msgid "_Playback"
+msgstr "ה_שמעה"
+
+#: ../plugins/gtkui/interface.c:329 ../plugins/gtkui/deadbeef.glade.h:75
+msgid "Order"
+msgstr "סדר"
+
+#: ../plugins/gtkui/interface.c:336 ../plugins/gtkui/deadbeef.glade.h:63
+msgid "Linear"
+msgstr "קווי"
+
+#: ../plugins/gtkui/interface.c:342 ../plugins/gtkui/deadbeef.glade.h:108
+msgid "Shuffle"
+msgstr "ערבול"
+
+#: ../plugins/gtkui/interface.c:348 ../plugins/gtkui/deadbeef.glade.h:94
+msgid "Random"
+msgstr "אקראי"
+
+#: ../plugins/gtkui/interface.c:354 ../plugins/gtkui/deadbeef.glade.h:67
+msgid "Looping"
+msgstr "נגינה בלולאה"
+
+#: ../plugins/gtkui/interface.c:361 ../plugins/gtkui/deadbeef.glade.h:65
+msgid "Loop All"
+msgstr "לולאה על הכול"
+
+#: ../plugins/gtkui/interface.c:367 ../plugins/gtkui/deadbeef.glade.h:66
+msgid "Loop Single Song"
+msgstr "לולאה על שיר בודד"
+
+#: ../plugins/gtkui/interface.c:373 ../plugins/gtkui/deadbeef.glade.h:28
+msgid "Don't Loop"
+msgstr "ללא לולאה"
+
+#: ../plugins/gtkui/interface.c:379 ../plugins/gtkui/deadbeef.glade.h:101
+msgid "Scroll follows playback"
+msgstr "הגלילה עוקבת אחר ההשמעה"
+
+#: ../plugins/gtkui/interface.c:384 ../plugins/gtkui/deadbeef.glade.h:21
+msgid "Cursor follows playback"
+msgstr "הסמן עוקב אחר ההשמעה"
+
+#: ../plugins/gtkui/interface.c:388 ../plugins/gtkui/deadbeef.glade.h:113
+msgid "Stop after current"
+msgstr "עצירה לאחר הנוכחי"
+
+#: ../plugins/gtkui/interface.c:395 ../plugins/gtkui/interface.c:402
+#: ../plugins/gtkui/deadbeef.glade.h:140
+msgid "_Help"
+msgstr "ע_זרה"
+
+#: ../plugins/gtkui/interface.c:410 ../plugins/gtkui/deadbeef.glade.h:134
+msgid "_ChangeLog"
+msgstr "יומן _שינויים"
+
+#: ../plugins/gtkui/interface.c:432 ../plugins/gtkui/deadbeef.glade.h:131
+msgid "_About"
+msgstr "על _אודות"
+
+#: ../plugins/gtkui/interface.c:816 ../plugins/gtkui/deadbeef.glade.h:102
+msgid "Search"
+msgstr "חיפוש"
+
+#: ../plugins/gtkui/interface.c:891 ../plugins/gtkui/deadbeef.glade.h:112
+msgid "Stop"
+msgstr "עצירה"
+
+#: ../plugins/gtkui/interface.c:899 ../plugins/gtkui/deadbeef.glade.h:81
+msgid "Play"
+msgstr "נגינה"
+
+#: ../plugins/gtkui/interface.c:907 ../plugins/gtkui/deadbeef.glade.h:80
+msgid "Pause"
+msgstr "השהיה"
+
+#: ../plugins/gtkui/interface.c:915 ../plugins/gtkui/deadbeef.glade.h:86
+msgid "Previous"
+msgstr "הקודם"
+
+#: ../plugins/gtkui/interface.c:923 ../plugins/gtkui/deadbeef.glade.h:73
+msgid "Next"
+msgstr "הבא"
+
+#: ../plugins/gtkui/interface.c:931 ../plugins/gtkui/deadbeef.glade.h:82
+msgid "Play Random"
+msgstr "נגינה אקראית"
+
+#: ../plugins/gtkui/interface.c:940 ../plugins/gtkui/deadbeef.glade.h:5
+msgid "About"
+msgstr "על אודות"
+
+#: ../plugins/gtkui/interface.c:953 ../plugins/gtkui/deadbeef.glade.h:93
+msgid "Quit"
+msgstr "יציאה"
+
+#: ../plugins/gtkui/interface.c:1025 ../plugins/gtkui/deadbeef.glade.h:10
+msgid "Adding files..."
+msgstr "מתבצעת הוספת קבצים..."
+
+#: ../plugins/gtkui/interface.c:1069 ../plugins/gtkui/deadbeef.glade.h:130
+msgid "_Abort"
+msgstr "_ביטול"
+
+#: ../plugins/gtkui/interface.c:1170 ../plugins/gtkui/deadbeef.glade.h:122
+msgid "Track Properties"
+msgstr "מאפייני הרצועה"
+
+#: ../plugins/gtkui/interface.c:1194 ../plugins/gtkui/deadbeef.glade.h:3
+msgid ""
+"<b>WARNING</b>: tag writing feature is still in development.\n"
+"<b>Make backup copies</b> before using."
+msgstr ""
+"<b>אזהרה</b>: תכונת כתיבת התגיות נמצאת עדיין בפיתוח.\n"
+"<b>יש ליצור עותקי גיבוי</b> בטרם השימוש."
+
+#: ../plugins/gtkui/interface.c:1221 ../plugins/gtkui/deadbeef.glade.h:132
+msgid "_Apply"
+msgstr "ה_חלה"
+
+#: ../plugins/gtkui/interface.c:1242 ../plugins/gtkui/interface.c:1288
+#: ../plugins/gtkui/interface.c:2436 ../plugins/gtkui/deadbeef.glade.h:136
+msgid "_Close"
+msgstr "_סגירה"
+
+#: ../plugins/gtkui/interface.c:1246 ../plugins/gtkui/deadbeef.glade.h:68
+msgid "Metadata"
+msgstr "נתוני על"
+
+#: ../plugins/gtkui/interface.c:1292 ../plugins/gtkui/plcommon.c:402
+#: ../plugins/gtkui/deadbeef.glade.h:87
+msgid "Properties"
+msgstr "מאפיינים"
+
+#: ../plugins/gtkui/interface.c:1378 ../plugins/gtkui/deadbeef.glade.h:146
+msgid "editcolumndlg"
+msgstr "editcolumndlg"
+
+#: ../plugins/gtkui/interface.c:1393 ../plugins/gtkui/interface.c:2770
+#: ../plugins/gtkui/deadbeef.glade.h:121
+msgid "Title:"
+msgstr "כותרת:"
+
+#: ../plugins/gtkui/interface.c:1401 ../plugins/gtkui/deadbeef.glade.h:31
+msgid "Enter new column title here"
+msgstr "יש להזין את הכותרת החדשה כאן"
+
+#: ../plugins/gtkui/interface.c:1409 ../plugins/gtkui/deadbeef.glade.h:123
+msgid "Type:"
+msgstr "סוג:"
+
+#: ../plugins/gtkui/interface.c:1417
+msgid "File number"
+msgstr "מספר הקובץ"
+
+#. create default set of columns
+#: ../plugins/gtkui/interface.c:1418 ../plugins/gtkui/mainplaylist.c:297
+msgid "Playing"
+msgstr "מתנגן"
+
+#: ../plugins/gtkui/interface.c:1419
+msgid "Album Art"
+msgstr "עטיפת האלבום"
+
+#: ../plugins/gtkui/interface.c:1420
+msgid "Artist - Album"
+msgstr "אומן – אלבום"
+
+#: ../plugins/gtkui/interface.c:1421 ../plugins/gtkui/plcommon.c:774
+msgid "Artist"
+msgstr "אומן"
+
+#: ../plugins/gtkui/interface.c:1422 ../plugins/gtkui/interface.c:1795
+msgid "Album"
+msgstr "אלבום"
+
+#: ../plugins/gtkui/interface.c:1423 ../plugins/gtkui/prefwin.c:488
+msgid "Title"
+msgstr "כותרת"
+
+#: ../plugins/gtkui/interface.c:1424
+msgid "Length"
+msgstr "משך"
+
+#: ../plugins/gtkui/interface.c:1425 ../plugins/gtkui/interface.c:1794
+msgid "Track"
+msgstr "רצועה"
+
+#: ../plugins/gtkui/interface.c:1426
+msgid "Band / Album Artist"
+msgstr "להקה / אומן האלבום"
+
+#: ../plugins/gtkui/interface.c:1427 ../plugins/gtkui/plcommon.c:778
+msgid "Custom"
+msgstr "מותאם אישית"
+
+#: ../plugins/gtkui/interface.c:1433 ../plugins/gtkui/interface.c:2997
+#: ../plugins/gtkui/deadbeef.glade.h:53
+msgid "Format:"
+msgstr "מבנה:"
+
+#: ../plugins/gtkui/interface.c:1448 ../plugins/gtkui/deadbeef.glade.h:11
+msgid "Alignment:"
+msgstr "יישור:"
+
+#: ../plugins/gtkui/interface.c:1456
+msgid "Left"
+msgstr "שמאל"
+
+#: ../plugins/gtkui/interface.c:1457
+msgid "Right"
+msgstr "ימין"
+
+#: ../plugins/gtkui/interface.c:1459 ../plugins/gtkui/interface.c:3007
+#: ../plugins/gtkui/deadbeef.glade.h:47
+#, fuzzy, no-c-format
+msgid ""
+"Format conversions (start with %):\n"
+" [a]rtist, [t]itle, al[b]um, [B]and, [C]omposer\n"
+" track[n]umber, [N]totaltracks,\n"
+" [l]ength, [y]ear, [g]enre, [c]omment,\n"
+" copy[r]ight, [f]ilename, [T]ags\n"
+"Example: %a - %t [%l]"
+msgstr ""
+"המרת מבנים (מתחיל ב־%):\n"
+" [a]rtist, [t]itle, al[b]um, [B]and,\n"
+" track[n]umber, [N]totaltracks,\n"
+" [l]ength, [y]ear, [g]enre, [c]omment,\n"
+" copy[r]ight, [f]ilename, [T]ags\n"
+"דוגמה: %a - %t [%l]"
+
+#: ../plugins/gtkui/interface.c:1488 ../plugins/gtkui/interface.c:2801
+#: ../plugins/gtkui/interface.c:2913 ../plugins/gtkui/interface.c:3036
+#: ../plugins/gtkui/deadbeef.glade.h:133
+msgid "_Cancel"
+msgstr "_ביטול"
+
+#: ../plugins/gtkui/interface.c:1509 ../plugins/gtkui/interface.c:2822
+#: ../plugins/gtkui/interface.c:2934 ../plugins/gtkui/interface.c:3057
+#: ../plugins/gtkui/deadbeef.glade.h:141
+msgid "_OK"
+msgstr "_אישור"
+
+#: ../plugins/gtkui/interface.c:1726 ../plugins/gtkui/deadbeef.glade.h:77
+msgid "Output plugin:"
+msgstr "תוסף פלט:"
+
+#: ../plugins/gtkui/interface.c:1739 ../plugins/gtkui/deadbeef.glade.h:76
+msgid "Output device:"
+msgstr "התקן הפלט:"
+
+#: ../plugins/gtkui/interface.c:1748 ../plugins/gtkui/deadbeef.glade.h:109
+msgid "Sound"
+msgstr "שמע"
+
+#: ../plugins/gtkui/interface.c:1757 ../plugins/gtkui/deadbeef.glade.h:12
+msgid "Allow dynamic samplerate switching"
+msgstr "הפעלת החלפת קצב דגימה דינמי"
+
+#: ../plugins/gtkui/interface.c:1765 ../plugins/gtkui/deadbeef.glade.h:98
+msgid "Samplerate conversion quality:"
+msgstr "איכות החלפת קצב הדגימה:"
+
+#: ../plugins/gtkui/interface.c:1784 ../plugins/gtkui/deadbeef.glade.h:96
+msgid "Replaygain mode:"
+msgstr "מצב הגברת נגינה חוזרת:"
+
+#: ../plugins/gtkui/interface.c:1793
+msgid "Disable"
+msgstr "לא פעיל"
+
+#: ../plugins/gtkui/interface.c:1797 ../plugins/gtkui/deadbeef.glade.h:97
+msgid "Replaygain peak scale"
+msgstr "מידת הגברת הנגינה החוזרת"
+
+#: ../plugins/gtkui/interface.c:1801 ../plugins/gtkui/deadbeef.glade.h:110
+msgid "Sound (adv.)"
+msgstr "שמע (מתקדם)"
+
+#: ../plugins/gtkui/interface.c:1810 ../plugins/gtkui/deadbeef.glade.h:16
+msgid "Close minimizes to tray"
+msgstr "סגירה ממזערת לאזור המערכת"
+
+#: ../plugins/gtkui/interface.c:1814 ../plugins/gtkui/deadbeef.glade.h:70
+msgid "Middle mouse button closes playlist"
+msgstr "לחצן אמצעי סוגר את רשימת ההשמעה"
+
+#: ../plugins/gtkui/interface.c:1827 ../plugins/gtkui/interface.c:1871
+#: ../plugins/gtkui/deadbeef.glade.h:78
+msgid "Override"
+msgstr "דריסה"
+
+#: ../plugins/gtkui/interface.c:1836 ../plugins/gtkui/deadbeef.glade.h:45
+msgid "Foreground"
+msgstr "קידמה"
+
+#: ../plugins/gtkui/interface.c:1843 ../plugins/gtkui/deadbeef.glade.h:14
+msgid "Background"
+msgstr "רקע"
+
+#: ../plugins/gtkui/interface.c:1862 ../plugins/gtkui/deadbeef.glade.h:103
+msgid "Seekbar/Volumebar colors"
+msgstr "צבעי פס גלילת ההשמעה/פס עוצמת השמע"
+
+#: ../plugins/gtkui/interface.c:1880 ../plugins/gtkui/deadbeef.glade.h:69
+msgid "Middle"
+msgstr "בינוני"
+
+#: ../plugins/gtkui/interface.c:1887 ../plugins/gtkui/deadbeef.glade.h:62
+msgid "Light"
+msgstr "בהיר"
+
+#: ../plugins/gtkui/interface.c:1894 ../plugins/gtkui/deadbeef.glade.h:22
+msgid "Dark"
+msgstr "כהה"
+
+#: ../plugins/gtkui/interface.c:1925 ../plugins/gtkui/deadbeef.glade.h:15
+msgid "Base"
+msgstr "בסיסי"
+
+#: ../plugins/gtkui/interface.c:1932 ../plugins/gtkui/deadbeef.glade.h:117
+msgid "Tab strip colors"
+msgstr "צבעי ראשי הלשוניות"
+
+#: ../plugins/gtkui/interface.c:1941 ../plugins/gtkui/deadbeef.glade.h:79
+msgid "Override (looses GTK treeview theming, but speeds up rendering)"
+msgstr "דריסה (רכיבי העיצוב של ה־GTK יאבדו אך העיבוד יהיה מהיר יותר)"
+
+#: ../plugins/gtkui/interface.c:1950 ../plugins/gtkui/deadbeef.glade.h:33
+msgid "Even row"
+msgstr "שורה זוגית"
+
+#: ../plugins/gtkui/interface.c:1957 ../plugins/gtkui/deadbeef.glade.h:74
+msgid "Odd row"
+msgstr "שורה אי־זוגית"
+
+#: ../plugins/gtkui/interface.c:1976 ../plugins/gtkui/deadbeef.glade.h:120
+msgid "Text"
+msgstr "טקסט"
+
+#: ../plugins/gtkui/interface.c:1983 ../plugins/gtkui/deadbeef.glade.h:105
+msgid "Selected row"
+msgstr "שורה נבחרת"
+
+#: ../plugins/gtkui/interface.c:2002 ../plugins/gtkui/deadbeef.glade.h:106
+msgid "Selected text"
+msgstr "טקסט שנבחר"
+
+#: ../plugins/gtkui/interface.c:2015 ../plugins/gtkui/deadbeef.glade.h:20
+msgid "Cursor"
+msgstr "סמן"
+
+#: ../plugins/gtkui/interface.c:2028 ../plugins/gtkui/deadbeef.glade.h:83
+msgid "Playlist colors"
+msgstr "צבעי רשימת ההשמעה"
+
+#: ../plugins/gtkui/interface.c:2032 ../plugins/gtkui/deadbeef.glade.h:54
+msgid "GUI"
+msgstr "מנשק משתמש"
+
+#: ../plugins/gtkui/interface.c:2041 ../plugins/gtkui/deadbeef.glade.h:30
+msgid "Enable Proxy Server"
+msgstr "הפעלת שרת מתווך"
+
+#: ../plugins/gtkui/interface.c:2049 ../plugins/gtkui/deadbeef.glade.h:89
+msgid "Proxy Server Address:"
+msgstr "כתובת שרת התיווך:"
+
+#: ../plugins/gtkui/interface.c:2063 ../plugins/gtkui/deadbeef.glade.h:90
+msgid "Proxy Server Port:"
+msgstr "פתחת שרת התיווך:"
+
+#: ../plugins/gtkui/interface.c:2077 ../plugins/gtkui/deadbeef.glade.h:91
+msgid "Proxy Type:"
+msgstr "סוג שרת התיווך:"
+
+#: ../plugins/gtkui/interface.c:2096 ../plugins/gtkui/deadbeef.glade.h:92
+msgid "Proxy Username:"
+msgstr "שם המשתמש במתווך:"
+
+#: ../plugins/gtkui/interface.c:2109 ../plugins/gtkui/deadbeef.glade.h:88
+msgid "Proxy Password:"
+msgstr "הססמה במתווך:"
+
+#: ../plugins/gtkui/interface.c:2119 ../plugins/gtkui/deadbeef.glade.h:71
+msgid "Network"
+msgstr "רשת"
+
+#: ../plugins/gtkui/interface.c:2147 ../plugins/gtkui/deadbeef.glade.h:128
+msgid "Write ID3v2"
+msgstr "כתיבת ID3v2"
+
+#: ../plugins/gtkui/interface.c:2151 ../plugins/gtkui/interface.c:2278
+#: ../plugins/gtkui/deadbeef.glade.h:127
+msgid "Write ID3v1"
+msgstr "כתיבת ID3v1"
+
+#: ../plugins/gtkui/interface.c:2155 ../plugins/gtkui/interface.c:2234
+#: ../plugins/gtkui/interface.c:2274 ../plugins/gtkui/deadbeef.glade.h:126
+msgid "Write APEv2"
+msgstr "כתיבת APEv2"
+
+#: ../plugins/gtkui/interface.c:2163 ../plugins/gtkui/interface.c:2242
+#: ../plugins/gtkui/deadbeef.glade.h:116
+msgid "Strip ID3v2"
+msgstr "הסרת ID3v2"
+
+#: ../plugins/gtkui/interface.c:2167 ../plugins/gtkui/interface.c:2290
+#: ../plugins/gtkui/deadbeef.glade.h:115
+msgid "Strip ID3v1"
+msgstr "הסרת ID3v1"
+
+#: ../plugins/gtkui/interface.c:2171 ../plugins/gtkui/interface.c:2246
+#: ../plugins/gtkui/interface.c:2286 ../plugins/gtkui/deadbeef.glade.h:114
+msgid "Strip APEv2"
+msgstr "הסרת APEv2"
+
+#: ../plugins/gtkui/interface.c:2179 ../plugins/gtkui/deadbeef.glade.h:58
+msgid "ID3v2 version"
+msgstr "גרסת ID3v2"
+
+#: ../plugins/gtkui/interface.c:2186
+msgid "2.3 (Recommended)"
+msgstr "2.3 (מומלץ)"
+
+#: ../plugins/gtkui/interface.c:2187
+msgid "2.4"
+msgstr "2.4"
+
+#: ../plugins/gtkui/interface.c:2193 ../plugins/gtkui/deadbeef.glade.h:57
+msgid "ID3v1 character encoding (default is iso8859-1)"
+msgstr "קידוד התווים של ID3v1 (ברירת המחדל היא iso8859-1)"
+
+#: ../plugins/gtkui/interface.c:2230 ../plugins/gtkui/deadbeef.glade.h:129
+msgid "Write ID3v2.4"
+msgstr "כתיבת ID3v2.4"
+
+#: ../plugins/gtkui/interface.c:2299 ../plugins/gtkui/deadbeef.glade.h:119
+msgid "Tag writer"
+msgstr "כותב תגיות"
+
+#: ../plugins/gtkui/interface.c:2330 ../plugins/gtkui/deadbeef.glade.h:23
+msgid "Description:"
+msgstr "תיאור:"
+
+#: ../plugins/gtkui/interface.c:2345 ../plugins/gtkui/deadbeef.glade.h:13
+msgid "Author(s):"
+msgstr "מחבר/ים:"
+
+#: ../plugins/gtkui/interface.c:2360 ../plugins/gtkui/deadbeef.glade.h:29
+msgid "Email:"
+msgstr "דוא\"ל:"
+
+#: ../plugins/gtkui/interface.c:2375 ../plugins/gtkui/deadbeef.glade.h:125
+msgid "Website:"
+msgstr "אתר:"
+
+#: ../plugins/gtkui/interface.c:2406 ../plugins/gtkui/deadbeef.glade.h:18
+msgid "Configure"
+msgstr "הגדרה"
+
+#: ../plugins/gtkui/interface.c:2410 ../plugins/gtkui/deadbeef.glade.h:84
+msgid "Plugins"
+msgstr "תוספים"
+
+#: ../plugins/gtkui/interface.c:2754 ../plugins/gtkui/deadbeef.glade.h:147
+msgid "editplaylistdlg"
+msgstr "editplaylistdlg"
+
+#: ../plugins/gtkui/interface.c:2881 ../plugins/gtkui/deadbeef.glade.h:124
+msgid "URL:"
+msgstr "כתובת:"
+
+#: ../plugins/gtkui/interface.c:2982 ../plugins/gtkui/deadbeef.glade.h:55
+msgid "Group By"
+msgstr "קיבוץ לפי"
+
+#: ../plugins/gtkui/mainplaylist.c:298 ../plugins/gtkui/search.c:433
+msgid "Artist / Album"
+msgstr "אומן / אלבום"
+
+#: ../plugins/gtkui/mainplaylist.c:299 ../plugins/gtkui/search.c:434
+msgid "Track No"
+msgstr "רצועה מספר"
+
+#: ../plugins/gtkui/mainplaylist.c:300 ../plugins/gtkui/search.c:435
+msgid "Title / Track Artist"
+msgstr "אמן הרצועה / כותרת"
+
+#: ../plugins/gtkui/mainplaylist.c:301 ../plugins/gtkui/search.c:436
+#: ../plugins/gtkui/trkproperties.c:175
+msgid "Duration"
+msgstr "משך"
+
+#: ../plugins/gtkui/plcommon.c:316
+msgid "Delete files from disk"
+msgstr "מחיקת הקובץ מהכונן"
+
+#: ../plugins/gtkui/plcommon.c:317
+msgid ""
+"Files will be lost. Proceed?\n"
+"(This dialog can be turned off in GTKUI plugin settings)"
+msgstr ""
+"הקבצים יאבדו. להמשיך?\n"
+"(ניתן לכבות תיבת דו־שיח זו בהגדרות התוסף GTKUI)"
+
+#: ../plugins/gtkui/plcommon.c:318 ../plugins/gtkui/trkproperties.c:56
+msgid "Warning"
+msgstr "אזהרה"
+
+#: ../plugins/gtkui/plcommon.c:363
+msgid "Add to playback queue"
+msgstr "הוספה לתור ההשמעה"
+
+#: ../plugins/gtkui/plcommon.c:368
+msgid "Remove from playback queue"
+msgstr "הסרה מתור ההשמעה"
+
+#: ../plugins/gtkui/plcommon.c:376
+msgid "Reload metadata"
+msgstr "טעינת נתוני העל מחדש"
+
+#: ../plugins/gtkui/plcommon.c:392
+msgid "Remove from disk"
+msgstr "הסרה מהכונן"
+
+#: ../plugins/gtkui/plcommon.c:616 ../plugins/gtkui/plcommon.c:741
+msgid "Add column"
+msgstr "הוספת עמודה"
+
+#: ../plugins/gtkui/plcommon.c:646 ../plugins/gtkui/plcommon.c:745
+msgid "Edit column"
+msgstr "עריכת עמודה"
+
+#: ../plugins/gtkui/plcommon.c:749
+msgid "Remove column"
+msgstr "הסרת עמודה"
+
+#: ../plugins/gtkui/plcommon.c:759
+msgid "Group by"
+msgstr "קיבוץ לפי"
+
+#: ../plugins/gtkui/plcommon.c:766
+msgid "None"
+msgstr "ללא"
+
+#: ../plugins/gtkui/plcommon.c:770
+msgid "Artist/Date/Album"
+msgstr "אומן/תאריך/אלבום"
+
+#: ../plugins/gtkui/pluginconf.c:41
+msgid "Open file..."
+msgstr "פתיחת קובץ..."
+
+#: ../plugins/gtkui/pluginconf.c:139
+#, c-format
+msgid "Setup %s"
+msgstr "הגדרת %s"
+
+#: ../plugins/gtkui/prefwin.c:98
+msgid "Default Audio Device"
+msgstr "התקן השמע כברירת מחדל"
+
+#: ../plugins/gtkui/prefwin.c:267
+msgid "Add"
+msgstr "הוספה"
+
+#: ../plugins/gtkui/prefwin.c:277
+msgid "Global Hotkeys"
+msgstr "מקשי קיצור גלובליים"
+
+#: ../plugins/gtkui/prefwin.c:332
+msgid "Slot"
+msgstr "חריץ"
+
+#: ../plugins/gtkui/prefwin.c:333
+msgid "Key combination"
+msgstr "צירוף מקשים"
+
+#. output plugin selection
+#: ../plugins/gtkui/prefwin.c:379 ../plugins/gtkui/prefwin.c:569
+#: ../plugins.c:833
+msgid "ALSA output plugin"
+msgstr "תוסף הפלט ALSA"
+
+#: ../plugins/gtkui/progress.c:64
+msgid "Initializing..."
+msgstr "בהפעלה..."
+
+#: ../plugins/gtkui/trkproperties.c:53
+msgid "You've modified data for this track."
+msgstr "השתנו נתונים ברצועה זו."
+
+#: ../plugins/gtkui/trkproperties.c:55
+msgid "Really close the window?"
+msgstr "האם באמת לסגור את החלון?"
+
+#: ../plugins/gtkui/trkproperties.c:178
+msgid "Tag Type(s)"
+msgstr "סוג/י התגים"
+
+#: ../plugins/gtkui/trkproperties.c:180
+msgid "Embedded Cuesheet"
+msgstr "רשימת Cue מוטמעת"
+
+#: ../plugins/gtkui/trkproperties.c:180
+msgid "Yes"
+msgstr "כן"
+
+#: ../plugins/gtkui/trkproperties.c:180
+msgid "No"
+msgstr "לא"
+
+#: ../plugins/gtkui/trkproperties.c:248 ../plugins/gtkui/trkproperties.c:260
+msgid "Key"
+msgstr "מפתח"
+
+#: ../plugins/gtkui/trkproperties.c:249 ../plugins/gtkui/trkproperties.c:261
+msgid "Value"
+msgstr "ערך"
+
+#: ../plugins/notify/notify.c:138
+#, fuzzy
+msgid "DeaDBeeF now playing"
+msgstr "יומן השינויים של DeaDBeeF %s"
+
+#: ../main.c:84
+#, c-format
+msgid "Usage: deadbeef [options] [file(s)]\n"
+msgstr "Usage: deadbeef [options] [file(s)]\n"
+
+#: ../main.c:85
+#, c-format
+msgid "Options:\n"
+msgstr "Options:\n"
+
+#: ../main.c:86
+#, c-format
+msgid " --help or -h Print help (this message) and exit\n"
+msgstr " --help or -h Print help (this message) and exit\n"
+
+#: ../main.c:87
+#, c-format
+msgid " --quit Quit player\n"
+msgstr " --quit Quit player\n"
+
+#: ../main.c:88
+#, c-format
+msgid " --version Print version info and exit\n"
+msgstr " --version Print version info and exit\n"
+
+#: ../main.c:89
+#, c-format
+msgid " --play Start playback\n"
+msgstr " --play Start playback\n"
+
+#: ../main.c:90
+#, c-format
+msgid " --stop Stop playback\n"
+msgstr " --stop Stop playback\n"
+
+#: ../main.c:91
+#, c-format
+msgid " --pause Pause playback\n"
+msgstr " --pause Pause playback\n"
+
+#: ../main.c:92
+#, c-format
+msgid " --next Next song in playlist\n"
+msgstr " --next Next song in playlist\n"
+
+#: ../main.c:93
+#, c-format
+msgid " --prev Previous song in playlist\n"
+msgstr " --prev Previous song in playlist\n"
+
+#: ../main.c:94
+#, c-format
+msgid " --random Random song in playlist\n"
+msgstr " --random Random song in playlist\n"
+
+#: ../main.c:95
+#, c-format
+msgid " --queue Append file(s) to existing playlist\n"
+msgstr " --queue Append file(s) to existing playlist\n"
+
+#: ../main.c:96
+#, c-format
+msgid " --nowplaying FMT Print formatted track name to stdout\n"
+msgstr " --nowplaying FMT Print formatted track name to stdout\n"
+
+#: ../main.c:97
+#, c-format
+msgid ""
+" FMT %%-syntax: [a]rtist, [t]itle, al[b]um,\n"
+" [l]ength, track[n]umber, [y]ear, [c]omment,\n"
+" copy[r]ight, [e]lapsed\n"
+msgstr ""
+" FMT %%-syntax: [a]rtist, [t]itle, al[b]um,\n"
+" [l]ength, track[n]umber, [y]ear, [c]omment,\n"
+" copy[r]ight, [e]lapsed\n"
+
+#: ../main.c:100
+#, c-format
+msgid ""
+" e.g.: --nowplaying \"%%a - %%t\" should print \"artist "
+"- title\"\n"
+msgstr ""
+" e.g.: --nowplaying \"%%a - %%t\" should print \"artist "
+"- title\"\n"
+
+#: ../playlist.c:369 ../playlist.c:2212
+msgid "Default"
+msgstr "ברירת מחדל"
+
+#: ../plugins/gtkui/deadbeef.glade.h:1
+#, fuzzy
+msgid ""
+"2.3 (Recommended)\n"
+"2.4"
+msgstr "2.3 (מומלץ)"
+
+#: ../plugins/gtkui/deadbeef.glade.h:25
+msgid ""
+"Disable\n"
+"Track\n"
+"Album"
+msgstr ""
+
+#: ../plugins/gtkui/deadbeef.glade.h:34
+msgid ""
+"File number\n"
+"Playing\n"
+"Album Art\n"
+"Artist - Album\n"
+"Artist\n"
+"Album\n"
+"Title\n"
+"Length\n"
+"Track\n"
+"Band / Album Artist\n"
+"Custom"
+msgstr ""
+
+#: ../plugins/gtkui/deadbeef.glade.h:60
+#, fuzzy
+msgid ""
+"Left\n"
+"Right"
+msgstr "ימין"
+
+#: ../plugins/gtkui/support.c:90 ../plugins/gtkui/support.c:114
+#, c-format
+msgid "Couldn't find pixmap file: %s"
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:129 ../plugins/vorbis/vcedit.c:155
+msgid "Couldn't get enough memory for input buffering."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:179 ../plugins/vorbis/vcedit.c:550
+msgid "Error reading first page of Ogg bitstream."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:185 ../plugins/vorbis/vcedit.c:557
+msgid "Error reading initial header packet."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:237
+msgid "Couldn't get enough memory to register new stream serial number."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:505
+msgid "Input truncated or empty."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:507
+msgid "Input is not an Ogg bitstream."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:565
+msgid "Ogg bitstream does not contain Vorbis data."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:578
+msgid "EOF before recognised stream."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:594
+msgid "Ogg bitstream does not contain a supported data-type."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:638
+msgid "Corrupt secondary header."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:659
+msgid "EOF before end of Vorbis headers."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:834
+msgid "Corrupt or missing data, continuing..."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:874
+msgid ""
+"Error writing stream to output. Output stream may be corrupted or truncated."
+msgstr ""
diff --git a/po/hr.po b/po/hr.po
new file mode 100644
index 00000000..d4d888b3
--- /dev/null
+++ b/po/hr.po
@@ -0,0 +1,982 @@
+# Croatian translations for PACKAGE package.
+# Copyright (C) 2010 THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# Ivica Kolić<ikoli@yahoo.com>, 2010.
+# Ivica Kolić<ikoli@yahoo.com> <>, 2010.
+msgid ""
+msgstr ""
+"Project-Id-Version: deadbeef\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-05-27 04:08+0000\n"
+"PO-Revision-Date: 2010-05-28 00:33+0200\n"
+"Last-Translator: Ivica Kolić<ikoli@yahoo.com> <>\n"
+"Language-Team: Croatian <>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%"
+"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+#: ../plugins/gtkui/callbacks.c:97
+msgid "Supported sound formats"
+msgstr "Podržani zvučni formati"
+
+#: ../plugins/gtkui/callbacks.c:108
+msgid "Other files (*)"
+msgstr "Ostale datoteke (*)"
+
+#: ../plugins/gtkui/callbacks.c:117
+msgid "Open file(s)..."
+msgstr "Otvori datoteku(e)"
+
+#: ../plugins/gtkui/callbacks.c:150
+msgid "Add file(s) to playlist..."
+msgstr "Dodaj datoteku(e) na listu izvođenja"
+
+#: ../plugins/gtkui/callbacks.c:182
+msgid "Add folder(s) to playlist..."
+msgstr "Dodaj mapu(e) na listu izvođenja"
+
+#: ../plugins/gtkui/callbacks.c:640
+msgid "Failed while reading help file"
+msgstr ""
+
+#: ../plugins/gtkui/callbacks.c:650
+msgid "Failed to load help file"
+msgstr ""
+
+#: ../plugins/gtkui/callbacks.c:664 ../plugins/gtkui/interface.c:1105
+msgid "Help"
+msgstr "Pomoć"
+
+#: ../plugins/gtkui/callbacks.c:674
+#, c-format
+msgid "About DeaDBeeF %s"
+msgstr "O DeaDBeeF %s"
+
+#: ../plugins/gtkui/callbacks.c:685
+#, c-format
+msgid "DeaDBeeF %s ChangeLog"
+msgstr ""
+
+#: ../plugins/gtkui/ddbtabstrip.c:527
+msgid "Edit playlist"
+msgstr "Uredi listu izvođenja"
+
+#: ../plugins/gtkui/ddbtabstrip.c:604
+msgid "Rename Playlist"
+msgstr "Preimenuj listu izvođenja"
+
+#: ../plugins/gtkui/ddbtabstrip.c:608
+msgid "Remove Playlist"
+msgstr "Ukloni listu izvođenja"
+
+#: ../plugins/gtkui/ddbtabstrip.c:612
+msgid "Add New Playlist"
+msgstr "Dodaj novu listu izvođenja"
+
+#: ../plugins/gtkui/eq.c:113
+msgid "Save DeaDBeeF EQ Preset"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:120
+msgid "DeaDBeeF EQ preset files (*.ddbeq)"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:151
+msgid "Load DeaDBeeF EQ Preset..."
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:155
+msgid "DeaDBeeF EQ presets (*.ddbeq)"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:214
+msgid "Import Foobar2000 EQ Preset..."
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:218
+msgid "Foobar2000 EQ presets (*.feq)"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:292
+msgid "Enable"
+msgstr "Omogući"
+
+#: ../plugins/gtkui/eq.c:299
+msgid "Zero All"
+msgstr "Nula sve"
+
+#: ../plugins/gtkui/eq.c:306
+msgid "Zero Preamp"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:313
+msgid "Zero Bands"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:320
+msgid "Save Preset"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:327
+msgid "Load Preset"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:334
+msgid "Import Foobar2000 Preset"
+msgstr ""
+
+#: ../plugins/gtkui/gtkui.c:128
+#, c-format
+msgid "1 day %d:%02d:%02d"
+msgstr ""
+
+#: ../plugins/gtkui/gtkui.c:131
+#, c-format
+msgid "%d days %d:%02d:%02d"
+msgstr ""
+
+#: ../plugins/gtkui/gtkui.c:140
+#, c-format
+msgid "Stopped | %d tracks | %s total playtime"
+msgstr ""
+
+#: ../plugins/gtkui/gtkui.c:150
+msgid "Mono"
+msgstr "Mono"
+
+#: ../plugins/gtkui/gtkui.c:150
+msgid "Stereo"
+msgstr "Stereo"
+
+#: ../plugins/gtkui/gtkui.c:170
+#, c-format
+msgid "| %4d kbps "
+msgstr ""
+
+#: ../plugins/gtkui/gtkui.c:176
+msgid "Paused | "
+msgstr "Pauzirano | "
+
+#: ../plugins/gtkui/gtkui.c:177
+#, c-format
+msgid ""
+"%s%s %s| %dHz | %d bit | %s | %d:%02d / %s | %d tracks | %s total playtime"
+msgstr ""
+
+#: ../plugins/gtkui/gtkui.c:533
+msgid "Save Playlist As"
+msgstr "Spremi listu izvođenja kao"
+
+#: ../plugins/gtkui/gtkui.c:542 ../plugins/gtkui/gtkui.c:603
+msgid "DeaDBeeF playlist files (*.dbpl)"
+msgstr "DeaDBeeF datoteke liste izvođenja"
+
+#: ../plugins/gtkui/gtkui.c:596
+msgid "Load Playlist"
+msgstr "Učitaj listu izvođenja"
+
+#: ../plugins/gtkui/gtkui.c:741
+msgid "New Playlist"
+msgstr "Nova lista izvođenja"
+
+#: ../plugins/gtkui/gtkui.c:744
+#, c-format
+msgid "New Playlist (%d)"
+msgstr "Nova lista izvođenja (%d)"
+
+#: ../plugins/gtkui/interface.c:140
+msgid "_File"
+msgstr "_Datoteka"
+
+#: ../plugins/gtkui/interface.c:147
+msgid "_Open file(s)"
+msgstr "_Otvori datoteku(e)"
+
+#: ../plugins/gtkui/interface.c:163
+msgid "Add file(s)"
+msgstr "Dodaj datoteku(e)"
+
+#: ../plugins/gtkui/interface.c:171
+msgid "Add folder(s)"
+msgstr "Dodaj mapu(e)"
+
+#: ../plugins/gtkui/interface.c:179
+msgid "Add Audio CD"
+msgstr "Dodaj audio CD"
+
+#: ../plugins/gtkui/interface.c:187 ../plugins/gtkui/interface.c:2870
+msgid "Add location"
+msgstr "Dodaj lokaciju"
+
+#: ../plugins/gtkui/interface.c:196
+msgid "New playlist"
+msgstr "Nova lista izvođenja"
+
+#: ../plugins/gtkui/interface.c:203
+msgid "Load playlist"
+msgstr "Učitaj listu izvođenja"
+
+#: ../plugins/gtkui/interface.c:207
+msgid "Save playlist"
+msgstr "Spremi listu izvođenja"
+
+#: ../plugins/gtkui/interface.c:211
+msgid "Save playlist as"
+msgstr "Spremi listu izvođenja kao"
+
+#: ../plugins/gtkui/interface.c:220
+msgid "_Quit"
+msgstr "_Iskjluči"
+
+#: ../plugins/gtkui/interface.c:231
+msgid "_Edit"
+msgstr "_Uredi"
+
+#: ../plugins/gtkui/interface.c:238
+msgid "_Clear"
+msgstr "_Očisti"
+
+#: ../plugins/gtkui/interface.c:246
+msgid "Select all"
+msgstr "Odaberi sve"
+
+#: ../plugins/gtkui/interface.c:253
+msgid "Deselect all"
+msgstr "Poništi odabrano"
+
+#: ../plugins/gtkui/interface.c:260
+msgid "Invert selection"
+msgstr "Obrnuti odabir"
+
+#: ../plugins/gtkui/interface.c:264
+msgid "Selection"
+msgstr "Odabir"
+
+#: ../plugins/gtkui/interface.c:271 ../plugins/gtkui/plcommon.c:387
+#: ../plugins/gtkui/prefwin.c:272
+msgid "Remove"
+msgstr "Ukloni"
+
+#: ../plugins/gtkui/interface.c:279
+msgid "Crop"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:283
+msgid "_Find"
+msgstr "_Nađi"
+
+#: ../plugins/gtkui/interface.c:295 ../plugins/gtkui/interface.c:1706
+msgid "Preferences"
+msgstr "Svojstva"
+
+#: ../plugins/gtkui/interface.c:299
+msgid "_View"
+msgstr "_Pogled"
+
+#: ../plugins/gtkui/interface.c:306
+msgid "Status bar"
+msgstr "Statusna traka"
+
+#: ../plugins/gtkui/interface.c:310
+msgid "Column headers"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:314
+msgid "Tabs"
+msgstr "Kartice"
+
+#: ../plugins/gtkui/interface.c:318
+msgid "Equalizer"
+msgstr "Ujednačivač"
+
+#: ../plugins/gtkui/interface.c:322
+msgid "_Playback"
+msgstr "_Reprodukcija"
+
+#: ../plugins/gtkui/interface.c:329
+msgid "Order"
+msgstr "Redoslijed"
+
+#: ../plugins/gtkui/interface.c:336
+msgid "Linear"
+msgstr "Linearni"
+
+#: ../plugins/gtkui/interface.c:342
+msgid "Shuffle"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:348
+msgid "Random"
+msgstr "Nasumično"
+
+#: ../plugins/gtkui/interface.c:354
+msgid "Looping"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:361
+msgid "Loop All"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:367
+msgid "Loop Single Song"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:373
+msgid "Don't Loop"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:379
+msgid "Scroll follows playback"
+msgstr "Klizač slijedi reprodukciju"
+
+#: ../plugins/gtkui/interface.c:384
+msgid "Cursor follows playback"
+msgstr "Pokazivač slijedi reprodukciju"
+
+#: ../plugins/gtkui/interface.c:388
+msgid "Stop after current"
+msgstr "Stop nakon trenutne"
+
+#: ../plugins/gtkui/interface.c:395 ../plugins/gtkui/interface.c:402
+msgid "_Help"
+msgstr "_Pomoć"
+
+#: ../plugins/gtkui/interface.c:410
+msgid "_ChangeLog"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:432
+msgid "_About"
+msgstr "_O programu"
+
+#: ../plugins/gtkui/interface.c:816
+msgid "Search"
+msgstr "Traži"
+
+#: ../plugins/gtkui/interface.c:891
+msgid "Stop"
+msgstr "Stop"
+
+#: ../plugins/gtkui/interface.c:899
+msgid "Play"
+msgstr "Sviraj"
+
+#: ../plugins/gtkui/interface.c:907
+msgid "Pause"
+msgstr "Pauza"
+
+#: ../plugins/gtkui/interface.c:915
+msgid "Previous"
+msgstr "Prethodno"
+
+#: ../plugins/gtkui/interface.c:923
+msgid "Next"
+msgstr "Slijedeće"
+
+#: ../plugins/gtkui/interface.c:931
+msgid "Play Random"
+msgstr "Sviraj nasumično"
+
+#: ../plugins/gtkui/interface.c:940
+msgid "About"
+msgstr "O programu"
+
+#: ../plugins/gtkui/interface.c:953
+msgid "Quit"
+msgstr "Isključi"
+
+#: ../plugins/gtkui/interface.c:1025
+msgid "Adding files..."
+msgstr "Dodavanje datoteka"
+
+#: ../plugins/gtkui/interface.c:1069
+msgid "_Abort"
+msgstr "_Prekini"
+
+#: ../plugins/gtkui/interface.c:1170
+msgid "Track Properties"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1194
+msgid ""
+"<b>WARNING</b>: tag writing feature is still in development.\n"
+"<b>Make backup copies</b> before using."
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1221
+msgid "_Apply"
+msgstr "_Primjeni"
+
+#: ../plugins/gtkui/interface.c:1242 ../plugins/gtkui/interface.c:1288
+#: ../plugins/gtkui/interface.c:2436
+msgid "_Close"
+msgstr "_Zatvori"
+
+#: ../plugins/gtkui/interface.c:1246
+msgid "Metadata"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1292 ../plugins/gtkui/plcommon.c:402
+msgid "Properties"
+msgstr "Svojstva"
+
+#: ../plugins/gtkui/interface.c:1378
+msgid "editcolumndlg"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1393 ../plugins/gtkui/interface.c:2770
+msgid "Title:"
+msgstr "Naslov:"
+
+#: ../plugins/gtkui/interface.c:1401
+msgid "Enter new column title here"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1409
+msgid "Type:"
+msgstr "Tip:"
+
+#: ../plugins/gtkui/interface.c:1417
+msgid "File number"
+msgstr "Broj datoteke"
+
+#. create default set of columns
+#: ../plugins/gtkui/interface.c:1418 ../plugins/gtkui/mainplaylist.c:297
+msgid "Playing"
+msgstr "Svira"
+
+#: ../plugins/gtkui/interface.c:1419
+msgid "Album Art"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1420
+msgid "Artist - Album"
+msgstr "Umjetnik _ album"
+
+#: ../plugins/gtkui/interface.c:1421 ../plugins/gtkui/plcommon.c:774
+msgid "Artist"
+msgstr "Umjetnik"
+
+#: ../plugins/gtkui/interface.c:1422 ../plugins/gtkui/interface.c:1795
+msgid "Album"
+msgstr "Album"
+
+#: ../plugins/gtkui/interface.c:1423 ../plugins/gtkui/prefwin.c:488
+msgid "Title"
+msgstr "Naslov"
+
+#: ../plugins/gtkui/interface.c:1424
+msgid "Length"
+msgstr "Dužina"
+
+#: ../plugins/gtkui/interface.c:1425 ../plugins/gtkui/interface.c:1794
+msgid "Track"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1426
+msgid "Band / Album Artist"
+msgstr "Grupa / album umjetnik"
+
+#: ../plugins/gtkui/interface.c:1427 ../plugins/gtkui/plcommon.c:778
+msgid "Custom"
+msgstr "Prolagođeno"
+
+#: ../plugins/gtkui/interface.c:1433 ../plugins/gtkui/interface.c:2997
+msgid "Format:"
+msgstr "Format:"
+
+#: ../plugins/gtkui/interface.c:1448
+msgid "Alignment:"
+msgstr "Poravnanje"
+
+#: ../plugins/gtkui/interface.c:1456
+msgid "Left"
+msgstr "Lijevo"
+
+#: ../plugins/gtkui/interface.c:1457
+msgid "Right"
+msgstr "Desno"
+
+#: ../plugins/gtkui/interface.c:1459 ../plugins/gtkui/interface.c:3007
+msgid ""
+"Format conversions (start with %):\n"
+" [a]rtist, [t]itle, al[b]um, [B]and, [C]omposer\n"
+" track[n]umber, [N]totaltracks,\n"
+" [l]ength, [y]ear, [g]enre, [c]omment,\n"
+" copy[r]ight, [f]ilename, [T]ags\n"
+"Example: %a - %t [%l]"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1488 ../plugins/gtkui/interface.c:2801
+#: ../plugins/gtkui/interface.c:2913 ../plugins/gtkui/interface.c:3036
+msgid "_Cancel"
+msgstr "_Odustani"
+
+#: ../plugins/gtkui/interface.c:1509 ../plugins/gtkui/interface.c:2822
+#: ../plugins/gtkui/interface.c:2934 ../plugins/gtkui/interface.c:3057
+msgid "_OK"
+msgstr "_OK"
+
+#: ../plugins/gtkui/interface.c:1726
+msgid "Output plugin:"
+msgstr "Izlazni priključak"
+
+#: ../plugins/gtkui/interface.c:1739
+msgid "Output device:"
+msgstr "Izlazni uređaj"
+
+#: ../plugins/gtkui/interface.c:1748
+msgid "Sound"
+msgstr "Zvuk"
+
+#: ../plugins/gtkui/interface.c:1757
+msgid "Allow dynamic samplerate switching"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1765
+msgid "Samplerate conversion quality:"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1784
+msgid "Replaygain mode:"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1793
+msgid "Disable"
+msgstr "Onemogući"
+
+#: ../plugins/gtkui/interface.c:1797
+msgid "Replaygain peak scale"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1801
+msgid "Sound (adv.)"
+msgstr "Zvuk (nap)"
+
+#: ../plugins/gtkui/interface.c:1810
+msgid "Close minimizes to tray"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1814
+msgid "Middle mouse button closes playlist"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1827 ../plugins/gtkui/interface.c:1871
+msgid "Override"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1836
+msgid "Foreground"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1843
+msgid "Background"
+msgstr "Pozadina"
+
+#: ../plugins/gtkui/interface.c:1862
+msgid "Seekbar/Volumebar colors"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1880
+msgid "Middle"
+msgstr "Srednje"
+
+#: ../plugins/gtkui/interface.c:1887
+msgid "Light"
+msgstr "Svijetlo"
+
+#: ../plugins/gtkui/interface.c:1894
+msgid "Dark"
+msgstr "Tamno"
+
+#: ../plugins/gtkui/interface.c:1925
+msgid "Base"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1932
+msgid "Tab strip colors"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1941
+msgid "Override (looses GTK treeview theming, but speeds up rendering)"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1950
+msgid "Even row"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1957
+msgid "Odd row"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1976
+msgid "Text"
+msgstr "Tekst"
+
+#: ../plugins/gtkui/interface.c:1983
+msgid "Selected row"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2002
+msgid "Selected text"
+msgstr "Odabrani tekst"
+
+#: ../plugins/gtkui/interface.c:2015
+msgid "Cursor"
+msgstr "Pokazivač"
+
+#: ../plugins/gtkui/interface.c:2028
+msgid "Playlist colors"
+msgstr "Boje liste izvođenja"
+
+#: ../plugins/gtkui/interface.c:2032
+msgid "GUI"
+msgstr "Grafičko sučelje"
+
+#: ../plugins/gtkui/interface.c:2041
+msgid "Enable Proxy Server"
+msgstr "Omogući proxy poslužitelj"
+
+#: ../plugins/gtkui/interface.c:2049
+msgid "Proxy Server Address:"
+msgstr "Adresa proxy poslužitelja"
+
+#: ../plugins/gtkui/interface.c:2063
+msgid "Proxy Server Port:"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2077
+msgid "Proxy Type:"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2096
+msgid "Proxy Username:"
+msgstr "Proxy korisničko ime"
+
+#: ../plugins/gtkui/interface.c:2109
+msgid "Proxy Password:"
+msgstr "Proxy lozinka"
+
+#: ../plugins/gtkui/interface.c:2119
+msgid "Network"
+msgstr "Mreža"
+
+#: ../plugins/gtkui/interface.c:2147
+msgid "Write ID3v2"
+msgstr "Piši ID3v2"
+
+#: ../plugins/gtkui/interface.c:2151 ../plugins/gtkui/interface.c:2278
+msgid "Write ID3v1"
+msgstr "Piši ID3v1"
+
+#: ../plugins/gtkui/interface.c:2155 ../plugins/gtkui/interface.c:2234
+#: ../plugins/gtkui/interface.c:2274
+msgid "Write APEv2"
+msgstr "Piši APEv2"
+
+#: ../plugins/gtkui/interface.c:2163 ../plugins/gtkui/interface.c:2242
+msgid "Strip ID3v2"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2167 ../plugins/gtkui/interface.c:2290
+msgid "Strip ID3v1"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2171 ../plugins/gtkui/interface.c:2246
+#: ../plugins/gtkui/interface.c:2286
+msgid "Strip APEv2"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2179
+msgid "ID3v2 version"
+msgstr "ID3v2 verzija"
+
+#: ../plugins/gtkui/interface.c:2186
+msgid "2.3 (Recommended)"
+msgstr "2.3 (preporučeno)"
+
+#: ../plugins/gtkui/interface.c:2187
+msgid "2.4"
+msgstr "2.4"
+
+#: ../plugins/gtkui/interface.c:2193
+msgid "ID3v1 character encoding (default is iso8859-1)"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2230
+msgid "Write ID3v2.4"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2299
+msgid "Tag writer"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2330
+msgid "Description:"
+msgstr "Opis:"
+
+#: ../plugins/gtkui/interface.c:2345
+msgid "Author(s):"
+msgstr "Aotor(i):"
+
+#: ../plugins/gtkui/interface.c:2360
+msgid "Email:"
+msgstr "Email:"
+
+#: ../plugins/gtkui/interface.c:2375
+msgid "Website:"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2406
+msgid "Configure"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2410
+msgid "Plugins"
+msgstr "Prikjlučci"
+
+#: ../plugins/gtkui/interface.c:2754
+msgid "editplaylistdlg"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2881
+msgid "URL:"
+msgstr "URL:"
+
+#: ../plugins/gtkui/interface.c:2982
+msgid "Group By"
+msgstr "Grupiraj po"
+
+#: ../plugins/gtkui/mainplaylist.c:298 ../plugins/gtkui/search.c:433
+msgid "Artist / Album"
+msgstr "Umjetnik /album"
+
+#: ../plugins/gtkui/mainplaylist.c:299 ../plugins/gtkui/search.c:434
+msgid "Track No"
+msgstr ""
+
+#: ../plugins/gtkui/mainplaylist.c:300 ../plugins/gtkui/search.c:435
+msgid "Title / Track Artist"
+msgstr ""
+
+#: ../plugins/gtkui/mainplaylist.c:301 ../plugins/gtkui/search.c:436
+#: ../plugins/gtkui/trkproperties.c:175
+msgid "Duration"
+msgstr "Trajanje"
+
+#: ../plugins/gtkui/plcommon.c:316
+msgid "Delete files from disk"
+msgstr "Izbriši datoteke sa diska"
+
+#: ../plugins/gtkui/plcommon.c:317
+msgid ""
+"Files will be lost. Proceed?\n"
+"(This dialog can be turned off in GTKUI plugin settings)"
+msgstr ""
+"Datoteke će biti izgubljene.Nastavi?\n"
+"(Ovaj dijalog može biti iskjlučen u GTKUI postavkama prikjlučaka)"
+
+#: ../plugins/gtkui/plcommon.c:318 ../plugins/gtkui/trkproperties.c:56
+msgid "Warning"
+msgstr "Upozorenje"
+
+#: ../plugins/gtkui/plcommon.c:363
+msgid "Add to playback queue"
+msgstr ""
+
+#: ../plugins/gtkui/plcommon.c:368
+msgid "Remove from playback queue"
+msgstr ""
+
+#: ../plugins/gtkui/plcommon.c:376
+msgid "Reload metadata"
+msgstr ""
+
+#: ../plugins/gtkui/plcommon.c:392
+msgid "Remove from disk"
+msgstr "Ukloni sa diska"
+
+#: ../plugins/gtkui/plcommon.c:616 ../plugins/gtkui/plcommon.c:741
+msgid "Add column"
+msgstr ""
+
+#: ../plugins/gtkui/plcommon.c:646 ../plugins/gtkui/plcommon.c:745
+msgid "Edit column"
+msgstr ""
+
+#: ../plugins/gtkui/plcommon.c:749
+msgid "Remove column"
+msgstr ""
+
+#: ../plugins/gtkui/plcommon.c:759
+msgid "Group by"
+msgstr "Grupiraj po"
+
+#: ../plugins/gtkui/plcommon.c:766
+msgid "None"
+msgstr "Ništa"
+
+#: ../plugins/gtkui/plcommon.c:770
+msgid "Artist/Date/Album"
+msgstr "Umjetnik/datum/album"
+
+#: ../plugins/gtkui/pluginconf.c:41
+msgid "Open file..."
+msgstr "Otvori datoteku"
+
+#: ../plugins/gtkui/pluginconf.c:139
+#, c-format
+msgid "Setup %s"
+msgstr "Postavi %s"
+
+#: ../plugins/gtkui/prefwin.c:98
+msgid "Default Audio Device"
+msgstr "Zadani audio uređaj"
+
+#: ../plugins/gtkui/prefwin.c:267
+msgid "Add"
+msgstr "Dodaj"
+
+#: ../plugins/gtkui/prefwin.c:277
+msgid "Global Hotkeys"
+msgstr ""
+
+#: ../plugins/gtkui/prefwin.c:332
+msgid "Slot"
+msgstr ""
+
+#: ../plugins/gtkui/prefwin.c:333
+msgid "Key combination"
+msgstr ""
+
+#. output plugin selection
+#: ../plugins/gtkui/prefwin.c:379 ../plugins/gtkui/prefwin.c:569
+#: ../plugins.c:833
+msgid "ALSA output plugin"
+msgstr "ALSA izlazni priključak"
+
+#: ../plugins/gtkui/progress.c:64
+msgid "Initializing..."
+msgstr ""
+
+#: ../plugins/gtkui/trkproperties.c:53
+msgid "You've modified data for this track."
+msgstr ""
+
+#: ../plugins/gtkui/trkproperties.c:55
+msgid "Really close the window?"
+msgstr "Stvarno zatvoriti prozor?"
+
+#: ../plugins/gtkui/trkproperties.c:178
+msgid "Tag Type(s)"
+msgstr ""
+
+#: ../plugins/gtkui/trkproperties.c:180
+msgid "Embedded Cuesheet"
+msgstr ""
+
+#: ../plugins/gtkui/trkproperties.c:180
+msgid "Yes"
+msgstr "Da"
+
+#: ../plugins/gtkui/trkproperties.c:180
+msgid "No"
+msgstr "Ne"
+
+#: ../plugins/gtkui/trkproperties.c:248 ../plugins/gtkui/trkproperties.c:260
+msgid "Key"
+msgstr ""
+
+#: ../plugins/gtkui/trkproperties.c:249 ../plugins/gtkui/trkproperties.c:261
+msgid "Value"
+msgstr ""
+
+#: ../plugins/notify/notify.c:138
+msgid "DeaDBeeF now playing"
+msgstr "DeaDBeeF sada svira"
+
+#: ../main.c:84
+#, c-format
+msgid "Usage: deadbeef [options] [file(s)]\n"
+msgstr ""
+
+#: ../main.c:85
+#, c-format
+msgid "Options:\n"
+msgstr "Opcije:\n"
+
+#: ../main.c:86
+#, c-format
+msgid " --help or -h Print help (this message) and exit\n"
+msgstr " --help or -h Ispisuje pomoć (ova poruka) i izlazi\n"
+
+#: ../main.c:87
+#, c-format
+msgid " --quit Quit player\n"
+msgstr " --quit Iskjluči svirač\n"
+
+#: ../main.c:88
+#, c-format
+msgid " --version Print version info and exit\n"
+msgstr " --version Ispis info verzije i izlaz\n"
+
+#: ../main.c:89
+#, c-format
+msgid " --play Start playback\n"
+msgstr " --play Početak reprodukcije\n"
+
+#: ../main.c:90
+#, c-format
+msgid " --stop Stop playback\n"
+msgstr " --stop Zaustavlja reprodukciju\n"
+
+#: ../main.c:91
+#, c-format
+msgid " --pause Pause playback\n"
+msgstr " --pause Zaustavlja reprodukciju\n"
+
+#: ../main.c:92
+#, c-format
+msgid " --next Next song in playlist\n"
+msgstr " --next Slijedaća pjesma na listi izvođenja\n"
+
+#: ../main.c:93
+#, c-format
+msgid " --prev Previous song in playlist\n"
+msgstr " --prev Prethodna pjesma na listi izvođenja\n"
+
+#: ../main.c:94
+#, c-format
+msgid " --random Random song in playlist\n"
+msgstr " --random nasumična pjesma na listi izvođenja\n"
+
+#: ../main.c:95
+#, c-format
+msgid " --queue Append file(s) to existing playlist\n"
+msgstr ""
+
+#: ../main.c:96
+#, c-format
+msgid " --nowplaying FMT Print formatted track name to stdout\n"
+msgstr ""
+
+#: ../main.c:97
+#, c-format
+msgid ""
+" FMT %%-syntax: [a]rtist, [t]itle, al[b]um,\n"
+" [l]ength, track[n]umber, [y]ear, [c]omment,\n"
+" copy[r]ight, [e]lapsed\n"
+msgstr ""
+
+#: ../main.c:100
+#, c-format
+msgid ""
+" e.g.: --nowplaying \"%%a - %%t\" should print \"artist "
+"- title\"\n"
+msgstr ""
+
+#: ../playlist.c:369 ../playlist.c:2212
+msgid "Default"
+msgstr "Zadano"
diff --git a/po/nl.po b/po/nl.po
new file mode 100644
index 00000000..3ee5e223
--- /dev/null
+++ b/po/nl.po
@@ -0,0 +1,1086 @@
+# Deadbeef Audio Player
+# Copyright (C) 2009-2001 Alexey Yakovenko <waker@users.sourceforge.net>
+# This file is distributed under the same license as the Deadbeef package.
+# depaz <depazzz@gmail.com>, 2010.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-05-29 04:08+0000\n"
+"PO-Revision-Date: 2010-05-21 18:34+0300\n"
+"Last-Translator: F.J. de Pablos <depazzz@gmail.com>\n"
+"Language-Team: Spanish\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: ../plugins/gtkui/callbacks.c:97
+msgid "Supported sound formats"
+msgstr "Ondersteunde geluidsformaten"
+
+#: ../plugins/gtkui/callbacks.c:108
+msgid "Other files (*)"
+msgstr "Andere bestanden (*)"
+
+#: ../plugins/gtkui/callbacks.c:117
+msgid "Open file(s)..."
+msgstr "Open bestand(en)..."
+
+#: ../plugins/gtkui/callbacks.c:150
+msgid "Add file(s) to playlist..."
+msgstr "Voeg bestand(en) toe aan de afspeellijst..."
+
+#: ../plugins/gtkui/callbacks.c:182
+msgid "Add folder(s) to playlist..."
+msgstr "Voeg map(pen) toe aan de afspeellijst..."
+
+#: ../plugins/gtkui/callbacks.c:640
+msgid "Failed while reading help file"
+msgstr "Error bij het lezen van het help bestand"
+
+#: ../plugins/gtkui/callbacks.c:650
+msgid "Failed to load help file"
+msgstr "Mislukt bij het lezen van het help bestand"
+
+#: ../plugins/gtkui/callbacks.c:664 ../plugins/gtkui/interface.c:1105
+#: ../plugins/gtkui/deadbeef.glade.h:56
+msgid "Help"
+msgstr "Help"
+
+#: ../plugins/gtkui/callbacks.c:674
+#, c-format
+msgid "About DeaDBeeF %s"
+msgstr "Over DeaDBeeF %s"
+
+#: ../plugins/gtkui/callbacks.c:685
+#, c-format
+msgid "DeaDBeeF %s ChangeLog"
+msgstr "DeaDBeeF %s ChangeLog"
+
+#: ../plugins/gtkui/ddbtabstrip.c:527
+msgid "Edit playlist"
+msgstr "Bewerk afspeellijst"
+
+#: ../plugins/gtkui/ddbtabstrip.c:604
+msgid "Rename Playlist"
+msgstr "Hernoem Afspeellijst"
+
+#: ../plugins/gtkui/ddbtabstrip.c:608
+msgid "Remove Playlist"
+msgstr "Verwijder Afspeellijst"
+
+#: ../plugins/gtkui/ddbtabstrip.c:612
+msgid "Add New Playlist"
+msgstr "Maak een nieuwe afspeellijst"
+
+#: ../plugins/gtkui/eq.c:113
+msgid "Save DeaDBeeF EQ Preset"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:120
+msgid "DeaDBeeF EQ preset files (*.ddbeq)"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:151
+msgid "Load DeaDBeeF EQ Preset..."
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:155
+msgid "DeaDBeeF EQ presets (*.ddbeq)"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:214
+msgid "Import Foobar2000 EQ Preset..."
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:218
+msgid "Foobar2000 EQ presets (*.feq)"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:292
+msgid "Enable"
+msgstr "Inschakelen"
+
+#: ../plugins/gtkui/eq.c:299
+msgid "Zero All"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:306
+msgid "Zero Preamp"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:313
+msgid "Zero Bands"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:320
+msgid "Save Preset"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:327
+msgid "Load Preset"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:334
+msgid "Import Foobar2000 Preset"
+msgstr ""
+
+#: ../plugins/gtkui/gtkui.c:128
+#, c-format
+msgid "1 day %d:%02d:%02d"
+msgstr "1 dag %d:%02d:%02d"
+
+#: ../plugins/gtkui/gtkui.c:131
+#, c-format
+msgid "%d days %d:%02d:%02d"
+msgstr "%d dagen %d:%02d:%02d"
+
+#: ../plugins/gtkui/gtkui.c:140
+#, c-format
+msgid "Stopped | %d tracks | %s total playtime"
+msgstr "Gestopt | %d titels | %s totale speeltijd"
+
+#: ../plugins/gtkui/gtkui.c:150
+msgid "Mono"
+msgstr "Mono"
+
+#: ../plugins/gtkui/gtkui.c:150
+msgid "Stereo"
+msgstr "Stereo"
+
+#: ../plugins/gtkui/gtkui.c:170
+#, c-format
+msgid "| %4d kbps "
+msgstr "| %4d kbps "
+
+#: ../plugins/gtkui/gtkui.c:176
+msgid "Paused | "
+msgstr "Gepauzeerd | "
+
+#: ../plugins/gtkui/gtkui.c:177
+#, c-format
+msgid "%s%s %s| %dHz | %d bit | %s | %d:%02d / %s | %d tracks | %s total playtime"
+msgstr "%s%s %s| %dHz | %d bit | %s | %d:%02d / %s | %d titels | %s totale speeltijd"
+
+#: ../plugins/gtkui/gtkui.c:533
+msgid "Save Playlist As"
+msgstr "Afspeellijst opslaan als"
+
+#: ../plugins/gtkui/gtkui.c:542 ../plugins/gtkui/gtkui.c:603
+msgid "DeaDBeeF playlist files (*.dbpl)"
+msgstr "DeaDBeeF afspeellijst bestand (*.dbpl)"
+
+#: ../plugins/gtkui/gtkui.c:596
+msgid "Load Playlist"
+msgstr "Afspeellijst laden"
+
+#: ../plugins/gtkui/gtkui.c:741
+msgid "New Playlist"
+msgstr "Nieuwe afspeellijst"
+
+#: ../plugins/gtkui/gtkui.c:744
+#, c-format
+msgid "New Playlist (%d)"
+msgstr "Nieuwe afspeellijst (%d)"
+
+#: ../plugins/gtkui/interface.c:140 ../plugins/gtkui/deadbeef.glade.h:138
+msgid "_File"
+msgstr "_Bestand"
+
+#: ../plugins/gtkui/interface.c:147 ../plugins/gtkui/deadbeef.glade.h:142
+msgid "_Open file(s)"
+msgstr "_Open bestand(en)"
+
+#: ../plugins/gtkui/interface.c:163 ../plugins/gtkui/deadbeef.glade.h:7
+msgid "Add file(s)"
+msgstr "Voeg bestand(en) toe"
+
+#: ../plugins/gtkui/interface.c:171 ../plugins/gtkui/deadbeef.glade.h:8
+msgid "Add folder(s)"
+msgstr "Voeg map(pen) toe"
+
+#: ../plugins/gtkui/interface.c:179 ../plugins/gtkui/deadbeef.glade.h:6
+msgid "Add Audio CD"
+msgstr "Voeg Audio CD toe"
+
+#: ../plugins/gtkui/interface.c:187 ../plugins/gtkui/interface.c:2870
+#: ../plugins/gtkui/deadbeef.glade.h:9
+msgid "Add location"
+msgstr "Voeg locatie toe"
+
+#: ../plugins/gtkui/interface.c:196 ../plugins/gtkui/deadbeef.glade.h:72
+msgid "New playlist"
+msgstr "Nieuwe afspeellijst"
+
+#: ../plugins/gtkui/interface.c:203 ../plugins/gtkui/deadbeef.glade.h:64
+msgid "Load playlist"
+msgstr "Laad afspeellijst"
+
+#: ../plugins/gtkui/interface.c:207 ../plugins/gtkui/deadbeef.glade.h:99
+msgid "Save playlist"
+msgstr "Afspeellijst opslaan"
+
+#: ../plugins/gtkui/interface.c:211 ../plugins/gtkui/deadbeef.glade.h:100
+msgid "Save playlist as"
+msgstr "Afspeellijst opslaan als.."
+
+#: ../plugins/gtkui/interface.c:220 ../plugins/gtkui/deadbeef.glade.h:144
+msgid "_Quit"
+msgstr "_Afsluiten"
+
+#: ../plugins/gtkui/interface.c:231 ../plugins/gtkui/deadbeef.glade.h:137
+msgid "_Edit"
+msgstr "_Bewerken"
+
+#: ../plugins/gtkui/interface.c:238 ../plugins/gtkui/deadbeef.glade.h:135
+msgid "_Clear"
+msgstr "_Wissen"
+
+#: ../plugins/gtkui/interface.c:246 ../plugins/gtkui/deadbeef.glade.h:104
+msgid "Select all"
+msgstr "Selecteer alles"
+
+#: ../plugins/gtkui/interface.c:253 ../plugins/gtkui/deadbeef.glade.h:24
+msgid "Deselect all"
+msgstr "Deselecteer alles"
+
+#: ../plugins/gtkui/interface.c:260 ../plugins/gtkui/deadbeef.glade.h:59
+msgid "Invert selection"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:264 ../plugins/gtkui/deadbeef.glade.h:107
+msgid "Selection"
+msgstr "Selectie"
+
+#: ../plugins/gtkui/interface.c:271 ../plugins/gtkui/plcommon.c:387
+#: ../plugins/gtkui/prefwin.c:272 ../plugins/gtkui/deadbeef.glade.h:95
+msgid "Remove"
+msgstr "Verwijderen"
+
+#: ../plugins/gtkui/interface.c:279 ../plugins/gtkui/deadbeef.glade.h:19
+msgid "Crop"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:283 ../plugins/gtkui/deadbeef.glade.h:139
+msgid "_Find"
+msgstr "_Zoeken"
+
+#: ../plugins/gtkui/interface.c:295 ../plugins/gtkui/interface.c:1706
+#: ../plugins/gtkui/deadbeef.glade.h:85
+msgid "Preferences"
+msgstr "Voorkeuren"
+
+#: ../plugins/gtkui/interface.c:299 ../plugins/gtkui/deadbeef.glade.h:145
+msgid "_View"
+msgstr "_Beeld"
+
+#: ../plugins/gtkui/interface.c:306 ../plugins/gtkui/deadbeef.glade.h:111
+msgid "Status bar"
+msgstr "Statusbalk"
+
+#: ../plugins/gtkui/interface.c:310 ../plugins/gtkui/deadbeef.glade.h:17
+msgid "Column headers"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:314 ../plugins/gtkui/deadbeef.glade.h:118
+msgid "Tabs"
+msgstr "Tabbladen"
+
+#: ../plugins/gtkui/interface.c:318 ../plugins/gtkui/deadbeef.glade.h:32
+msgid "Equalizer"
+msgstr "Equalizer"
+
+#: ../plugins/gtkui/interface.c:322 ../plugins/gtkui/deadbeef.glade.h:143
+msgid "_Playback"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:329 ../plugins/gtkui/deadbeef.glade.h:75
+msgid "Order"
+msgstr "Ordenen"
+
+#: ../plugins/gtkui/interface.c:336 ../plugins/gtkui/deadbeef.glade.h:63
+msgid "Linear"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:342 ../plugins/gtkui/deadbeef.glade.h:108
+msgid "Shuffle"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:348 ../plugins/gtkui/deadbeef.glade.h:94
+msgid "Random"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:354 ../plugins/gtkui/deadbeef.glade.h:67
+msgid "Looping"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:361 ../plugins/gtkui/deadbeef.glade.h:65
+msgid "Loop All"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:367 ../plugins/gtkui/deadbeef.glade.h:66
+msgid "Loop Single Song"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:373 ../plugins/gtkui/deadbeef.glade.h:28
+msgid "Don't Loop"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:379 ../plugins/gtkui/deadbeef.glade.h:101
+msgid "Scroll follows playback"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:384 ../plugins/gtkui/deadbeef.glade.h:21
+msgid "Cursor follows playback"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:388 ../plugins/gtkui/deadbeef.glade.h:113
+msgid "Stop after current"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:395 ../plugins/gtkui/interface.c:402
+#: ../plugins/gtkui/deadbeef.glade.h:140
+msgid "_Help"
+msgstr "_Help"
+
+#: ../plugins/gtkui/interface.c:410 ../plugins/gtkui/deadbeef.glade.h:134
+msgid "_ChangeLog"
+msgstr "_ChangeLog"
+
+#: ../plugins/gtkui/interface.c:432 ../plugins/gtkui/deadbeef.glade.h:131
+msgid "_About"
+msgstr "_Over"
+
+#: ../plugins/gtkui/interface.c:816 ../plugins/gtkui/deadbeef.glade.h:102
+msgid "Search"
+msgstr "Zoeken"
+
+#: ../plugins/gtkui/interface.c:891 ../plugins/gtkui/deadbeef.glade.h:112
+msgid "Stop"
+msgstr "Stoppen"
+
+#: ../plugins/gtkui/interface.c:899 ../plugins/gtkui/deadbeef.glade.h:81
+msgid "Play"
+msgstr "Afspelen"
+
+#: ../plugins/gtkui/interface.c:907 ../plugins/gtkui/deadbeef.glade.h:80
+msgid "Pause"
+msgstr "Pauzeren"
+
+#: ../plugins/gtkui/interface.c:915 ../plugins/gtkui/deadbeef.glade.h:86
+msgid "Previous"
+msgstr "Vorige"
+
+#: ../plugins/gtkui/interface.c:923 ../plugins/gtkui/deadbeef.glade.h:73
+msgid "Next"
+msgstr "Volgende"
+
+#: ../plugins/gtkui/interface.c:931 ../plugins/gtkui/deadbeef.glade.h:82
+msgid "Play Random"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:940 ../plugins/gtkui/deadbeef.glade.h:5
+msgid "About"
+msgstr "Over"
+
+#: ../plugins/gtkui/interface.c:953 ../plugins/gtkui/deadbeef.glade.h:93
+msgid "Quit"
+msgstr "Afsluiten"
+
+#: ../plugins/gtkui/interface.c:1025 ../plugins/gtkui/deadbeef.glade.h:10
+msgid "Adding files..."
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1069 ../plugins/gtkui/deadbeef.glade.h:130
+msgid "_Abort"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1170 ../plugins/gtkui/deadbeef.glade.h:122
+msgid "Track Properties"
+msgstr "Titel eigenschappen"
+
+#: ../plugins/gtkui/interface.c:1194 ../plugins/gtkui/deadbeef.glade.h:3
+msgid ""
+"<b>WARNING</b>: tag writing feature is still in development.\n"
+"<b>Make backup copies</b> before using."
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1221 ../plugins/gtkui/deadbeef.glade.h:132
+msgid "_Apply"
+msgstr "_Toepassen"
+
+#: ../plugins/gtkui/interface.c:1242 ../plugins/gtkui/interface.c:1288
+#: ../plugins/gtkui/interface.c:2436 ../plugins/gtkui/deadbeef.glade.h:136
+msgid "_Close"
+msgstr "_Sluiten"
+
+#: ../plugins/gtkui/interface.c:1246 ../plugins/gtkui/deadbeef.glade.h:68
+msgid "Metadata"
+msgstr "Metadata"
+
+#: ../plugins/gtkui/interface.c:1292 ../plugins/gtkui/plcommon.c:402
+#: ../plugins/gtkui/deadbeef.glade.h:87
+msgid "Properties"
+msgstr "Eigenschappen"
+
+#: ../plugins/gtkui/interface.c:1378 ../plugins/gtkui/deadbeef.glade.h:146
+msgid "editcolumndlg"
+msgstr "editcolumndlg"
+
+#: ../plugins/gtkui/interface.c:1393 ../plugins/gtkui/interface.c:2770
+#: ../plugins/gtkui/deadbeef.glade.h:121
+msgid "Title:"
+msgstr "Titel:"
+
+#: ../plugins/gtkui/interface.c:1401 ../plugins/gtkui/deadbeef.glade.h:31
+msgid "Enter new column title here"
+msgstr "Voer een nieuwe column titel in"
+
+#: ../plugins/gtkui/interface.c:1409 ../plugins/gtkui/deadbeef.glade.h:123
+msgid "Type:"
+msgstr "Type:"
+
+#: ../plugins/gtkui/interface.c:1417
+msgid "File number"
+msgstr "Bestand´s nummer"
+
+#. create default set of columns
+#: ../plugins/gtkui/interface.c:1418 ../plugins/gtkui/mainplaylist.c:297
+msgid "Playing"
+msgstr "Aan het afspelen"
+
+#: ../plugins/gtkui/interface.c:1419
+msgid "Album Art"
+msgstr "Albumhoes"
+
+#: ../plugins/gtkui/interface.c:1420
+msgid "Artist - Album"
+msgstr "Artiest - Album"
+
+#: ../plugins/gtkui/interface.c:1421 ../plugins/gtkui/plcommon.c:774
+msgid "Artist"
+msgstr "Artiest"
+
+#: ../plugins/gtkui/interface.c:1422 ../plugins/gtkui/interface.c:1795
+msgid "Album"
+msgstr "Album"
+
+#: ../plugins/gtkui/interface.c:1423 ../plugins/gtkui/prefwin.c:488
+msgid "Title"
+msgstr "Titel"
+
+#: ../plugins/gtkui/interface.c:1424
+msgid "Length"
+msgstr "Lengte"
+
+#: ../plugins/gtkui/interface.c:1425 ../plugins/gtkui/interface.c:1794
+msgid "Track"
+msgstr "Titel"
+
+#: ../plugins/gtkui/interface.c:1426
+msgid "Band / Album Artist"
+msgstr "Band / Album Artiest"
+
+#: ../plugins/gtkui/interface.c:1427 ../plugins/gtkui/plcommon.c:778
+msgid "Custom"
+msgstr "Aangepast"
+
+#: ../plugins/gtkui/interface.c:1433 ../plugins/gtkui/interface.c:2997
+#: ../plugins/gtkui/deadbeef.glade.h:53
+msgid "Format:"
+msgstr "Formaat:"
+
+#: ../plugins/gtkui/interface.c:1448 ../plugins/gtkui/deadbeef.glade.h:11
+msgid "Alignment:"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1456
+msgid "Left"
+msgstr "Links"
+
+#: ../plugins/gtkui/interface.c:1457
+msgid "Right"
+msgstr "Rechts"
+
+#: ../plugins/gtkui/interface.c:1459 ../plugins/gtkui/interface.c:3007
+#: ../plugins/gtkui/deadbeef.glade.h:47
+#, no-c-format
+msgid ""
+"Format conversions (start with %):\n"
+" [a]rtist, [t]itle, al[b]um, [B]and, [C]omposer\n"
+" track[n]umber, [N]totaltracks,\n"
+" [l]ength, [y]ear, [g]enre, [c]omment,\n"
+" copy[r]ight, [f]ilename, [T]ags\n"
+"Example: %a - %t [%l]"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1488 ../plugins/gtkui/interface.c:2801
+#: ../plugins/gtkui/interface.c:2913 ../plugins/gtkui/interface.c:3036
+#: ../plugins/gtkui/deadbeef.glade.h:133
+msgid "_Cancel"
+msgstr "_Annuleer"
+
+#: ../plugins/gtkui/interface.c:1509 ../plugins/gtkui/interface.c:2822
+#: ../plugins/gtkui/interface.c:2934 ../plugins/gtkui/interface.c:3057
+#: ../plugins/gtkui/deadbeef.glade.h:141
+msgid "_OK"
+msgstr "_Accepteer"
+
+#: ../plugins/gtkui/interface.c:1726 ../plugins/gtkui/deadbeef.glade.h:77
+msgid "Output plugin:"
+msgstr "Output plugin: "
+
+#: ../plugins/gtkui/interface.c:1739 ../plugins/gtkui/deadbeef.glade.h:76
+msgid "Output device:"
+msgstr "Output apparaat:"
+
+#: ../plugins/gtkui/interface.c:1748 ../plugins/gtkui/deadbeef.glade.h:109
+msgid "Sound"
+msgstr "Geluid"
+
+#: ../plugins/gtkui/interface.c:1757 ../plugins/gtkui/deadbeef.glade.h:12
+msgid "Allow dynamic samplerate switching"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1765 ../plugins/gtkui/deadbeef.glade.h:98
+msgid "Samplerate conversion quality:"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1784 ../plugins/gtkui/deadbeef.glade.h:96
+msgid "Replaygain mode:"
+msgstr "opnieuwafspelen mode:"
+
+#: ../plugins/gtkui/interface.c:1793
+msgid "Disable"
+msgstr "Uitschakelen"
+
+#: ../plugins/gtkui/interface.c:1797 ../plugins/gtkui/deadbeef.glade.h:97
+msgid "Replaygain peak scale"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1801 ../plugins/gtkui/deadbeef.glade.h:110
+msgid "Sound (adv.)"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1810 ../plugins/gtkui/deadbeef.glade.h:16
+msgid "Close minimizes to tray"
+msgstr "Sluiten minimaliseert naar tray"
+
+#: ../plugins/gtkui/interface.c:1814 ../plugins/gtkui/deadbeef.glade.h:70
+msgid "Middle mouse button closes playlist"
+msgstr "Middelste muis knop sloot afspeellijst"
+
+#: ../plugins/gtkui/interface.c:1827 ../plugins/gtkui/interface.c:1871
+#: ../plugins/gtkui/deadbeef.glade.h:78
+msgid "Override"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1836 ../plugins/gtkui/deadbeef.glade.h:45
+msgid "Foreground"
+msgstr "Voorgrond"
+
+#: ../plugins/gtkui/interface.c:1843 ../plugins/gtkui/deadbeef.glade.h:14
+msgid "Background"
+msgstr "Achtergrond"
+
+#: ../plugins/gtkui/interface.c:1862 ../plugins/gtkui/deadbeef.glade.h:103
+msgid "Seekbar/Volumebar colors"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1880 ../plugins/gtkui/deadbeef.glade.h:69
+msgid "Middle"
+msgstr "Midden"
+
+#: ../plugins/gtkui/interface.c:1887 ../plugins/gtkui/deadbeef.glade.h:62
+msgid "Light"
+msgstr "Licht"
+
+#: ../plugins/gtkui/interface.c:1894 ../plugins/gtkui/deadbeef.glade.h:22
+msgid "Dark"
+msgstr "Donker"
+
+#: ../plugins/gtkui/interface.c:1925 ../plugins/gtkui/deadbeef.glade.h:15
+msgid "Base"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1932 ../plugins/gtkui/deadbeef.glade.h:117
+msgid "Tab strip colors"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1941 ../plugins/gtkui/deadbeef.glade.h:79
+msgid "Override (looses GTK treeview theming, but speeds up rendering)"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1950 ../plugins/gtkui/deadbeef.glade.h:33
+msgid "Even row"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1957 ../plugins/gtkui/deadbeef.glade.h:74
+msgid "Odd row"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1976 ../plugins/gtkui/deadbeef.glade.h:120
+msgid "Text"
+msgstr "Text"
+
+#: ../plugins/gtkui/interface.c:1983 ../plugins/gtkui/deadbeef.glade.h:105
+msgid "Selected row"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2002 ../plugins/gtkui/deadbeef.glade.h:106
+msgid "Selected text"
+msgstr "Geselecteerde text"
+
+#: ../plugins/gtkui/interface.c:2015 ../plugins/gtkui/deadbeef.glade.h:20
+msgid "Cursor"
+msgstr "Muisaanwijzer"
+
+#: ../plugins/gtkui/interface.c:2028 ../plugins/gtkui/deadbeef.glade.h:83
+msgid "Playlist colors"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2032 ../plugins/gtkui/deadbeef.glade.h:54
+msgid "GUI"
+msgstr "Interface"
+
+#: ../plugins/gtkui/interface.c:2041 ../plugins/gtkui/deadbeef.glade.h:30
+msgid "Enable Proxy Server"
+msgstr "Schakel Proxy Server in"
+
+#: ../plugins/gtkui/interface.c:2049 ../plugins/gtkui/deadbeef.glade.h:89
+msgid "Proxy Server Address:"
+msgstr "Proxy Server Adres:"
+
+#: ../plugins/gtkui/interface.c:2063 ../plugins/gtkui/deadbeef.glade.h:90
+msgid "Proxy Server Port:"
+msgstr "Proxy Server Poort:"
+
+#: ../plugins/gtkui/interface.c:2077 ../plugins/gtkui/deadbeef.glade.h:91
+msgid "Proxy Type:"
+msgstr "Proxy type"
+
+#: ../plugins/gtkui/interface.c:2096 ../plugins/gtkui/deadbeef.glade.h:92
+msgid "Proxy Username:"
+msgstr "Proxy Gebruikersnaam:"
+
+#: ../plugins/gtkui/interface.c:2109 ../plugins/gtkui/deadbeef.glade.h:88
+msgid "Proxy Password:"
+msgstr "Proxy wachtwoord:"
+
+#: ../plugins/gtkui/interface.c:2119 ../plugins/gtkui/deadbeef.glade.h:71
+msgid "Network"
+msgstr "Netwerk"
+
+#: ../plugins/gtkui/interface.c:2147 ../plugins/gtkui/deadbeef.glade.h:128
+msgid "Write ID3v2"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2151 ../plugins/gtkui/interface.c:2278
+#: ../plugins/gtkui/deadbeef.glade.h:127
+msgid "Write ID3v1"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2155 ../plugins/gtkui/interface.c:2234
+#: ../plugins/gtkui/interface.c:2274 ../plugins/gtkui/deadbeef.glade.h:126
+msgid "Write APEv2"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2163 ../plugins/gtkui/interface.c:2242
+#: ../plugins/gtkui/deadbeef.glade.h:116
+msgid "Strip ID3v2"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2167 ../plugins/gtkui/interface.c:2290
+#: ../plugins/gtkui/deadbeef.glade.h:115
+msgid "Strip ID3v1"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2171 ../plugins/gtkui/interface.c:2246
+#: ../plugins/gtkui/interface.c:2286 ../plugins/gtkui/deadbeef.glade.h:114
+msgid "Strip APEv2"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2179 ../plugins/gtkui/deadbeef.glade.h:58
+msgid "ID3v2 version"
+msgstr "ID3v2 versie"
+
+#: ../plugins/gtkui/interface.c:2186
+msgid "2.3 (Recommended)"
+msgstr "2.3 (Aangeraden)"
+
+#: ../plugins/gtkui/interface.c:2187
+msgid "2.4"
+msgstr "2.4"
+
+#: ../plugins/gtkui/interface.c:2193 ../plugins/gtkui/deadbeef.glade.h:57
+msgid "ID3v1 character encoding (default is iso8859-1)"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2230 ../plugins/gtkui/deadbeef.glade.h:129
+msgid "Write ID3v2.4"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2299 ../plugins/gtkui/deadbeef.glade.h:119
+msgid "Tag writer"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2330 ../plugins/gtkui/deadbeef.glade.h:23
+msgid "Description:"
+msgstr "Beschrijfing:"
+
+#: ../plugins/gtkui/interface.c:2345 ../plugins/gtkui/deadbeef.glade.h:13
+msgid "Author(s):"
+msgstr "Auteur:"
+
+#: ../plugins/gtkui/interface.c:2360 ../plugins/gtkui/deadbeef.glade.h:29
+msgid "Email:"
+msgstr "Email:"
+
+#: ../plugins/gtkui/interface.c:2375 ../plugins/gtkui/deadbeef.glade.h:125
+msgid "Website:"
+msgstr "Website:"
+
+#: ../plugins/gtkui/interface.c:2406 ../plugins/gtkui/deadbeef.glade.h:18
+msgid "Configure"
+msgstr "Configureer"
+
+#: ../plugins/gtkui/interface.c:2410 ../plugins/gtkui/deadbeef.glade.h:84
+msgid "Plugins"
+msgstr "Plugins"
+
+#: ../plugins/gtkui/interface.c:2754 ../plugins/gtkui/deadbeef.glade.h:147
+msgid "editplaylistdlg"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2881 ../plugins/gtkui/deadbeef.glade.h:124
+msgid "URL:"
+msgstr "URL:"
+
+#: ../plugins/gtkui/interface.c:2982 ../plugins/gtkui/deadbeef.glade.h:55
+msgid "Group By"
+msgstr ""
+
+#: ../plugins/gtkui/mainplaylist.c:298 ../plugins/gtkui/search.c:433
+msgid "Artist / Album"
+msgstr "Artiest / Album"
+
+#: ../plugins/gtkui/mainplaylist.c:299 ../plugins/gtkui/search.c:434
+msgid "Track No"
+msgstr "Title nr."
+
+#: ../plugins/gtkui/mainplaylist.c:300 ../plugins/gtkui/search.c:435
+msgid "Title / Track Artist"
+msgstr "Titel / Titel Artiest"
+
+#: ../plugins/gtkui/mainplaylist.c:301 ../plugins/gtkui/search.c:436
+#: ../plugins/gtkui/trkproperties.c:175
+msgid "Duration"
+msgstr "Speeltijd"
+
+#: ../plugins/gtkui/plcommon.c:316
+msgid "Delete files from disk"
+msgstr "Verwijder bestanden van schijf"
+
+#: ../plugins/gtkui/plcommon.c:317
+msgid ""
+"Files will be lost. Proceed?\n"
+"(This dialog can be turned off in GTKUI plugin settings)"
+msgstr ""
+"Bestanden zullen verloren worden. Doorgaan?\n"
+"(Dit venster kunt u uitschakelen in de GTKUI plugin instellingen)"
+
+#: ../plugins/gtkui/plcommon.c:318 ../plugins/gtkui/trkproperties.c:56
+msgid "Warning"
+msgstr "Waarschuwing"
+
+#: ../plugins/gtkui/plcommon.c:363
+msgid "Add to playback queue"
+msgstr ""
+
+#: ../plugins/gtkui/plcommon.c:368
+msgid "Remove from playback queue"
+msgstr ""
+
+#: ../plugins/gtkui/plcommon.c:376
+msgid "Reload metadata"
+msgstr "Herlaad metadata"
+
+#: ../plugins/gtkui/plcommon.c:392
+msgid "Remove from disk"
+msgstr "Verwijder van schijf"
+
+#: ../plugins/gtkui/plcommon.c:616 ../plugins/gtkui/plcommon.c:741
+msgid "Add column"
+msgstr "Kolom toevoegen"
+
+#: ../plugins/gtkui/plcommon.c:646 ../plugins/gtkui/plcommon.c:745
+msgid "Edit column"
+msgstr "Kolom bewerken"
+
+#: ../plugins/gtkui/plcommon.c:749
+msgid "Remove column"
+msgstr "Kolom verwijderen"
+
+#: ../plugins/gtkui/plcommon.c:759
+msgid "Group by"
+msgstr ""
+
+#: ../plugins/gtkui/plcommon.c:766
+msgid "None"
+msgstr "Geen"
+
+#: ../plugins/gtkui/plcommon.c:770
+msgid "Artist/Date/Album"
+msgstr "Artiest/Datum/Album"
+
+#: ../plugins/gtkui/pluginconf.c:41
+msgid "Open file..."
+msgstr "Open bestand.."
+
+#: ../plugins/gtkui/pluginconf.c:139
+#, c-format
+msgid "Setup %s"
+msgstr "Configuratie %s"
+
+#: ../plugins/gtkui/prefwin.c:98
+msgid "Default Audio Device"
+msgstr "Standaard Geluids Apparaat"
+
+#: ../plugins/gtkui/prefwin.c:267
+msgid "Add"
+msgstr "Toevoegen"
+
+#: ../plugins/gtkui/prefwin.c:277
+msgid "Global Hotkeys"
+msgstr ""
+
+#: ../plugins/gtkui/prefwin.c:332
+msgid "Slot"
+msgstr ""
+
+#: ../plugins/gtkui/prefwin.c:333
+msgid "Key combination"
+msgstr ""
+
+#. output plugin selection
+#: ../plugins/gtkui/prefwin.c:379 ../plugins/gtkui/prefwin.c:569
+#: ../plugins.c:833
+msgid "ALSA output plugin"
+msgstr "ALSA output plugin"
+
+#: ../plugins/gtkui/progress.c:64
+msgid "Initializing..."
+msgstr "Initialiseren..."
+
+#: ../plugins/gtkui/trkproperties.c:53
+msgid "You've modified data for this track."
+msgstr "U heeft data aangepast voor deze track."
+
+#: ../plugins/gtkui/trkproperties.c:55
+msgid "Really close the window?"
+msgstr "Weet u zeker dat u dit venster wilt sluiten?"
+
+#: ../plugins/gtkui/trkproperties.c:178
+msgid "Tag Type(s)"
+msgstr ""
+
+#: ../plugins/gtkui/trkproperties.c:180
+msgid "Embedded Cuesheet"
+msgstr ""
+
+#: ../plugins/gtkui/trkproperties.c:180
+msgid "Yes"
+msgstr "Ja"
+
+#: ../plugins/gtkui/trkproperties.c:180
+msgid "No"
+msgstr "Nee"
+
+#: ../plugins/gtkui/trkproperties.c:248 ../plugins/gtkui/trkproperties.c:260
+msgid "Key"
+msgstr "Toets"
+
+#: ../plugins/gtkui/trkproperties.c:249 ../plugins/gtkui/trkproperties.c:261
+msgid "Value"
+msgstr "Waarde"
+
+#: ../plugins/notify/notify.c:138
+msgid "DeaDBeeF now playing"
+msgstr "DeaDBeeF speelt nu af"
+
+#: ../main.c:84
+#, c-format
+msgid "Usage: deadbeef [options] [file(s)]\n"
+msgstr ""
+
+#: ../main.c:85
+#, c-format
+msgid "Options:\n"
+msgstr "Opties:\n"
+
+#: ../main.c:86
+#, c-format
+msgid " --help or -h Print help (this message) and exit\n"
+msgstr ""
+
+#: ../main.c:87
+#, c-format
+msgid " --quit Quit player\n"
+msgstr ""
+
+#: ../main.c:88
+#, c-format
+msgid " --version Print version info and exit\n"
+msgstr ""
+
+#: ../main.c:89
+#, c-format
+msgid " --play Start playback\n"
+msgstr ""
+
+#: ../main.c:90
+#, c-format
+msgid " --stop Stop playback\n"
+msgstr ""
+
+#: ../main.c:91
+#, c-format
+msgid " --pause Pause playback\n"
+msgstr ""
+
+#: ../main.c:92
+#, c-format
+msgid " --next Next song in playlist\n"
+msgstr ""
+
+#: ../main.c:93
+#, c-format
+msgid " --prev Previous song in playlist\n"
+msgstr ""
+
+#: ../main.c:94
+#, c-format
+msgid " --random Random song in playlist\n"
+msgstr ""
+
+#: ../main.c:95
+#, c-format
+msgid " --queue Append file(s) to existing playlist\n"
+msgstr ""
+
+#: ../main.c:96
+#, c-format
+msgid " --nowplaying FMT Print formatted track name to stdout\n"
+msgstr ""
+
+#: ../main.c:97
+#, c-format
+msgid ""
+" FMT %%-syntax: [a]rtist, [t]itle, al[b]um,\n"
+" [l]ength, track[n]umber, [y]ear, [c]omment,\n"
+" copy[r]ight, [e]lapsed\n"
+msgstr ""
+
+#: ../main.c:100
+#, c-format
+msgid " e.g.: --nowplaying \"%%a - %%t\" should print \"artist - title\"\n"
+msgstr ""
+
+#: ../playlist.c:362 ../playlist.c:2227
+msgid "Default"
+msgstr "Standaard"
+
+#: ../plugins/gtkui/deadbeef.glade.h:1
+#, fuzzy
+msgid ""
+"2.3 (Recommended)\n"
+"2.4"
+msgstr "2.3 (Aangeraden)"
+
+#: ../plugins/gtkui/deadbeef.glade.h:25
+msgid ""
+"Disable\n"
+"Track\n"
+"Album"
+msgstr ""
+
+#: ../plugins/gtkui/deadbeef.glade.h:34
+msgid ""
+"File number\n"
+"Playing\n"
+"Album Art\n"
+"Artist - Album\n"
+"Artist\n"
+"Album\n"
+"Title\n"
+"Length\n"
+"Track\n"
+"Band / Album Artist\n"
+"Custom"
+msgstr ""
+
+#: ../plugins/gtkui/deadbeef.glade.h:60
+#, fuzzy
+msgid ""
+"Left\n"
+"Right"
+msgstr "Rechts"
+
+#: ../plugins/gtkui/support.c:90 ../plugins/gtkui/support.c:114
+#, c-format
+msgid "Couldn't find pixmap file: %s"
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:129 ../plugins/vorbis/vcedit.c:155
+msgid "Couldn't get enough memory for input buffering."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:179 ../plugins/vorbis/vcedit.c:550
+msgid "Error reading first page of Ogg bitstream."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:185 ../plugins/vorbis/vcedit.c:557
+msgid "Error reading initial header packet."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:237
+msgid "Couldn't get enough memory to register new stream serial number."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:505
+msgid "Input truncated or empty."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:507
+msgid "Input is not an Ogg bitstream."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:565
+msgid "Ogg bitstream does not contain Vorbis data."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:578
+msgid "EOF before recognised stream."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:594
+msgid "Ogg bitstream does not contain a supported data-type."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:638
+msgid "Corrupt secondary header."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:659
+msgid "EOF before end of Vorbis headers."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:834
+msgid "Corrupt or missing data, continuing..."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:874
+msgid "Error writing stream to output. Output stream may be corrupted or truncated."
+msgstr ""
diff --git a/po/ru.po b/po/ru.po
new file mode 100644
index 00000000..3d917c28
--- /dev/null
+++ b/po/ru.po
@@ -0,0 +1,1124 @@
+# Deadbeef Audio Player
+# Copyright (C) 2009-2001 Alexey Yakovenko <waker@users.sourceforge.net>
+# This file is distributed under the same license as the Deadbeef package.
+# Dmitriy Simbiriatin <slpiv@mail.ru>, 2010.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: 0.4.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-05-27 16:47+0200\n"
+"PO-Revision-Date: 2010-05-25 18:12+0200\n"
+"Last-Translator: Max <mpui@tut.by>\n"
+"Language-Team: ru <slpiv@mail.ru>\n"
+"Language: ru\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: ru\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%"
+"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+"X-Generator: Pootle 2.0.1\n"
+
+#: ../plugins/gtkui/callbacks.c:97
+msgid "Supported sound formats"
+msgstr "Поддерживаемые форматы"
+
+#: ../plugins/gtkui/callbacks.c:108
+msgid "Other files (*)"
+msgstr "Другие файлы (*)"
+
+#: ../plugins/gtkui/callbacks.c:117
+msgid "Open file(s)..."
+msgstr "Открыть файл(ы)..."
+
+#: ../plugins/gtkui/callbacks.c:150
+msgid "Add file(s) to playlist..."
+msgstr "Добавить файл(ы) в плейлист..."
+
+#: ../plugins/gtkui/callbacks.c:182
+msgid "Add folder(s) to playlist..."
+msgstr "Добавить каталог(и) в плейлист..."
+
+#: ../plugins/gtkui/callbacks.c:640
+msgid "Failed while reading help file"
+msgstr "Не удалось прочитать файл справки"
+
+#: ../plugins/gtkui/callbacks.c:650
+msgid "Failed to load help file"
+msgstr "Не удалось загрузить файл справки"
+
+#: ../plugins/gtkui/callbacks.c:664 ../plugins/gtkui/interface.c:1105
+#: ../plugins/gtkui/deadbeef.glade.h:56
+msgid "Help"
+msgstr "Справка"
+
+#: ../plugins/gtkui/callbacks.c:674
+#, c-format
+msgid "About DeaDBeeF %s"
+msgstr "О программе DeaDBeeF %s"
+
+#: ../plugins/gtkui/callbacks.c:685
+#, c-format
+msgid "DeaDBeeF %s ChangeLog"
+msgstr "Изменения в DeaDBeeF %s"
+
+#: ../plugins/gtkui/ddbtabstrip.c:527
+msgid "Edit playlist"
+msgstr "Редактировать плейлист"
+
+#: ../plugins/gtkui/ddbtabstrip.c:604
+msgid "Rename Playlist"
+msgstr "Переименовать плейлист"
+
+#: ../plugins/gtkui/ddbtabstrip.c:608
+msgid "Remove Playlist"
+msgstr "Удалить плейлист"
+
+#: ../plugins/gtkui/ddbtabstrip.c:612
+msgid "Add New Playlist"
+msgstr "Добавить новый плейлист"
+
+#: ../plugins/gtkui/eq.c:113
+msgid "Save DeaDBeeF EQ Preset"
+msgstr "Сохранить предустановку эквалайзера DeaDBeeF"
+
+#: ../plugins/gtkui/eq.c:120
+msgid "DeaDBeeF EQ preset files (*.ddbeq)"
+msgstr "Файлы предустановок DeaDBeeF (*.ddbeq)"
+
+#: ../plugins/gtkui/eq.c:151
+msgid "Load DeaDBeeF EQ Preset..."
+msgstr "Загрузить предустановку эквалайзера DeaDBeeF..."
+
+#: ../plugins/gtkui/eq.c:155
+msgid "DeaDBeeF EQ presets (*.ddbeq)"
+msgstr "Предустановки эквалайзера DeaDBeeF (*.ddbeq)"
+
+#: ../plugins/gtkui/eq.c:214
+msgid "Import Foobar2000 EQ Preset..."
+msgstr "Импортировать предустановку эквалайзера Foobar2000..."
+
+#: ../plugins/gtkui/eq.c:218
+msgid "Foobar2000 EQ presets (*.feq)"
+msgstr "Предустановки эквалайзера Foobar2000 (*.feq)"
+
+#: ../plugins/gtkui/eq.c:292
+msgid "Enable"
+msgstr "Включить"
+
+#: ../plugins/gtkui/eq.c:299
+msgid "Zero All"
+msgstr "Обнулить все"
+
+#: ../plugins/gtkui/eq.c:306
+msgid "Zero Preamp"
+msgstr "Обнулить предусиление"
+
+#: ../plugins/gtkui/eq.c:313
+msgid "Zero Bands"
+msgstr "Обнулить частоты"
+
+#: ../plugins/gtkui/eq.c:320
+msgid "Save Preset"
+msgstr "Сохранить"
+
+#: ../plugins/gtkui/eq.c:327
+msgid "Load Preset"
+msgstr "Загрузить"
+
+#: ../plugins/gtkui/eq.c:334
+msgid "Import Foobar2000 Preset"
+msgstr "Импортировать предустановку Foobar2000"
+
+#: ../plugins/gtkui/gtkui.c:128
+#, c-format
+msgid "1 day %d:%02d:%02d"
+msgstr "1 день %d:%02d:%02d"
+
+#: ../plugins/gtkui/gtkui.c:131
+#, c-format
+msgid "%d days %d:%02d:%02d"
+msgstr "%d дней %d:%02d:%02d"
+
+#: ../plugins/gtkui/gtkui.c:140
+#, c-format
+msgid "Stopped | %d tracks | %s total playtime"
+msgstr "Стоп | %d композиций | %s общее время"
+
+#: ../plugins/gtkui/gtkui.c:150
+msgid "Mono"
+msgstr "Моно"
+
+#: ../plugins/gtkui/gtkui.c:150
+msgid "Stereo"
+msgstr "Стерео"
+
+#: ../plugins/gtkui/gtkui.c:170
+#, c-format
+msgid "| %4d kbps "
+msgstr "| %4d Кбит/с "
+
+#: ../plugins/gtkui/gtkui.c:176
+msgid "Paused | "
+msgstr "Пауза | "
+
+#: ../plugins/gtkui/gtkui.c:177
+#, c-format
+msgid ""
+"%s%s %s| %dHz | %d bit | %s | %d:%02d / %s | %d tracks | %s total playtime"
+msgstr ""
+"%s%s %s| %dГц | %d бит | %s | %d:%02d / %s | %d композиций | %s общее время"
+
+#: ../plugins/gtkui/gtkui.c:533
+msgid "Save Playlist As"
+msgstr "Сохранить плейлист как"
+
+#: ../plugins/gtkui/gtkui.c:542 ../plugins/gtkui/gtkui.c:603
+msgid "DeaDBeeF playlist files (*.dbpl)"
+msgstr "Файлы плейлистов DeaDBeeF (*.dbpl)"
+
+#: ../plugins/gtkui/gtkui.c:596
+msgid "Load Playlist"
+msgstr "Загрузить плейлист"
+
+#: ../plugins/gtkui/gtkui.c:741
+msgid "New Playlist"
+msgstr "Новый плейлист"
+
+#: ../plugins/gtkui/gtkui.c:744
+#, c-format
+msgid "New Playlist (%d)"
+msgstr "Новый плейлист (%d)"
+
+#: ../plugins/gtkui/interface.c:140 ../plugins/gtkui/deadbeef.glade.h:138
+msgid "_File"
+msgstr "_Файл"
+
+#: ../plugins/gtkui/interface.c:147 ../plugins/gtkui/deadbeef.glade.h:142
+msgid "_Open file(s)"
+msgstr "_Открыть файл(ы)"
+
+#: ../plugins/gtkui/interface.c:163 ../plugins/gtkui/deadbeef.glade.h:7
+msgid "Add file(s)"
+msgstr "Добавить файл(ы)"
+
+#: ../plugins/gtkui/interface.c:171 ../plugins/gtkui/deadbeef.glade.h:8
+msgid "Add folder(s)"
+msgstr "Добавить каталог(и)"
+
+#: ../plugins/gtkui/interface.c:179 ../plugins/gtkui/deadbeef.glade.h:6
+msgid "Add Audio CD"
+msgstr "Добавить аудио CD"
+
+#: ../plugins/gtkui/interface.c:187 ../plugins/gtkui/interface.c:2870
+#: ../plugins/gtkui/deadbeef.glade.h:9
+msgid "Add location"
+msgstr "Добавить расположение"
+
+#: ../plugins/gtkui/interface.c:196 ../plugins/gtkui/deadbeef.glade.h:72
+msgid "New playlist"
+msgstr "Новый плейлист"
+
+#: ../plugins/gtkui/interface.c:203 ../plugins/gtkui/deadbeef.glade.h:64
+msgid "Load playlist"
+msgstr "Загрузить плейлист"
+
+#: ../plugins/gtkui/interface.c:207 ../plugins/gtkui/deadbeef.glade.h:99
+msgid "Save playlist"
+msgstr "Сохранить плейлист"
+
+#: ../plugins/gtkui/interface.c:211 ../plugins/gtkui/deadbeef.glade.h:100
+msgid "Save playlist as"
+msgstr "Сохранить плейлист как"
+
+#: ../plugins/gtkui/interface.c:220 ../plugins/gtkui/deadbeef.glade.h:144
+msgid "_Quit"
+msgstr "_Выход"
+
+#: ../plugins/gtkui/interface.c:231 ../plugins/gtkui/deadbeef.glade.h:137
+msgid "_Edit"
+msgstr "_Правка"
+
+#: ../plugins/gtkui/interface.c:238 ../plugins/gtkui/deadbeef.glade.h:135
+msgid "_Clear"
+msgstr "_Очистить"
+
+#: ../plugins/gtkui/interface.c:246 ../plugins/gtkui/deadbeef.glade.h:104
+msgid "Select all"
+msgstr "Выделить всё"
+
+#: ../plugins/gtkui/interface.c:253 ../plugins/gtkui/deadbeef.glade.h:24
+msgid "Deselect all"
+msgstr "Снять выделение"
+
+#: ../plugins/gtkui/interface.c:260 ../plugins/gtkui/deadbeef.glade.h:59
+msgid "Invert selection"
+msgstr "Обратить выделение"
+
+#: ../plugins/gtkui/interface.c:264 ../plugins/gtkui/deadbeef.glade.h:107
+msgid "Selection"
+msgstr "Выделенное"
+
+#: ../plugins/gtkui/interface.c:271 ../plugins/gtkui/plcommon.c:387
+#: ../plugins/gtkui/prefwin.c:272 ../plugins/gtkui/deadbeef.glade.h:95
+msgid "Remove"
+msgstr "Удалить"
+
+#: ../plugins/gtkui/interface.c:279 ../plugins/gtkui/deadbeef.glade.h:19
+msgid "Crop"
+msgstr "Удалить невыделенное"
+
+#: ../plugins/gtkui/interface.c:283 ../plugins/gtkui/deadbeef.glade.h:139
+msgid "_Find"
+msgstr "_Найти"
+
+#: ../plugins/gtkui/interface.c:295 ../plugins/gtkui/interface.c:1706
+#: ../plugins/gtkui/deadbeef.glade.h:85
+msgid "Preferences"
+msgstr "Настройки"
+
+#: ../plugins/gtkui/interface.c:299 ../plugins/gtkui/deadbeef.glade.h:145
+msgid "_View"
+msgstr "_Вид"
+
+#: ../plugins/gtkui/interface.c:306 ../plugins/gtkui/deadbeef.glade.h:111
+msgid "Status bar"
+msgstr "Строка состояния"
+
+#: ../plugins/gtkui/interface.c:310 ../plugins/gtkui/deadbeef.glade.h:17
+msgid "Column headers"
+msgstr "Заголовки столбцов"
+
+#: ../plugins/gtkui/interface.c:314 ../plugins/gtkui/deadbeef.glade.h:118
+msgid "Tabs"
+msgstr "Вкладки"
+
+#: ../plugins/gtkui/interface.c:318 ../plugins/gtkui/deadbeef.glade.h:32
+msgid "Equalizer"
+msgstr "Эквалайзер"
+
+#: ../plugins/gtkui/interface.c:322 ../plugins/gtkui/deadbeef.glade.h:143
+msgid "_Playback"
+msgstr "_Воспроизведение"
+
+#: ../plugins/gtkui/interface.c:329 ../plugins/gtkui/deadbeef.glade.h:75
+msgid "Order"
+msgstr "Порядок"
+
+#: ../plugins/gtkui/interface.c:336 ../plugins/gtkui/deadbeef.glade.h:63
+msgid "Linear"
+msgstr "По порядку"
+
+#: ../plugins/gtkui/interface.c:342 ../plugins/gtkui/deadbeef.glade.h:108
+msgid "Shuffle"
+msgstr "Вперемешку"
+
+#: ../plugins/gtkui/interface.c:348 ../plugins/gtkui/deadbeef.glade.h:94
+msgid "Random"
+msgstr "Случайно"
+
+#: ../plugins/gtkui/interface.c:354 ../plugins/gtkui/deadbeef.glade.h:67
+msgid "Looping"
+msgstr "Повторять"
+
+#: ../plugins/gtkui/interface.c:361 ../plugins/gtkui/deadbeef.glade.h:65
+msgid "Loop All"
+msgstr "Все"
+
+#: ../plugins/gtkui/interface.c:367 ../plugins/gtkui/deadbeef.glade.h:66
+msgid "Loop Single Song"
+msgstr "Композицию"
+
+#: ../plugins/gtkui/interface.c:373 ../plugins/gtkui/deadbeef.glade.h:28
+msgid "Don't Loop"
+msgstr "Не повторять"
+
+#: ../plugins/gtkui/interface.c:379 ../plugins/gtkui/deadbeef.glade.h:101
+msgid "Scroll follows playback"
+msgstr "Прокручивать текущую композицию"
+
+#: ../plugins/gtkui/interface.c:384 ../plugins/gtkui/deadbeef.glade.h:21
+msgid "Cursor follows playback"
+msgstr "Выделять текущую композицию"
+
+#: ../plugins/gtkui/interface.c:388 ../plugins/gtkui/deadbeef.glade.h:113
+msgid "Stop after current"
+msgstr "Остановить после текущей"
+
+#: ../plugins/gtkui/interface.c:395 ../plugins/gtkui/interface.c:402
+#: ../plugins/gtkui/deadbeef.glade.h:140
+msgid "_Help"
+msgstr "_Справка"
+
+#: ../plugins/gtkui/interface.c:410 ../plugins/gtkui/deadbeef.glade.h:134
+msgid "_ChangeLog"
+msgstr "_Изменения"
+
+#: ../plugins/gtkui/interface.c:432 ../plugins/gtkui/deadbeef.glade.h:131
+msgid "_About"
+msgstr "_О программе"
+
+#: ../plugins/gtkui/interface.c:816 ../plugins/gtkui/deadbeef.glade.h:102
+msgid "Search"
+msgstr "Поиск"
+
+#: ../plugins/gtkui/interface.c:891 ../plugins/gtkui/deadbeef.glade.h:112
+msgid "Stop"
+msgstr "Стоп"
+
+#: ../plugins/gtkui/interface.c:899 ../plugins/gtkui/deadbeef.glade.h:81
+msgid "Play"
+msgstr "Воспроизвести"
+
+#: ../plugins/gtkui/interface.c:907 ../plugins/gtkui/deadbeef.glade.h:80
+msgid "Pause"
+msgstr "Пауза"
+
+#: ../plugins/gtkui/interface.c:915 ../plugins/gtkui/deadbeef.glade.h:86
+msgid "Previous"
+msgstr "Предыдущая"
+
+#: ../plugins/gtkui/interface.c:923 ../plugins/gtkui/deadbeef.glade.h:73
+msgid "Next"
+msgstr "Следующая"
+
+#: ../plugins/gtkui/interface.c:931 ../plugins/gtkui/deadbeef.glade.h:82
+msgid "Play Random"
+msgstr "Играть вразброс"
+
+#: ../plugins/gtkui/interface.c:940 ../plugins/gtkui/deadbeef.glade.h:5
+msgid "About"
+msgstr "О программе"
+
+#: ../plugins/gtkui/interface.c:953 ../plugins/gtkui/deadbeef.glade.h:93
+msgid "Quit"
+msgstr "Выход"
+
+#: ../plugins/gtkui/interface.c:1025 ../plugins/gtkui/deadbeef.glade.h:10
+msgid "Adding files..."
+msgstr "Добавление файлов..."
+
+#: ../plugins/gtkui/interface.c:1069 ../plugins/gtkui/deadbeef.glade.h:130
+msgid "_Abort"
+msgstr "_Отменить"
+
+#: ../plugins/gtkui/interface.c:1170 ../plugins/gtkui/deadbeef.glade.h:122
+msgid "Track Properties"
+msgstr "Свойства композиции"
+
+#: ../plugins/gtkui/interface.c:1194 ../plugins/gtkui/deadbeef.glade.h:3
+msgid ""
+"<b>WARNING</b>: tag writing feature is still in development.\n"
+"<b>Make backup copies</b> before using."
+msgstr ""
+"<b>Внимание</b>: возможность редактирования тегов находится\n"
+"в разработке.\n"
+"<b>Создавайте резервные копии</b> перед использованием."
+
+#: ../plugins/gtkui/interface.c:1221 ../plugins/gtkui/deadbeef.glade.h:132
+msgid "_Apply"
+msgstr "_Применить"
+
+#: ../plugins/gtkui/interface.c:1242 ../plugins/gtkui/interface.c:1288
+#: ../plugins/gtkui/interface.c:2436 ../plugins/gtkui/deadbeef.glade.h:136
+msgid "_Close"
+msgstr "_Закрыть"
+
+#: ../plugins/gtkui/interface.c:1246 ../plugins/gtkui/deadbeef.glade.h:68
+msgid "Metadata"
+msgstr "Метаданные"
+
+#: ../plugins/gtkui/interface.c:1292 ../plugins/gtkui/plcommon.c:402
+#: ../plugins/gtkui/deadbeef.glade.h:87
+msgid "Properties"
+msgstr "Свойства"
+
+#: ../plugins/gtkui/interface.c:1378 ../plugins/gtkui/deadbeef.glade.h:146
+msgid "editcolumndlg"
+msgstr "Редактировать столбец"
+
+#: ../plugins/gtkui/interface.c:1393 ../plugins/gtkui/interface.c:2770
+#: ../plugins/gtkui/deadbeef.glade.h:121
+msgid "Title:"
+msgstr "Название:"
+
+#: ../plugins/gtkui/interface.c:1401 ../plugins/gtkui/deadbeef.glade.h:31
+msgid "Enter new column title here"
+msgstr "Введите название нового столбца"
+
+#: ../plugins/gtkui/interface.c:1409 ../plugins/gtkui/deadbeef.glade.h:123
+msgid "Type:"
+msgstr "Тип:"
+
+#: ../plugins/gtkui/interface.c:1417
+msgid "File number"
+msgstr "Номер композиции"
+
+#. create default set of columns
+#: ../plugins/gtkui/interface.c:1418 ../plugins/gtkui/mainplaylist.c:297
+msgid "Playing"
+msgstr "Воспроизводится"
+
+#: ../plugins/gtkui/interface.c:1419
+msgid "Album Art"
+msgstr "Обложка альбома"
+
+#: ../plugins/gtkui/interface.c:1420
+msgid "Artist - Album"
+msgstr "Исполнитель - Альбом"
+
+#: ../plugins/gtkui/interface.c:1421 ../plugins/gtkui/plcommon.c:774
+msgid "Artist"
+msgstr "Исполнитель"
+
+#: ../plugins/gtkui/interface.c:1422 ../plugins/gtkui/interface.c:1795
+msgid "Album"
+msgstr "Альбом"
+
+#: ../plugins/gtkui/interface.c:1423 ../plugins/gtkui/prefwin.c:488
+msgid "Title"
+msgstr "Название"
+
+#: ../plugins/gtkui/interface.c:1424
+msgid "Length"
+msgstr "Длина"
+
+#: ../plugins/gtkui/interface.c:1425 ../plugins/gtkui/interface.c:1794
+msgid "Track"
+msgstr "Композиция"
+
+#: ../plugins/gtkui/interface.c:1426
+msgid "Band / Album Artist"
+msgstr "Группа / Исполнитель"
+
+#: ../plugins/gtkui/interface.c:1427 ../plugins/gtkui/plcommon.c:778
+msgid "Custom"
+msgstr "Пользовательский"
+
+#: ../plugins/gtkui/interface.c:1433 ../plugins/gtkui/interface.c:2997
+#: ../plugins/gtkui/deadbeef.glade.h:53
+msgid "Format:"
+msgstr "Формат:"
+
+#: ../plugins/gtkui/interface.c:1448 ../plugins/gtkui/deadbeef.glade.h:11
+msgid "Alignment:"
+msgstr "Выравнивание:"
+
+#: ../plugins/gtkui/interface.c:1456
+msgid "Left"
+msgstr "По левому краю"
+
+#: ../plugins/gtkui/interface.c:1457
+msgid "Right"
+msgstr "По правому краю"
+
+#: ../plugins/gtkui/interface.c:1459 ../plugins/gtkui/interface.c:3007
+#: ../plugins/gtkui/deadbeef.glade.h:47
+#, fuzzy, no-c-format
+msgid ""
+"Format conversions (start with %):\n"
+" [a]rtist, [t]itle, al[b]um, [B]and, [C]omposer\n"
+" track[n]umber, [N]totaltracks,\n"
+" [l]ength, [y]ear, [g]enre, [c]omment,\n"
+" copy[r]ight, [f]ilename, [T]ags\n"
+"Example: %a - %t [%l]"
+msgstr ""
+"Формат преобразования (начинается с %):\n"
+" [a]rtist, [t]itle, al[b]um, [B]and,\n"
+" track[n]umber, [N]totaltracks,\n"
+" [l]ength, [y]ear, [g]enre, [c]omment,\n"
+" copy[r]ight, [f]ilename, [T]ags\n"
+"Пример: %a - %t [%l]"
+
+#: ../plugins/gtkui/interface.c:1488 ../plugins/gtkui/interface.c:2801
+#: ../plugins/gtkui/interface.c:2913 ../plugins/gtkui/interface.c:3036
+#: ../plugins/gtkui/deadbeef.glade.h:133
+msgid "_Cancel"
+msgstr "_Отмена"
+
+#: ../plugins/gtkui/interface.c:1509 ../plugins/gtkui/interface.c:2822
+#: ../plugins/gtkui/interface.c:2934 ../plugins/gtkui/interface.c:3057
+#: ../plugins/gtkui/deadbeef.glade.h:141
+msgid "_OK"
+msgstr "_ОК"
+
+#: ../plugins/gtkui/interface.c:1726 ../plugins/gtkui/deadbeef.glade.h:77
+msgid "Output plugin:"
+msgstr "Модуль вывода:"
+
+#: ../plugins/gtkui/interface.c:1739 ../plugins/gtkui/deadbeef.glade.h:76
+msgid "Output device:"
+msgstr "Устройство вывода:"
+
+#: ../plugins/gtkui/interface.c:1748 ../plugins/gtkui/deadbeef.glade.h:109
+msgid "Sound"
+msgstr "Звук"
+
+#: ../plugins/gtkui/interface.c:1757 ../plugins/gtkui/deadbeef.glade.h:12
+msgid "Allow dynamic samplerate switching"
+msgstr "Разрешить преобразование частоты дискретизации"
+
+#: ../plugins/gtkui/interface.c:1765 ../plugins/gtkui/deadbeef.glade.h:98
+msgid "Samplerate conversion quality:"
+msgstr "Алгоритм интерполяции:"
+
+#: ../plugins/gtkui/interface.c:1784 ../plugins/gtkui/deadbeef.glade.h:96
+msgid "Replaygain mode:"
+msgstr "Режим автовыравнивания громкости:"
+
+#: ../plugins/gtkui/interface.c:1793
+msgid "Disable"
+msgstr "Отключён"
+
+#: ../plugins/gtkui/interface.c:1797 ../plugins/gtkui/deadbeef.glade.h:97
+msgid "Replaygain peak scale"
+msgstr "Использовать пиковое значение"
+
+#: ../plugins/gtkui/interface.c:1801 ../plugins/gtkui/deadbeef.glade.h:110
+msgid "Sound (adv.)"
+msgstr "Звук (прод.)"
+
+#: ../plugins/gtkui/interface.c:1810 ../plugins/gtkui/deadbeef.glade.h:16
+msgid "Close minimizes to tray"
+msgstr "Сворачивать в трей при закрытии"
+
+#: ../plugins/gtkui/interface.c:1814 ../plugins/gtkui/deadbeef.glade.h:70
+msgid "Middle mouse button closes playlist"
+msgstr "Средняя кнопка мыши закрывает плейлист"
+
+#: ../plugins/gtkui/interface.c:1827 ../plugins/gtkui/interface.c:1871
+#: ../plugins/gtkui/deadbeef.glade.h:78
+msgid "Override"
+msgstr "Заменить"
+
+#: ../plugins/gtkui/interface.c:1836 ../plugins/gtkui/deadbeef.glade.h:45
+msgid "Foreground"
+msgstr "Передний план"
+
+#: ../plugins/gtkui/interface.c:1843 ../plugins/gtkui/deadbeef.glade.h:14
+msgid "Background"
+msgstr "Фон"
+
+#: ../plugins/gtkui/interface.c:1862 ../plugins/gtkui/deadbeef.glade.h:103
+msgid "Seekbar/Volumebar colors"
+msgstr "Полоса проигрывания/Регулятор громкости"
+
+#: ../plugins/gtkui/interface.c:1880 ../plugins/gtkui/deadbeef.glade.h:69
+msgid "Middle"
+msgstr "Средний"
+
+#: ../plugins/gtkui/interface.c:1887 ../plugins/gtkui/deadbeef.glade.h:62
+msgid "Light"
+msgstr "Светлый"
+
+#: ../plugins/gtkui/interface.c:1894 ../plugins/gtkui/deadbeef.glade.h:22
+msgid "Dark"
+msgstr "Тёмный"
+
+#: ../plugins/gtkui/interface.c:1925 ../plugins/gtkui/deadbeef.glade.h:15
+msgid "Base"
+msgstr "Базовый"
+
+#: ../plugins/gtkui/interface.c:1932 ../plugins/gtkui/deadbeef.glade.h:117
+msgid "Tab strip colors"
+msgstr "Вкладки"
+
+#: ../plugins/gtkui/interface.c:1941 ../plugins/gtkui/deadbeef.glade.h:79
+msgid "Override (looses GTK treeview theming, but speeds up rendering)"
+msgstr ""
+"Заменить (теряются настройки GTK темы, но увеличивается скорость "
+"визуализации)"
+
+#: ../plugins/gtkui/interface.c:1950 ../plugins/gtkui/deadbeef.glade.h:33
+msgid "Even row"
+msgstr ""
+"Чётная \n"
+" строка"
+
+#: ../plugins/gtkui/interface.c:1957 ../plugins/gtkui/deadbeef.glade.h:74
+msgid "Odd row"
+msgstr ""
+"Нечётная \n"
+" строка"
+
+#: ../plugins/gtkui/interface.c:1976 ../plugins/gtkui/deadbeef.glade.h:120
+msgid "Text"
+msgstr "Текст"
+
+#: ../plugins/gtkui/interface.c:1983 ../plugins/gtkui/deadbeef.glade.h:105
+msgid "Selected row"
+msgstr ""
+"Выделенная \n"
+" строка"
+
+#: ../plugins/gtkui/interface.c:2002 ../plugins/gtkui/deadbeef.glade.h:106
+msgid "Selected text"
+msgstr ""
+"Выделенный \n"
+" текст"
+
+#: ../plugins/gtkui/interface.c:2015 ../plugins/gtkui/deadbeef.glade.h:20
+msgid "Cursor"
+msgstr "Указатель"
+
+#: ../plugins/gtkui/interface.c:2028 ../plugins/gtkui/deadbeef.glade.h:83
+msgid "Playlist colors"
+msgstr "Плейлист"
+
+#: ../plugins/gtkui/interface.c:2032 ../plugins/gtkui/deadbeef.glade.h:54
+msgid "GUI"
+msgstr "Интерфейс"
+
+#: ../plugins/gtkui/interface.c:2041 ../plugins/gtkui/deadbeef.glade.h:30
+msgid "Enable Proxy Server"
+msgstr "Включить прокси-сервер"
+
+#: ../plugins/gtkui/interface.c:2049 ../plugins/gtkui/deadbeef.glade.h:89
+msgid "Proxy Server Address:"
+msgstr "Адрес:"
+
+#: ../plugins/gtkui/interface.c:2063 ../plugins/gtkui/deadbeef.glade.h:90
+msgid "Proxy Server Port:"
+msgstr "Порт:"
+
+#: ../plugins/gtkui/interface.c:2077 ../plugins/gtkui/deadbeef.glade.h:91
+msgid "Proxy Type:"
+msgstr "Тип прокси:"
+
+#: ../plugins/gtkui/interface.c:2096 ../plugins/gtkui/deadbeef.glade.h:92
+msgid "Proxy Username:"
+msgstr "Имя пользователя:"
+
+#: ../plugins/gtkui/interface.c:2109 ../plugins/gtkui/deadbeef.glade.h:88
+msgid "Proxy Password:"
+msgstr "Пароль:"
+
+#: ../plugins/gtkui/interface.c:2119 ../plugins/gtkui/deadbeef.glade.h:71
+msgid "Network"
+msgstr "Сеть"
+
+#: ../plugins/gtkui/interface.c:2147 ../plugins/gtkui/deadbeef.glade.h:128
+msgid "Write ID3v2"
+msgstr "Писать ID3v2"
+
+#: ../plugins/gtkui/interface.c:2151 ../plugins/gtkui/interface.c:2278
+#: ../plugins/gtkui/deadbeef.glade.h:127
+msgid "Write ID3v1"
+msgstr "Писать ID3v1"
+
+#: ../plugins/gtkui/interface.c:2155 ../plugins/gtkui/interface.c:2234
+#: ../plugins/gtkui/interface.c:2274 ../plugins/gtkui/deadbeef.glade.h:126
+msgid "Write APEv2"
+msgstr "Писать APEv2"
+
+#: ../plugins/gtkui/interface.c:2163 ../plugins/gtkui/interface.c:2242
+#: ../plugins/gtkui/deadbeef.glade.h:116
+msgid "Strip ID3v2"
+msgstr "Вырезать ID3v2"
+
+#: ../plugins/gtkui/interface.c:2167 ../plugins/gtkui/interface.c:2290
+#: ../plugins/gtkui/deadbeef.glade.h:115
+msgid "Strip ID3v1"
+msgstr "Вырезать ID3v1"
+
+#: ../plugins/gtkui/interface.c:2171 ../plugins/gtkui/interface.c:2246
+#: ../plugins/gtkui/interface.c:2286 ../plugins/gtkui/deadbeef.glade.h:114
+msgid "Strip APEv2"
+msgstr "Вырезать APEv2"
+
+#: ../plugins/gtkui/interface.c:2179 ../plugins/gtkui/deadbeef.glade.h:58
+msgid "ID3v2 version"
+msgstr "Версия ID3v2"
+
+#: ../plugins/gtkui/interface.c:2186
+msgid "2.3 (Recommended)"
+msgstr "2.3 (Рекомендуемая)"
+
+#: ../plugins/gtkui/interface.c:2187
+msgid "2.4"
+msgstr "2.4"
+
+#: ../plugins/gtkui/interface.c:2193 ../plugins/gtkui/deadbeef.glade.h:57
+msgid "ID3v1 character encoding (default is iso8859-1)"
+msgstr "Кодировка ID3v1 (по умолчанию iso8859-1)"
+
+#: ../plugins/gtkui/interface.c:2230 ../plugins/gtkui/deadbeef.glade.h:129
+msgid "Write ID3v2.4"
+msgstr "Писать ID3v2.4"
+
+#: ../plugins/gtkui/interface.c:2299 ../plugins/gtkui/deadbeef.glade.h:119
+msgid "Tag writer"
+msgstr "Редактор тегов"
+
+#: ../plugins/gtkui/interface.c:2330 ../plugins/gtkui/deadbeef.glade.h:23
+msgid "Description:"
+msgstr "Описание:"
+
+#: ../plugins/gtkui/interface.c:2345 ../plugins/gtkui/deadbeef.glade.h:13
+msgid "Author(s):"
+msgstr "Автор(ы):"
+
+#: ../plugins/gtkui/interface.c:2360 ../plugins/gtkui/deadbeef.glade.h:29
+msgid "Email:"
+msgstr "Электронный адрес:"
+
+#: ../plugins/gtkui/interface.c:2375 ../plugins/gtkui/deadbeef.glade.h:125
+msgid "Website:"
+msgstr "Веб-сайт:"
+
+#: ../plugins/gtkui/interface.c:2406 ../plugins/gtkui/deadbeef.glade.h:18
+msgid "Configure"
+msgstr "Настроить"
+
+#: ../plugins/gtkui/interface.c:2410 ../plugins/gtkui/deadbeef.glade.h:84
+msgid "Plugins"
+msgstr "Расширения"
+
+#: ../plugins/gtkui/interface.c:2754 ../plugins/gtkui/deadbeef.glade.h:147
+msgid "editplaylistdlg"
+msgstr "Редактировать плейлист"
+
+#: ../plugins/gtkui/interface.c:2881 ../plugins/gtkui/deadbeef.glade.h:124
+msgid "URL:"
+msgstr "Адрес:"
+
+#: ../plugins/gtkui/interface.c:2982 ../plugins/gtkui/deadbeef.glade.h:55
+msgid "Group By"
+msgstr "Группировать по"
+
+#: ../plugins/gtkui/mainplaylist.c:298 ../plugins/gtkui/search.c:433
+msgid "Artist / Album"
+msgstr "Исполнитель / Альбом"
+
+#: ../plugins/gtkui/mainplaylist.c:299 ../plugins/gtkui/search.c:434
+msgid "Track No"
+msgstr "№"
+
+#: ../plugins/gtkui/mainplaylist.c:300 ../plugins/gtkui/search.c:435
+msgid "Title / Track Artist"
+msgstr "Заголовок / Исполнитель"
+
+#: ../plugins/gtkui/mainplaylist.c:301 ../plugins/gtkui/search.c:436
+#: ../plugins/gtkui/trkproperties.c:175
+msgid "Duration"
+msgstr "Продолжительность"
+
+#: ../plugins/gtkui/plcommon.c:316
+msgid "Delete files from disk"
+msgstr "Удалить файлы с жёсткого диска"
+
+#: ../plugins/gtkui/plcommon.c:317
+msgid ""
+"Files will be lost. Proceed?\n"
+"(This dialog can be turned off in GTKUI plugin settings)"
+msgstr ""
+"Файлы будут потеряны. Продолжить?\n"
+"(Этот диалог может быть отключён в настройках расширения GTKUI)"
+
+#: ../plugins/gtkui/plcommon.c:318 ../plugins/gtkui/trkproperties.c:56
+msgid "Warning"
+msgstr "Предупреждение"
+
+#: ../plugins/gtkui/plcommon.c:363
+msgid "Add to playback queue"
+msgstr "Добавить в очередь"
+
+#: ../plugins/gtkui/plcommon.c:368
+msgid "Remove from playback queue"
+msgstr "Удалить из очереди"
+
+#: ../plugins/gtkui/plcommon.c:376
+msgid "Reload metadata"
+msgstr "Обновить метаданные"
+
+#: ../plugins/gtkui/plcommon.c:392
+msgid "Remove from disk"
+msgstr "Удалить с жёсткого диска"
+
+#: ../plugins/gtkui/plcommon.c:616 ../plugins/gtkui/plcommon.c:741
+msgid "Add column"
+msgstr "Добавить столбец"
+
+#: ../plugins/gtkui/plcommon.c:646 ../plugins/gtkui/plcommon.c:745
+msgid "Edit column"
+msgstr "Редактировать столбец"
+
+#: ../plugins/gtkui/plcommon.c:749
+msgid "Remove column"
+msgstr "Удалить столбец"
+
+#: ../plugins/gtkui/plcommon.c:759
+msgid "Group by"
+msgstr "Группировать по"
+
+#: ../plugins/gtkui/plcommon.c:766
+msgid "None"
+msgstr "Отсутствует"
+
+#: ../plugins/gtkui/plcommon.c:770
+msgid "Artist/Date/Album"
+msgstr "Исполнитель/Дата/Альбом"
+
+#: ../plugins/gtkui/pluginconf.c:41
+msgid "Open file..."
+msgstr "Открыть файл..."
+
+#: ../plugins/gtkui/pluginconf.c:139
+#, c-format
+msgid "Setup %s"
+msgstr "Настройки %s"
+
+#: ../plugins/gtkui/prefwin.c:98
+msgid "Default Audio Device"
+msgstr "Аудио устройство по умолчанию"
+
+#: ../plugins/gtkui/prefwin.c:267
+msgid "Add"
+msgstr "Добавить"
+
+#: ../plugins/gtkui/prefwin.c:277
+msgid "Global Hotkeys"
+msgstr "Горячие клавиши"
+
+#: ../plugins/gtkui/prefwin.c:332
+msgid "Slot"
+msgstr "Слот"
+
+#: ../plugins/gtkui/prefwin.c:333
+msgid "Key combination"
+msgstr "Комбинация клавиш"
+
+#. output plugin selection
+#: ../plugins/gtkui/prefwin.c:379 ../plugins/gtkui/prefwin.c:569
+#: ../plugins.c:833
+msgid "ALSA output plugin"
+msgstr "Модуль вывода ALSA"
+
+#: ../plugins/gtkui/progress.c:64
+msgid "Initializing..."
+msgstr "Загрузка..."
+
+#: ../plugins/gtkui/trkproperties.c:53
+msgid "You've modified data for this track."
+msgstr "Данные для этой композиции были изменены."
+
+#: ../plugins/gtkui/trkproperties.c:55
+msgid "Really close the window?"
+msgstr "Закрыть окно?"
+
+#: ../plugins/gtkui/trkproperties.c:178
+msgid "Tag Type(s)"
+msgstr "Тип(ы) тегов"
+
+#: ../plugins/gtkui/trkproperties.c:180
+msgid "Embedded Cuesheet"
+msgstr "Встроенный файл cue"
+
+#: ../plugins/gtkui/trkproperties.c:180
+msgid "Yes"
+msgstr "Да"
+
+#: ../plugins/gtkui/trkproperties.c:180
+msgid "No"
+msgstr "Нет"
+
+#: ../plugins/gtkui/trkproperties.c:248 ../plugins/gtkui/trkproperties.c:260
+msgid "Key"
+msgstr "Ключ"
+
+#: ../plugins/gtkui/trkproperties.c:249 ../plugins/gtkui/trkproperties.c:261
+msgid "Value"
+msgstr "Значение"
+
+#: ../plugins/notify/notify.c:138
+msgid "DeaDBeeF now playing"
+msgstr "DeaDBeeF сейчас играет"
+
+#: ../main.c:84
+#, c-format
+msgid "Usage: deadbeef [options] [file(s)]\n"
+msgstr "Использование: deadbeef [опции] [файл(ы)]\n"
+
+#: ../main.c:85
+#, c-format
+msgid "Options:\n"
+msgstr "Опции:\n"
+
+#: ../main.c:86
+#, c-format
+msgid " --help or -h Print help (this message) and exit\n"
+msgstr ""
+" --help или -h Вывести на экран справку (это сообщение) и выйти\n"
+
+#: ../main.c:87
+#, c-format
+msgid " --quit Quit player\n"
+msgstr " --quit Выйти из плеера\n"
+
+#: ../main.c:88
+#, c-format
+msgid " --version Print version info and exit\n"
+msgstr ""
+" --version Вывести на экран информацию о версии программы и "
+"выйти\n"
+
+#: ../main.c:89
+#, c-format
+msgid " --play Start playback\n"
+msgstr " --play Начать воспроизведение\n"
+
+#: ../main.c:90
+#, c-format
+msgid " --stop Stop playback\n"
+msgstr " --stop Остановить воспроизведение\n"
+
+#: ../main.c:91
+#, c-format
+msgid " --pause Pause playback\n"
+msgstr " --pause Приостановить воспроизведение\n"
+
+#: ../main.c:92
+#, c-format
+msgid " --next Next song in playlist\n"
+msgstr " --next Следующая песня в плейлисте\n"
+
+#: ../main.c:93
+#, c-format
+msgid " --prev Previous song in playlist\n"
+msgstr " --prev Предыдущая песня в плейлисте\n"
+
+#: ../main.c:94
+#, c-format
+msgid " --random Random song in playlist\n"
+msgstr " --random Воспроизведение случайной песни в плейлисте\n"
+
+#: ../main.c:95
+#, c-format
+msgid " --queue Append file(s) to existing playlist\n"
+msgstr " --queue Добавить файл(ы) в существующий плейлист\n"
+
+#: ../main.c:96
+#, c-format
+msgid " --nowplaying FMT Print formatted track name to stdout\n"
+msgstr ""
+" --nowplaying ФМТ Вывести на экран форматированное название композиции\n"
+
+#: ../main.c:97
+#, c-format
+msgid ""
+" FMT %%-syntax: [a]rtist, [t]itle, al[b]um,\n"
+" [l]ength, track[n]umber, [y]ear, [c]omment,\n"
+" copy[r]ight, [e]lapsed\n"
+msgstr ""
+" Формат %%-синтаксис: [a]rtist, [t]itle, al[b]um,\n"
+" [l]ength, track[n]umber, [y]ear, [c]omment,\n"
+" copy[r]ight, [e]lapsed\n"
+
+#: ../main.c:100
+#, c-format
+msgid ""
+" e.g.: --nowplaying \"%%a - %%t\" should print \"artist "
+"- title\"\n"
+msgstr ""
+" Например: --nowplaying \"%%a - %%t\" должна вывести "
+"на экран \"artist - title\"\n"
+
+#: ../playlist.c:369 ../playlist.c:2212
+msgid "Default"
+msgstr "Плейлист"
+
+#: ../plugins/gtkui/deadbeef.glade.h:1
+#, fuzzy
+msgid ""
+"2.3 (Recommended)\n"
+"2.4"
+msgstr "2.3 (Рекомендуемая)"
+
+#: ../plugins/gtkui/deadbeef.glade.h:25
+msgid ""
+"Disable\n"
+"Track\n"
+"Album"
+msgstr ""
+
+#: ../plugins/gtkui/deadbeef.glade.h:34
+msgid ""
+"File number\n"
+"Playing\n"
+"Album Art\n"
+"Artist - Album\n"
+"Artist\n"
+"Album\n"
+"Title\n"
+"Length\n"
+"Track\n"
+"Band / Album Artist\n"
+"Custom"
+msgstr ""
+
+#: ../plugins/gtkui/deadbeef.glade.h:60
+#, fuzzy
+msgid ""
+"Left\n"
+"Right"
+msgstr "По правому краю"
+
+#: ../plugins/gtkui/support.c:90 ../plugins/gtkui/support.c:114
+#, c-format
+msgid "Couldn't find pixmap file: %s"
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:129 ../plugins/vorbis/vcedit.c:155
+msgid "Couldn't get enough memory for input buffering."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:179 ../plugins/vorbis/vcedit.c:550
+msgid "Error reading first page of Ogg bitstream."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:185 ../plugins/vorbis/vcedit.c:557
+msgid "Error reading initial header packet."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:237
+msgid "Couldn't get enough memory to register new stream serial number."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:505
+msgid "Input truncated or empty."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:507
+msgid "Input is not an Ogg bitstream."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:565
+msgid "Ogg bitstream does not contain Vorbis data."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:578
+msgid "EOF before recognised stream."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:594
+msgid "Ogg bitstream does not contain a supported data-type."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:638
+msgid "Corrupt secondary header."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:659
+msgid "EOF before end of Vorbis headers."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:834
+msgid "Corrupt or missing data, continuing..."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:874
+msgid ""
+"Error writing stream to output. Output stream may be corrupted or truncated."
+msgstr ""
+
diff --git a/po/sv.po b/po/sv.po
new file mode 100644
index 00000000..3b743e1f
--- /dev/null
+++ b/po/sv.po
@@ -0,0 +1,1122 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-05-27 16:47+0200\n"
+"PO-Revision-Date: 2010-05-27 20:57+0200\n"
+"Last-Translator: Martin <brother@bsnet.se>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: sv\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Pootle 2.0.1\n"
+
+#: ../plugins/gtkui/callbacks.c:97
+msgid "Supported sound formats"
+msgstr "Ljudformat med stöd"
+
+#: ../plugins/gtkui/callbacks.c:108
+msgid "Other files (*)"
+msgstr "Andra filer (*)"
+
+#: ../plugins/gtkui/callbacks.c:117
+msgid "Open file(s)..."
+msgstr "Öppna fil(er)..."
+
+#: ../plugins/gtkui/callbacks.c:150
+msgid "Add file(s) to playlist..."
+msgstr "Lägg till fil(er) till spellista..."
+
+#: ../plugins/gtkui/callbacks.c:182
+msgid "Add folder(s) to playlist..."
+msgstr "Lägg till katalog(er) till spellista..."
+
+#: ../plugins/gtkui/callbacks.c:640
+msgid "Failed while reading help file"
+msgstr "Misslyckades vid läsning av hjälpfil"
+
+#: ../plugins/gtkui/callbacks.c:650
+msgid "Failed to load help file"
+msgstr "MIsslyckades med att läsa hjälpfil"
+
+#: ../plugins/gtkui/callbacks.c:664 ../plugins/gtkui/interface.c:1105
+#: ../plugins/gtkui/deadbeef.glade.h:56
+msgid "Help"
+msgstr "Hjälp"
+
+#: ../plugins/gtkui/callbacks.c:674
+#, c-format
+msgid "About DeaDBeeF %s"
+msgstr "Om DeaDBeeF %s"
+
+#: ../plugins/gtkui/callbacks.c:685
+#, c-format
+msgid "DeaDBeeF %s ChangeLog"
+msgstr "DeadBeeF %s Ändrligslogg"
+
+#: ../plugins/gtkui/ddbtabstrip.c:527
+msgid "Edit playlist"
+msgstr "Redigera spellista"
+
+#: ../plugins/gtkui/ddbtabstrip.c:604
+msgid "Rename Playlist"
+msgstr "Byt namn på spellista"
+
+#: ../plugins/gtkui/ddbtabstrip.c:608
+msgid "Remove Playlist"
+msgstr "Ta bort spellista"
+
+#: ../plugins/gtkui/ddbtabstrip.c:612
+msgid "Add New Playlist"
+msgstr "Lägg till ny spellista"
+
+#: ../plugins/gtkui/eq.c:113
+msgid "Save DeaDBeeF EQ Preset"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:120
+msgid "DeaDBeeF EQ preset files (*.ddbeq)"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:151
+msgid "Load DeaDBeeF EQ Preset..."
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:155
+msgid "DeaDBeeF EQ presets (*.ddbeq)"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:214
+msgid "Import Foobar2000 EQ Preset..."
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:218
+msgid "Foobar2000 EQ presets (*.feq)"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:292
+msgid "Enable"
+msgstr "Aktivera"
+
+#: ../plugins/gtkui/eq.c:299
+msgid "Zero All"
+msgstr "Nollställ alla"
+
+#: ../plugins/gtkui/eq.c:306
+msgid "Zero Preamp"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:313
+msgid "Zero Bands"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:320
+msgid "Save Preset"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:327
+msgid "Load Preset"
+msgstr ""
+
+#: ../plugins/gtkui/eq.c:334
+msgid "Import Foobar2000 Preset"
+msgstr ""
+
+#: ../plugins/gtkui/gtkui.c:128
+#, c-format
+msgid "1 day %d:%02d:%02d"
+msgstr "1 dag %d:%02d:%02d"
+
+#: ../plugins/gtkui/gtkui.c:131
+#, c-format
+msgid "%d days %d:%02d:%02d"
+msgstr "%d dagar %d:%02d:%02d"
+
+#: ../plugins/gtkui/gtkui.c:140
+#, c-format
+msgid "Stopped | %d tracks | %s total playtime"
+msgstr "Stoppad | %d spår | %s total speltid"
+
+#: ../plugins/gtkui/gtkui.c:150
+msgid "Mono"
+msgstr "Mono"
+
+#: ../plugins/gtkui/gtkui.c:150
+msgid "Stereo"
+msgstr "Stereo"
+
+#: ../plugins/gtkui/gtkui.c:170
+#, c-format
+msgid "| %4d kbps "
+msgstr "| %4d kbps "
+
+#: ../plugins/gtkui/gtkui.c:176
+msgid "Paused | "
+msgstr "Pausad | "
+
+#: ../plugins/gtkui/gtkui.c:177
+#, c-format
+msgid ""
+"%s%s %s| %dHz | %d bit | %s | %d:%02d / %s | %d tracks | %s total playtime"
+msgstr "%s%s %s| %dHz | %d bit | %s | %d:%02d / %s | %d spår | %s total speltid"
+
+#: ../plugins/gtkui/gtkui.c:533
+msgid "Save Playlist As"
+msgstr "Spara spellista som"
+
+#: ../plugins/gtkui/gtkui.c:542 ../plugins/gtkui/gtkui.c:603
+msgid "DeaDBeeF playlist files (*.dbpl)"
+msgstr "DeaDBeeF spellistfil (*.dbpl)"
+
+#: ../plugins/gtkui/gtkui.c:596
+msgid "Load Playlist"
+msgstr "Läs in spellista"
+
+#: ../plugins/gtkui/gtkui.c:741
+msgid "New Playlist"
+msgstr "Ny spellista"
+
+#: ../plugins/gtkui/gtkui.c:744
+#, c-format
+msgid "New Playlist (%d)"
+msgstr "Ny spellista (%d)"
+
+#: ../plugins/gtkui/interface.c:140 ../plugins/gtkui/deadbeef.glade.h:138
+msgid "_File"
+msgstr "_Arkiv"
+
+#: ../plugins/gtkui/interface.c:147 ../plugins/gtkui/deadbeef.glade.h:142
+msgid "_Open file(s)"
+msgstr "_Öppna fil(er)"
+
+#: ../plugins/gtkui/interface.c:163 ../plugins/gtkui/deadbeef.glade.h:7
+msgid "Add file(s)"
+msgstr "Lägg till fil(er)"
+
+#: ../plugins/gtkui/interface.c:171 ../plugins/gtkui/deadbeef.glade.h:8
+msgid "Add folder(s)"
+msgstr "Lägg till katalog(er)"
+
+#: ../plugins/gtkui/interface.c:179 ../plugins/gtkui/deadbeef.glade.h:6
+msgid "Add Audio CD"
+msgstr "Lägg till ljud-CD"
+
+#: ../plugins/gtkui/interface.c:187 ../plugins/gtkui/interface.c:2870
+#: ../plugins/gtkui/deadbeef.glade.h:9
+msgid "Add location"
+msgstr "Lägg till plats"
+
+#: ../plugins/gtkui/interface.c:196 ../plugins/gtkui/deadbeef.glade.h:72
+msgid "New playlist"
+msgstr "Ny spellista"
+
+#: ../plugins/gtkui/interface.c:203 ../plugins/gtkui/deadbeef.glade.h:64
+msgid "Load playlist"
+msgstr "Läs in spellista"
+
+#: ../plugins/gtkui/interface.c:207 ../plugins/gtkui/deadbeef.glade.h:99
+msgid "Save playlist"
+msgstr "Spara spellista"
+
+#: ../plugins/gtkui/interface.c:211 ../plugins/gtkui/deadbeef.glade.h:100
+msgid "Save playlist as"
+msgstr "Spara spellista som"
+
+#: ../plugins/gtkui/interface.c:220 ../plugins/gtkui/deadbeef.glade.h:144
+msgid "_Quit"
+msgstr "A_vsluta"
+
+#: ../plugins/gtkui/interface.c:231 ../plugins/gtkui/deadbeef.glade.h:137
+msgid "_Edit"
+msgstr "_Redigera"
+
+#: ../plugins/gtkui/interface.c:238 ../plugins/gtkui/deadbeef.glade.h:135
+msgid "_Clear"
+msgstr "R_ensa"
+
+#: ../plugins/gtkui/interface.c:246 ../plugins/gtkui/deadbeef.glade.h:104
+msgid "Select all"
+msgstr "Markera allt"
+
+#: ../plugins/gtkui/interface.c:253 ../plugins/gtkui/deadbeef.glade.h:24
+msgid "Deselect all"
+msgstr "Avmarkera allt"
+
+#: ../plugins/gtkui/interface.c:260 ../plugins/gtkui/deadbeef.glade.h:59
+msgid "Invert selection"
+msgstr "Invertera markering"
+
+#: ../plugins/gtkui/interface.c:264 ../plugins/gtkui/deadbeef.glade.h:107
+msgid "Selection"
+msgstr "Markering"
+
+#: ../plugins/gtkui/interface.c:271 ../plugins/gtkui/plcommon.c:387
+#: ../plugins/gtkui/prefwin.c:272 ../plugins/gtkui/deadbeef.glade.h:95
+msgid "Remove"
+msgstr "Ta bort"
+
+#: ../plugins/gtkui/interface.c:279 ../plugins/gtkui/deadbeef.glade.h:19
+msgid "Crop"
+msgstr "Beskär"
+
+#: ../plugins/gtkui/interface.c:283 ../plugins/gtkui/deadbeef.glade.h:139
+msgid "_Find"
+msgstr "_Sök"
+
+#: ../plugins/gtkui/interface.c:295 ../plugins/gtkui/interface.c:1706
+#: ../plugins/gtkui/deadbeef.glade.h:85
+msgid "Preferences"
+msgstr "Egenskaper"
+
+#: ../plugins/gtkui/interface.c:299 ../plugins/gtkui/deadbeef.glade.h:145
+msgid "_View"
+msgstr "_Visa"
+
+#: ../plugins/gtkui/interface.c:306 ../plugins/gtkui/deadbeef.glade.h:111
+msgid "Status bar"
+msgstr "Statusrad"
+
+#: ../plugins/gtkui/interface.c:310 ../plugins/gtkui/deadbeef.glade.h:17
+msgid "Column headers"
+msgstr "Kolumnhuvuden"
+
+#: ../plugins/gtkui/interface.c:314 ../plugins/gtkui/deadbeef.glade.h:118
+msgid "Tabs"
+msgstr "Flikar"
+
+#: ../plugins/gtkui/interface.c:318 ../plugins/gtkui/deadbeef.glade.h:32
+msgid "Equalizer"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:322 ../plugins/gtkui/deadbeef.glade.h:143
+msgid "_Playback"
+msgstr "_Uppspelning"
+
+#: ../plugins/gtkui/interface.c:329 ../plugins/gtkui/deadbeef.glade.h:75
+msgid "Order"
+msgstr "Ordning"
+
+#: ../plugins/gtkui/interface.c:336 ../plugins/gtkui/deadbeef.glade.h:63
+msgid "Linear"
+msgstr "Linjär"
+
+#: ../plugins/gtkui/interface.c:342 ../plugins/gtkui/deadbeef.glade.h:108
+msgid "Shuffle"
+msgstr "Blanda"
+
+#: ../plugins/gtkui/interface.c:348 ../plugins/gtkui/deadbeef.glade.h:94
+msgid "Random"
+msgstr "Slumpa"
+
+#: ../plugins/gtkui/interface.c:354 ../plugins/gtkui/deadbeef.glade.h:67
+msgid "Looping"
+msgstr "Upprepning"
+
+#: ../plugins/gtkui/interface.c:361 ../plugins/gtkui/deadbeef.glade.h:65
+msgid "Loop All"
+msgstr "Upprepa alla"
+
+#: ../plugins/gtkui/interface.c:367 ../plugins/gtkui/deadbeef.glade.h:66
+msgid "Loop Single Song"
+msgstr "Upprepa ett spår"
+
+#: ../plugins/gtkui/interface.c:373 ../plugins/gtkui/deadbeef.glade.h:28
+msgid "Don't Loop"
+msgstr "Upprepa inte"
+
+#: ../plugins/gtkui/interface.c:379 ../plugins/gtkui/deadbeef.glade.h:101
+msgid "Scroll follows playback"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:384 ../plugins/gtkui/deadbeef.glade.h:21
+msgid "Cursor follows playback"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:388 ../plugins/gtkui/deadbeef.glade.h:113
+msgid "Stop after current"
+msgstr "Stanna efter nuvarande"
+
+#: ../plugins/gtkui/interface.c:395 ../plugins/gtkui/interface.c:402
+#: ../plugins/gtkui/deadbeef.glade.h:140
+msgid "_Help"
+msgstr "_Hjälp"
+
+#: ../plugins/gtkui/interface.c:410 ../plugins/gtkui/deadbeef.glade.h:134
+msgid "_ChangeLog"
+msgstr "_Ändringslogg"
+
+#: ../plugins/gtkui/interface.c:432 ../plugins/gtkui/deadbeef.glade.h:131
+msgid "_About"
+msgstr "_Om"
+
+#: ../plugins/gtkui/interface.c:816 ../plugins/gtkui/deadbeef.glade.h:102
+msgid "Search"
+msgstr "Sök"
+
+#: ../plugins/gtkui/interface.c:891 ../plugins/gtkui/deadbeef.glade.h:112
+msgid "Stop"
+msgstr "Stopp"
+
+#: ../plugins/gtkui/interface.c:899 ../plugins/gtkui/deadbeef.glade.h:81
+msgid "Play"
+msgstr "Spela"
+
+#: ../plugins/gtkui/interface.c:907 ../plugins/gtkui/deadbeef.glade.h:80
+msgid "Pause"
+msgstr "Paus"
+
+#: ../plugins/gtkui/interface.c:915 ../plugins/gtkui/deadbeef.glade.h:86
+msgid "Previous"
+msgstr "Föregående"
+
+#: ../plugins/gtkui/interface.c:923 ../plugins/gtkui/deadbeef.glade.h:73
+msgid "Next"
+msgstr "Nästa"
+
+#: ../plugins/gtkui/interface.c:931 ../plugins/gtkui/deadbeef.glade.h:82
+msgid "Play Random"
+msgstr "Spela slumpad"
+
+#: ../plugins/gtkui/interface.c:940 ../plugins/gtkui/deadbeef.glade.h:5
+msgid "About"
+msgstr "Om"
+
+#: ../plugins/gtkui/interface.c:953 ../plugins/gtkui/deadbeef.glade.h:93
+msgid "Quit"
+msgstr "Avsluta"
+
+#: ../plugins/gtkui/interface.c:1025 ../plugins/gtkui/deadbeef.glade.h:10
+msgid "Adding files..."
+msgstr "Lägger till filer..."
+
+#: ../plugins/gtkui/interface.c:1069 ../plugins/gtkui/deadbeef.glade.h:130
+msgid "_Abort"
+msgstr "_Avbryt"
+
+#: ../plugins/gtkui/interface.c:1170 ../plugins/gtkui/deadbeef.glade.h:122
+msgid "Track Properties"
+msgstr "Spåregenskaper"
+
+#: ../plugins/gtkui/interface.c:1194 ../plugins/gtkui/deadbeef.glade.h:3
+msgid ""
+"<b>WARNING</b>: tag writing feature is still in development.\n"
+"<b>Make backup copies</b> before using."
+msgstr ""
+"<b>VARNING</b>: funktionen för att skriva taggar är fortfarande i "
+"utvecklingsfasen.\n"
+"<b>Gör säkerhetskopior</b> innan den används."
+
+#: ../plugins/gtkui/interface.c:1221 ../plugins/gtkui/deadbeef.glade.h:132
+msgid "_Apply"
+msgstr "_Verkställ"
+
+#: ../plugins/gtkui/interface.c:1242 ../plugins/gtkui/interface.c:1288
+#: ../plugins/gtkui/interface.c:2436 ../plugins/gtkui/deadbeef.glade.h:136
+msgid "_Close"
+msgstr "_Stäng"
+
+#: ../plugins/gtkui/interface.c:1246 ../plugins/gtkui/deadbeef.glade.h:68
+msgid "Metadata"
+msgstr "Metadata"
+
+#: ../plugins/gtkui/interface.c:1292 ../plugins/gtkui/plcommon.c:402
+#: ../plugins/gtkui/deadbeef.glade.h:87
+msgid "Properties"
+msgstr "Egenskaper"
+
+#: ../plugins/gtkui/interface.c:1378 ../plugins/gtkui/deadbeef.glade.h:146
+msgid "editcolumndlg"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1393 ../plugins/gtkui/interface.c:2770
+#: ../plugins/gtkui/deadbeef.glade.h:121
+msgid "Title:"
+msgstr "Titel:"
+
+#: ../plugins/gtkui/interface.c:1401 ../plugins/gtkui/deadbeef.glade.h:31
+msgid "Enter new column title here"
+msgstr "Ange ny kolumntitel här"
+
+#: ../plugins/gtkui/interface.c:1409 ../plugins/gtkui/deadbeef.glade.h:123
+msgid "Type:"
+msgstr "Typ:"
+
+#: ../plugins/gtkui/interface.c:1417
+msgid "File number"
+msgstr "Filnummer"
+
+#. create default set of columns
+#: ../plugins/gtkui/interface.c:1418 ../plugins/gtkui/mainplaylist.c:297
+msgid "Playing"
+msgstr "Spelar"
+
+#: ../plugins/gtkui/interface.c:1419
+msgid "Album Art"
+msgstr "Albumillustration"
+
+#: ../plugins/gtkui/interface.c:1420
+msgid "Artist - Album"
+msgstr "Artist - Album"
+
+#: ../plugins/gtkui/interface.c:1421 ../plugins/gtkui/plcommon.c:774
+msgid "Artist"
+msgstr "Artist"
+
+#: ../plugins/gtkui/interface.c:1422 ../plugins/gtkui/interface.c:1795
+msgid "Album"
+msgstr "Album"
+
+#: ../plugins/gtkui/interface.c:1423 ../plugins/gtkui/prefwin.c:488
+msgid "Title"
+msgstr "Titel"
+
+#: ../plugins/gtkui/interface.c:1424
+msgid "Length"
+msgstr "Längd"
+
+#: ../plugins/gtkui/interface.c:1425 ../plugins/gtkui/interface.c:1794
+msgid "Track"
+msgstr "Spår"
+
+#: ../plugins/gtkui/interface.c:1426
+msgid "Band / Album Artist"
+msgstr "Artist"
+
+#: ../plugins/gtkui/interface.c:1427 ../plugins/gtkui/plcommon.c:778
+msgid "Custom"
+msgstr "Anpassad"
+
+#: ../plugins/gtkui/interface.c:1433 ../plugins/gtkui/interface.c:2997
+#: ../plugins/gtkui/deadbeef.glade.h:53
+msgid "Format:"
+msgstr "Format:"
+
+#: ../plugins/gtkui/interface.c:1448 ../plugins/gtkui/deadbeef.glade.h:11
+msgid "Alignment:"
+msgstr "Justering:"
+
+#: ../plugins/gtkui/interface.c:1456
+msgid "Left"
+msgstr "Vänster"
+
+#: ../plugins/gtkui/interface.c:1457
+msgid "Right"
+msgstr "Höger"
+
+# sanslöst kass uppställning
+#: ../plugins/gtkui/interface.c:1459 ../plugins/gtkui/interface.c:3007
+#: ../plugins/gtkui/deadbeef.glade.h:47
+#, no-c-format
+msgid ""
+"Format conversions (start with %):\n"
+" [a]rtist, [t]itle, al[b]um, [B]and, [C]omposer\n"
+" track[n]umber, [N]totaltracks,\n"
+" [l]ength, [y]ear, [g]enre, [c]omment,\n"
+" copy[r]ight, [f]ilename, [T]ags\n"
+"Example: %a - %t [%l]"
+msgstr ""
+"Formateringsregler (börja med %):\n"
+" artist ([a]), titel ([t]), album ([b]), band ([B]), kompositör ([C])\n"
+" spårnummer ([n]), antal spår ([N]),\n"
+" längd ([l]), år ([y]), genre ([g]), kommentar ([c]),\n"
+" upphovs[r]ätt, [f]ilnamn, taggar ([T])\n"
+"Exempel: %a - %t [%l]"
+
+#: ../plugins/gtkui/interface.c:1488 ../plugins/gtkui/interface.c:2801
+#: ../plugins/gtkui/interface.c:2913 ../plugins/gtkui/interface.c:3036
+#: ../plugins/gtkui/deadbeef.glade.h:133
+msgid "_Cancel"
+msgstr "_Avbryt"
+
+#: ../plugins/gtkui/interface.c:1509 ../plugins/gtkui/interface.c:2822
+#: ../plugins/gtkui/interface.c:2934 ../plugins/gtkui/interface.c:3057
+#: ../plugins/gtkui/deadbeef.glade.h:141
+msgid "_OK"
+msgstr "_OK"
+
+#: ../plugins/gtkui/interface.c:1726 ../plugins/gtkui/deadbeef.glade.h:77
+msgid "Output plugin:"
+msgstr "Instick för uppspelning:"
+
+#: ../plugins/gtkui/interface.c:1739 ../plugins/gtkui/deadbeef.glade.h:76
+msgid "Output device:"
+msgstr "Enhet för uppspelning:"
+
+#: ../plugins/gtkui/interface.c:1748 ../plugins/gtkui/deadbeef.glade.h:109
+msgid "Sound"
+msgstr "Ljud"
+
+#: ../plugins/gtkui/interface.c:1757 ../plugins/gtkui/deadbeef.glade.h:12
+msgid "Allow dynamic samplerate switching"
+msgstr "Tillåt att dynamisk samplingsnivå skiftar"
+
+#: ../plugins/gtkui/interface.c:1765 ../plugins/gtkui/deadbeef.glade.h:98
+msgid "Samplerate conversion quality:"
+msgstr "Konverteringskvalité för samplingsnivå:"
+
+#: ../plugins/gtkui/interface.c:1784 ../plugins/gtkui/deadbeef.glade.h:96
+msgid "Replaygain mode:"
+msgstr "Läge för justering av uppspelningsvolym:"
+
+#: ../plugins/gtkui/interface.c:1793
+msgid "Disable"
+msgstr "Avaktivera"
+
+#: ../plugins/gtkui/interface.c:1797 ../plugins/gtkui/deadbeef.glade.h:97
+msgid "Replaygain peak scale"
+msgstr "Övre gräns för justering av uppspelningsvolym"
+
+#: ../plugins/gtkui/interface.c:1801 ../plugins/gtkui/deadbeef.glade.h:110
+msgid "Sound (adv.)"
+msgstr "Ljud (avancerat)"
+
+#: ../plugins/gtkui/interface.c:1810 ../plugins/gtkui/deadbeef.glade.h:16
+msgid "Close minimizes to tray"
+msgstr "Stäng minimerar till systembricka"
+
+#: ../plugins/gtkui/interface.c:1814 ../plugins/gtkui/deadbeef.glade.h:70
+msgid "Middle mouse button closes playlist"
+msgstr "Klicka med musknappen i mitten för att stänga spellista"
+
+#: ../plugins/gtkui/interface.c:1827 ../plugins/gtkui/interface.c:1871
+#: ../plugins/gtkui/deadbeef.glade.h:78
+msgid "Override"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1836 ../plugins/gtkui/deadbeef.glade.h:45
+msgid "Foreground"
+msgstr "Förgrund"
+
+#: ../plugins/gtkui/interface.c:1843 ../plugins/gtkui/deadbeef.glade.h:14
+msgid "Background"
+msgstr "Bakgrund"
+
+#: ../plugins/gtkui/interface.c:1862 ../plugins/gtkui/deadbeef.glade.h:103
+msgid "Seekbar/Volumebar colors"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1880 ../plugins/gtkui/deadbeef.glade.h:69
+msgid "Middle"
+msgstr "Mitten"
+
+#: ../plugins/gtkui/interface.c:1887 ../plugins/gtkui/deadbeef.glade.h:62
+msgid "Light"
+msgstr "Ljus"
+
+#: ../plugins/gtkui/interface.c:1894 ../plugins/gtkui/deadbeef.glade.h:22
+msgid "Dark"
+msgstr "Mörk"
+
+#: ../plugins/gtkui/interface.c:1925 ../plugins/gtkui/deadbeef.glade.h:15
+msgid "Base"
+msgstr "Bas"
+
+#: ../plugins/gtkui/interface.c:1932 ../plugins/gtkui/deadbeef.glade.h:117
+msgid "Tab strip colors"
+msgstr "Färg för flikrad"
+
+#: ../plugins/gtkui/interface.c:1941 ../plugins/gtkui/deadbeef.glade.h:79
+msgid "Override (looses GTK treeview theming, but speeds up rendering)"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:1950 ../plugins/gtkui/deadbeef.glade.h:33
+msgid "Even row"
+msgstr "Jämn rad"
+
+#: ../plugins/gtkui/interface.c:1957 ../plugins/gtkui/deadbeef.glade.h:74
+msgid "Odd row"
+msgstr "Ojämn rad"
+
+#: ../plugins/gtkui/interface.c:1976 ../plugins/gtkui/deadbeef.glade.h:120
+msgid "Text"
+msgstr "Text"
+
+#: ../plugins/gtkui/interface.c:1983 ../plugins/gtkui/deadbeef.glade.h:105
+msgid "Selected row"
+msgstr "Markerad rad"
+
+#: ../plugins/gtkui/interface.c:2002 ../plugins/gtkui/deadbeef.glade.h:106
+msgid "Selected text"
+msgstr "Markerad text"
+
+#: ../plugins/gtkui/interface.c:2015 ../plugins/gtkui/deadbeef.glade.h:20
+msgid "Cursor"
+msgstr "Markör"
+
+#: ../plugins/gtkui/interface.c:2028 ../plugins/gtkui/deadbeef.glade.h:83
+msgid "Playlist colors"
+msgstr "Spellistans färger"
+
+#: ../plugins/gtkui/interface.c:2032 ../plugins/gtkui/deadbeef.glade.h:54
+msgid "GUI"
+msgstr "GUI"
+
+#: ../plugins/gtkui/interface.c:2041 ../plugins/gtkui/deadbeef.glade.h:30
+msgid "Enable Proxy Server"
+msgstr "Aktivera proxyserver"
+
+#: ../plugins/gtkui/interface.c:2049 ../plugins/gtkui/deadbeef.glade.h:89
+msgid "Proxy Server Address:"
+msgstr "Adress för proxyserver:"
+
+#: ../plugins/gtkui/interface.c:2063 ../plugins/gtkui/deadbeef.glade.h:90
+msgid "Proxy Server Port:"
+msgstr "Port för proxyserver:"
+
+#: ../plugins/gtkui/interface.c:2077 ../plugins/gtkui/deadbeef.glade.h:91
+msgid "Proxy Type:"
+msgstr "Proxytyp:"
+
+#: ../plugins/gtkui/interface.c:2096 ../plugins/gtkui/deadbeef.glade.h:92
+msgid "Proxy Username:"
+msgstr "Användarnamn för proxy:"
+
+#: ../plugins/gtkui/interface.c:2109 ../plugins/gtkui/deadbeef.glade.h:88
+msgid "Proxy Password:"
+msgstr "Lösenord för proxy:"
+
+#: ../plugins/gtkui/interface.c:2119 ../plugins/gtkui/deadbeef.glade.h:71
+msgid "Network"
+msgstr "Nätverk"
+
+#: ../plugins/gtkui/interface.c:2147 ../plugins/gtkui/deadbeef.glade.h:128
+msgid "Write ID3v2"
+msgstr "Skriv ID3v2"
+
+#: ../plugins/gtkui/interface.c:2151 ../plugins/gtkui/interface.c:2278
+#: ../plugins/gtkui/deadbeef.glade.h:127
+msgid "Write ID3v1"
+msgstr "Skriv ID3v1"
+
+#: ../plugins/gtkui/interface.c:2155 ../plugins/gtkui/interface.c:2234
+#: ../plugins/gtkui/interface.c:2274 ../plugins/gtkui/deadbeef.glade.h:126
+msgid "Write APEv2"
+msgstr "Skriv APEv2"
+
+#: ../plugins/gtkui/interface.c:2163 ../plugins/gtkui/interface.c:2242
+#: ../plugins/gtkui/deadbeef.glade.h:116
+msgid "Strip ID3v2"
+msgstr "Rensa ID3v2"
+
+#: ../plugins/gtkui/interface.c:2167 ../plugins/gtkui/interface.c:2290
+#: ../plugins/gtkui/deadbeef.glade.h:115
+msgid "Strip ID3v1"
+msgstr "Rensa ID3v1"
+
+#: ../plugins/gtkui/interface.c:2171 ../plugins/gtkui/interface.c:2246
+#: ../plugins/gtkui/interface.c:2286 ../plugins/gtkui/deadbeef.glade.h:114
+msgid "Strip APEv2"
+msgstr "Rensa APEv2"
+
+#: ../plugins/gtkui/interface.c:2179 ../plugins/gtkui/deadbeef.glade.h:58
+msgid "ID3v2 version"
+msgstr "ID3v2 version"
+
+#: ../plugins/gtkui/interface.c:2186
+msgid "2.3 (Recommended)"
+msgstr "2.3 (Rekomenderad)"
+
+#: ../plugins/gtkui/interface.c:2187
+msgid "2.4"
+msgstr "2.4"
+
+#: ../plugins/gtkui/interface.c:2193 ../plugins/gtkui/deadbeef.glade.h:57
+msgid "ID3v1 character encoding (default is iso8859-1)"
+msgstr "ID3v1 teckenkodning ( iso8859-1 är standard)"
+
+#: ../plugins/gtkui/interface.c:2230 ../plugins/gtkui/deadbeef.glade.h:129
+msgid "Write ID3v2.4"
+msgstr "Skriv ID3v2.4"
+
+#: ../plugins/gtkui/interface.c:2299 ../plugins/gtkui/deadbeef.glade.h:119
+msgid "Tag writer"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2330 ../plugins/gtkui/deadbeef.glade.h:23
+msgid "Description:"
+msgstr "Beskrivning:"
+
+#: ../plugins/gtkui/interface.c:2345 ../plugins/gtkui/deadbeef.glade.h:13
+msgid "Author(s):"
+msgstr "Författare:"
+
+#: ../plugins/gtkui/interface.c:2360 ../plugins/gtkui/deadbeef.glade.h:29
+msgid "Email:"
+msgstr "E-post:"
+
+#: ../plugins/gtkui/interface.c:2375 ../plugins/gtkui/deadbeef.glade.h:125
+msgid "Website:"
+msgstr "Webbplats:"
+
+#: ../plugins/gtkui/interface.c:2406 ../plugins/gtkui/deadbeef.glade.h:18
+msgid "Configure"
+msgstr "Inställningar"
+
+#: ../plugins/gtkui/interface.c:2410 ../plugins/gtkui/deadbeef.glade.h:84
+msgid "Plugins"
+msgstr "Instick"
+
+#: ../plugins/gtkui/interface.c:2754 ../plugins/gtkui/deadbeef.glade.h:147
+msgid "editplaylistdlg"
+msgstr ""
+
+#: ../plugins/gtkui/interface.c:2881 ../plugins/gtkui/deadbeef.glade.h:124
+msgid "URL:"
+msgstr "URL:"
+
+#: ../plugins/gtkui/interface.c:2982 ../plugins/gtkui/deadbeef.glade.h:55
+msgid "Group By"
+msgstr "Gruppera efter"
+
+#: ../plugins/gtkui/mainplaylist.c:298 ../plugins/gtkui/search.c:433
+msgid "Artist / Album"
+msgstr "Artist / Album"
+
+#: ../plugins/gtkui/mainplaylist.c:299 ../plugins/gtkui/search.c:434
+msgid "Track No"
+msgstr "Spårnummer"
+
+#: ../plugins/gtkui/mainplaylist.c:300 ../plugins/gtkui/search.c:435
+msgid "Title / Track Artist"
+msgstr "Titel / Artist för spåret"
+
+#: ../plugins/gtkui/mainplaylist.c:301 ../plugins/gtkui/search.c:436
+#: ../plugins/gtkui/trkproperties.c:175
+msgid "Duration"
+msgstr "Längd"
+
+#: ../plugins/gtkui/plcommon.c:316
+msgid "Delete files from disk"
+msgstr "Radera filer från disk"
+
+#: ../plugins/gtkui/plcommon.c:317
+msgid ""
+"Files will be lost. Proceed?\n"
+"(This dialog can be turned off in GTKUI plugin settings)"
+msgstr ""
+"Filer kommer att förloras. Fortsätta?\n"
+"(Denna dialogruta kan stängas av i inställningarna för GTKUI-instick)"
+
+#: ../plugins/gtkui/plcommon.c:318 ../plugins/gtkui/trkproperties.c:56
+msgid "Warning"
+msgstr "Varning"
+
+#: ../plugins/gtkui/plcommon.c:363
+msgid "Add to playback queue"
+msgstr "Lägg till i uppspelningskön"
+
+#: ../plugins/gtkui/plcommon.c:368
+msgid "Remove from playback queue"
+msgstr "Ta bort från uppspelningskön"
+
+#: ../plugins/gtkui/plcommon.c:376
+msgid "Reload metadata"
+msgstr "Ladda om metadata"
+
+#: ../plugins/gtkui/plcommon.c:392
+msgid "Remove from disk"
+msgstr "Ta bort från disk"
+
+#: ../plugins/gtkui/plcommon.c:616 ../plugins/gtkui/plcommon.c:741
+msgid "Add column"
+msgstr "Lägg till kolumn"
+
+#: ../plugins/gtkui/plcommon.c:646 ../plugins/gtkui/plcommon.c:745
+msgid "Edit column"
+msgstr "Redigera kolumn"
+
+#: ../plugins/gtkui/plcommon.c:749
+msgid "Remove column"
+msgstr "Ta bort kolumn"
+
+#: ../plugins/gtkui/plcommon.c:759
+msgid "Group by"
+msgstr "Gruppera efter"
+
+#: ../plugins/gtkui/plcommon.c:766
+msgid "None"
+msgstr "Ingen"
+
+#: ../plugins/gtkui/plcommon.c:770
+msgid "Artist/Date/Album"
+msgstr "Artist/Datum/Album"
+
+#: ../plugins/gtkui/pluginconf.c:41
+msgid "Open file..."
+msgstr "Öppna fil..."
+
+#: ../plugins/gtkui/pluginconf.c:139
+#, c-format
+msgid "Setup %s"
+msgstr ""
+
+#: ../plugins/gtkui/prefwin.c:98
+msgid "Default Audio Device"
+msgstr "Standardljudenhet"
+
+#: ../plugins/gtkui/prefwin.c:267
+msgid "Add"
+msgstr "Lägg till"
+
+#: ../plugins/gtkui/prefwin.c:277
+msgid "Global Hotkeys"
+msgstr "Globala snabbtangenter"
+
+#: ../plugins/gtkui/prefwin.c:332
+msgid "Slot"
+msgstr ""
+
+#: ../plugins/gtkui/prefwin.c:333
+msgid "Key combination"
+msgstr ""
+
+#. output plugin selection
+#: ../plugins/gtkui/prefwin.c:379 ../plugins/gtkui/prefwin.c:569
+#: ../plugins.c:833
+msgid "ALSA output plugin"
+msgstr ""
+
+#: ../plugins/gtkui/progress.c:64
+msgid "Initializing..."
+msgstr "Förbereder..."
+
+#: ../plugins/gtkui/trkproperties.c:53
+msgid "You've modified data for this track."
+msgstr "Du har ändrat data för detta spår."
+
+#: ../plugins/gtkui/trkproperties.c:55
+msgid "Really close the window?"
+msgstr "Ska fönstret verkligen stängas?"
+
+#: ../plugins/gtkui/trkproperties.c:178
+msgid "Tag Type(s)"
+msgstr ""
+
+#: ../plugins/gtkui/trkproperties.c:180
+msgid "Embedded Cuesheet"
+msgstr ""
+
+#: ../plugins/gtkui/trkproperties.c:180
+msgid "Yes"
+msgstr "Ja"
+
+#: ../plugins/gtkui/trkproperties.c:180
+msgid "No"
+msgstr "Nej"
+
+#: ../plugins/gtkui/trkproperties.c:248 ../plugins/gtkui/trkproperties.c:260
+msgid "Key"
+msgstr "Nyckel"
+
+#: ../plugins/gtkui/trkproperties.c:249 ../plugins/gtkui/trkproperties.c:261
+msgid "Value"
+msgstr "Värde"
+
+#: ../plugins/notify/notify.c:138
+msgid "DeaDBeeF now playing"
+msgstr "DeaDBeeF spelar"
+
+#: ../main.c:84
+#, c-format
+msgid "Usage: deadbeef [options] [file(s)]\n"
+msgstr "Användning: deadbeef [flaggor] [fil(er)]\n"
+
+#: ../main.c:85
+#, c-format
+msgid "Options:\n"
+msgstr "Flaggor:\n"
+
+#: ../main.c:86
+#, c-format
+msgid " --help or -h Print help (this message) and exit\n"
+msgstr ""
+
+#: ../main.c:87
+#, c-format
+msgid " --quit Quit player\n"
+msgstr ""
+
+#: ../main.c:88
+#, c-format
+msgid " --version Print version info and exit\n"
+msgstr ""
+
+#: ../main.c:89
+#, c-format
+msgid " --play Start playback\n"
+msgstr ""
+
+#: ../main.c:90
+#, c-format
+msgid " --stop Stop playback\n"
+msgstr ""
+
+#: ../main.c:91
+#, c-format
+msgid " --pause Pause playback\n"
+msgstr ""
+
+#: ../main.c:92
+#, c-format
+msgid " --next Next song in playlist\n"
+msgstr ""
+
+#: ../main.c:93
+#, c-format
+msgid " --prev Previous song in playlist\n"
+msgstr ""
+
+#: ../main.c:94
+#, c-format
+msgid " --random Random song in playlist\n"
+msgstr ""
+
+#: ../main.c:95
+#, c-format
+msgid " --queue Append file(s) to existing playlist\n"
+msgstr ""
+
+#: ../main.c:96
+#, c-format
+msgid " --nowplaying FMT Print formatted track name to stdout\n"
+msgstr ""
+
+#: ../main.c:97
+#, c-format
+msgid ""
+" FMT %%-syntax: [a]rtist, [t]itle, al[b]um,\n"
+" [l]ength, track[n]umber, [y]ear, [c]omment,\n"
+" copy[r]ight, [e]lapsed\n"
+msgstr ""
+
+#: ../main.c:100
+#, c-format
+msgid ""
+" e.g.: --nowplaying \"%%a - %%t\" should print \"artist "
+"- title\"\n"
+msgstr ""
+
+#: ../playlist.c:369 ../playlist.c:2212
+msgid "Default"
+msgstr "Standard"
+
+#: ../plugins/gtkui/deadbeef.glade.h:1
+msgid ""
+"2.3 (Recommended)\n"
+"2.4"
+msgstr ""
+"2.3 (rekomenderad)\n"
+"2.4"
+
+#: ../plugins/gtkui/deadbeef.glade.h:25
+msgid ""
+"Disable\n"
+"Track\n"
+"Album"
+msgstr ""
+"Avaktiver\n"
+"Spår\n"
+"Album"
+
+#: ../plugins/gtkui/deadbeef.glade.h:34
+msgid ""
+"File number\n"
+"Playing\n"
+"Album Art\n"
+"Artist - Album\n"
+"Artist\n"
+"Album\n"
+"Title\n"
+"Length\n"
+"Track\n"
+"Band / Album Artist\n"
+"Custom"
+msgstr ""
+"Filnummer\n"
+"Spelar\n"
+"Albumbild\n"
+"Artist -Album\n"
+"Artist\n"
+"Album\n"
+"Titel\n"
+"Längd\n"
+"Spår\n"
+"Band / Artist på album\n"
+"Anpassad"
+
+#: ../plugins/gtkui/deadbeef.glade.h:60
+msgid ""
+"Left\n"
+"Right"
+msgstr ""
+"Vänster\n"
+"Höger"
+
+#: ../plugins/gtkui/support.c:90 ../plugins/gtkui/support.c:114
+#, c-format
+msgid "Couldn't find pixmap file: %s"
+msgstr "Kunde inte hitta pixmap-fil: %s"
+
+#: ../plugins/vorbis/vcedit.c:129 ../plugins/vorbis/vcedit.c:155
+msgid "Couldn't get enough memory for input buffering."
+msgstr "Kunde inte allokera tillräckligt med minne för att buffra inläsning."
+
+#: ../plugins/vorbis/vcedit.c:179 ../plugins/vorbis/vcedit.c:550
+msgid "Error reading first page of Ogg bitstream."
+msgstr "Fel vid läsning av första sidan av Ogg-bitströmmen."
+
+#: ../plugins/vorbis/vcedit.c:185 ../plugins/vorbis/vcedit.c:557
+msgid "Error reading initial header packet."
+msgstr "Fel vid läsning av inledande pakethuvud."
+
+#: ../plugins/vorbis/vcedit.c:237
+msgid "Couldn't get enough memory to register new stream serial number."
+msgstr ""
+"Kunde inte allokera tillräckligt med minne för att registrera nytt "
+"serienummer."
+
+#: ../plugins/vorbis/vcedit.c:505
+msgid "Input truncated or empty."
+msgstr "Inläsning trunkerad eller tom."
+
+#: ../plugins/vorbis/vcedit.c:507
+msgid "Input is not an Ogg bitstream."
+msgstr "Källan är inte en Ogg-bitström."
+
+#: ../plugins/vorbis/vcedit.c:565
+msgid "Ogg bitstream does not contain Vorbis data."
+msgstr "Ogg-bitströmmen innehåller ingen Vorbis-data."
+
+#: ../plugins/vorbis/vcedit.c:578
+msgid "EOF before recognised stream."
+msgstr "Fick EOF innan strömtypen kunde identifieras."
+
+#: ../plugins/vorbis/vcedit.c:594
+msgid "Ogg bitstream does not contain a supported data-type."
+msgstr "Ogg-bitströmmen innehåller inte en datatyp som stöds."
+
+#: ../plugins/vorbis/vcedit.c:638
+msgid "Corrupt secondary header."
+msgstr "Trasigt sekundärt huvud."
+
+#: ../plugins/vorbis/vcedit.c:659
+msgid "EOF before end of Vorbis headers."
+msgstr "Fick EOF innan Vorbis-huvudet blev komplett."
+
+#: ../plugins/vorbis/vcedit.c:834
+msgid "Corrupt or missing data, continuing..."
+msgstr "Trasig eller saknas data, fortsätter..."
+
+#: ../plugins/vorbis/vcedit.c:874
+msgid ""
+"Error writing stream to output. Output stream may be corrupted or truncated."
+msgstr ""
+"Fel vid skrivning av ström till utkälla. Strömmen kan vara skadad eller "
+"trunkerad."
diff --git a/po/uk.po b/po/uk.po
new file mode 100644
index 00000000..5fa8039a
--- /dev/null
+++ b/po/uk.po
@@ -0,0 +1,1113 @@
+# Deadbeef Audio Player
+# Copyright (C) 2009-2001 Alexey Yakovenko <waker@users.sourceforge.net>
+# This file is distributed under the same license as the Deadbeef package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: deadbeef\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-05-27 16:47+0200\n"
+"PO-Revision-Date: 2010-05-24 00:21+0100\n"
+"Last-Translator: Yarema aka Knedlyk <yupadmin@gmail.com>\n"
+"Language-Team: UKRAINIAN <translate@linux.org.ua>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: \n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%"
+"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+"X-Poedit-Language: Ukrainian\n"
+"X-Poedit-SourceCharset: utf-8\n"
+"X-Poedit-Country: UKRAINE\n"
+"X-Generator: Pootle 1.1.0\n"
+
+#: ../plugins/gtkui/callbacks.c:97
+msgid "Supported sound formats"
+msgstr "Формати аудіо, що підтримується"
+
+#: ../plugins/gtkui/callbacks.c:108
+msgid "Other files (*)"
+msgstr "Інші файли (*)"
+
+#: ../plugins/gtkui/callbacks.c:117
+msgid "Open file(s)..."
+msgstr "Відкрити файл(и)..."
+
+#: ../plugins/gtkui/callbacks.c:150
+msgid "Add file(s) to playlist..."
+msgstr "Додати файл(и) до списку програвання..."
+
+#: ../plugins/gtkui/callbacks.c:182
+msgid "Add folder(s) to playlist..."
+msgstr "Додати теку(и) до списку програвання..."
+
+#: ../plugins/gtkui/callbacks.c:640
+msgid "Failed while reading help file"
+msgstr "Невдача при читанні файлу допомоги"
+
+#: ../plugins/gtkui/callbacks.c:650
+msgid "Failed to load help file"
+msgstr "Не можу прочитати файл перемоги"
+
+#: ../plugins/gtkui/callbacks.c:664 ../plugins/gtkui/interface.c:1105
+#: ../plugins/gtkui/deadbeef.glade.h:56
+msgid "Help"
+msgstr "Допомога"
+
+#: ../plugins/gtkui/callbacks.c:674
+#, c-format
+msgid "About DeaDBeeF %s"
+msgstr "Про DeaDBeeF %s"
+
+#: ../plugins/gtkui/callbacks.c:685
+#, c-format
+msgid "DeaDBeeF %s ChangeLog"
+msgstr "DeaDBeeF %s Список Змін"
+
+#: ../plugins/gtkui/ddbtabstrip.c:527
+msgid "Edit playlist"
+msgstr "Редагувати список програвання"
+
+#: ../plugins/gtkui/ddbtabstrip.c:604
+msgid "Rename Playlist"
+msgstr "Перейменувати список програвання"
+
+#: ../plugins/gtkui/ddbtabstrip.c:608
+msgid "Remove Playlist"
+msgstr "Вилучити список програвання"
+
+#: ../plugins/gtkui/ddbtabstrip.c:612
+msgid "Add New Playlist"
+msgstr "Додати новий список програвання"
+
+#: ../plugins/gtkui/eq.c:113
+msgid "Save DeaDBeeF EQ Preset"
+msgstr "Зберегти типові значення еквалайзера DeaDBeeF"
+
+#: ../plugins/gtkui/eq.c:120
+msgid "DeaDBeeF EQ preset files (*.ddbeq)"
+msgstr "Файли типових значень еквалайзера DeaDBeeF (*.ddbeq)"
+
+#: ../plugins/gtkui/eq.c:151
+msgid "Load DeaDBeeF EQ Preset..."
+msgstr "Завантаження типові значення еквалайзера DeaDBeeF..."
+
+#: ../plugins/gtkui/eq.c:155
+msgid "DeaDBeeF EQ presets (*.ddbeq)"
+msgstr "Типові значення еквалайзера DeaDBeeF (*.ddbeq)"
+
+#: ../plugins/gtkui/eq.c:214
+msgid "Import Foobar2000 EQ Preset..."
+msgstr "Імпорт типових значень еквалайзера Foobar2000"
+
+#: ../plugins/gtkui/eq.c:218
+msgid "Foobar2000 EQ presets (*.feq)"
+msgstr "Типові значення еквалайзера Foobar2000 (*.feq)"
+
+#: ../plugins/gtkui/eq.c:292
+msgid "Enable"
+msgstr "Включити"
+
+#: ../plugins/gtkui/eq.c:299
+msgid "Zero All"
+msgstr "Скинути все на нуль"
+
+#: ../plugins/gtkui/eq.c:306
+msgid "Zero Preamp"
+msgstr "Скинути на нуль підсилення"
+
+#: ../plugins/gtkui/eq.c:313
+msgid "Zero Bands"
+msgstr "Скинути на нуль частоти"
+
+#: ../plugins/gtkui/eq.c:320
+msgid "Save Preset"
+msgstr "Зберегти типові значення"
+
+#: ../plugins/gtkui/eq.c:327
+msgid "Load Preset"
+msgstr "Завантажити типові значення"
+
+#: ../plugins/gtkui/eq.c:334
+msgid "Import Foobar2000 Preset"
+msgstr "Імортувати типові значення Foobar2000"
+
+#: ../plugins/gtkui/gtkui.c:128
+#, c-format
+msgid "1 day %d:%02d:%02d"
+msgstr "1 день %d:%02d:%02d"
+
+#: ../plugins/gtkui/gtkui.c:131
+#, c-format
+msgid "%d days %d:%02d:%02d"
+msgstr "%d дні %d:%02d:%02d"
+
+#: ../plugins/gtkui/gtkui.c:140
+#, c-format
+msgid "Stopped | %d tracks | %s total playtime"
+msgstr "Зупинено | %d треків | %s повна тривалість програвання"
+
+#: ../plugins/gtkui/gtkui.c:150
+msgid "Mono"
+msgstr "Моно"
+
+#: ../plugins/gtkui/gtkui.c:150
+msgid "Stereo"
+msgstr "Стерео"
+
+#: ../plugins/gtkui/gtkui.c:170
+#, c-format
+msgid "| %4d kbps "
+msgstr "| %4d kbps"
+
+#: ../plugins/gtkui/gtkui.c:176
+msgid "Paused | "
+msgstr "На паузі |"
+
+#: ../plugins/gtkui/gtkui.c:177
+#, c-format
+msgid ""
+"%s%s %s| %dHz | %d bit | %s | %d:%02d / %s | %d tracks | %s total playtime"
+msgstr ""
+"%s%s %s| %dГц | %d біт | %s | %d:%02d / %s | %d треків | %s повна тривалість "
+"програвання"
+
+#: ../plugins/gtkui/gtkui.c:533
+msgid "Save Playlist As"
+msgstr "Зберегти список програвання як"
+
+#: ../plugins/gtkui/gtkui.c:542 ../plugins/gtkui/gtkui.c:603
+msgid "DeaDBeeF playlist files (*.dbpl)"
+msgstr "Файли списків програвання DeaDBeeF (*.dbpl)"
+
+#: ../plugins/gtkui/gtkui.c:596
+msgid "Load Playlist"
+msgstr "Завантажити список програвання"
+
+#: ../plugins/gtkui/gtkui.c:741
+msgid "New Playlist"
+msgstr "Новий список програвання"
+
+#: ../plugins/gtkui/gtkui.c:744
+#, c-format
+msgid "New Playlist (%d)"
+msgstr "Новий список програвання (%d)"
+
+#: ../plugins/gtkui/interface.c:140 ../plugins/gtkui/deadbeef.glade.h:138
+msgid "_File"
+msgstr "_Файл"
+
+#: ../plugins/gtkui/interface.c:147 ../plugins/gtkui/deadbeef.glade.h:142
+msgid "_Open file(s)"
+msgstr "_Відкрити файл(и)"
+
+#: ../plugins/gtkui/interface.c:163 ../plugins/gtkui/deadbeef.glade.h:7
+msgid "Add file(s)"
+msgstr "Додати файл(и)"
+
+#: ../plugins/gtkui/interface.c:171 ../plugins/gtkui/deadbeef.glade.h:8
+msgid "Add folder(s)"
+msgstr "Додати теку(и)"
+
+#: ../plugins/gtkui/interface.c:179 ../plugins/gtkui/deadbeef.glade.h:6
+msgid "Add Audio CD"
+msgstr "Додати Аудіо CD"
+
+#: ../plugins/gtkui/interface.c:187 ../plugins/gtkui/interface.c:2870
+#: ../plugins/gtkui/deadbeef.glade.h:9
+msgid "Add location"
+msgstr "Додати URL-посилання"
+
+#: ../plugins/gtkui/interface.c:196 ../plugins/gtkui/deadbeef.glade.h:72
+msgid "New playlist"
+msgstr "Новий список програвання"
+
+#: ../plugins/gtkui/interface.c:203 ../plugins/gtkui/deadbeef.glade.h:64
+msgid "Load playlist"
+msgstr "Викликати список програвання"
+
+#: ../plugins/gtkui/interface.c:207 ../plugins/gtkui/deadbeef.glade.h:99
+msgid "Save playlist"
+msgstr "Зберегти список програвання"
+
+#: ../plugins/gtkui/interface.c:211 ../plugins/gtkui/deadbeef.glade.h:100
+msgid "Save playlist as"
+msgstr "Зберегти список програвання як"
+
+#: ../plugins/gtkui/interface.c:220 ../plugins/gtkui/deadbeef.glade.h:144
+msgid "_Quit"
+msgstr "_Закінчити"
+
+#: ../plugins/gtkui/interface.c:231 ../plugins/gtkui/deadbeef.glade.h:137
+msgid "_Edit"
+msgstr "_Редагувати"
+
+#: ../plugins/gtkui/interface.c:238 ../plugins/gtkui/deadbeef.glade.h:135
+msgid "_Clear"
+msgstr "_Очистити"
+
+#: ../plugins/gtkui/interface.c:246 ../plugins/gtkui/deadbeef.glade.h:104
+msgid "Select all"
+msgstr "Вибрати все"
+
+#: ../plugins/gtkui/interface.c:253 ../plugins/gtkui/deadbeef.glade.h:24
+msgid "Deselect all"
+msgstr "Забрати вибирання всього"
+
+#: ../plugins/gtkui/interface.c:260 ../plugins/gtkui/deadbeef.glade.h:59
+msgid "Invert selection"
+msgstr "Інвертувати виділення"
+
+#: ../plugins/gtkui/interface.c:264 ../plugins/gtkui/deadbeef.glade.h:107
+msgid "Selection"
+msgstr "Вибір"
+
+#: ../plugins/gtkui/interface.c:271 ../plugins/gtkui/plcommon.c:387
+#: ../plugins/gtkui/prefwin.c:272 ../plugins/gtkui/deadbeef.glade.h:95
+msgid "Remove"
+msgstr "Вилучити"
+
+#: ../plugins/gtkui/interface.c:279 ../plugins/gtkui/deadbeef.glade.h:19
+msgid "Crop"
+msgstr "Вилучити невиділене"
+
+#: ../plugins/gtkui/interface.c:283 ../plugins/gtkui/deadbeef.glade.h:139
+msgid "_Find"
+msgstr "_Знайти"
+
+#: ../plugins/gtkui/interface.c:295 ../plugins/gtkui/interface.c:1706
+#: ../plugins/gtkui/deadbeef.glade.h:85
+msgid "Preferences"
+msgstr "Параметри"
+
+#: ../plugins/gtkui/interface.c:299 ../plugins/gtkui/deadbeef.glade.h:145
+msgid "_View"
+msgstr "_Вигляд"
+
+#: ../plugins/gtkui/interface.c:306 ../plugins/gtkui/deadbeef.glade.h:111
+msgid "Status bar"
+msgstr "Рядок стану"
+
+#: ../plugins/gtkui/interface.c:310 ../plugins/gtkui/deadbeef.glade.h:17
+msgid "Column headers"
+msgstr "Заголовки колонок"
+
+#: ../plugins/gtkui/interface.c:314 ../plugins/gtkui/deadbeef.glade.h:118
+msgid "Tabs"
+msgstr "Вкладки"
+
+#: ../plugins/gtkui/interface.c:318 ../plugins/gtkui/deadbeef.glade.h:32
+msgid "Equalizer"
+msgstr "Еквалайзер"
+
+#: ../plugins/gtkui/interface.c:322 ../plugins/gtkui/deadbeef.glade.h:143
+msgid "_Playback"
+msgstr "_Програвання"
+
+#: ../plugins/gtkui/interface.c:329 ../plugins/gtkui/deadbeef.glade.h:75
+msgid "Order"
+msgstr "Порядок"
+
+#: ../plugins/gtkui/interface.c:336 ../plugins/gtkui/deadbeef.glade.h:63
+msgid "Linear"
+msgstr "Одне за одним"
+
+#: ../plugins/gtkui/interface.c:342 ../plugins/gtkui/deadbeef.glade.h:108
+msgid "Shuffle"
+msgstr "Перемішане"
+
+#: ../plugins/gtkui/interface.c:348 ../plugins/gtkui/deadbeef.glade.h:94
+msgid "Random"
+msgstr "Випадково"
+
+#: ../plugins/gtkui/interface.c:354 ../plugins/gtkui/deadbeef.glade.h:67
+msgid "Looping"
+msgstr "Повторювати"
+
+#: ../plugins/gtkui/interface.c:361 ../plugins/gtkui/deadbeef.glade.h:65
+msgid "Loop All"
+msgstr "Повторювати все"
+
+#: ../plugins/gtkui/interface.c:367 ../plugins/gtkui/deadbeef.glade.h:66
+msgid "Loop Single Song"
+msgstr "Повторювати тільки одну пісню"
+
+#: ../plugins/gtkui/interface.c:373 ../plugins/gtkui/deadbeef.glade.h:28
+msgid "Don't Loop"
+msgstr "Не повторювати"
+
+#: ../plugins/gtkui/interface.c:379 ../plugins/gtkui/deadbeef.glade.h:101
+msgid "Scroll follows playback"
+msgstr "Прокручувати поточну пісню"
+
+#: ../plugins/gtkui/interface.c:384 ../plugins/gtkui/deadbeef.glade.h:21
+msgid "Cursor follows playback"
+msgstr "Виділяти поточну пісню"
+
+#: ../plugins/gtkui/interface.c:388 ../plugins/gtkui/deadbeef.glade.h:113
+msgid "Stop after current"
+msgstr "Зупинити піля поточного"
+
+#: ../plugins/gtkui/interface.c:395 ../plugins/gtkui/interface.c:402
+#: ../plugins/gtkui/deadbeef.glade.h:140
+msgid "_Help"
+msgstr "_Допомога"
+
+#: ../plugins/gtkui/interface.c:410 ../plugins/gtkui/deadbeef.glade.h:134
+msgid "_ChangeLog"
+msgstr "_Впроваджені зміни"
+
+#: ../plugins/gtkui/interface.c:432 ../plugins/gtkui/deadbeef.glade.h:131
+msgid "_About"
+msgstr "_Про"
+
+#: ../plugins/gtkui/interface.c:816 ../plugins/gtkui/deadbeef.glade.h:102
+msgid "Search"
+msgstr "Пошук"
+
+#: ../plugins/gtkui/interface.c:891 ../plugins/gtkui/deadbeef.glade.h:112
+msgid "Stop"
+msgstr "Стоп"
+
+#: ../plugins/gtkui/interface.c:899 ../plugins/gtkui/deadbeef.glade.h:81
+msgid "Play"
+msgstr "Програвати"
+
+#: ../plugins/gtkui/interface.c:907 ../plugins/gtkui/deadbeef.glade.h:80
+msgid "Pause"
+msgstr "Пауза"
+
+#: ../plugins/gtkui/interface.c:915 ../plugins/gtkui/deadbeef.glade.h:86
+msgid "Previous"
+msgstr "Попереднє"
+
+#: ../plugins/gtkui/interface.c:923 ../plugins/gtkui/deadbeef.glade.h:73
+msgid "Next"
+msgstr "Наступне"
+
+#: ../plugins/gtkui/interface.c:931 ../plugins/gtkui/deadbeef.glade.h:82
+msgid "Play Random"
+msgstr "Програвати випадково"
+
+#: ../plugins/gtkui/interface.c:940 ../plugins/gtkui/deadbeef.glade.h:5
+msgid "About"
+msgstr "Про"
+
+#: ../plugins/gtkui/interface.c:953 ../plugins/gtkui/deadbeef.glade.h:93
+msgid "Quit"
+msgstr "Вийти"
+
+#: ../plugins/gtkui/interface.c:1025 ../plugins/gtkui/deadbeef.glade.h:10
+msgid "Adding files..."
+msgstr "Додавання файлів"
+
+#: ../plugins/gtkui/interface.c:1069 ../plugins/gtkui/deadbeef.glade.h:130
+msgid "_Abort"
+msgstr "_Припинити"
+
+#: ../plugins/gtkui/interface.c:1170 ../plugins/gtkui/deadbeef.glade.h:122
+msgid "Track Properties"
+msgstr "Властивості треків"
+
+#: ../plugins/gtkui/interface.c:1194 ../plugins/gtkui/deadbeef.glade.h:3
+msgid ""
+"<b>WARNING</b>: tag writing feature is still in development.\n"
+"<b>Make backup copies</b> before using."
+msgstr ""
+"<b>ПОПЕРЕДЖЕННЯ</b>: запис міток все ще в розробці.\n"
+"<b>Зробіть копії</b> перед використанням."
+
+#: ../plugins/gtkui/interface.c:1221 ../plugins/gtkui/deadbeef.glade.h:132
+msgid "_Apply"
+msgstr "_Застосувати"
+
+#: ../plugins/gtkui/interface.c:1242 ../plugins/gtkui/interface.c:1288
+#: ../plugins/gtkui/interface.c:2436 ../plugins/gtkui/deadbeef.glade.h:136
+msgid "_Close"
+msgstr "З_акрити"
+
+#: ../plugins/gtkui/interface.c:1246 ../plugins/gtkui/deadbeef.glade.h:68
+msgid "Metadata"
+msgstr "Метадані"
+
+#: ../plugins/gtkui/interface.c:1292 ../plugins/gtkui/plcommon.c:402
+#: ../plugins/gtkui/deadbeef.glade.h:87
+msgid "Properties"
+msgstr "Властивості"
+
+#: ../plugins/gtkui/interface.c:1378 ../plugins/gtkui/deadbeef.glade.h:146
+msgid "editcolumndlg"
+msgstr "Редагувати колонку"
+
+#: ../plugins/gtkui/interface.c:1393 ../plugins/gtkui/interface.c:2770
+#: ../plugins/gtkui/deadbeef.glade.h:121
+msgid "Title:"
+msgstr "Назва:"
+
+#: ../plugins/gtkui/interface.c:1401 ../plugins/gtkui/deadbeef.glade.h:31
+msgid "Enter new column title here"
+msgstr "Введіть назву нової колонки тут:"
+
+#: ../plugins/gtkui/interface.c:1409 ../plugins/gtkui/deadbeef.glade.h:123
+msgid "Type:"
+msgstr "Тип:"
+
+#: ../plugins/gtkui/interface.c:1417
+msgid "File number"
+msgstr "Номер файлу"
+
+#. create default set of columns
+#: ../plugins/gtkui/interface.c:1418 ../plugins/gtkui/mainplaylist.c:297
+msgid "Playing"
+msgstr "Програвання"
+
+#: ../plugins/gtkui/interface.c:1419
+msgid "Album Art"
+msgstr "Обкладинка альбому"
+
+#: ../plugins/gtkui/interface.c:1420
+msgid "Artist - Album"
+msgstr "Виконавець - Альбом"
+
+#: ../plugins/gtkui/interface.c:1421 ../plugins/gtkui/plcommon.c:774
+msgid "Artist"
+msgstr "Виконавець"
+
+#: ../plugins/gtkui/interface.c:1422 ../plugins/gtkui/interface.c:1795
+msgid "Album"
+msgstr "Альбом"
+
+#: ../plugins/gtkui/interface.c:1423 ../plugins/gtkui/prefwin.c:488
+msgid "Title"
+msgstr "Назва"
+
+#: ../plugins/gtkui/interface.c:1424
+msgid "Length"
+msgstr "Тривалість"
+
+#: ../plugins/gtkui/interface.c:1425 ../plugins/gtkui/interface.c:1794
+msgid "Track"
+msgstr "Трек"
+
+#: ../plugins/gtkui/interface.c:1426
+msgid "Band / Album Artist"
+msgstr "Гурт / Альбом Виконавець"
+
+#: ../plugins/gtkui/interface.c:1427 ../plugins/gtkui/plcommon.c:778
+msgid "Custom"
+msgstr "Користувацький"
+
+#: ../plugins/gtkui/interface.c:1433 ../plugins/gtkui/interface.c:2997
+#: ../plugins/gtkui/deadbeef.glade.h:53
+msgid "Format:"
+msgstr "Формат:"
+
+#: ../plugins/gtkui/interface.c:1448 ../plugins/gtkui/deadbeef.glade.h:11
+msgid "Alignment:"
+msgstr "Вирівнювання"
+
+#: ../plugins/gtkui/interface.c:1456
+msgid "Left"
+msgstr "По лівому краю"
+
+#: ../plugins/gtkui/interface.c:1457
+msgid "Right"
+msgstr "По правому краю"
+
+#: ../plugins/gtkui/interface.c:1459 ../plugins/gtkui/interface.c:3007
+#: ../plugins/gtkui/deadbeef.glade.h:47
+#, no-c-format
+msgid ""
+"Format conversions (start with %):\n"
+" [a]rtist, [t]itle, al[b]um, [B]and, [C]omposer\n"
+" track[n]umber, [N]totaltracks,\n"
+" [l]ength, [y]ear, [g]enre, [c]omment,\n"
+" copy[r]ight, [f]ilename, [T]ags\n"
+"Example: %a - %t [%l]"
+msgstr ""
+"Перетворення формату (початок з %):\n"
+" [a]виконавець, [t]назва, [b]альбом, [B]гурт, [C]композитор\n"
+" [n]номер треку, [N]всіх треків,\n"
+" [l]протяжність, [y]рік, [g]жанр, [c]коментар,\n"
+" [r]копірайт, [f]назва файлу, [T]мітки\n"
+"Приклад: %a - %t [%l]"
+
+#: ../plugins/gtkui/interface.c:1488 ../plugins/gtkui/interface.c:2801
+#: ../plugins/gtkui/interface.c:2913 ../plugins/gtkui/interface.c:3036
+#: ../plugins/gtkui/deadbeef.glade.h:133
+msgid "_Cancel"
+msgstr "_Скасувати"
+
+#: ../plugins/gtkui/interface.c:1509 ../plugins/gtkui/interface.c:2822
+#: ../plugins/gtkui/interface.c:2934 ../plugins/gtkui/interface.c:3057
+#: ../plugins/gtkui/deadbeef.glade.h:141
+msgid "_OK"
+msgstr "_ОК"
+
+#: ../plugins/gtkui/interface.c:1726 ../plugins/gtkui/deadbeef.glade.h:77
+msgid "Output plugin:"
+msgstr "Плагін виводу:"
+
+#: ../plugins/gtkui/interface.c:1739 ../plugins/gtkui/deadbeef.glade.h:76
+msgid "Output device:"
+msgstr "Пристрій виводу:"
+
+#: ../plugins/gtkui/interface.c:1748 ../plugins/gtkui/deadbeef.glade.h:109
+msgid "Sound"
+msgstr "Звук"
+
+#: ../plugins/gtkui/interface.c:1757 ../plugins/gtkui/deadbeef.glade.h:12
+msgid "Allow dynamic samplerate switching"
+msgstr "Дозволити перетворення частоти дискретизації"
+
+#: ../plugins/gtkui/interface.c:1765 ../plugins/gtkui/deadbeef.glade.h:98
+msgid "Samplerate conversion quality:"
+msgstr "Алгоритм інтерполяції:"
+
+#: ../plugins/gtkui/interface.c:1784 ../plugins/gtkui/deadbeef.glade.h:96
+msgid "Replaygain mode:"
+msgstr "Режим автовирівнювання гучності:"
+
+#: ../plugins/gtkui/interface.c:1793
+msgid "Disable"
+msgstr "Виключити"
+
+#: ../plugins/gtkui/interface.c:1797 ../plugins/gtkui/deadbeef.glade.h:97
+msgid "Replaygain peak scale"
+msgstr "Використовувати пікове значення"
+
+#: ../plugins/gtkui/interface.c:1801 ../plugins/gtkui/deadbeef.glade.h:110
+msgid "Sound (adv.)"
+msgstr "Звук (розш.)"
+
+#: ../plugins/gtkui/interface.c:1810 ../plugins/gtkui/deadbeef.glade.h:16
+msgid "Close minimizes to tray"
+msgstr "Закрити мінімізує до сист. лотка"
+
+#: ../plugins/gtkui/interface.c:1814 ../plugins/gtkui/deadbeef.glade.h:70
+msgid "Middle mouse button closes playlist"
+msgstr "Середня кнопка миші закриває список програвання"
+
+#: ../plugins/gtkui/interface.c:1827 ../plugins/gtkui/interface.c:1871
+#: ../plugins/gtkui/deadbeef.glade.h:78
+msgid "Override"
+msgstr "Перезаписати"
+
+#: ../plugins/gtkui/interface.c:1836 ../plugins/gtkui/deadbeef.glade.h:45
+msgid "Foreground"
+msgstr "Передній план"
+
+#: ../plugins/gtkui/interface.c:1843 ../plugins/gtkui/deadbeef.glade.h:14
+msgid "Background"
+msgstr "Тло"
+
+#: ../plugins/gtkui/interface.c:1862 ../plugins/gtkui/deadbeef.glade.h:103
+msgid "Seekbar/Volumebar colors"
+msgstr "Кольори Рядка Пошуку/Регулятора Гучності"
+
+#: ../plugins/gtkui/interface.c:1880 ../plugins/gtkui/deadbeef.glade.h:69
+msgid "Middle"
+msgstr "Середньо"
+
+#: ../plugins/gtkui/interface.c:1887 ../plugins/gtkui/deadbeef.glade.h:62
+msgid "Light"
+msgstr "Легко"
+
+#: ../plugins/gtkui/interface.c:1894 ../plugins/gtkui/deadbeef.glade.h:22
+msgid "Dark"
+msgstr "Темно"
+
+#: ../plugins/gtkui/interface.c:1925 ../plugins/gtkui/deadbeef.glade.h:15
+msgid "Base"
+msgstr "Основний"
+
+#: ../plugins/gtkui/interface.c:1932 ../plugins/gtkui/deadbeef.glade.h:117
+msgid "Tab strip colors"
+msgstr "Кольори смужки вкладок"
+
+#: ../plugins/gtkui/interface.c:1941 ../plugins/gtkui/deadbeef.glade.h:79
+msgid "Override (looses GTK treeview theming, but speeds up rendering)"
+msgstr ""
+"Перезаписати (втрачаються налаштування GTK, але пришвидшується візуалізація)"
+
+#: ../plugins/gtkui/interface.c:1950 ../plugins/gtkui/deadbeef.glade.h:33
+msgid "Even row"
+msgstr "Парний рядок"
+
+#: ../plugins/gtkui/interface.c:1957 ../plugins/gtkui/deadbeef.glade.h:74
+msgid "Odd row"
+msgstr "Непарний рядок"
+
+#: ../plugins/gtkui/interface.c:1976 ../plugins/gtkui/deadbeef.glade.h:120
+msgid "Text"
+msgstr "Текст"
+
+#: ../plugins/gtkui/interface.c:1983 ../plugins/gtkui/deadbeef.glade.h:105
+msgid "Selected row"
+msgstr "Вибраний рядок"
+
+#: ../plugins/gtkui/interface.c:2002 ../plugins/gtkui/deadbeef.glade.h:106
+msgid "Selected text"
+msgstr "Вибраний текст"
+
+#: ../plugins/gtkui/interface.c:2015 ../plugins/gtkui/deadbeef.glade.h:20
+msgid "Cursor"
+msgstr "Курсор"
+
+#: ../plugins/gtkui/interface.c:2028 ../plugins/gtkui/deadbeef.glade.h:83
+msgid "Playlist colors"
+msgstr "Кольори списку програвання"
+
+#: ../plugins/gtkui/interface.c:2032 ../plugins/gtkui/deadbeef.glade.h:54
+msgid "GUI"
+msgstr "Графічний інтерфейс"
+
+#: ../plugins/gtkui/interface.c:2041 ../plugins/gtkui/deadbeef.glade.h:30
+msgid "Enable Proxy Server"
+msgstr "Включити сервер проксі"
+
+#: ../plugins/gtkui/interface.c:2049 ../plugins/gtkui/deadbeef.glade.h:89
+msgid "Proxy Server Address:"
+msgstr "Адреса сервера проксі:"
+
+#: ../plugins/gtkui/interface.c:2063 ../plugins/gtkui/deadbeef.glade.h:90
+msgid "Proxy Server Port:"
+msgstr "Порт сервера проксі:"
+
+#: ../plugins/gtkui/interface.c:2077 ../plugins/gtkui/deadbeef.glade.h:91
+msgid "Proxy Type:"
+msgstr "Тип проксі:"
+
+#: ../plugins/gtkui/interface.c:2096 ../plugins/gtkui/deadbeef.glade.h:92
+msgid "Proxy Username:"
+msgstr "Назва користувача проксі:"
+
+#: ../plugins/gtkui/interface.c:2109 ../plugins/gtkui/deadbeef.glade.h:88
+msgid "Proxy Password:"
+msgstr "Пароль користувача проксі:"
+
+#: ../plugins/gtkui/interface.c:2119 ../plugins/gtkui/deadbeef.glade.h:71
+msgid "Network"
+msgstr "Мережа"
+
+#: ../plugins/gtkui/interface.c:2147 ../plugins/gtkui/deadbeef.glade.h:128
+msgid "Write ID3v2"
+msgstr "Вписати ID3v2"
+
+#: ../plugins/gtkui/interface.c:2151 ../plugins/gtkui/interface.c:2278
+#: ../plugins/gtkui/deadbeef.glade.h:127
+msgid "Write ID3v1"
+msgstr "Вписати ID3v1"
+
+#: ../plugins/gtkui/interface.c:2155 ../plugins/gtkui/interface.c:2234
+#: ../plugins/gtkui/interface.c:2274 ../plugins/gtkui/deadbeef.glade.h:126
+msgid "Write APEv2"
+msgstr "Вписати APEv2"
+
+#: ../plugins/gtkui/interface.c:2163 ../plugins/gtkui/interface.c:2242
+#: ../plugins/gtkui/deadbeef.glade.h:116
+msgid "Strip ID3v2"
+msgstr "Вирізати ID3v2"
+
+#: ../plugins/gtkui/interface.c:2167 ../plugins/gtkui/interface.c:2290
+#: ../plugins/gtkui/deadbeef.glade.h:115
+msgid "Strip ID3v1"
+msgstr "Вирізати ID3v1"
+
+#: ../plugins/gtkui/interface.c:2171 ../plugins/gtkui/interface.c:2246
+#: ../plugins/gtkui/interface.c:2286 ../plugins/gtkui/deadbeef.glade.h:114
+msgid "Strip APEv2"
+msgstr "Вирізати APEv2"
+
+#: ../plugins/gtkui/interface.c:2179 ../plugins/gtkui/deadbeef.glade.h:58
+msgid "ID3v2 version"
+msgstr "Версія ID3v2"
+
+#: ../plugins/gtkui/interface.c:2186
+msgid "2.3 (Recommended)"
+msgstr "2.3 (Рекомендовано)"
+
+#: ../plugins/gtkui/interface.c:2187
+msgid "2.4"
+msgstr "2.4"
+
+#: ../plugins/gtkui/interface.c:2193 ../plugins/gtkui/deadbeef.glade.h:57
+msgid "ID3v1 character encoding (default is iso8859-1)"
+msgstr "Кодування символів у ID3v1 (типово є iso8859-1)"
+
+#: ../plugins/gtkui/interface.c:2230 ../plugins/gtkui/deadbeef.glade.h:129
+msgid "Write ID3v2.4"
+msgstr "Вписати ID3v2.4"
+
+#: ../plugins/gtkui/interface.c:2299 ../plugins/gtkui/deadbeef.glade.h:119
+msgid "Tag writer"
+msgstr "Записувач мітки"
+
+#: ../plugins/gtkui/interface.c:2330 ../plugins/gtkui/deadbeef.glade.h:23
+msgid "Description:"
+msgstr "Опис:"
+
+#: ../plugins/gtkui/interface.c:2345 ../plugins/gtkui/deadbeef.glade.h:13
+msgid "Author(s):"
+msgstr "Автор(и):"
+
+#: ../plugins/gtkui/interface.c:2360 ../plugins/gtkui/deadbeef.glade.h:29
+msgid "Email:"
+msgstr "Електронна пошта:"
+
+#: ../plugins/gtkui/interface.c:2375 ../plugins/gtkui/deadbeef.glade.h:125
+msgid "Website:"
+msgstr "Веб-сторінка:"
+
+#: ../plugins/gtkui/interface.c:2406 ../plugins/gtkui/deadbeef.glade.h:18
+msgid "Configure"
+msgstr "Налаштувати"
+
+#: ../plugins/gtkui/interface.c:2410 ../plugins/gtkui/deadbeef.glade.h:84
+msgid "Plugins"
+msgstr "Додатки"
+
+#: ../plugins/gtkui/interface.c:2754 ../plugins/gtkui/deadbeef.glade.h:147
+msgid "editplaylistdlg"
+msgstr "Редагувати список програвання"
+
+#: ../plugins/gtkui/interface.c:2881 ../plugins/gtkui/deadbeef.glade.h:124
+msgid "URL:"
+msgstr "URL:"
+
+#: ../plugins/gtkui/interface.c:2982 ../plugins/gtkui/deadbeef.glade.h:55
+msgid "Group By"
+msgstr "Групувати по"
+
+#: ../plugins/gtkui/mainplaylist.c:298 ../plugins/gtkui/search.c:433
+msgid "Artist / Album"
+msgstr "Виконавець / Альбом"
+
+#: ../plugins/gtkui/mainplaylist.c:299 ../plugins/gtkui/search.c:434
+msgid "Track No"
+msgstr "Номер треку"
+
+#: ../plugins/gtkui/mainplaylist.c:300 ../plugins/gtkui/search.c:435
+msgid "Title / Track Artist"
+msgstr "Назва / Виконавець треку"
+
+#: ../plugins/gtkui/mainplaylist.c:301 ../plugins/gtkui/search.c:436
+#: ../plugins/gtkui/trkproperties.c:175
+msgid "Duration"
+msgstr "Тривалість"
+
+#: ../plugins/gtkui/plcommon.c:316
+msgid "Delete files from disk"
+msgstr "Вилучити файли з диску"
+
+#: ../plugins/gtkui/plcommon.c:317
+msgid ""
+"Files will be lost. Proceed?\n"
+"(This dialog can be turned off in GTKUI plugin settings)"
+msgstr ""
+"Файли буде втрачено. Продовжити?\n"
+"(Цей діалог можна виключити в налаштуваннях плагіна GTKUI)"
+
+#: ../plugins/gtkui/plcommon.c:318 ../plugins/gtkui/trkproperties.c:56
+msgid "Warning"
+msgstr "Попередження"
+
+#: ../plugins/gtkui/plcommon.c:363
+msgid "Add to playback queue"
+msgstr "Додати до черги програвання"
+
+#: ../plugins/gtkui/plcommon.c:368
+msgid "Remove from playback queue"
+msgstr "Вилучити з черги програвання"
+
+#: ../plugins/gtkui/plcommon.c:376
+msgid "Reload metadata"
+msgstr "Перезавантажити метадані"
+
+#: ../plugins/gtkui/plcommon.c:392
+msgid "Remove from disk"
+msgstr "Вилучити з диску"
+
+#: ../plugins/gtkui/plcommon.c:616 ../plugins/gtkui/plcommon.c:741
+msgid "Add column"
+msgstr "Додати колонку"
+
+#: ../plugins/gtkui/plcommon.c:646 ../plugins/gtkui/plcommon.c:745
+msgid "Edit column"
+msgstr "Редагувати колонку"
+
+#: ../plugins/gtkui/plcommon.c:749
+msgid "Remove column"
+msgstr "Вилучити колонку"
+
+#: ../plugins/gtkui/plcommon.c:759
+msgid "Group by"
+msgstr "Групувати по"
+
+#: ../plugins/gtkui/plcommon.c:766
+msgid "None"
+msgstr "Нічого"
+
+#: ../plugins/gtkui/plcommon.c:770
+msgid "Artist/Date/Album"
+msgstr "Виконавець/Дата/Альбом"
+
+#: ../plugins/gtkui/pluginconf.c:41
+msgid "Open file..."
+msgstr "Відкрити файл..."
+
+#: ../plugins/gtkui/pluginconf.c:139
+#, c-format
+msgid "Setup %s"
+msgstr "Встановлення %s"
+
+#: ../plugins/gtkui/prefwin.c:98
+msgid "Default Audio Device"
+msgstr "Типовий пристрій Аудіо"
+
+#: ../plugins/gtkui/prefwin.c:267
+msgid "Add"
+msgstr "Додати"
+
+#: ../plugins/gtkui/prefwin.c:277
+msgid "Global Hotkeys"
+msgstr "Глобальні скорочення клавіатури"
+
+#: ../plugins/gtkui/prefwin.c:332
+msgid "Slot"
+msgstr "Слот"
+
+#: ../plugins/gtkui/prefwin.c:333
+msgid "Key combination"
+msgstr "Комбінації клавіш"
+
+#. output plugin selection
+#: ../plugins/gtkui/prefwin.c:379 ../plugins/gtkui/prefwin.c:569
+#: ../plugins.c:833
+msgid "ALSA output plugin"
+msgstr "Вихідний плагін ALSA"
+
+#: ../plugins/gtkui/progress.c:64
+msgid "Initializing..."
+msgstr "Ініціалізація..."
+
+#: ../plugins/gtkui/trkproperties.c:53
+msgid "You've modified data for this track."
+msgstr "Ви змінили дані для цього треку"
+
+#: ../plugins/gtkui/trkproperties.c:55
+msgid "Really close the window?"
+msgstr "Дійсно закрити вікно?"
+
+#: ../plugins/gtkui/trkproperties.c:178
+msgid "Tag Type(s)"
+msgstr "Тип(и) мітки"
+
+#: ../plugins/gtkui/trkproperties.c:180
+msgid "Embedded Cuesheet"
+msgstr "Вбудований список"
+
+#: ../plugins/gtkui/trkproperties.c:180
+msgid "Yes"
+msgstr "Так"
+
+#: ../plugins/gtkui/trkproperties.c:180
+msgid "No"
+msgstr "Ні"
+
+#: ../plugins/gtkui/trkproperties.c:248 ../plugins/gtkui/trkproperties.c:260
+msgid "Key"
+msgstr "Клавіша"
+
+#: ../plugins/gtkui/trkproperties.c:249 ../plugins/gtkui/trkproperties.c:261
+msgid "Value"
+msgstr "Значення"
+
+#: ../plugins/notify/notify.c:138
+msgid "DeaDBeeF now playing"
+msgstr "DeaDBeeF почав програвання"
+
+#: ../main.c:84
+#, c-format
+msgid "Usage: deadbeef [options] [file(s)]\n"
+msgstr "Використання: deadbeef [опції] [файл(и)]\n"
+
+#: ../main.c:85
+#, c-format
+msgid "Options:\n"
+msgstr "Опції:\n"
+
+#: ../main.c:86
+#, c-format
+msgid " --help or -h Print help (this message) and exit\n"
+msgstr ""
+" --help або -h Показати цю допомогу (це повідомлення) і вийти\n"
+
+#: ../main.c:87
+#, c-format
+msgid " --quit Quit player\n"
+msgstr " --quit Вийти з програвача\n"
+
+#: ../main.c:88
+#, c-format
+msgid " --version Print version info and exit\n"
+msgstr " --version Показати інформацію про версію і вийти\n"
+
+#: ../main.c:89
+#, c-format
+msgid " --play Start playback\n"
+msgstr " --play Почати програвання\n"
+
+#: ../main.c:90
+#, c-format
+msgid " --stop Stop playback\n"
+msgstr " --stop Зупинити програвання\n"
+
+#: ../main.c:91
+#, c-format
+msgid " --pause Pause playback\n"
+msgstr " --pause Призупинити програвання\n"
+
+#: ../main.c:92
+#, c-format
+msgid " --next Next song in playlist\n"
+msgstr " --next Наступна пісня в списку програвання\n"
+
+#: ../main.c:93
+#, c-format
+msgid " --prev Previous song in playlist\n"
+msgstr " --prev Попередня пісня в списку програвання\n"
+
+#: ../main.c:94
+#, c-format
+msgid " --random Random song in playlist\n"
+msgstr " --random Випадкова пісня в списку програвання\n"
+
+#: ../main.c:95
+#, c-format
+msgid " --queue Append file(s) to existing playlist\n"
+msgstr " --queue Додати файл(и) до існуючого списку програвання\n"
+
+#: ../main.c:96
+#, c-format
+msgid " --nowplaying FMT Print formatted track name to stdout\n"
+msgstr " --nowplaying FMT Показати форматовану назву треку до виводу\n"
+
+#: ../main.c:97
+#, c-format
+msgid ""
+" FMT %%-syntax: [a]rtist, [t]itle, al[b]um,\n"
+" [l]ength, track[n]umber, [y]ear, [c]omment,\n"
+" copy[r]ight, [e]lapsed\n"
+msgstr ""
+" FMT %%-синтаксис: [a]виконавець, [t]назва, [b]альбом,\n"
+" [l]тривалість, [n]номер треку, [y]рік, [c]коментар,\n"
+" [r]копірайт, [e]час що пройшов\n"
+
+#: ../main.c:100
+#, c-format
+msgid ""
+" e.g.: --nowplaying \"%%a - %%t\" should print \"artist "
+"- title\"\n"
+msgstr ""
+" наприклад: --nowplaying \"%%a - %%t\" повинно показати "
+"\"виконавець - назва\"\n"
+
+#: ../playlist.c:369 ../playlist.c:2212
+msgid "Default"
+msgstr "Типово"
+
+#: ../plugins/gtkui/deadbeef.glade.h:1
+#, fuzzy
+msgid ""
+"2.3 (Recommended)\n"
+"2.4"
+msgstr "2.3 (Рекомендовано)"
+
+#: ../plugins/gtkui/deadbeef.glade.h:25
+msgid ""
+"Disable\n"
+"Track\n"
+"Album"
+msgstr ""
+
+#: ../plugins/gtkui/deadbeef.glade.h:34
+msgid ""
+"File number\n"
+"Playing\n"
+"Album Art\n"
+"Artist - Album\n"
+"Artist\n"
+"Album\n"
+"Title\n"
+"Length\n"
+"Track\n"
+"Band / Album Artist\n"
+"Custom"
+msgstr ""
+
+#: ../plugins/gtkui/deadbeef.glade.h:60
+#, fuzzy
+msgid ""
+"Left\n"
+"Right"
+msgstr "По правому краю"
+
+#: ../plugins/gtkui/support.c:90 ../plugins/gtkui/support.c:114
+#, c-format
+msgid "Couldn't find pixmap file: %s"
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:129 ../plugins/vorbis/vcedit.c:155
+msgid "Couldn't get enough memory for input buffering."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:179 ../plugins/vorbis/vcedit.c:550
+msgid "Error reading first page of Ogg bitstream."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:185 ../plugins/vorbis/vcedit.c:557
+msgid "Error reading initial header packet."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:237
+msgid "Couldn't get enough memory to register new stream serial number."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:505
+msgid "Input truncated or empty."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:507
+msgid "Input is not an Ogg bitstream."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:565
+msgid "Ogg bitstream does not contain Vorbis data."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:578
+msgid "EOF before recognised stream."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:594
+msgid "Ogg bitstream does not contain a supported data-type."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:638
+msgid "Corrupt secondary header."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:659
+msgid "EOF before end of Vorbis headers."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:834
+msgid "Corrupt or missing data, continuing..."
+msgstr ""
+
+#: ../plugins/vorbis/vcedit.c:874
+msgid ""
+"Error writing stream to output. Output stream may be corrupted or truncated."
+msgstr ""