diff options
author | Alexey Yakovenko <wakeroid@gmail.com> | 2010-05-30 15:48:40 +0200 |
---|---|---|
committer | Alexey Yakovenko <wakeroid@gmail.com> | 2010-05-30 15:48:40 +0200 |
commit | 754fc088625e95ec3266d2db5a148cc95db51557 (patch) | |
tree | f694659121e9afc6f99e0293fd85f17cd01c5890 | |
parent | 52332cffdbbe27776b125061a17e14a47dfa55be (diff) | |
parent | 288ad1d3a653383c59c0e1f1b088ef652a6c2149 (diff) |
Merge branch 'i18n' into devel
Conflicts:
configure.ac
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 @@ -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__ @@ -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); @@ -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"><b>MP3</b></property> + <property name="label"><b>MP3</b></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"><b>APE</b></property> + <property name="label"><b>APE</b></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"><b>WavPack</b></property> + <property name="label"><b>WavPack</b></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 "" |